SelectCustomerProduct.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. <template>
  2. <div class="user">
  3. <div class="tree">
  4. <treeList title="产品分类" submitType="1" :data="treeListData" v-model="sourceList.pagination.productClassifyId" @change="treeChange"
  5. @changeTreeList="getTreeList">
  6. </treeList>
  7. </div>
  8. <div class="content">
  9. <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" highlight-current-row
  10. :selectConfig="selectConfig" :table-events="{
  11. //element talbe事件都能传
  12. select: select,
  13. }" :action-list="[]" @get-list="getList">
  14. <template #name="{ item }">
  15. <div>
  16. <span style="color: #409eff; cursor: pointer; word-break: break-all" @click="handleOpenProductContract(item)">{{ item.name }}</span>
  17. </div>
  18. </template>
  19. <template #pic="{ item }">
  20. <div v-if="item.fileList.length > 0">
  21. <img :src="item.fileList[0].fileUrl" class="pic" @click="handleClickFile(item.fileList[0])" />
  22. </div>
  23. <div v-else></div>
  24. </template>
  25. <template #size="{ item }">
  26. <div>
  27. <span>{{ item.productLong }}cm</span>*
  28. <span>{{ item.productWide }}cm</span>*
  29. <span>{{ item.productHigh }}cm</span>
  30. </div>
  31. </template>
  32. <template #price="{ item }">
  33. <div>
  34. <span v-if="item.price">{{ item.currency }} {{ item.price }}</span>
  35. </div>
  36. </template>
  37. <template #costPrice="{ item }">
  38. <div>
  39. <span v-if="item.costPrice">{{ item.costCurrency }} {{ item.costPrice }}</span>
  40. </div>
  41. </template>
  42. </byTable>
  43. </div>
  44. <div class="right">
  45. <div style="margin-bottom:30px">
  46. <TitleInfo :content="'已选择商品'"></TitleInfo>
  47. </div>
  48. <el-tag style="margin-right: 10px; margin-bottom: 10px" type="info" v-for="(good, index) in goodList" :key="good.productId">
  49. {{ good.productCnName || good.productName }}
  50. </el-tag>
  51. </div>
  52. <el-dialog :title="modalType == 'add' ? '添加产品' : '编辑产品'" v-model="dialogVisible" width="700" v-loading="submitLoading" destroy-on-close>
  53. <div class="public_height_dialog">
  54. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform">
  55. <template #customerId>
  56. <div>
  57. <el-select v-model="formData.data.customerId" filterable remote reserve-keyword placeholder="请输入关键字" remote-show-suffix
  58. :remote-method="remoteMethod" :loading="loadingSearch" @input="remoteMethod" v-if="modalType == 'add'">
  59. <el-option v-for="item in customerData" :key="item.value" :label="item.label" :value="item.value" />
  60. </el-select>
  61. <el-select v-model="formData.data.customerName" disabled v-else>
  62. </el-select>
  63. </div>
  64. </template>
  65. <template #nameEnglish>
  66. <div style="width: 100%">
  67. <el-form-item label="英文名" prop="nameEnglish">
  68. <el-input v-model="formData.data.nameEnglish" placeholder="请输入" onkeyup="value=value.replace(/[^\x00-\xff]/g, '')"></el-input>
  69. <!-- @input="(val) => handleKeyup(val)" -->
  70. </el-form-item>
  71. </div>
  72. </template>
  73. <template #productPic>
  74. <div>
  75. <el-upload v-model:fileList="fileList" action="https://winfaster.obs.cn-south-1.myhuaweicloud.com" :data="uploadData"
  76. list-type="picture-card" :on-remove="handleRemove" :before-upload="handleBeforeUpload" :on-preview="handlePreview"
  77. accept=".gif, .jpeg, .jpg, .png">
  78. <el-icon>
  79. <Plus />
  80. </el-icon>
  81. </el-upload>
  82. </div>
  83. </template>
  84. </byForm>
  85. </div>
  86. <template #footer>
  87. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  88. <el-button type="primary" @click="submitForm('byform')" size="large" :loading="submitLoading">确 定</el-button>
  89. </template>
  90. </el-dialog>
  91. <el-dialog title="导入产品" v-model="openExcelDialog" width="400" v-loading="excelLoading">
  92. <el-upload :action="actionUrl + '/productInfo/excelImportByEhsd'" :headers="headers" :on-success="handleSuccess" :on-progress="handleProgress"
  93. :show-file-list="false" :on-error="handleError" accept=".xlsx">
  94. <el-button type="primary">点击导入</el-button>
  95. </el-upload>
  96. <template #footer>
  97. <el-button @click="openExcelDialog = false" size="large">取 消</el-button>
  98. </template>
  99. </el-dialog>
  100. <el-dialog v-if="productContractDialog" v-model="productContractDialog" :title="'外销合同'" width="80%" append-to-body>
  101. <ProductContract :currentProductId="currentProductId"></ProductContract>
  102. </el-dialog>
  103. </div>
  104. </template>
  105. <script setup>
  106. import { ElMessage, ElMessageBox } from "element-plus";
  107. import byTable from "@/components/byTable/index";
  108. import byForm from "@/components/byForm/index";
  109. import treeList from "@/components/product/treeList";
  110. import { getToken } from "@/utils/auth";
  111. import ProductContract from "@/components/contractCom/productContract.vue";
  112. import TitleInfo from "@/components/TitleInfo/index.vue";
  113. const props = defineProps({
  114. buyCorporationId: String,
  115. alreadySelectData: Array,
  116. });
  117. const goodList = ref([]);
  118. onMounted(() => {
  119. goodList.value = proxy.deepClone(props.alreadySelectData);
  120. });
  121. const headers = ref({ Authorization: "Bearer " + getToken() });
  122. const actionUrl = import.meta.env.VITE_APP_BASE_API;
  123. const loading = ref(false);
  124. const innerMethon = ref([]);
  125. const outsideMethon = ref([]);
  126. const productUnit = ref([]);
  127. const accountCurrency = ref([]);
  128. const customerData = ref([]);
  129. const submitLoading = ref(false);
  130. const sourceList = ref({
  131. data: [],
  132. pagination: {
  133. total: 3,
  134. pageNum: 1,
  135. pageSize: 10,
  136. type: "",
  137. productClassifyId: "",
  138. keyword: "",
  139. definition: "1",
  140. customerId: "",
  141. },
  142. });
  143. let dialogVisible = ref(false);
  144. let openExcelDialog = ref(false);
  145. let excelLoading = ref(false);
  146. let modalType = ref("add");
  147. let rules = ref({
  148. customerId: [
  149. { required: true, message: "请选择客户名称", trigger: "change" },
  150. ],
  151. productClassifyId: [
  152. { required: true, message: "请选择产品分类", trigger: "change" },
  153. ],
  154. name: [{ required: true, message: "请输入产品名称", trigger: "blur" }],
  155. nameEnglish: [
  156. { required: true, message: "请输入产品英文名", trigger: "blur" },
  157. ],
  158. productLong: [
  159. { required: true, message: "请输入长 (cm)", trigger: "blur" },
  160. ],
  161. productWide: [
  162. { required: true, message: "请输入宽 (cm)", trigger: "blur" },
  163. ],
  164. productHigh: [
  165. { required: true, message: "请输入高 (cm)", trigger: "blur" },
  166. ],
  167. innerPackMethod: [
  168. { required: true, message: "请选择内包装方式", trigger: "change" },
  169. ],
  170. outerPackMethod: [
  171. { required: true, message: "请选择外包装方式", trigger: "change" },
  172. ],
  173. });
  174. const { proxy } = getCurrentInstance();
  175. const selectConfig = reactive([
  176. // {
  177. // label: "产品类型",
  178. // prop: "type",
  179. // data: [],
  180. // },
  181. ]);
  182. const config = computed(() => {
  183. return [
  184. {
  185. attrs: {
  186. label: "客户名称",
  187. prop: "customerName",
  188. align: "left",
  189. width: 180,
  190. },
  191. },
  192. {
  193. attrs: {
  194. label: "图片",
  195. slot: "pic",
  196. align: "center",
  197. width: 100,
  198. },
  199. },
  200. {
  201. attrs: {
  202. label: "产品编码",
  203. prop: "code",
  204. },
  205. },
  206. {
  207. attrs: {
  208. label: "产品名称",
  209. slot: "name",
  210. },
  211. },
  212. {
  213. attrs: {
  214. label: "尺寸",
  215. slot: "size",
  216. },
  217. },
  218. {
  219. attrs: {
  220. label: "销售指导价",
  221. slot: "price",
  222. width: 150,
  223. },
  224. },
  225. {
  226. attrs: {
  227. label: "成本价",
  228. slot: "costPrice",
  229. width: 150,
  230. },
  231. },
  232. {
  233. attrs: {
  234. label: "操作",
  235. width: "80",
  236. align: "center",
  237. fixed: "right",
  238. },
  239. // 渲染 el-button,一般用在最后一列。
  240. renderHTML(row) {
  241. return [
  242. {
  243. attrs: {
  244. label: "选择",
  245. type: "primary",
  246. text: true,
  247. },
  248. el: "button",
  249. click() {
  250. clickSelect(row);
  251. },
  252. },
  253. ];
  254. },
  255. },
  256. ];
  257. });
  258. const uploadData = ref({});
  259. const fileList = ref([]);
  260. const fileListCopy = ref([]);
  261. let formData = reactive({
  262. data: {},
  263. });
  264. const formOption = reactive({
  265. disabled: false,
  266. inline: true,
  267. labelWidth: 100,
  268. itemWidth: 100,
  269. rules: [],
  270. });
  271. const byform = ref(null);
  272. const treeListData = ref([]);
  273. const formConfig = computed(() => {
  274. return [
  275. {
  276. type: "title",
  277. title: "客户信息",
  278. },
  279. // {
  280. // type: "select",
  281. // prop: modalType.value == "add" ? "customerId" : "customerName",
  282. // label: "客户名称",
  283. // required: true,
  284. // itemWidth: 100,
  285. // data: customerData.value,
  286. // style: {
  287. // width: "50%",
  288. // },
  289. // disabled: false,
  290. // },
  291. {
  292. type: "slot",
  293. slotName: "customerId",
  294. label: "客户名称",
  295. },
  296. {
  297. type: "title",
  298. title: "基本信息",
  299. },
  300. {
  301. type: "treeSelect",
  302. prop: "productClassifyId",
  303. label: "产品分类",
  304. data: treeListData.value,
  305. itemWidth: 100,
  306. disabled: false,
  307. style: {
  308. width: "100%",
  309. },
  310. },
  311. {
  312. type: "input",
  313. prop: "name",
  314. label: "产品名称",
  315. itemWidth: 100,
  316. disabled: false,
  317. },
  318. {
  319. type: "slot",
  320. slotName: "nameEnglish",
  321. label: "",
  322. },
  323. {
  324. type: "slot",
  325. slotName: "productPic",
  326. prop: "fileList",
  327. label: "产品图片",
  328. },
  329. {
  330. type: "title",
  331. title: "价格信息",
  332. },
  333. {
  334. type: "selectInput",
  335. prop: "price",
  336. selectProp: "currency",
  337. label: "销售指导价",
  338. itemWidth: 50,
  339. style: {
  340. width: "100%",
  341. },
  342. data: accountCurrency.value,
  343. },
  344. {
  345. type: "selectInput",
  346. prop: "costPrice",
  347. selectProp: "costCurrency",
  348. label: "成本价",
  349. itemWidth: 50,
  350. style: {
  351. width: "100%",
  352. },
  353. data: accountCurrency.value,
  354. },
  355. {
  356. type: "title",
  357. title: "属性信息",
  358. },
  359. {
  360. type: "input",
  361. prop: "spec",
  362. label: "规格型号",
  363. itemWidth: 100,
  364. disabled: false,
  365. },
  366. {
  367. type: "input",
  368. prop: "productLong",
  369. label: "尺寸",
  370. itemWidth: 33.33,
  371. placeholder: "长(cm)",
  372. disabled: false,
  373. },
  374. {
  375. type: "input",
  376. prop: "productWide",
  377. label: " ",
  378. itemWidth: 33.33,
  379. placeholder: "宽(cm)",
  380. disabled: false,
  381. },
  382. {
  383. type: "input",
  384. prop: "productHigh",
  385. label: " ",
  386. itemWidth: 33.33,
  387. placeholder: "高(cm)",
  388. disabled: false,
  389. },
  390. {
  391. type: "select",
  392. prop: "innerPackMethod",
  393. label: "内包装方式",
  394. required: true,
  395. itemWidth: 50,
  396. multiple: true,
  397. data: innerMethon.value,
  398. placeholder: "内包装方式",
  399. style: {
  400. width: "100%",
  401. },
  402. disabled: false,
  403. },
  404. {
  405. type: "select",
  406. prop: "outerPackMethod",
  407. label: "外包装方式",
  408. required: true,
  409. itemWidth: 50,
  410. multiple: true,
  411. data: outsideMethon.value,
  412. placeholder: "外包装方式",
  413. style: {
  414. width: "100%",
  415. },
  416. disabled: false,
  417. },
  418. {
  419. type: "input",
  420. prop: "netWeight",
  421. label: "净重(kg)",
  422. itemWidth: 100,
  423. style: {
  424. width: "30%",
  425. },
  426. },
  427. {
  428. type: "input",
  429. prop: "hsCode",
  430. label: "海关编码",
  431. itemWidth: 100,
  432. style: {
  433. width: "30%",
  434. },
  435. disabled: false,
  436. },
  437. {
  438. type: "input",
  439. itemType: "textarea",
  440. prop: "remark",
  441. label: "备注",
  442. itemWidth: 100,
  443. },
  444. ];
  445. });
  446. const getList = async (req) => {
  447. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  448. if (props.buyCorporationId) {
  449. sourceList.value.pagination.customerId = props.buyCorporationId;
  450. }
  451. loading.value = true;
  452. proxy
  453. .post("/productInfo/getCustomerProductList", sourceList.value.pagination)
  454. .then(
  455. (message) => {
  456. message.rows = message.rows.map((x) => ({
  457. ...x,
  458. fileList: [],
  459. ...JSON.parse(x.ehsdJson),
  460. }));
  461. sourceList.value.data = message.rows;
  462. sourceList.value.pagination.total = message.total;
  463. setTimeout(() => {
  464. loading.value = false;
  465. }, 200);
  466. const productIdList = message.rows.map((x) => x.id);
  467. // 请求文件数据并回显
  468. if (productIdList.length > 0) {
  469. proxy
  470. .post("/fileInfo/getList", {
  471. businessIdList: productIdList,
  472. })
  473. .then((fileObj) => {
  474. for (let i = 0; i < sourceList.value.data.length; i++) {
  475. const e = sourceList.value.data[i];
  476. for (const key in fileObj) {
  477. if (e.id === key) {
  478. e.fileList = fileObj[key];
  479. }
  480. }
  481. }
  482. });
  483. }
  484. },
  485. (err) => {
  486. loading.value = false;
  487. }
  488. );
  489. };
  490. const treeChange = (e) => {
  491. sourceList.value.pagination.productClassifyId = e.id;
  492. getList({ productClassifyId: e.id });
  493. };
  494. const openModal = () => {
  495. fileList.value = [];
  496. dialogVisible.value = true;
  497. modalType.value = "add";
  498. formData.data = {
  499. definition: "1",
  500. outerPackMethod: [],
  501. innerPackMethod: [],
  502. fileList: [],
  503. fileListCopy: [],
  504. currency: "",
  505. costCurrency: "",
  506. };
  507. if (accountCurrency.value && accountCurrency.value.length > 0) {
  508. formData.data.currency = accountCurrency.value[0].value;
  509. formData.data.costCurrency = accountCurrency.value[0].value;
  510. }
  511. fileList.value = [];
  512. fileListCopy.value = [];
  513. };
  514. const openExcel = () => {
  515. openExcelDialog.value = true;
  516. };
  517. const tree = ref(null);
  518. const needAtt = [
  519. "productClassifyId",
  520. "name",
  521. "spec",
  522. "remark",
  523. "fileList",
  524. "id",
  525. "unit",
  526. "definition",
  527. ];
  528. let jsonObj = {};
  529. const submitForm = () => {
  530. byform.value.handleSubmit((valid) => {
  531. // if (!fileListCopy.value.length > 0) {
  532. // return ElMessage({
  533. // message: "请上传产品图片",
  534. // type: "info",
  535. // });
  536. // }
  537. formData.data.fileList = fileListCopy.value.map((x) => ({
  538. id: x.id,
  539. fileName: x.fileName,
  540. }));
  541. for (const key in formData.data) {
  542. if (needAtt.includes(key)) {
  543. } else {
  544. jsonObj[key] = formData.data[key];
  545. delete formData.data[key];
  546. }
  547. }
  548. jsonObj.innerPackMethod = jsonObj.innerPackMethod.join(",");
  549. jsonObj.outerPackMethod = jsonObj.outerPackMethod.join(",");
  550. // jsonObj.customerId = jsonObj.customerId + "";
  551. jsonObj.type = "2"; //2为客户产品库
  552. formData.data.ehsdJson = JSON.stringify(jsonObj);
  553. submitLoading.value = true;
  554. proxy.post(`/productInfo/${modalType.value}ByEhsd`, formData.data).then(
  555. (res) => {
  556. ElMessage({
  557. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  558. type: "success",
  559. });
  560. dialogVisible.value = false;
  561. submitLoading.value = false;
  562. getList();
  563. },
  564. (err) => {
  565. for (const key in jsonObj) {
  566. formData.data[key] = jsonObj[key];
  567. }
  568. formData.data.innerPackMethod =
  569. formData.data.innerPackMethod.split(",");
  570. formData.data.outerPackMethod =
  571. formData.data.outerPackMethod.split(",");
  572. submitLoading.value = false;
  573. }
  574. );
  575. });
  576. };
  577. const getTreeList = () => {
  578. proxy
  579. .post("/productClassify/tree", { parentId: "", name: "", definition: "1" })
  580. .then((message) => {
  581. treeListData.value = message;
  582. });
  583. };
  584. const getDtl = (row) => {
  585. fileList.value = [];
  586. modalType.value = "edit";
  587. proxy.post("/productInfo/detailByEhsd", { id: row.id }).then((res) => {
  588. res.definition = "1"; //产品
  589. let jsonObj = JSON.parse(res.ehsdJson);
  590. res = {
  591. ...res,
  592. currency: jsonObj.currency
  593. ? jsonObj.currency
  594. : accountCurrency.value[0].value,
  595. costCurrency: jsonObj.costCurrency
  596. ? jsonObj.costCurrency
  597. : accountCurrency.value[0].value,
  598. ...jsonObj,
  599. };
  600. if (res.innerPackMethod) {
  601. res.innerPackMethod = res.innerPackMethod.split(",");
  602. } else {
  603. res.innerPackMethod = [];
  604. }
  605. if (res.outerPackMethod) {
  606. res.outerPackMethod = res.outerPackMethod.split(",");
  607. } else {
  608. res.outerPackMethod = [];
  609. }
  610. formData.data = res;
  611. dialogVisible.value = true;
  612. proxy
  613. .post("/fileInfo/getList", { businessIdList: [row.id] })
  614. .then((fileObj) => {
  615. if (fileObj[row.id]) {
  616. fileList.value = fileObj[row.id].map((x) => ({
  617. ...x,
  618. url: x.fileUrl,
  619. }));
  620. fileListCopy.value = fileObj[row.id].map((x) => ({
  621. ...x,
  622. url: x.fileUrl,
  623. }));
  624. } else {
  625. fileList.value = [];
  626. fileListCopy.value = [];
  627. }
  628. });
  629. });
  630. };
  631. const isdisabled = ["price", "costPrice", "remark", "netWeight"];
  632. // watch(modalType, (val) => {
  633. // if (val) {
  634. // for (let i = 0; i < formConfig.value.length; i++) {
  635. // const element = formConfig.value[i];
  636. // if (element.type != "title" || element.type != "slot") {
  637. // if (!isdisabled.includes(element.prop)) {
  638. // element.disabled = val == "edit" ? true : false;
  639. // }
  640. // }
  641. // }
  642. // }
  643. // });
  644. const handleBeforeUpload = async (file) => {
  645. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  646. uploadData.value = res.uploadBody;
  647. fileListCopy.value.push({
  648. id: res.id,
  649. fileName: res.fileName,
  650. path: res.fileUrl,
  651. url: res.fileUrl,
  652. uid: file.uid,
  653. });
  654. };
  655. const handleRemove = (file) => {
  656. const index = fileListCopy.value.findIndex(
  657. (x) => x.uid === file.uid || x.id === file.id
  658. );
  659. fileListCopy.value.splice(index, 1);
  660. };
  661. const handleClickFile = (file) => {
  662. window.open(file.fileUrl, "_blank");
  663. };
  664. const handleProgress = () => {
  665. excelLoading.value = true;
  666. };
  667. const handleError = (err) => {
  668. ElMessage({
  669. message: `${err},请重试!`,
  670. type: "info",
  671. });
  672. openExcelDialog.value = false;
  673. excelLoading.value = false;
  674. };
  675. const handleSuccess = (res) => {
  676. if (res.code != 200) {
  677. return ElMessage({
  678. message: `${res.msg},请重试!`,
  679. type: "info",
  680. });
  681. } else {
  682. ElMessage({
  683. message: "导入成功!",
  684. type: "success",
  685. });
  686. openExcelDialog.value = false;
  687. excelLoading.value = false;
  688. getList();
  689. }
  690. };
  691. const getDict = () => {
  692. proxy.post("/customer/selPage", { pageNum: 1, pageSize: 50 }).then((res) => {
  693. customerData.value = res.rows.map((x) => ({
  694. ...x,
  695. label: x.name,
  696. value: x.id,
  697. }));
  698. });
  699. proxy
  700. .getDictOne([
  701. "inner_packaging_method_ehsd",
  702. "outside_packaging_method_ehsd",
  703. "unit",
  704. "account_currency",
  705. ])
  706. .then((res) => {
  707. innerMethon.value = res["inner_packaging_method_ehsd"].map((x) => ({
  708. label: x.dictValue,
  709. value: x.dictKey,
  710. }));
  711. outsideMethon.value = res["outside_packaging_method_ehsd"].map((x) => ({
  712. label: x.dictValue,
  713. value: x.dictKey,
  714. }));
  715. productUnit.value = res["unit"].map((x) => ({
  716. label: x.dictValue,
  717. value: x.dictKey,
  718. }));
  719. accountCurrency.value = res["account_currency"].map((x) => ({
  720. label: x.dictValue,
  721. value: x.dictKey,
  722. }));
  723. });
  724. };
  725. getDict();
  726. getTreeList();
  727. getList();
  728. const clickSelect = (item) => {
  729. item.selectType = "2";
  730. goodList.value.push({
  731. ...item,
  732. productName: item.name,
  733. });
  734. proxy.$emit("selectProduct", item);
  735. };
  736. const loadingSearch = ref(false);
  737. const remoteMethod = (keyword) => {
  738. if (keyword && typeof keyword === "string") {
  739. loadingSearch.value = true;
  740. proxy.post("/customer/selPage", { keyword }).then((res) => {
  741. customerData.value = res.rows.map((x) => ({
  742. ...x,
  743. label: x.name,
  744. value: x.id,
  745. }));
  746. loadingSearch.value = false;
  747. });
  748. }
  749. return;
  750. };
  751. const handlePreview = (file) => {
  752. if (file && file.fileUrl) {
  753. window.open(file.fileUrl, "_black");
  754. }
  755. };
  756. const productContractDialog = ref(false);
  757. const currentProductId = ref("");
  758. const handleOpenProductContract = (row) => {
  759. currentProductId.value = row.id;
  760. productContractDialog.value = true;
  761. };
  762. </script>
  763. <style lang="scss" scoped>
  764. .user {
  765. padding: 20px;
  766. display: flex;
  767. justify-content: space-between;
  768. .tree {
  769. width: 300px;
  770. }
  771. .content {
  772. width: calc(100% - 320px - 170px);
  773. }
  774. .right {
  775. padding-left: 10px;
  776. width: 170px;
  777. border-left: 1px solid #eee;
  778. }
  779. }
  780. .pic {
  781. object-fit: contain;
  782. width: 50px;
  783. height: 50px;
  784. cursor: pointer;
  785. vertical-align: middle;
  786. }
  787. </style>