index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. <template>
  2. <div class="pageIndexClass">
  3. <div class="content">
  4. <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" :selectConfig="selectConfig"
  5. highlight-current-row :action-list="[
  6. {
  7. text: '其他入库',
  8. action: () => openModal(),
  9. },
  10. ]" @get-list="getList">
  11. <template #pic="{item}">
  12. <div style="width: 100%">
  13. <img v-if="item.fileUrl" :src="item.fileUrl" class="pic" @click="openImg(item.fileUrl)" />
  14. </div>
  15. </template>
  16. </byTable>
  17. </div>
  18. <el-dialog title="其他入库" v-if="dialogVisible" v-model="dialogVisible" width="1200" v-loading="loadingDialog">
  19. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
  20. <template #details>
  21. <div style="width: 100%">
  22. <el-button type="primary" @click="openProduct = true" :disabled="['100','103'].includes(formData.data.type)">添加明细</el-button>
  23. <el-table :data="formData.data.list" style="width: 100%; margin-top: 16px">
  24. <el-table-column label="图片" width="70" align="center">
  25. <template #default="{ row, $index }">
  26. <div style="width: 100%">
  27. <img v-if="row.fileUrl" :src="row.fileUrl" class="pic" @click="handleClickFile(row.fileUrl)" />
  28. </div>
  29. </template>
  30. </el-table-column>
  31. <el-table-column prop="productCode" label="编码" width="160" />
  32. <el-table-column prop="productName" label="名称" min-width="220" />
  33. <el-table-column label="规格尺寸 (cm)" min-width="160">
  34. <template #default="{ row, $index }">
  35. <div style="width: 100%">
  36. {{row.productLength}} * {{row.productWidth}} * {{row.productHeight}}
  37. </div>
  38. </template>
  39. </el-table-column>
  40. <!-- <el-table-column prop="productUnit" label="单位" width="100" :formatter="
  41. (row) => dictKeyValue(row.productUnit, materialUnitData)
  42. " /> -->
  43. <el-table-column label="入库数量" width="140">
  44. <template #default="{ row, $index }">
  45. <div style="width: 100%">
  46. <el-form-item :prop="'list.' + $index + '.quantity'" :rules="rules.quantity" :inline-message="true" class="margin-b-0">
  47. <el-input-number v-model="row.quantity" placeholder="请输入数量" style="width: 100%" :precision="0" :controls="false" :min="1"
  48. onmousewheel="return false;" :disabled="['100','103'].includes(formData.data.type)" />
  49. </el-form-item>
  50. </div>
  51. </template>
  52. </el-table-column>
  53. <el-table-column align="center" label="操作" width="80" fixed="right" v-if="!['100','103'].includes(formData.data.type)">
  54. <template #default="{ row, $index }">
  55. <el-button type="primary" link @click="handleDelete($index)">删除</el-button>
  56. </template>
  57. </el-table-column>
  58. </el-table>
  59. </div>
  60. </template>
  61. </byForm>
  62. <template #footer>
  63. <el-button @click="dialogVisible = false" size="default">取 消</el-button>
  64. <el-button type="primary" @click="submitForm()" size="default">确 定</el-button>
  65. </template>
  66. </el-dialog>
  67. <el-dialog v-if="openProduct" v-model="openProduct" title="物品选择" width="90%" append-to-body>
  68. <SelectAllGood @selectGood="selectGood"></SelectAllGood>
  69. <!-- <SelectMaterial @selectMaterial="selectMaterial"></SelectMaterial> -->
  70. </el-dialog>
  71. </div>
  72. </template>
  73. <script setup>
  74. import { computed, ref } from "vue";
  75. import byTable from "@/components/byTable/index";
  76. import byForm from "@/components/byForm/index";
  77. import { ElMessage } from "element-plus";
  78. import SelectAllGood from "@/components/product/SelectAllGood";
  79. // import SelectMaterial from "@/components/product/SelectMaterial.vue";
  80. const { proxy } = getCurrentInstance();
  81. const warehouseList = ref([]);
  82. const warehouseListOne = ref([]);
  83. const materialUnitData = computed(
  84. () => proxy.useUserStore().allDict["material_unit"]
  85. );
  86. const inBoundReason = ref([
  87. {
  88. label: "借用归还",
  89. value: "100",
  90. },
  91. {
  92. label: "退料入库",
  93. value: "101",
  94. },
  95. {
  96. label: "废料入库",
  97. value: "102",
  98. },
  99. {
  100. label: "丢件寻回",
  101. value: "103",
  102. },
  103. {
  104. label: "超领归还",
  105. value: "108",
  106. },
  107. {
  108. label: "错领归还",
  109. value: "109",
  110. },
  111. {
  112. label: "其他入库",
  113. value: "110",
  114. },
  115. ]);
  116. const produceOrder = ref([]);
  117. const lendData = ref([]);
  118. const lendDataOne = ref([]);
  119. const sourceList = ref({
  120. data: [],
  121. pagination: {
  122. total: 0,
  123. pageNum: 1,
  124. pageSize: 10,
  125. keyword: "",
  126. warehouseId: "",
  127. type: "",
  128. opType: "1",
  129. },
  130. });
  131. const loading = ref(false);
  132. const selectConfig = computed(() => {
  133. return [
  134. {
  135. label: "业务公司",
  136. prop: "companyId",
  137. data: proxy.useUserStore().allDict["list_company_data"],
  138. },
  139. {
  140. label: "仓库名称",
  141. prop: "warehouseId",
  142. data: warehouseList.value,
  143. },
  144. {
  145. label: "入库原因",
  146. prop: "type",
  147. data: inBoundReason.value,
  148. },
  149. ];
  150. });
  151. const config = computed(() => {
  152. return [
  153. {
  154. attrs: {
  155. label: "业务公司",
  156. prop: "companyName",
  157. width: 110,
  158. },
  159. },
  160. {
  161. attrs: {
  162. label: "操作时间",
  163. prop: "createTime",
  164. width: 160,
  165. fixed: "left",
  166. },
  167. },
  168. {
  169. attrs: {
  170. label: "单号",
  171. prop: "code",
  172. width: 120,
  173. fixed: "left",
  174. },
  175. },
  176. {
  177. attrs: {
  178. label: "入库原因",
  179. prop: "type",
  180. width: 110,
  181. },
  182. render(val) {
  183. return proxy.dictValueLabel(val, inBoundReason.value);
  184. },
  185. },
  186. {
  187. attrs: {
  188. label: "仓库名称",
  189. prop: "warehouseName",
  190. width: 150,
  191. },
  192. },
  193. {
  194. attrs: {
  195. label: "图片",
  196. slot: "pic",
  197. align: "center",
  198. width: 80,
  199. },
  200. },
  201. {
  202. attrs: {
  203. label: "物品编码",
  204. prop: "productCustomCode",
  205. width: 160,
  206. },
  207. },
  208. {
  209. attrs: {
  210. label: "物品名称",
  211. prop: "productName",
  212. "min-width": 220,
  213. },
  214. },
  215. // {
  216. // attrs: {
  217. // label: "规格型号",
  218. // prop: "productSpec",
  219. // width: 160,
  220. // },
  221. // },
  222. // {
  223. // attrs: {
  224. // label: "单位",
  225. // prop: "productUnit",
  226. // width: 120,
  227. // },
  228. // render(unit) {
  229. // return proxy.dictKeyValue(unit, materialUnitData.value);
  230. // },
  231. // },
  232. {
  233. attrs: {
  234. label: "关联生产订单",
  235. prop: "prodOrderCode",
  236. width: 150,
  237. },
  238. render(val) {
  239. if (val) {
  240. return val;
  241. }
  242. return "-";
  243. },
  244. },
  245. {
  246. attrs: {
  247. label: "入库数量",
  248. prop: "quantity",
  249. width: 140,
  250. },
  251. },
  252. {
  253. attrs: {
  254. label: "申请入库人",
  255. prop: "exWarehousePerson",
  256. width: 110,
  257. },
  258. },
  259. {
  260. attrs: {
  261. label: "备注",
  262. prop: "remarks",
  263. "min-width": 200,
  264. },
  265. },
  266. {
  267. attrs: {
  268. label: "操作人",
  269. prop: "opUserName",
  270. width: 110,
  271. },
  272. },
  273. ];
  274. });
  275. const getDict = () => {
  276. proxy.post("/warehouse/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  277. if (res.rows && res.rows.length > 0) {
  278. warehouseList.value = res.rows.map((item) => {
  279. return {
  280. label: item.name,
  281. value: item.id,
  282. };
  283. });
  284. }
  285. });
  286. proxy
  287. .post("produceOrder/page", {
  288. pageNum: 1,
  289. pageSize: 9999,
  290. neProduceStatus: "10,99",
  291. })
  292. .then((res) => {
  293. produceOrder.value = res.rows.map((x) => ({
  294. label: x.code,
  295. value: x.id,
  296. }));
  297. produceOrder.value.unshift({
  298. label: "无",
  299. value: -1,
  300. });
  301. });
  302. proxy
  303. .post("/stockJournal/page", {
  304. pageNum: 1,
  305. pageSize: 9999,
  306. isRestitution: 0,
  307. type: "3",
  308. })
  309. .then((res) => {
  310. lendData.value = res.rows.map((x) => ({
  311. label:
  312. x.code +
  313. " " +
  314. x.expectRestitutionTime.slice(0, 10) +
  315. " " +
  316. x.exWarehousePerson +
  317. " " +
  318. x.remarks,
  319. value: x.id,
  320. }));
  321. });
  322. proxy
  323. .post("/reportLossesDetails/page", {
  324. pageNum: 1,
  325. pageSize: 9999,
  326. type: "2",
  327. })
  328. .then((res) => {
  329. lendDataOne.value = res.rows.map((x) => ({
  330. ...x,
  331. label:
  332. // x.code +
  333. // " " +
  334. x.repoTime.slice(0, 10) + " " + x.respUserName + " 数量" + x.quantity,
  335. value: x.id,
  336. }));
  337. });
  338. };
  339. const getList = async (req) => {
  340. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  341. loading.value = true;
  342. proxy
  343. .post("/stockJournalDetails/page", sourceList.value.pagination)
  344. .then((res) => {
  345. sourceList.value.data = res.rows;
  346. sourceList.value.pagination.total = res.total;
  347. setTimeout(() => {
  348. loading.value = false;
  349. }, 200);
  350. const productIdList = res.rows.map((x) => x.productId);
  351. // 请求文件数据并回显
  352. if (productIdList.length > 0) {
  353. proxy.getFileData({
  354. businessIdList: productIdList,
  355. data: sourceList.value.data,
  356. att: "productId",
  357. businessType: "0",
  358. fileAtt: "fileList",
  359. filePathAtt: "fileUrl",
  360. });
  361. }
  362. });
  363. };
  364. getDict();
  365. getList();
  366. const dialogVisible = ref(false);
  367. const loadingDialog = ref(false);
  368. const submit = ref(null);
  369. const openProduct = ref(false);
  370. const formOption = reactive({
  371. inline: true,
  372. labelWidth: 100,
  373. itemWidth: 100,
  374. rules: [],
  375. });
  376. const formData = reactive({
  377. data: {},
  378. });
  379. const formConfig = computed(() => {
  380. return [
  381. {
  382. type: "title1",
  383. title: "基本信息",
  384. },
  385. {
  386. type: "treeSelect",
  387. prop: "companyId",
  388. label: "业务公司",
  389. data: proxy.useUserStore().allDict["tree_company_data"],
  390. propsTreeLabel: "deptName",
  391. propsTreeValue: "deptId",
  392. itemWidth: 50,
  393. fn: (val) => {
  394. proxy
  395. .post("/warehouse/page", {
  396. pageNum: 1,
  397. pageSize: 999,
  398. companyId: val,
  399. })
  400. .then((res) => {
  401. if (res.rows && res.rows.length > 0) {
  402. warehouseListOne.value = res.rows.map((item) => {
  403. return {
  404. label: item.name,
  405. value: item.id,
  406. };
  407. });
  408. }
  409. });
  410. },
  411. },
  412. {
  413. type: "select",
  414. prop: "warehouseId",
  415. label: "仓库名称",
  416. required: true,
  417. data: warehouseListOne.value,
  418. itemWidth: 50,
  419. },
  420. {
  421. type: "input",
  422. prop: "exWarehousePerson",
  423. label: "申请入库人",
  424. itemWidth: 50,
  425. },
  426. {
  427. type: "select",
  428. prop: "type",
  429. label: "入库原因",
  430. required: true,
  431. data: inBoundReason.value,
  432. fn: (val) => {
  433. formData.data.list = [];
  434. if (["101", "102", "108", "109", "110"].includes(val)) {
  435. formData.data.borrowId = "";
  436. formData.data.loseId = "";
  437. } else if (val == "103") {
  438. formData.data.borrowId = "";
  439. formData.data.prodOrderId = "";
  440. } else {
  441. formData.data.loseId = "";
  442. formData.data.prodOrderId = "";
  443. }
  444. },
  445. itemWidth: 50,
  446. },
  447. {
  448. type: "select",
  449. prop: "prodOrderId",
  450. label: "生产订单",
  451. data: produceOrder.value,
  452. filterable: true,
  453. itemWidth: 50,
  454. isShow: ["101", "102", "108", "109", "110"].includes(formData.data.type),
  455. },
  456. {
  457. type: "select",
  458. prop: "borrowId",
  459. label: "借出单",
  460. data: lendData.value,
  461. filterable: true,
  462. itemWidth: 50,
  463. isShow: formData.data.type == "100",
  464. fn: (val) => {
  465. if (val) {
  466. proxy.post("/stockJournal/detail", { id: val }).then((res) => {
  467. if (res.list && res.list.length < 1) {
  468. return;
  469. }
  470. let ids = res.list.map((x) => x.productId);
  471. formData.data.list = res.list.map((x) => ({
  472. fileUrl: "",
  473. productCode: x.productCode,
  474. productId: x.productId,
  475. productName: x.productName,
  476. productLength: x.productLength,
  477. productWidth: x.productWidth,
  478. productHeight: x.productHeight,
  479. quantity: x.quantity,
  480. }));
  481. proxy.getFileData({
  482. businessIdList: ids,
  483. data: formData.data.list,
  484. att: "productId",
  485. businessType: "0",
  486. fileAtt: "fileList",
  487. filePathAtt: "fileUrl",
  488. });
  489. });
  490. }
  491. },
  492. },
  493. {
  494. type: "select",
  495. prop: "loseId",
  496. label: "丢件单",
  497. data: lendDataOne.value,
  498. filterable: true,
  499. itemWidth: 50,
  500. isShow: formData.data.type == "103",
  501. fn: (val) => {
  502. const current = lendDataOne.value.find((x) => x.value == val);
  503. if (current && current.materialId) {
  504. let ids = [current.materialId];
  505. formData.data.list = [
  506. {
  507. fileUrl: "",
  508. productCode: current.materialCode,
  509. productId: current.materialId,
  510. productName: current.materialName,
  511. productLength: current.materialLength,
  512. productWidth: current.materialWidth,
  513. productHeight: current.materialHeight,
  514. quantity: current.quantity,
  515. },
  516. ];
  517. proxy.getFileData({
  518. businessIdList: ids,
  519. data: formData.data.list,
  520. att: "productId",
  521. businessType: "0",
  522. fileAtt: "fileList",
  523. filePathAtt: "fileUrl",
  524. });
  525. }
  526. },
  527. },
  528. {
  529. type: "input",
  530. itemType: "textarea",
  531. prop: "remarks",
  532. label: "备注",
  533. itemWidth: 100,
  534. },
  535. {
  536. type: "slot",
  537. slotName: "details",
  538. label: "入库明细",
  539. },
  540. ];
  541. });
  542. const rules = ref({
  543. companyId: [{ required: true, message: "请选择业务公司", trigger: "change" }],
  544. warehouseId: [{ required: true, message: "请选择仓库", trigger: "change" }],
  545. exWarehousePerson: [
  546. { required: true, message: "请输入领料人", trigger: "blur" },
  547. ],
  548. type: [{ required: true, message: "请选择入库原因", trigger: "change" }],
  549. prodOrderId: [
  550. { required: true, message: "请选择生产订单", trigger: "change" },
  551. ],
  552. borrowId: [
  553. { required: true, message: "请选择借用出库单", trigger: "change" },
  554. ],
  555. loseId: [{ required: true, message: "请选择丢件单", trigger: "change" }],
  556. quantity: [{ required: true, message: "请输入入库数量", trigger: "blur" }],
  557. remarks: [{ required: true, message: "请输入备注", trigger: "blur" }],
  558. });
  559. const openModal = () => {
  560. getDict();
  561. formData.data = {
  562. type: "",
  563. list: [],
  564. };
  565. loadingDialog.value = false;
  566. dialogVisible.value = true;
  567. };
  568. const pushGoods = (goods) => {
  569. if (goods && goods.length > 0) {
  570. let afterFiltering = [];
  571. if (formData.data.list && formData.data.list.length > 0) {
  572. afterFiltering = goods.filter((item) => {
  573. let data = formData.data.list.filter(
  574. (itemProduct) => itemProduct.productId === item.id
  575. );
  576. if (data && data.length > 0) {
  577. return false;
  578. }
  579. return true;
  580. });
  581. } else {
  582. afterFiltering = goods;
  583. }
  584. formData.data.list = formData.data.list.concat(
  585. afterFiltering.map((item) => {
  586. return {
  587. productCode: item.code,
  588. productId: item.id,
  589. productName: item.name,
  590. productSpec: item.spec,
  591. productUnit: item.unit,
  592. quantity: undefined,
  593. };
  594. })
  595. );
  596. ElMessage({
  597. message: "添加成功!",
  598. type: "success",
  599. });
  600. openProduct.value = false;
  601. } else {
  602. ElMessage("请选择至少一件产品");
  603. }
  604. };
  605. const selectMaterial = (row) => {
  606. let flag = formData.data.list.some((x) => x.productId == row.id);
  607. if (!flag) {
  608. formData.data.list.push({
  609. productCode: row.customCode,
  610. productId: row.id,
  611. productName: row.name,
  612. productSpec: row.spec,
  613. productUnit: row.unit,
  614. quantity: null,
  615. });
  616. proxy.msgTip("选择成功");
  617. } else {
  618. proxy.msgTip("该物料已选择", 2);
  619. }
  620. };
  621. const selectGood = (row) => {
  622. let fileUrl = "";
  623. if (row.fileList && row.fileList.length > 0) {
  624. fileUrl = row.fileList[0].fileUrl;
  625. }
  626. formData.data.list.push({
  627. fileUrl: fileUrl,
  628. productCode: row.customCode,
  629. productId: row.id,
  630. productName: row.name,
  631. productLength: row["length"],
  632. productWidth: row.width,
  633. productHeight: row.height,
  634. quantity: null,
  635. });
  636. proxy.msgTip("选择成功");
  637. };
  638. const submitForm = () => {
  639. submit.value.handleSubmit(() => {
  640. if (!(formData.data.list.length > 0)) {
  641. return proxy.msgTip("请添加入库明细");
  642. }
  643. loadingDialog.value = true;
  644. proxy.post("/stock/add", formData.data).then(
  645. () => {
  646. ElMessage({
  647. message: "提交成功",
  648. type: "success",
  649. });
  650. dialogVisible.value = false;
  651. getList();
  652. },
  653. (err) => {
  654. console.log(err);
  655. loadingDialog.value = false;
  656. }
  657. );
  658. });
  659. };
  660. const handleDelete = (index) => {
  661. formData.data.list.splice(index, 1);
  662. };
  663. const acquireSelectList = () => {
  664. let data = [];
  665. if (formData.data.list && formData.data.list.length > 0) {
  666. data = formData.data.list.map((item) => {
  667. return {
  668. id: item.productId,
  669. name: item.productName,
  670. };
  671. });
  672. }
  673. return data;
  674. };
  675. const handleClickFile = (fileUrl) => {
  676. window.open(fileUrl, "_blank");
  677. };
  678. </script>
  679. <style lang="scss" scoped>
  680. .tenant {
  681. padding: 20px;
  682. }
  683. ::v-deep(.el-input-number .el-input__inner) {
  684. text-align: left;
  685. }
  686. </style>