index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. <template>
  2. <div class="tenant">
  3. <!-- <Banner /> -->
  4. <div class="content">
  5. <byTable
  6. :source="sourceList.data"
  7. :pagination="sourceList.pagination"
  8. :config="config"
  9. :loading="loading"
  10. highlight-current-row
  11. :selectConfig="selectConfig"
  12. :table-events="{
  13. //element talbe事件都能传
  14. select: select,
  15. }"
  16. :action-list="[
  17. {
  18. text: '添加BOM',
  19. action: () => openModal('add'),
  20. },
  21. ]"
  22. @get-list="getList"
  23. >
  24. <template #versionSlot="{ item }">
  25. <div
  26. style="cursor: pointer; color: #409eff"
  27. @click="hanldeOpenVer(item)"
  28. >
  29. v{{ item.versionNumber }}
  30. </div>
  31. </template>
  32. </byTable>
  33. </div>
  34. <el-dialog
  35. :title="titleText"
  36. v-model="dialogVisible"
  37. width="800"
  38. v-loading="loading"
  39. >
  40. <byForm
  41. :formConfig="formConfig"
  42. :formOption="formOption"
  43. v-model="formData.data"
  44. :rules="rules"
  45. ref="byform"
  46. >
  47. <template #slot>
  48. <div>
  49. <el-button type="primary" plain @click="openMaterial = true"
  50. >添加物料/半成品</el-button
  51. >
  52. <el-button type="primary" plain> Excel导入</el-button>
  53. <el-form
  54. ref="tableForm"
  55. :model="formData.data"
  56. :rules="rules"
  57. label-width="0px"
  58. style="margin-top: 15px"
  59. >
  60. <el-table :data="formData.data.bomDetailList">
  61. <el-table-column prop="productCode" label="物料编码" />
  62. <el-table-column prop="productName" label="物料名称" />
  63. <el-table-column prop="productUnit" label="单位" />
  64. <el-table-column prop="quantity" label="数量" width="150">
  65. <template #default="{ row, $index }">
  66. <el-form-item
  67. :prop="'bomDetailList.' + $index + '.quantity'"
  68. :rules="rules.quantity"
  69. :inline-message="true"
  70. >
  71. <el-input-number
  72. v-model="row.quantity"
  73. :precision="2"
  74. :controls="false"
  75. :min="1"
  76. />
  77. </el-form-item>
  78. </template>
  79. </el-table-column>
  80. <el-table-column prop="zip" label="成本" width="150">
  81. <template #default="{ row, $index }">
  82. <el-form-item
  83. :prop="'bomDetailList.' + $index + '.cost'"
  84. :rules="rules.cost"
  85. :inline-message="true"
  86. >
  87. <el-input-number
  88. v-model="row.cost"
  89. :precision="2"
  90. :controls="false"
  91. :min="1"
  92. />
  93. </el-form-item>
  94. </template>
  95. </el-table-column>
  96. <el-table-column prop="zip" label="操作" width="100">
  97. <template #default="{ $index }">
  98. <el-button type="primary" link @click="handleRemove($index)"
  99. >删除</el-button
  100. >
  101. </template>
  102. </el-table-column>
  103. </el-table>
  104. </el-form>
  105. </div>
  106. </template>
  107. </byForm>
  108. <template #footer>
  109. <div v-if="isShowBtns">
  110. <el-button @click="dialogVisible = false" size="large"
  111. >取 消</el-button
  112. >
  113. <el-button
  114. type="primary"
  115. @click="submitForm('byform')"
  116. size="large"
  117. :loading="submitLoading"
  118. >
  119. 确 定
  120. </el-button>
  121. </div>
  122. </template>
  123. </el-dialog>
  124. <el-dialog
  125. v-model="openMaterial"
  126. title="选择产品"
  127. width="70%"
  128. append-to-body
  129. >
  130. <SelectMaterial @handleSelect="handleSelect"></SelectMaterial>
  131. <template #footer>
  132. <span class="dialog-footer">
  133. <el-button @click="openMaterial = false">取消</el-button>
  134. </span>
  135. </template>
  136. </el-dialog>
  137. <el-dialog v-model="openVersion" title="切换版本" width="30%">
  138. <byForm
  139. :formConfig="formConfig1"
  140. :formOption="formOption"
  141. v-model="formData.data1"
  142. :rules="rules1"
  143. ref="byform1"
  144. >
  145. <template #versionSlot>
  146. <div>
  147. <el-select
  148. v-model="formData.data1.versionNumber"
  149. placeholder="请选择版本号"
  150. @change="changeRowData"
  151. >
  152. <el-option
  153. v-for="item in versionData"
  154. :label="'v' + item.versionNumber"
  155. :value="item.versionNumber"
  156. />
  157. </el-select>
  158. <el-button
  159. type="primary"
  160. link
  161. style="margin-left: 10px"
  162. @click="handleGetDetails"
  163. v-if="formData.data1.versionNumber"
  164. >查看</el-button
  165. >
  166. </div>
  167. </template>
  168. </byForm>
  169. <template #footer>
  170. <el-button @click="openVersion = false" size="large">取 消</el-button>
  171. <el-button
  172. type="primary"
  173. @click="handleChangeVer('byform1')"
  174. size="large"
  175. >
  176. 确 定
  177. </el-button>
  178. </template>
  179. </el-dialog>
  180. </div>
  181. </template>
  182. <script setup>
  183. /* eslint-disabled vue/no-unused-components */
  184. import { ElMessage, ElMessageBox } from "element-plus";
  185. import byTable from "@/components/byTable/index";
  186. import byForm from "@/components/byForm/index";
  187. import { computed, defineComponent, ref, watch, watchEffect } from "vue";
  188. import SelectMaterial from "@/components/product/SelectMaterial";
  189. const loading = ref(false);
  190. const submitLoading = ref(false);
  191. const sourceList = ref({
  192. data: [],
  193. pagination: {
  194. total: 3,
  195. pageNum: 1,
  196. pageSize: 10,
  197. },
  198. });
  199. let dialogVisible = ref(false);
  200. let openMaterial = ref(false);
  201. let openVersion = ref(false);
  202. let titleText = ref("");
  203. let modalType = ref("add");
  204. let rules = ref({
  205. productId: [{ required: true, message: "请选择产品", trigger: "change" }],
  206. quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
  207. cost: [{ required: true, message: "请输入成本", trigger: "blur" }],
  208. personLiableId: [
  209. { required: true, message: "请选择负责人", trigger: "change" },
  210. ],
  211. });
  212. let rules1 = ref({
  213. versionNumber: [
  214. { required: true, message: "请选择版本号", trigger: "change" },
  215. ],
  216. });
  217. const { proxy } = getCurrentInstance();
  218. const selectConfig = reactive([
  219. // {
  220. // label: "车间类型",
  221. // prop: "type",
  222. // data: [
  223. // {
  224. // label: "普通车间",
  225. // value: "1",
  226. // },
  227. // {
  228. // label: "半自动化车间",
  229. // value: "2",
  230. // },
  231. // {
  232. // label: "自动化车间",
  233. // value: "3",
  234. // },
  235. // ],
  236. // },
  237. ]);
  238. const config = computed(() => {
  239. return [
  240. {
  241. attrs: {
  242. label: "产品类型",
  243. prop: "productType",
  244. width: 100,
  245. },
  246. render(productType) {
  247. return productType ? "成品" : "半成品";
  248. },
  249. },
  250. {
  251. attrs: {
  252. label: "产品编码",
  253. prop: "productCode",
  254. width: 150,
  255. },
  256. },
  257. {
  258. attrs: {
  259. label: "产品名称",
  260. prop: "productName",
  261. },
  262. },
  263. {
  264. attrs: {
  265. label: "状态",
  266. prop: "status",
  267. },
  268. render(status) {
  269. return status === 1 ? "启用" : "禁用";
  270. },
  271. },
  272. {
  273. attrs: {
  274. label: "当前版本",
  275. prop: "versionNumber",
  276. slot: "versionSlot",
  277. },
  278. },
  279. {
  280. attrs: {
  281. label: "最近维护人",
  282. prop: "updateUserName",
  283. },
  284. },
  285. {
  286. attrs: {
  287. label: "最近维护时间",
  288. prop: "updateTime",
  289. },
  290. },
  291. // {
  292. // attrs: {
  293. // label: "BOM文件",
  294. // prop: "type",
  295. // width: 120,
  296. // },
  297. // render(type) {
  298. // return type == 1
  299. // ? "普通车间"
  300. // : type == 2
  301. // ? "半自动化车间"
  302. // : type == "3"
  303. // ? "自动化车间"
  304. // : "";
  305. // },
  306. // },
  307. {
  308. attrs: {
  309. label: "操作",
  310. width: "200",
  311. align: "right",
  312. },
  313. // 渲染 el-button,一般用在最后一列。
  314. renderHTML(row) {
  315. return [
  316. {
  317. attrs: {
  318. label: "新建版本",
  319. type: "primary",
  320. text: true,
  321. },
  322. el: "button",
  323. click() {
  324. getDtl(row, "add", true);
  325. },
  326. },
  327. {
  328. attrs: {
  329. label: "修改",
  330. type: "primary",
  331. text: true,
  332. },
  333. el: "button",
  334. click() {
  335. getDtl(row, "edit");
  336. },
  337. },
  338. {
  339. attrs: {
  340. label: row.status === 1 ? "禁用" : "启用",
  341. type: "primary",
  342. text: true,
  343. },
  344. el: "button",
  345. click() {
  346. ElMessageBox.confirm(
  347. `是否${row.status === 1 ? "禁用" : "启用"} ?`,
  348. "提示",
  349. {
  350. confirmButtonText: "确定",
  351. cancelButtonText: "取消",
  352. type: "warning",
  353. }
  354. ).then(() => {
  355. proxy.post("/bomInfo/detail", { id: row.id }).then((res) => {
  356. res.bomDetailList = res.bomDetailVoList;
  357. res.status = row.status ? 0 : 1;
  358. formData.data = res;
  359. proxy.post("/bomInfo/edit", formData.data).then((res) => {
  360. ElMessage({
  361. message: "操作成功",
  362. type: "success",
  363. });
  364. getList();
  365. });
  366. });
  367. });
  368. },
  369. },
  370. // {
  371. // attrs: {
  372. // label: "删除",
  373. // type: "danger",
  374. // text: true,
  375. // },
  376. // el: "button",
  377. // click() {
  378. // // 弹窗提示是否删除
  379. // ElMessageBox.confirm(
  380. // "此操作将永久删除该数据, 是否继续?",
  381. // "提示",
  382. // {
  383. // confirmButtonText: "确定",
  384. // cancelButtonText: "取消",
  385. // type: "warning",
  386. // }
  387. // ).then(() => {
  388. // // 删除
  389. // proxy
  390. // .post("/workshop/delete", {
  391. // id: row.id,
  392. // })
  393. // .then((res) => {
  394. // ElMessage({
  395. // message: "删除成功",
  396. // type: "success",
  397. // });
  398. // getList();
  399. // });
  400. // });
  401. // },
  402. // },
  403. ];
  404. },
  405. },
  406. ];
  407. });
  408. let formData = reactive({
  409. data: {
  410. productId: "",
  411. addType: "1",
  412. bomDetailList: [],
  413. },
  414. data1: {
  415. productId: "",
  416. versionNumber: "",
  417. },
  418. });
  419. const formOption = reactive({
  420. inline: true,
  421. labelWidth: 100,
  422. itemWidth: 100,
  423. rules: [],
  424. });
  425. const byform = ref(null);
  426. const formConfig = reactive([
  427. {
  428. type: "select",
  429. prop: "productId",
  430. label: "产品名称",
  431. required: true,
  432. disabled: false,
  433. isLoad: {
  434. url: "/productInfo/page",
  435. req: {
  436. pageNum: 1,
  437. pageSize: 9999,
  438. definition: "1",
  439. },
  440. labelKey: "name",
  441. labelVal: "id",
  442. method: "post",
  443. resUrl: "rows",
  444. },
  445. },
  446. {
  447. type: "slot",
  448. slotName: "slot",
  449. label: "物料信息",
  450. },
  451. ]);
  452. const formConfig1 = reactive([
  453. {
  454. type: "select",
  455. prop: "productId",
  456. label: "产品名称",
  457. required: true,
  458. disabled: true,
  459. isLoad: {
  460. url: "/productInfo/page",
  461. req: {
  462. pageNum: 1,
  463. pageSize: 9999,
  464. definition: "1",
  465. },
  466. labelKey: "name",
  467. labelVal: "id",
  468. method: "post",
  469. resUrl: "rows",
  470. },
  471. },
  472. {
  473. type: "slot",
  474. slotName: "versionSlot",
  475. label: "切换版本",
  476. required: true,
  477. },
  478. ]);
  479. const getList = async (req) => {
  480. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  481. loading.value = true;
  482. proxy.post("/bomInfo/page", sourceList.value.pagination).then((message) => {
  483. console.log(message);
  484. sourceList.value.data = message.rows;
  485. sourceList.value.pagination.total = message.total;
  486. setTimeout(() => {
  487. loading.value = false;
  488. }, 200);
  489. });
  490. };
  491. const openModal = () => {
  492. dialogVisible.value = true;
  493. titleText.value = "添加BOM";
  494. modalType.value = "add";
  495. formData.data = {
  496. productId: "",
  497. addType: "1",
  498. bomDetailList: [],
  499. };
  500. formConfig[0].disabled = false;
  501. };
  502. const submitForm = () => {
  503. byform.value.handleSubmit((valid) => {
  504. if (!formData.data.bomDetailList.length > 0)
  505. return ElMessage({
  506. message: "请添加物料/半成品",
  507. type: "info",
  508. });
  509. proxy.$refs.tableForm.validate((vaild) => {
  510. if (vaild) {
  511. submitLoading.value = true;
  512. formData.data.bomDetailList = formData.data.bomDetailList.map((x) => ({
  513. productId: x.productId,
  514. quantity: x.quantity,
  515. cost: x.cost,
  516. }));
  517. proxy.post("/bomInfo/" + modalType.value, formData.data).then(
  518. (res) => {
  519. ElMessage({
  520. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  521. type: "success",
  522. });
  523. dialogVisible.value = false;
  524. submitLoading.value = false;
  525. getList();
  526. },
  527. (err) => {
  528. console.log(err, "aswwwww");
  529. submitLoading.value = false;
  530. }
  531. );
  532. }
  533. });
  534. });
  535. };
  536. const byform1 = ref(null);
  537. const handleChangeVer = () => {
  538. if (formData.data1.versionNumber === "")
  539. return ElMessage({
  540. message: "请选择版本号",
  541. type: "info",
  542. });
  543. byform1.value.handleSubmit((valid) => {
  544. submitLoading.value = true;
  545. proxy.post("/bomInfo/editVersion", formData.data1).then(
  546. (res) => {
  547. ElMessage({
  548. message: "切换成功",
  549. type: "success",
  550. });
  551. openVersion.value = false;
  552. submitLoading.value = false;
  553. getList();
  554. },
  555. (err) => {
  556. submitLoading.value = false;
  557. }
  558. );
  559. });
  560. };
  561. const getDtl = (row, type, isNew) => {
  562. formConfig[0].disabled = true; //禁止修改产品信息
  563. modalType.value = type;
  564. proxy.post("/bomInfo/detail", { id: row.id }).then((res) => {
  565. if (isNew) {
  566. titleText.value = "新建版本";
  567. formData.data = {
  568. addType: "2", //2为新建版本
  569. productId: res.productId,
  570. bomDetailList: [],
  571. };
  572. } else {
  573. titleText.value = openVersion.value ? "版本详情" : "编辑BOM";
  574. res.bomDetailList = res.bomDetailVoList;
  575. formData.data = res;
  576. }
  577. dialogVisible.value = true;
  578. });
  579. };
  580. const handleSelect = (row) => {
  581. const flag = formData.data.bomDetailList.some((x) => x.productId === row.id);
  582. if (flag)
  583. return ElMessage({
  584. message: "该物料已选择",
  585. type: "info",
  586. });
  587. formData.data.bomDetailList.push({
  588. productId: row.id,
  589. productCode: row.code,
  590. productName: row.name,
  591. productUnit: row.unit,
  592. quantity: null,
  593. cost: null,
  594. });
  595. return ElMessage({
  596. message: "选择成功",
  597. type: "success",
  598. });
  599. };
  600. const handleRemove = (index) => {
  601. console.log(index, "as");
  602. formData.data.bomDetailList.splice(index, 1);
  603. return ElMessage({
  604. message: "删除成功",
  605. type: "success",
  606. });
  607. };
  608. const versionData = ref([]);
  609. let isShowBtns = ref(true);
  610. let rowData = ref({});
  611. const hanldeOpenVer = (row) => {
  612. formData.data1 = {
  613. productId: "",
  614. versionNumber: "",
  615. };
  616. rowData.value = row;
  617. formData.data1.productId = row.productId;
  618. proxy
  619. .post("/bomInfo/getVersion", { productId: row.productId })
  620. .then((res) => {
  621. versionData.value = res;
  622. formData.data1.versionNumber = res.filter(
  623. (x) => x.currentVersion === 1
  624. )[0].versionNumber;
  625. openVersion.value = true;
  626. });
  627. };
  628. const handleGetDetails = () => {
  629. getDtl(rowData.value);
  630. };
  631. watchEffect(() => {
  632. isShowBtns.value = openVersion.value ? false : true;
  633. //监听是否是在切换版本中,如是隐藏提交添加弹窗的按钮模块
  634. });
  635. const changeRowData = (val) => {
  636. const data = versionData.value.find((x) => x.versionNumber === val);
  637. rowData.value = data ? data : {};
  638. };
  639. getList();
  640. </script>
  641. <style lang="scss" scoped>
  642. .tenant {
  643. padding: 20px;
  644. }
  645. </style>