index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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", { pageNum: 1, pageSize: 9999 })
  288. .then((res) => {
  289. produceOrder.value = res.rows.map((x) => ({
  290. label: x.code,
  291. value: x.id,
  292. }));
  293. produceOrder.value.unshift({
  294. label: "无",
  295. value: -1,
  296. });
  297. });
  298. proxy
  299. .post("/stockJournal/page", {
  300. pageNum: 1,
  301. pageSize: 9999,
  302. isRestitution: 0,
  303. type: "3",
  304. })
  305. .then((res) => {
  306. lendData.value = res.rows.map((x) => ({
  307. label:
  308. x.code +
  309. " " +
  310. x.expectRestitutionTime.slice(0, 10) +
  311. " " +
  312. x.exWarehousePerson +
  313. " " +
  314. x.remarks,
  315. value: x.id,
  316. }));
  317. });
  318. proxy
  319. .post("/reportLossesDetails/page", {
  320. pageNum: 1,
  321. pageSize: 9999,
  322. type: "2",
  323. })
  324. .then((res) => {
  325. lendDataOne.value = res.rows.map((x) => ({
  326. ...x,
  327. label:
  328. // x.code +
  329. // " " +
  330. x.repoTime.slice(0, 10) + " " + x.respUserName + " 数量" + x.quantity,
  331. value: x.id,
  332. }));
  333. });
  334. };
  335. const getList = async (req) => {
  336. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  337. loading.value = true;
  338. proxy
  339. .post("/stockJournalDetails/page", sourceList.value.pagination)
  340. .then((res) => {
  341. sourceList.value.data = res.rows;
  342. sourceList.value.pagination.total = res.total;
  343. setTimeout(() => {
  344. loading.value = false;
  345. }, 200);
  346. const productIdList = res.rows.map((x) => x.productId);
  347. // 请求文件数据并回显
  348. if (productIdList.length > 0) {
  349. proxy.getFileData({
  350. businessIdList: productIdList,
  351. data: sourceList.value.data,
  352. att: "productId",
  353. businessType: "0",
  354. fileAtt: "fileList",
  355. filePathAtt: "fileUrl",
  356. });
  357. }
  358. });
  359. };
  360. getDict();
  361. getList();
  362. const dialogVisible = ref(false);
  363. const loadingDialog = ref(false);
  364. const submit = ref(null);
  365. const openProduct = ref(false);
  366. const formOption = reactive({
  367. inline: true,
  368. labelWidth: 100,
  369. itemWidth: 100,
  370. rules: [],
  371. });
  372. const formData = reactive({
  373. data: {},
  374. });
  375. const formConfig = computed(() => {
  376. return [
  377. {
  378. type: "title1",
  379. title: "基本信息",
  380. },
  381. {
  382. type: "treeSelect",
  383. prop: "companyId",
  384. label: "业务公司",
  385. data: proxy.useUserStore().allDict["tree_company_data"],
  386. propsTreeLabel: "deptName",
  387. propsTreeValue: "deptId",
  388. itemWidth: 50,
  389. fn: (val) => {
  390. proxy
  391. .post("/warehouse/page", {
  392. pageNum: 1,
  393. pageSize: 999,
  394. companyId: val,
  395. })
  396. .then((res) => {
  397. if (res.rows && res.rows.length > 0) {
  398. warehouseListOne.value = res.rows.map((item) => {
  399. return {
  400. label: item.name,
  401. value: item.id,
  402. };
  403. });
  404. }
  405. });
  406. },
  407. },
  408. {
  409. type: "select",
  410. prop: "warehouseId",
  411. label: "仓库名称",
  412. required: true,
  413. data: warehouseListOne.value,
  414. itemWidth: 50,
  415. },
  416. {
  417. type: "input",
  418. prop: "exWarehousePerson",
  419. label: "申请入库人",
  420. itemWidth: 50,
  421. },
  422. {
  423. type: "select",
  424. prop: "type",
  425. label: "入库原因",
  426. required: true,
  427. data: inBoundReason.value,
  428. fn: (val) => {
  429. formData.data.list = [];
  430. if (["101", "102", "108", "109", "110"].includes(val)) {
  431. formData.data.borrowId = "";
  432. formData.data.loseId = "";
  433. } else if (val == "103") {
  434. formData.data.borrowId = "";
  435. formData.data.prodOrderId = "";
  436. } else {
  437. formData.data.loseId = "";
  438. formData.data.prodOrderId = "";
  439. }
  440. },
  441. itemWidth: 50,
  442. },
  443. {
  444. type: "select",
  445. prop: "prodOrderId",
  446. label: "生产订单",
  447. data: produceOrder.value,
  448. filterable: true,
  449. itemWidth: 50,
  450. isShow: ["101", "102", "108", "109", "110"].includes(formData.data.type),
  451. },
  452. {
  453. type: "select",
  454. prop: "borrowId",
  455. label: "借出单",
  456. data: lendData.value,
  457. filterable: true,
  458. itemWidth: 50,
  459. isShow: formData.data.type == "100",
  460. fn: (val) => {
  461. if (val) {
  462. proxy.post("/stockJournal/detail", { id: val }).then((res) => {
  463. if (res.list && res.list.length < 1) {
  464. return;
  465. }
  466. let ids = res.list.map((x) => x.productId);
  467. formData.data.list = res.list.map((x) => ({
  468. fileUrl: "",
  469. productCode: x.productCode,
  470. productId: x.productId,
  471. productName: x.productName,
  472. productLength: x.productLength,
  473. productWidth: x.productWidth,
  474. productHeight: x.productHeight,
  475. quantity: x.quantity,
  476. }));
  477. proxy.getFileData({
  478. businessIdList: ids,
  479. data: formData.data.list,
  480. att: "productId",
  481. businessType: "0",
  482. fileAtt: "fileList",
  483. filePathAtt: "fileUrl",
  484. });
  485. });
  486. }
  487. },
  488. },
  489. {
  490. type: "select",
  491. prop: "loseId",
  492. label: "丢件单",
  493. data: lendDataOne.value,
  494. filterable: true,
  495. itemWidth: 50,
  496. isShow: formData.data.type == "103",
  497. fn: (val) => {
  498. const current = lendDataOne.value.find((x) => x.value == val);
  499. if (current && current.materialId) {
  500. let ids = [current.materialId];
  501. formData.data.list = [
  502. {
  503. fileUrl: "",
  504. productCode: current.materialCode,
  505. productId: current.materialId,
  506. productName: current.materialName,
  507. productLength: current.materialLength,
  508. productWidth: current.materialWidth,
  509. productHeight: current.materialHeight,
  510. quantity: current.quantity,
  511. },
  512. ];
  513. proxy.getFileData({
  514. businessIdList: ids,
  515. data: formData.data.list,
  516. att: "productId",
  517. businessType: "0",
  518. fileAtt: "fileList",
  519. filePathAtt: "fileUrl",
  520. });
  521. }
  522. },
  523. },
  524. {
  525. type: "input",
  526. itemType: "textarea",
  527. prop: "remarks",
  528. label: "备注",
  529. itemWidth: 100,
  530. },
  531. {
  532. type: "slot",
  533. slotName: "details",
  534. label: "入库明细",
  535. },
  536. ];
  537. });
  538. const rules = ref({
  539. companyId: [{ required: true, message: "请选择业务公司", trigger: "change" }],
  540. warehouseId: [{ required: true, message: "请选择仓库", trigger: "change" }],
  541. exWarehousePerson: [
  542. { required: true, message: "请输入领料人", trigger: "blur" },
  543. ],
  544. type: [{ required: true, message: "请选择入库原因", trigger: "change" }],
  545. prodOrderId: [
  546. { required: true, message: "请选择生产订单", trigger: "change" },
  547. ],
  548. borrowId: [
  549. { required: true, message: "请选择借用出库单", trigger: "change" },
  550. ],
  551. loseId: [{ required: true, message: "请选择丢件单", trigger: "change" }],
  552. quantity: [{ required: true, message: "请输入入库数量", trigger: "blur" }],
  553. remarks: [{ required: true, message: "请输入备注", trigger: "blur" }],
  554. });
  555. const openModal = () => {
  556. getDict();
  557. formData.data = {
  558. type: "",
  559. list: [],
  560. };
  561. loadingDialog.value = false;
  562. dialogVisible.value = true;
  563. };
  564. const pushGoods = (goods) => {
  565. if (goods && goods.length > 0) {
  566. let afterFiltering = [];
  567. if (formData.data.list && formData.data.list.length > 0) {
  568. afterFiltering = goods.filter((item) => {
  569. let data = formData.data.list.filter(
  570. (itemProduct) => itemProduct.productId === item.id
  571. );
  572. if (data && data.length > 0) {
  573. return false;
  574. }
  575. return true;
  576. });
  577. } else {
  578. afterFiltering = goods;
  579. }
  580. formData.data.list = formData.data.list.concat(
  581. afterFiltering.map((item) => {
  582. return {
  583. productCode: item.code,
  584. productId: item.id,
  585. productName: item.name,
  586. productSpec: item.spec,
  587. productUnit: item.unit,
  588. quantity: undefined,
  589. };
  590. })
  591. );
  592. ElMessage({
  593. message: "添加成功!",
  594. type: "success",
  595. });
  596. openProduct.value = false;
  597. } else {
  598. ElMessage("请选择至少一件产品");
  599. }
  600. };
  601. const selectMaterial = (row) => {
  602. let flag = formData.data.list.some((x) => x.productId == row.id);
  603. if (!flag) {
  604. formData.data.list.push({
  605. productCode: row.customCode,
  606. productId: row.id,
  607. productName: row.name,
  608. productSpec: row.spec,
  609. productUnit: row.unit,
  610. quantity: null,
  611. });
  612. proxy.msgTip("选择成功");
  613. } else {
  614. proxy.msgTip("该物料已选择", 2);
  615. }
  616. };
  617. const selectGood = (row) => {
  618. let fileUrl = "";
  619. if (row.fileList && row.fileList.length > 0) {
  620. fileUrl = row.fileList[0].fileUrl;
  621. }
  622. formData.data.list.push({
  623. fileUrl: fileUrl,
  624. productCode: row.customCode,
  625. productId: row.id,
  626. productName: row.name,
  627. productLength: row["length"],
  628. productWidth: row.width,
  629. productHeight: row.height,
  630. quantity: null,
  631. });
  632. proxy.msgTip("选择成功");
  633. };
  634. const submitForm = () => {
  635. submit.value.handleSubmit(() => {
  636. loadingDialog.value = true;
  637. proxy.post("/stock/add", formData.data).then(
  638. () => {
  639. ElMessage({
  640. message: "提交成功",
  641. type: "success",
  642. });
  643. dialogVisible.value = false;
  644. getList();
  645. },
  646. (err) => {
  647. console.log(err);
  648. loadingDialog.value = false;
  649. }
  650. );
  651. });
  652. };
  653. const handleDelete = (index) => {
  654. formData.data.list.splice(index, 1);
  655. };
  656. const acquireSelectList = () => {
  657. let data = [];
  658. if (formData.data.list && formData.data.list.length > 0) {
  659. data = formData.data.list.map((item) => {
  660. return {
  661. id: item.productId,
  662. name: item.productName,
  663. };
  664. });
  665. }
  666. return data;
  667. };
  668. const handleClickFile = (fileUrl) => {
  669. window.open(fileUrl, "_blank");
  670. };
  671. </script>
  672. <style lang="scss" scoped>
  673. .tenant {
  674. padding: 20px;
  675. }
  676. ::v-deep(.el-input-number .el-input__inner) {
  677. text-align: left;
  678. }
  679. </style>