index.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. <template>
  2. <div class="user">
  3. <div class="tree">
  4. <treeList title="物料分类" submitType="2" :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" :tableHeight="tableHeight" :pagination="sourceList.pagination" :config="config" :loading="loading"
  10. highlight-current-row :selectConfig="selectConfig" :action-list="[
  11. {
  12. text: '添加物料',
  13. action: () => openModal('add'),
  14. disabled: false,
  15. },
  16. ]" @get-list="getList" v-if="!isShowNoAttributes">
  17. <template #pic="{ item }">
  18. <div v-if="item.fileList.length > 0">
  19. <img :src="item.fileList[0].fileUrl" class="pic" @click="handleClickFile(item.fileList[0])" />
  20. </div>
  21. <div v-else></div>
  22. </template>
  23. <template #name="{ item }">
  24. <div>
  25. <span class="el-click">{{ item.name }}</span>
  26. </div>
  27. </template>
  28. <template #size="{ item }">
  29. <div v-if="item['length'] && item.width && item.height">
  30. <span>{{ item['length'] }}</span>*
  31. <span>{{ item.width }}</span>*
  32. <span>{{ item.height }}</span>
  33. </div>
  34. <div v-else></div>
  35. </template>
  36. <template #price="{ item }">
  37. <div v-if="item.price">
  38. <span>{{ item.currency }} {{ moneyFormat(item.price ,2)}}</span>
  39. </div>
  40. <div v-else></div>
  41. </template>
  42. <template #costPrice="{ item }">
  43. <div v-if="item.costPrice">
  44. <span>{{ item.currency }} {{ moneyFormat(item.costPrice ,2)}}</span>
  45. </div>
  46. <div v-else></div>
  47. </template>
  48. </byTable>
  49. <byTable :source="sourceList.data" :tableHeight="tableHeight" :pagination="sourceList.pagination" :config="configOne" :loading="loading"
  50. highlight-current-row :selectConfig="selectConfig" :action-list="[
  51. {
  52. text: '添加物料',
  53. action: () => openModal('add'),
  54. disabled: false,
  55. },
  56. ]" @get-list="getList" v-else>
  57. <template #pic="{ item }">
  58. <div v-if="item.fileList.length > 0">
  59. <img :src="item.fileList[0].fileUrl" class="pic" @click="handleClickFile(item.fileList[0])" />
  60. </div>
  61. <div v-else></div>
  62. </template>
  63. <template #name="{ item }">
  64. <div>
  65. <span class="el-click">{{ item.name }}</span>
  66. </div>
  67. </template>
  68. <template #size="{ item }">
  69. <div v-if="item['length'] && item.width && item.height">
  70. <span>{{ item['length'] }}</span>*
  71. <span>{{ item.width }}</span>*
  72. <span>{{ item.height }}</span>
  73. </div>
  74. <div v-else></div>
  75. </template>
  76. <template #price="{ item }">
  77. <div v-if="item.price">
  78. <span>{{ item.currency }} {{ moneyFormat(item.price ,2)}}</span>
  79. </div>
  80. <div v-else></div>
  81. </template>
  82. <template #costPrice="{ item }">
  83. <div v-if="item.costPrice">
  84. <span>{{ item.currency }} {{ moneyFormat(item.costPrice ,2)}}</span>
  85. </div>
  86. <div v-else></div>
  87. </template>
  88. </byTable>
  89. </div>
  90. <el-dialog :title="modalType == 'add' ? '添加物料' : '编辑物料'" v-model="dialogVisible" width="80%" destroy-on-close>
  91. <div class="public_height_dialog">
  92. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="formDom" v-loading="submitLoading">
  93. <template #size>
  94. <div style="width: 100%">
  95. <el-form-item label="尺寸" class="margin-b-0 wid100" required>
  96. <el-row>
  97. <el-col :span="8">
  98. <el-form-item prop="length" label-width="0px" class="margin-b-0 wid100">
  99. <el-input-number v-model="formData.data.length" placeholder="请输入" style="width: 100%" :precision="2" :controls="false" :min="0"
  100. onmousewheel="return false;" />
  101. </el-form-item>
  102. </el-col>
  103. <el-col :span="8">
  104. <el-form-item prop="width" label-width="0px" class="margin-b-0 wid100">
  105. <el-input-number v-model="formData.data.width" placeholder="请输入" style="width: 100%" :precision="2" :controls="false" :min="0"
  106. onmousewheel="return false;" />
  107. </el-form-item>
  108. </el-col>
  109. <el-col :span="8">
  110. <el-form-item prop="height" label-width="0px" class="margin-b-0 wid100">
  111. <el-input-number v-model="formData.data.height" placeholder="请输入" style="width: 100%" :precision="2" :controls="false" :min="0"
  112. onmousewheel="return false;" />
  113. </el-form-item>
  114. </el-col>
  115. </el-row>
  116. </el-form-item>
  117. </div>
  118. </template>
  119. </byForm>
  120. </div>
  121. <template #footer>
  122. <el-button @click="dialogVisible = false" size="defualt" v-debounce>取 消</el-button>
  123. <el-button type="primary" @click="submitForm()" size="defualt" :loading="submitLoading" v-debounce>
  124. 确 定
  125. </el-button>
  126. </template>
  127. </el-dialog>
  128. <el-dialog :title="'关联产品'" v-model="openAssociationProduct" width="70%" destroy-on-close>
  129. <div>
  130. <!-- class="public_height_dialog" -->
  131. <!-- <el-table :data="associationProductData" style="width: 100%;">
  132. <el-table-column label="产品图片" width="80">
  133. <template #default="{ row }">
  134. <div v-if="row.fileUrl">
  135. <img :src="row.fileUrl" class="pic" @click="openImg(row.fileUrl)" />
  136. </div>
  137. </template>
  138. </el-table-column>
  139. <el-table-column prop="name" label="产品名称" min-width="130" />
  140. <el-table-column prop="customCode" label="产品编码" width="180" />
  141. <el-table-column label="规格尺寸 (cm)" width="130">
  142. <template #default="{ row, $index }">
  143. <div style="width: 100%">
  144. {{row['length']}} * {{row.width}} * {{row.height}}
  145. </div>
  146. </template>
  147. </el-table-column>
  148. <el-table-column prop="color" label="颜色" width="150" />
  149. </el-table> -->
  150. <byTable :source="associationData.data" :pagination="associationData.pagination" :config="associationConfig" :loading="loading"
  151. highlight-current-row :selectConfig="[]" :action-list="[]" @get-list="getAssociationList">
  152. <template #pic="{ item }">
  153. <div v-if="item.fileUrl">
  154. <img :src="item.fileUrl" class="pic" @click="openImg(item.fileUrl)" />
  155. </div>
  156. <div v-else></div>
  157. </template>
  158. <template #size="{ item }">
  159. <div v-if="item['length'] && item.width && item.height">
  160. <span>{{ item['length'] }}</span>*
  161. <span>{{ item.width }}</span>*
  162. <span>{{ item.height }}</span>
  163. </div>
  164. <div v-else></div>
  165. </template>
  166. </byTable>
  167. </div>
  168. <!-- <template #footer>
  169. <el-button @click="openAssociationProduct = false" size="defualt" v-debounce>关 闭</el-button>
  170. </template> -->
  171. </el-dialog>
  172. </div>
  173. </template>
  174. <script setup>
  175. import byTable from "@/components/byTable/index";
  176. import byForm from "@/components/byForm/index";
  177. import treeList from "@/components/product/treeList";
  178. const { proxy } = getCurrentInstance();
  179. const currencyData = computed(
  180. () => proxy.useUserStore().allDict["account_currency"]
  181. );
  182. const materialUnitData = computed(
  183. () => proxy.useUserStore().allDict["material_unit"]
  184. );
  185. const colorLayerData = computed(
  186. () => proxy.useUserStore().allDict["color_layer"]
  187. );
  188. const backLinesData = computed(
  189. () => proxy.useUserStore().allDict["back_lines"]
  190. );
  191. const frontLinesData = computed(
  192. () => proxy.useUserStore().allDict["front_lines"]
  193. );
  194. const tableHeight = ref(0);
  195. const getTableHeight = () => {
  196. tableHeight.value = window.innerHeight - 245;
  197. };
  198. getTableHeight();
  199. window.addEventListener("resize", () => {
  200. getTableHeight();
  201. });
  202. const loading = ref(false);
  203. const submitLoading = ref(false);
  204. const sourceList = ref({
  205. data: [],
  206. pagination: {
  207. total: 3,
  208. pageNum: 1,
  209. pageSize: 10,
  210. type: "",
  211. productClassifyId: "",
  212. keyword: "",
  213. definition: "2",
  214. },
  215. });
  216. const dialogVisible = ref(false);
  217. const modalType = ref("add");
  218. const treeData = ref([]);
  219. const rules = ref({
  220. productClassifyId: [
  221. { required: true, message: "请选择物料分类", trigger: "change" },
  222. ],
  223. attrRawMaterialId: [
  224. { required: true, message: "请选择关联原材料无属性", trigger: "change" },
  225. ],
  226. name: [{ required: true, message: "请输入物料名称", trigger: "blur" }],
  227. customCode: [{ required: true, message: "请输入物料编码", trigger: "blur" }],
  228. length: [{ required: true, message: "请输入长 (cm)", trigger: "blur" }],
  229. width: [{ required: true, message: "请输入宽 (cm)", trigger: "blur" }],
  230. height: [{ required: true, message: "请输入高 (cm)", trigger: "blur" }],
  231. price: [{ required: true, message: "请输入销售价", trigger: "blur" }],
  232. });
  233. const selectConfig = computed(() => []);
  234. const configOne = computed(() => {
  235. return [
  236. {
  237. attrs: {
  238. label: "图片",
  239. slot: "pic",
  240. align: "center",
  241. width: 80,
  242. },
  243. },
  244. {
  245. attrs: {
  246. label: "物料分类",
  247. prop: "classifyName",
  248. "min-width": 200,
  249. },
  250. },
  251. {
  252. attrs: {
  253. label: "物料编码",
  254. prop: "customCode",
  255. width: 190,
  256. },
  257. },
  258. {
  259. attrs: {
  260. label: "物料名称",
  261. slot: "name",
  262. "min-width": 300,
  263. },
  264. },
  265. {
  266. attrs: {
  267. label: "销售价",
  268. prop: "price",
  269. width: 100,
  270. },
  271. render(val) {
  272. return proxy.moneyFormat(val, 3);
  273. },
  274. },
  275. {
  276. attrs: {
  277. label: "操作",
  278. width: "180",
  279. align: "center",
  280. fixed: "right",
  281. },
  282. renderHTML(row) {
  283. return [
  284. {
  285. attrs: {
  286. label: "产品反查",
  287. type: "primary",
  288. text: true,
  289. },
  290. el: "button",
  291. click() {
  292. getAssociationProduct(row);
  293. },
  294. },
  295. {
  296. attrs: {
  297. label: "修改",
  298. type: "primary",
  299. text: true,
  300. },
  301. el: "button",
  302. click() {
  303. getDtl(row);
  304. },
  305. },
  306. {
  307. attrs: {
  308. label: "删除",
  309. type: "danger",
  310. text: true,
  311. },
  312. el: "button",
  313. click() {
  314. proxy
  315. .msgConfirm()
  316. .then((res) => {
  317. proxy
  318. .post("/productInfo/delete", {
  319. id: row.id,
  320. })
  321. .then((res) => {
  322. proxy.msgTip("删除成功", 1);
  323. getList();
  324. });
  325. })
  326. .catch((err) => {});
  327. },
  328. },
  329. ];
  330. },
  331. },
  332. ];
  333. });
  334. const config = computed(() => {
  335. return [
  336. {
  337. attrs: {
  338. label: "图片",
  339. slot: "pic",
  340. align: "center",
  341. width: 80,
  342. },
  343. },
  344. {
  345. attrs: {
  346. label: "物料分类",
  347. prop: "classifyName",
  348. "min-width": 200,
  349. },
  350. },
  351. {
  352. attrs: {
  353. label: "物料编码",
  354. prop: "customCode",
  355. width: 190,
  356. },
  357. },
  358. {
  359. attrs: {
  360. label: "物料名称",
  361. slot: "name",
  362. "min-width": 300,
  363. },
  364. },
  365. {
  366. attrs: {
  367. label: "安全库存",
  368. prop: "stockThreshold",
  369. width: 100,
  370. },
  371. },
  372. // {
  373. // attrs: {
  374. // label: "物料材质",
  375. // prop: "material",
  376. // width: 120,
  377. // },
  378. // },
  379. // {
  380. // attrs: {
  381. // label: "物料型号",
  382. // prop: "spec",
  383. // width: 120,
  384. // },
  385. // },
  386. {
  387. attrs: {
  388. label: "单位",
  389. prop: "unit",
  390. width: 80,
  391. },
  392. // render(val) {
  393. // return proxy.dictKeyValue(val, materialUnitData.value);
  394. // },
  395. },
  396. {
  397. attrs: {
  398. label: "尺寸",
  399. slot: "size",
  400. width: 130,
  401. },
  402. },
  403. {
  404. attrs: {
  405. label: "净重",
  406. prop: "netWeight",
  407. width: 100,
  408. },
  409. render(val) {
  410. if (val) {
  411. return val + " kg";
  412. }
  413. },
  414. },
  415. {
  416. attrs: {
  417. label: "成本价",
  418. prop: "costPrice",
  419. width: 100,
  420. },
  421. render(val) {
  422. return proxy.moneyFormat(val, 2);
  423. },
  424. },
  425. {
  426. attrs: {
  427. label: "销售价",
  428. prop: "price",
  429. width: 100,
  430. },
  431. render(val) {
  432. return proxy.moneyFormat(val, 3);
  433. },
  434. },
  435. {
  436. attrs: {
  437. label: "操作",
  438. width: "180",
  439. align: "center",
  440. fixed: "right",
  441. },
  442. renderHTML(row) {
  443. return [
  444. // {
  445. // attrs: {
  446. // label: "产品反查",
  447. // type: "primary",
  448. // text: true,
  449. // },
  450. // el: "button",
  451. // click() {
  452. // getAssociationProduct(row);
  453. // },
  454. // },
  455. {
  456. attrs: {
  457. label: "修改",
  458. type: "primary",
  459. text: true,
  460. },
  461. el: "button",
  462. click() {
  463. getDtl(row);
  464. },
  465. },
  466. {
  467. attrs: {
  468. label: "删除",
  469. type: "danger",
  470. text: true,
  471. },
  472. el: "button",
  473. click() {
  474. proxy
  475. .msgConfirm()
  476. .then((res) => {
  477. proxy
  478. .post("/productInfo/delete", {
  479. id: row.id,
  480. })
  481. .then((res) => {
  482. proxy.msgTip("删除成功", 1);
  483. getList();
  484. });
  485. })
  486. .catch((err) => {});
  487. },
  488. },
  489. ];
  490. },
  491. },
  492. ];
  493. });
  494. const formData = reactive({
  495. data: {},
  496. });
  497. const formOption = reactive({
  498. inline: true,
  499. labelWidth: 100,
  500. itemWidth: 100,
  501. });
  502. const formDom = ref(null);
  503. const treeListData = ref([]);
  504. function findNodeById(treeData, nodeId) {
  505. // 遍历当前层级的所有节点
  506. for (let i = 0; i < treeData.length; i++) {
  507. let node = treeData[i];
  508. // 如果当前节点的 ID 匹配目标节点的 ID,则返回当前节点
  509. if (node.id === nodeId) {
  510. return node;
  511. }
  512. // 如果当前节点有子节点,则递归调用当前函数继续查找子节点
  513. if (node.children && node.children.length > 0) {
  514. let foundNode = findNodeById(node.children, nodeId);
  515. // 如果在子节点中找到了目标节点,则返回找到的节点
  516. if (foundNode) {
  517. return foundNode;
  518. }
  519. }
  520. }
  521. // 如果遍历完所有节点仍未找到目标节点,则返回 null
  522. return null;
  523. }
  524. const isShowLabel = ref(false);
  525. const formConfig = computed(() => {
  526. return [
  527. {
  528. type: "title1",
  529. title: "基本信息",
  530. },
  531. {
  532. type: "treeSelect",
  533. prop: "productClassifyId",
  534. label: "物料分类",
  535. data: treeData.value,
  536. itemWidth: 100,
  537. disabled: false,
  538. fn: (val) => {
  539. changeProductClassifyId(val);
  540. },
  541. },
  542. {
  543. type: "input",
  544. prop: "name",
  545. label: "物料名称",
  546. itemWidth: 50,
  547. disabled: false,
  548. },
  549. {
  550. type: "input",
  551. prop: "customCode",
  552. label: "物料编码",
  553. itemWidth: 50,
  554. disabled: false,
  555. },
  556. {
  557. type: "number",
  558. prop: "price",
  559. label: "销售价(cm²)",
  560. precision: 3,
  561. min: 0.01,
  562. controls: false,
  563. itemWidth: 50,
  564. isShow: isSpecial.value,
  565. },
  566. {
  567. type: "select",
  568. prop: "attrRawMaterialId",
  569. label: "关联原材料(无属性)",
  570. itemWidth: 50,
  571. data: rawMaterialData.value,
  572. filterable: true,
  573. disabled: false,
  574. fn: (val) => {},
  575. isShow: !isSpecial.value && isShowLabel.value,
  576. },
  577. {
  578. type: "uploadImg",
  579. // limit: 1,
  580. // listType: "picture-card",
  581. // accept: ".gif, .jpeg, .jpg, .png",
  582. imgProp: "imageUrl",
  583. prop: "fileList",
  584. label: "物料缩略图",
  585. // isShow: !isSpecial.value,
  586. },
  587. {
  588. type: "title1",
  589. title: "材质特征",
  590. isShow: !isSpecial.value,
  591. },
  592. {
  593. type: "input",
  594. prop: "material",
  595. label: "材质",
  596. itemWidth: 50,
  597. isShow: !isSpecial.value,
  598. },
  599. {
  600. type: "input",
  601. prop: "spec",
  602. label: "型号",
  603. itemWidth: 50,
  604. isShow: !isSpecial.value,
  605. },
  606. {
  607. type: "select",
  608. prop: "frontalTexture",
  609. label: "正面纹路",
  610. data: frontLinesData.value,
  611. itemWidth: 50,
  612. isShow: !isSpecial.value,
  613. },
  614. {
  615. type: "select",
  616. prop: "reverseTexture",
  617. label: "背面纹路",
  618. data: backLinesData.value,
  619. itemWidth: 50,
  620. isShow: !isSpecial.value,
  621. },
  622. {
  623. type: "input",
  624. prop: "unit",
  625. label: "单位",
  626. // data: materialUnitData.value,
  627. itemWidth: 50,
  628. isShow: !isSpecial.value,
  629. },
  630. // {
  631. // type: "select",
  632. // prop: "unit",
  633. // label: "单位",
  634. // data: materialUnitData.value,
  635. // itemWidth: 50,
  636. // },
  637. {
  638. type: "select",
  639. prop: "colorLayer",
  640. label: "色层",
  641. data: colorLayerData.value,
  642. itemWidth: 50,
  643. isShow: !isSpecial.value,
  644. },
  645. // {
  646. // type: "input",
  647. // prop: "remark",
  648. // label: "备注",
  649. // itemType: "textarea",
  650. // },
  651. // {
  652. // type: "title1",
  653. // title: "规格",
  654. // isShow: !isSpecial.value,
  655. // },
  656. {
  657. type: "input",
  658. prop: "color",
  659. label: "颜色",
  660. itemWidth: 50,
  661. isShow: !isSpecial.value,
  662. },
  663. {
  664. type: "number",
  665. prop: "stockThreshold",
  666. label: "安全库存",
  667. precision: 0,
  668. min: 0,
  669. controls: false,
  670. itemWidth: 50,
  671. isShow: !isSpecial.value,
  672. },
  673. {
  674. type: "number",
  675. prop: "costPrice",
  676. label: "成本价" + (isShowLabel.value ? "(cm²)" : ""),
  677. precision: 2,
  678. min: 0.01,
  679. controls: false,
  680. itemWidth: 50,
  681. isShow: !isSpecial.value,
  682. },
  683. // {
  684. // type: "selectInput",
  685. // prop: "costPrice",
  686. // selectProp: "costCurrency",
  687. // label: "成本价",
  688. // itemWidth: 50,
  689. // disabledSelect: true,
  690. // data: currencyData.value,
  691. // },
  692. {
  693. type: "number",
  694. prop: "price",
  695. label: "销售价" + (isShowLabel.value ? "(cm²)" : ""),
  696. precision: 2,
  697. min: 0.01,
  698. controls: false,
  699. itemWidth: 50,
  700. isShow: !isSpecial.value,
  701. },
  702. // {
  703. // type: "selectInput",
  704. // prop: "price",
  705. // selectProp: "currency",
  706. // label: "销售价",
  707. // itemWidth: 50,
  708. // disabledSelect: true,
  709. // data: currencyData.value,
  710. // },
  711. {
  712. type: "slot",
  713. slotName: "size",
  714. prop: "size",
  715. label: "",
  716. itemWidth: 50,
  717. disabled: false,
  718. isShow: !isSpecial.value,
  719. },
  720. {
  721. type: "number",
  722. prop: "netWeight",
  723. label: "净重(kg)",
  724. precision: 2,
  725. min: 0,
  726. controls: false,
  727. itemWidth: 50,
  728. isShow: !isSpecial.value,
  729. },
  730. ];
  731. });
  732. const getList = async (req) => {
  733. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  734. loading.value = true;
  735. proxy.post("/productInfo/page", sourceList.value.pagination).then((res) => {
  736. sourceList.value.data = res.rows.map((x) => ({ ...x, fileList: [] }));
  737. sourceList.value.pagination.total = res.total;
  738. setTimeout(() => {
  739. loading.value = false;
  740. }, 200);
  741. const productIdList = res.rows.map((x) => x.id);
  742. // 请求文件数据并回显
  743. if (productIdList.length > 0) {
  744. proxy.getFile(productIdList, sourceList.value.data, "id");
  745. }
  746. });
  747. };
  748. const isShowNoAttributes = ref(false);
  749. const treeChange = (e) => {
  750. console.log(e, "asa");
  751. if (e.id != undefined) {
  752. sourceList.value.pagination.productClassifyId = e.id;
  753. getList({ productClassifyId: e.id });
  754. if (e.id == "110") {
  755. isShowNoAttributes.value = true;
  756. } else {
  757. if (e.parentIdSet) {
  758. isShowNoAttributes.value = e.parentIdSet.includes("110");
  759. } else {
  760. isShowNoAttributes.value = false;
  761. }
  762. }
  763. }
  764. };
  765. const isSpecial = ref(false);
  766. const openModal = () => {
  767. isSpecial.value = false;
  768. dialogVisible.value = true;
  769. modalType.value = "add";
  770. formData.data = {
  771. definition: "2",
  772. fileList: [],
  773. productClassifyId: sourceList.value.pagination.productClassifyId || "",
  774. };
  775. if (formData.data.productClassifyId) {
  776. changeProductClassifyId(formData.data.productClassifyId);
  777. }
  778. // if (currencyData.value && currencyData.value.length > 0) {
  779. // formData.data.currency = currencyData.value[0].dictKey;
  780. // formData.data.costCurrency = currencyData.value[0].dictKey;
  781. // }
  782. };
  783. const submitForm = () => {
  784. formDom.value.handleSubmit((valid) => {
  785. // if (!formData.data.fileList.length > 0) {
  786. // return proxy.msgTip("请上传图片", 2);
  787. // }
  788. submitLoading.value = true;
  789. proxy.post("/productInfo/" + modalType.value, formData.data).then(
  790. (res) => {
  791. proxy.msgTip("操作成功", 1);
  792. dialogVisible.value = false;
  793. submitLoading.value = false;
  794. getList();
  795. },
  796. (err) => {
  797. submitLoading.value = false;
  798. }
  799. );
  800. });
  801. };
  802. const getTreeList = () => {
  803. proxy
  804. .post("/productClassify/tree", { parentId: "", name: "", definition: "2" })
  805. .then((message) => {
  806. message = message.map((x) => ({ ...x, id: x.id + "" }));
  807. treeListData.value = [
  808. {
  809. id: "",
  810. label: "全部",
  811. parentId: "",
  812. children: message,
  813. },
  814. ];
  815. treeData.value = message;
  816. });
  817. };
  818. const changeProductClassifyId = (val) => {
  819. let current = findNodeById(treeData.value, val);
  820. if (current) {
  821. // 判断是否是无属性原材料
  822. if (current.id == 110) {
  823. isSpecial.value = true;
  824. } else {
  825. if (current.parentIdSet) {
  826. // 判断父级id是否包含无属性原材料
  827. isSpecial.value = current.parentIdSet.includes("110");
  828. } else {
  829. // 不是无属性原材料
  830. isSpecial.value = false;
  831. }
  832. }
  833. if (isSpecial.value == true) {
  834. for (const key in formData.data) {
  835. if (
  836. [
  837. "id",
  838. "name",
  839. "customCode",
  840. "price",
  841. "productClassifyId",
  842. "definition",
  843. "fileList",
  844. ].includes(key)
  845. ) {
  846. } else {
  847. delete formData.data[key];
  848. }
  849. }
  850. }
  851. if (current.id == 100) {
  852. isShowLabel.value = true;
  853. } else {
  854. if (current.parentIdSet) {
  855. isShowLabel.value = current.parentIdSet.includes("100");
  856. } else {
  857. isShowLabel.value = false;
  858. }
  859. }
  860. }
  861. };
  862. const getDtl = (row) => {
  863. modalType.value = "edit";
  864. proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
  865. formData.data = res;
  866. changeProductClassifyId(res.productClassifyId);
  867. formData.data.fileList = row.fileList.map((x) => ({
  868. ...x,
  869. url: x.fileUrl,
  870. name: x.fileName,
  871. }));
  872. if (formData.data.fileList.length > 0) {
  873. formData.data.imageUrl = formData.data.fileList[0].fileUrl;
  874. }
  875. dialogVisible.value = true;
  876. });
  877. };
  878. // const getDtlOne = (row) => {
  879. // modalType.value = "add";
  880. // proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
  881. // fileList.value = [];
  882. // fileListCopy.value = [];
  883. // res.type = res.type + "";
  884. // res.definition = "2";
  885. // delete res.id;
  886. // formData.data = res;
  887. // dialogVisible.value = true;
  888. // });
  889. // };
  890. const handleClickFile = (file) => {
  891. window.open(file.fileUrl, "_blank");
  892. };
  893. getTreeList();
  894. getList();
  895. const associationConfig = computed(() => {
  896. return [
  897. {
  898. attrs: {
  899. label: "产品图片",
  900. slot: "pic",
  901. align: "center",
  902. width: 80,
  903. },
  904. },
  905. {
  906. attrs: {
  907. label: "产品编码",
  908. prop: "customCode",
  909. width: 190,
  910. },
  911. },
  912. {
  913. attrs: {
  914. label: "产品名称",
  915. prop: "name",
  916. "min-width": 300,
  917. },
  918. },
  919. {
  920. attrs: {
  921. label: "尺寸",
  922. slot: "size",
  923. width: 130,
  924. },
  925. },
  926. {
  927. attrs: {
  928. label: "产品颜色",
  929. prop: "color",
  930. width: 160,
  931. },
  932. },
  933. ];
  934. });
  935. const rawMaterialData = ref([]);
  936. const getRawMaterialData = () => {
  937. proxy.post("/productInfo/page", { productClassifyId: 110 }).then((res) => {
  938. rawMaterialData.value = res.rows.map((x) => ({
  939. label: x.name + "," + x.customCode,
  940. value: x.id,
  941. }));
  942. });
  943. };
  944. getRawMaterialData();
  945. const associationData = ref({
  946. data: [],
  947. pagination: {
  948. pageNum: 1,
  949. pageSize: 10,
  950. total: 3,
  951. },
  952. });
  953. const openAssociationProduct = ref(false);
  954. const getAssociationList = (req = {}) => {
  955. associationData.value.pagination = {
  956. ...associationData.value.pagination,
  957. ...req,
  958. };
  959. proxy
  960. .post(
  961. "/productInfo/getProductByMaterialId",
  962. associationData.value.pagination
  963. )
  964. .then((res) => {
  965. associationData.value.data = res.rows;
  966. associationData.value.pagination.total = res.total;
  967. let productIds = associationData.value.data.map((x) => x.id);
  968. if (productIds && productIds.length > 0) {
  969. proxy.getFileData({
  970. businessIdList: productIds,
  971. data: associationData.value.data,
  972. att: "id",
  973. businessType: "0",
  974. fileAtt: "fileList",
  975. filePathAtt: "fileUrl",
  976. });
  977. }
  978. });
  979. };
  980. const getAssociationProduct = (row) => {
  981. openAssociationProduct.value = true;
  982. associationData.value.pagination = {
  983. pageNum: 1,
  984. pageSize: 10,
  985. total: 3,
  986. materialId: row.id,
  987. };
  988. getAssociationList();
  989. };
  990. </script>
  991. <style lang="scss" scoped>
  992. .user {
  993. padding: 10px;
  994. display: flex;
  995. justify-content: space-between;
  996. .tree {
  997. width: 300px;
  998. }
  999. .content {
  1000. width: calc(100% - 310px);
  1001. }
  1002. }
  1003. .pic {
  1004. object-fit: contain;
  1005. width: 50px;
  1006. height: 50px;
  1007. cursor: pointer;
  1008. vertical-align: middle;
  1009. }
  1010. </style>