index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <div>
  3. <el-card class="box-card">
  4. <el-tabs v-model="activeName" type="card" @tab-change="changeActiveName">
  5. <el-tab-pane :label="'待备料(半成品)' + numData.data.semiFinishedCount" name="first">
  6. <byTable
  7. :hideTable="true"
  8. :hidePagination="true"
  9. :source="sourceList.data"
  10. :pagination="sourceList.pagination"
  11. :config="config"
  12. :searchConfig="searchConfig"
  13. highlight-current-row
  14. :action-list="[
  15. {
  16. text: '打印备料单',
  17. action: () => outExcel(0),
  18. },
  19. {
  20. text: '快捷出库',
  21. action: () => clickQuickDelivery(),
  22. },
  23. ]"
  24. @get-list="getList"
  25. @clickReset="clickReset">
  26. </byTable>
  27. <table class="table-class" border="0" cellpadding="0" cellspacing="0" v-loading="loading">
  28. <tr>
  29. <th style="width: 200px">BOM品号</th>
  30. <th style="min-width: 320px">BOM品名</th>
  31. <th style="width: 200px">SKU品号</th>
  32. <th style="width: 120px; text-align: center">数量小计</th>
  33. <th style="width: 140px; text-align: center">数量总计</th>
  34. </tr>
  35. <tbody v-for="(item, index) in sourceList.data" :key="index">
  36. <tr v-for="(itemSKU, indexSKU) in item.skuInfoList" :key="indexSKU">
  37. <td v-if="indexSKU === 0" :rowspan="item.skuInfoList.length">{{ item.bomSpecCode }}</td>
  38. <td v-if="indexSKU === 0" :rowspan="item.skuInfoList.length">{{ item.bomSpecName }}</td>
  39. <td>{{ itemSKU.skuSpecCode }}</td>
  40. <td style="text-align: center">{{ itemSKU.quantity }}</td>
  41. <td v-if="indexSKU === 0" :rowspan="item.skuInfoList.length" style="text-align: center">{{ item.totalQuantity }}</td>
  42. </tr>
  43. </tbody>
  44. </table>
  45. </el-tab-pane>
  46. <el-tab-pane :label="'待备料(成品)' + numData.data.finishedCount" name="third">
  47. <byTable
  48. :hideTable="true"
  49. :hidePagination="true"
  50. :source="sourceListThree.data"
  51. :pagination="sourceListThree.pagination"
  52. :config="config"
  53. :searchConfig="searchConfig"
  54. highlight-current-row
  55. :action-list="[
  56. {
  57. text: '打印备料单',
  58. action: () => outExcel(1),
  59. },
  60. {
  61. text: '快捷出库',
  62. action: () => clickQuickDelivery(),
  63. },
  64. ]"
  65. @get-list="getListThree"
  66. @clickReset="clickResetThree">
  67. </byTable>
  68. <table class="table-class" border="0" cellpadding="0" cellspacing="0" v-loading="loading">
  69. <tr>
  70. <th style="width: 200px">SKU品号</th>
  71. <th style="min-width: 320px">SKU品名</th>
  72. <th style="width: 120px; text-align: center">数量</th>
  73. </tr>
  74. <tbody v-for="(item, index) in sourceListThree.data" :key="index">
  75. <tr v-for="(itemSKU, indexSKU) in item.skuInfoList" :key="indexSKU">
  76. <td>{{ itemSKU.skuSpecCode }}</td>
  77. <td>{{ itemSKU.skuSpecName }}</td>
  78. <td style="text-align: center">{{ itemSKU.quantity }}</td>
  79. </tr>
  80. </tbody>
  81. </table>
  82. </el-tab-pane>
  83. <el-tab-pane label="已备料" name="second">
  84. <byTable
  85. :source="sourceListTwo.data"
  86. :pagination="sourceListTwo.pagination"
  87. :config="configTwo"
  88. :loading="loading"
  89. :searchConfig="searchConfigTwo"
  90. highlight-current-row
  91. @get-list="getListTwo"
  92. @clickReset="clickResetTwo">
  93. <template #blueprint="{ item }">
  94. <div>
  95. <img
  96. v-if="item.blueprint"
  97. style="margin-top: 3px; width: 40px; height: 40px; cursor: pointer; object-fit: contain; vertical-align: middle"
  98. v-lazy="item.blueprint"
  99. @click="openFile(item.blueprint)" />
  100. </div>
  101. </template>
  102. <template #size="{ item }">
  103. <span>{{ `${item.length} * ${item.width} * ${item.height}` }}</span>
  104. </template>
  105. </byTable>
  106. </el-tab-pane>
  107. </el-tabs>
  108. </el-card>
  109. <el-dialog title="打印" v-if="openPrint" v-model="openPrint" width="1200px">
  110. <div v-loading="loadingPrint">
  111. <div style="height: calc(100vh - 174px); overflow-y: auto; overflow-x: hidden">
  112. <div class="printBomList" id="printMe">
  113. <div class="t">生产备料单</div>
  114. <div class="time" style="text-align: right">
  115. {{ printTime }}
  116. </div>
  117. <table border="1" cellspacing="0" class="table">
  118. <thead>
  119. <tr>
  120. <td style="width: 40px; text-align: center">编号</td>
  121. <td style="width: 120px">图稿类型</td>
  122. <td style="width: 100px">规格</td>
  123. <td style="width: 120px">颜色</td>
  124. <td style="width: 110px">BOM品号</td>
  125. <td>图稿名称</td>
  126. <td style="width: 120px">SKU品号</td>
  127. <td style="width: 80px; text-align: center">数量小计</td>
  128. <td style="width: 80px; text-align: center">数量总计</td>
  129. </tr>
  130. </thead>
  131. <tbody v-if="formData && formData.length > 0">
  132. <tr v-for="(item, index) in formData" :key="index">
  133. <td style="text-align: center">{{ item.index }}</td>
  134. <td>{{ dictKeyValue(item.machinedPanel, useUserStore().allDict["charge_item"]) }}</td>
  135. <td :rowspan="item.specIndex" v-if="item.specStatus">{{ item.spec }}</td>
  136. <td :rowspan="item.colourIndex" v-if="item.colourStatus">{{ item.colour }}</td>
  137. <td :rowspan="item.bomIndex" v-if="item.bomStatus">{{ item.bomSpecCode }}</td>
  138. <td>{{ item.artworkName }}</td>
  139. <td>{{ item.skuSpecCode }}</td>
  140. <td style="text-align: center">{{ item.quantity }}</td>
  141. <td :rowspan="item.bomIndex" v-if="item.bomStatus" style="text-align: center">{{ item.totalQuantity }}</td>
  142. </tr>
  143. </tbody>
  144. </table>
  145. </div>
  146. </div>
  147. <div style="text-align: center; margin: 10px">
  148. <el-button @click="openPrint = false" size="large">取消</el-button>
  149. <el-button type="primary" v-print="printObj" size="large">打印</el-button>
  150. </div>
  151. </div>
  152. </el-dialog>
  153. <el-dialog title="快捷出库" v-if="openQuick" v-model="openQuick" width="90%">
  154. <Quick :pagination="activeName === 'first' ? sourceList.pagination : sourceListThree.pagination" @clickCancel="clickCancel"></Quick>
  155. </el-dialog>
  156. </div>
  157. </template>
  158. <script setup>
  159. import byTable from "/src/components/byTable/index";
  160. import moment from "moment";
  161. import Quick from "/src/views/production/operation/batching/quick";
  162. const { proxy } = getCurrentInstance();
  163. const activeName = ref("first");
  164. const departmentList = ref([]);
  165. const sourceList = ref({
  166. data: [],
  167. pagination: {
  168. bomSpecCode: "",
  169. bomSpecName: "",
  170. skuSpecCode: "",
  171. skuSpecName: "",
  172. departmentId: "1689164627162529793",
  173. orderStockType: "0",
  174. },
  175. });
  176. const sourceListThree = ref({
  177. data: [],
  178. pagination: {
  179. bomSpecCode: "",
  180. bomSpecName: "",
  181. skuSpecCode: "",
  182. skuSpecName: "",
  183. departmentId: "1689164627162529793",
  184. orderStockType: "1",
  185. },
  186. });
  187. const sourceListTwo = ref({
  188. data: [],
  189. pagination: {
  190. total: 0,
  191. pageNum: 1,
  192. pageSize: 10,
  193. type: "1",
  194. orderCode: "",
  195. orderWlnCode: "",
  196. bomSpecCode: "",
  197. bomSpecName: "",
  198. skuSpecCode: "",
  199. skuSpecName: "",
  200. departmentId: "",
  201. width: "",
  202. },
  203. });
  204. const loading = ref(false);
  205. const searchConfig = computed(() => {
  206. return [
  207. {
  208. type: "input",
  209. prop: "bomSpecCode",
  210. label: "BOM品号",
  211. },
  212. {
  213. type: "input",
  214. prop: "bomSpecName",
  215. label: "BOM品名",
  216. },
  217. {
  218. type: "input",
  219. prop: "skuSpecCode",
  220. label: "SKU品号",
  221. },
  222. {
  223. type: "input",
  224. prop: "skuSpecName",
  225. label: "SKU品名",
  226. },
  227. {
  228. type: "select",
  229. prop: "departmentId",
  230. data: departmentList.value,
  231. label: "事业部",
  232. clearable: true,
  233. },
  234. ];
  235. });
  236. const searchConfigTwo = computed(() => {
  237. return [
  238. {
  239. type: "input",
  240. prop: "orderCode",
  241. label: "订单号",
  242. },
  243. {
  244. type: "input",
  245. prop: "orderWlnCode",
  246. label: "E10单号",
  247. },
  248. {
  249. type: "input",
  250. prop: "bomSpecCode",
  251. label: "BOM品号",
  252. },
  253. {
  254. type: "input",
  255. prop: "bomSpecName",
  256. label: "BOM品名",
  257. },
  258. {
  259. type: "input",
  260. prop: "skuSpecCode",
  261. label: "SKU品号",
  262. },
  263. {
  264. type: "input",
  265. prop: "skuSpecName",
  266. label: "SKU品名",
  267. },
  268. {
  269. type: "select",
  270. prop: "departmentId",
  271. data: departmentList.value,
  272. label: "事业部",
  273. },
  274. {
  275. type: "input",
  276. prop: "width",
  277. label: "幅宽(cm)",
  278. },
  279. ];
  280. });
  281. const config = computed(() => {
  282. return [
  283. {
  284. attrs: {
  285. label: "BOM品号",
  286. prop: "bomSpecCode",
  287. width: 200,
  288. },
  289. },
  290. {
  291. attrs: {
  292. label: "BOM品名",
  293. prop: "bomSpecName",
  294. "min-width": 320,
  295. },
  296. },
  297. {
  298. attrs: {
  299. label: "SKU品号",
  300. prop: "skuSpecCode",
  301. width: 180,
  302. },
  303. },
  304. {
  305. attrs: {
  306. label: "数量",
  307. prop: "quantity",
  308. width: 120,
  309. },
  310. },
  311. ];
  312. });
  313. const configTwo = computed(() => {
  314. return [
  315. {
  316. attrs: {
  317. label: "设计图",
  318. slot: "blueprint",
  319. width: 80,
  320. },
  321. },
  322. {
  323. attrs: {
  324. label: "事业部",
  325. prop: "departmentName",
  326. width: 160,
  327. },
  328. },
  329. {
  330. attrs: {
  331. label: "BOM品号",
  332. prop: "bomSpecCode",
  333. width: 160,
  334. },
  335. },
  336. {
  337. attrs: {
  338. label: "BOM品名",
  339. prop: "bomSpecName",
  340. "min-width": 240,
  341. },
  342. },
  343. {
  344. attrs: {
  345. label: "SKU品号",
  346. prop: "skuSpecCode",
  347. width: 160,
  348. },
  349. },
  350. {
  351. attrs: {
  352. label: "SKU品名",
  353. prop: "skuSpecName",
  354. "min-width": 200,
  355. },
  356. },
  357. {
  358. attrs: {
  359. label: "尺寸(长宽高,cm)",
  360. slot: "size",
  361. width: 160,
  362. },
  363. },
  364. {
  365. attrs: {
  366. label: "数量",
  367. prop: "quantity",
  368. width: 100,
  369. },
  370. },
  371. {
  372. attrs: {
  373. label: "投产时间",
  374. prop: "createTime",
  375. width: 160,
  376. align: "center",
  377. },
  378. },
  379. {
  380. attrs: {
  381. label: "订单号",
  382. prop: "orderCode",
  383. width: 160,
  384. },
  385. },
  386. {
  387. attrs: {
  388. label: "E10单号",
  389. prop: "orderWlnCode",
  390. width: 160,
  391. },
  392. },
  393. ];
  394. });
  395. const getList = async (req, status) => {
  396. if (status) {
  397. sourceList.value.pagination = {
  398. departmentId: "1689164627162529793",
  399. orderStockType: "0",
  400. };
  401. } else {
  402. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  403. }
  404. loading.value = true;
  405. proxy.post("/stockPreparation/uncompletedList", sourceList.value.pagination).then((res) => {
  406. sourceList.value.data = res;
  407. setTimeout(() => {
  408. loading.value = false;
  409. }, 200);
  410. });
  411. };
  412. getList();
  413. const clickReset = () => {
  414. getList("", true);
  415. };
  416. const getListThree = async (req, status) => {
  417. if (status) {
  418. sourceListThree.value.pagination = {
  419. departmentId: "1689164627162529793",
  420. orderStockType: "0",
  421. };
  422. } else {
  423. sourceListThree.value.pagination = { ...sourceListThree.value.pagination, ...req };
  424. }
  425. loading.value = true;
  426. proxy.post("/stockPreparation/uncompletedList", sourceListThree.value.pagination).then((res) => {
  427. sourceListThree.value.data = res;
  428. setTimeout(() => {
  429. loading.value = false;
  430. }, 200);
  431. });
  432. };
  433. const clickResetThree = () => {
  434. getListThree("", true);
  435. };
  436. const getListTwo = async (req, status) => {
  437. if (status) {
  438. sourceListTwo.value.pagination = {
  439. pageNum: sourceListTwo.value.pagination.pageNum,
  440. pageSize: sourceListTwo.value.pagination.pageSize,
  441. type: "1",
  442. };
  443. } else {
  444. sourceListTwo.value.pagination = { ...sourceListTwo.value.pagination, ...req };
  445. }
  446. loading.value = true;
  447. proxy.post("/stockPreparation/completedPage", sourceListTwo.value.pagination).then((res) => {
  448. sourceListTwo.value.data = res.rows;
  449. sourceListTwo.value.pagination.total = res.total;
  450. setTimeout(() => {
  451. loading.value = false;
  452. }, 200);
  453. });
  454. };
  455. const clickResetTwo = () => {
  456. getListTwo("", true);
  457. };
  458. const changeActiveName = (val) => {
  459. if (val === "first") {
  460. getList();
  461. } else if (val === "second") {
  462. getListTwo();
  463. } else if (val === "third") {
  464. getListThree();
  465. } else {
  466. getList();
  467. }
  468. };
  469. const numData = reactive({
  470. data: {
  471. finishedCount: 0,
  472. semiFinishedCount: 0,
  473. },
  474. });
  475. const getNum = () => {
  476. proxy.post("/stockPreparation/uncompletedListStatistics", { orderStockType: 0 }).then((res) => {
  477. numData.data = res;
  478. });
  479. };
  480. const getDemandData = () => {
  481. proxy.post("/department/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  482. if (res.rows && res.rows.length > 0) {
  483. departmentList.value = res.rows.map((item) => {
  484. return {
  485. dictKey: item.id,
  486. dictValue: item.name,
  487. };
  488. });
  489. }
  490. });
  491. getNum();
  492. };
  493. getDemandData();
  494. const openFile = (path) => {
  495. window.open(path);
  496. };
  497. const openPrint = ref(false);
  498. const printTime = ref("");
  499. const formData = ref([]);
  500. const loadingPrint = ref(false);
  501. const outExcel = (orderStockType) => {
  502. formData.value = [];
  503. printTime.value = moment().format("yyyy-MM-DD HH:mm:ss");
  504. loadingPrint.value = true;
  505. openPrint.value = true;
  506. let bodyParameter = proxy.deepClone(sourceList.value.pagination);
  507. if (orderStockType === 1) {
  508. bodyParameter = proxy.deepClone(sourceListThree.value.pagination);
  509. }
  510. proxy.post("/stockPreparation/printUncompletedList", bodyParameter).then((res) => {
  511. if (res && res.length > 0) {
  512. for (let i = 0; i < res.length; i++) {
  513. if (res[i].colourGroupingInfoList && res[i].colourGroupingInfoList.length > 0) {
  514. res[i].specIndex = 0;
  515. for (let j = 0; j < res[i].colourGroupingInfoList.length; j++) {
  516. res[i].colourGroupingInfoList[j].colourIndex = 0;
  517. let colourGroupingInfoList = res[i].colourGroupingInfoList[j];
  518. if (colourGroupingInfoList.uncompletedVoList && colourGroupingInfoList.uncompletedVoList.length > 0) {
  519. for (let x = 0; x < colourGroupingInfoList.uncompletedVoList.length; x++) {
  520. res[i].colourGroupingInfoList[j].uncompletedVoList[x].bomIndex = 0;
  521. let uncompletedVoList = colourGroupingInfoList.uncompletedVoList[x];
  522. if (uncompletedVoList.skuInfoList && uncompletedVoList.skuInfoList.length > 0) {
  523. for (let y = 0; y < uncompletedVoList.skuInfoList.length; y++) {
  524. res[i].specIndex++;
  525. res[i].colourGroupingInfoList[j].colourIndex++;
  526. res[i].colourGroupingInfoList[j].uncompletedVoList[x].bomIndex++;
  527. }
  528. }
  529. }
  530. }
  531. }
  532. }
  533. }
  534. }
  535. let list = [];
  536. if (res && res.length > 0) {
  537. let index = 0;
  538. for (let i = 0; i < res.length; i++) {
  539. if (res[i].colourGroupingInfoList && res[i].colourGroupingInfoList.length > 0) {
  540. let specStatus = true;
  541. for (let j = 0; j < res[i].colourGroupingInfoList.length; j++) {
  542. let colourStatus = true;
  543. let colourGroupingInfoList = res[i].colourGroupingInfoList[j];
  544. if (colourGroupingInfoList.uncompletedVoList && colourGroupingInfoList.uncompletedVoList.length > 0) {
  545. for (let x = 0; x < colourGroupingInfoList.uncompletedVoList.length; x++) {
  546. let bomStatus = true;
  547. let uncompletedVoList = colourGroupingInfoList.uncompletedVoList[x];
  548. if (uncompletedVoList.skuInfoList && uncompletedVoList.skuInfoList.length > 0) {
  549. for (let y = 0; y < uncompletedVoList.skuInfoList.length; y++) {
  550. let skuInfoList = uncompletedVoList.skuInfoList[y];
  551. index++;
  552. list.push({
  553. index: index,
  554. spec: res[i].spec,
  555. colour: colourGroupingInfoList.colour,
  556. bomSpecCode: uncompletedVoList.bomSpecCode,
  557. artworkName: skuInfoList.artworkName,
  558. skuSpecCode: skuInfoList.skuSpecCode,
  559. machinedPanel: skuInfoList.machinedPanel,
  560. quantity: skuInfoList.quantity,
  561. totalQuantity: uncompletedVoList.totalQuantity,
  562. specStatus: specStatus,
  563. specIndex: res[i].specIndex,
  564. colourStatus: colourStatus,
  565. colourIndex: res[i].colourGroupingInfoList[j].colourIndex,
  566. bomStatus: bomStatus,
  567. bomIndex: res[i].colourGroupingInfoList[j].uncompletedVoList[x].bomIndex,
  568. });
  569. specStatus = false;
  570. colourStatus = false;
  571. bomStatus = false;
  572. }
  573. }
  574. }
  575. }
  576. }
  577. }
  578. }
  579. }
  580. formData.value = Object.freeze(list);
  581. loadingPrint.value = false;
  582. });
  583. };
  584. const printObj = ref({
  585. id: "printMe",
  586. popTitle: "",
  587. extraCss: "https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css",
  588. extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
  589. });
  590. const openQuick = ref(false);
  591. const clickQuickDelivery = () => {
  592. openQuick.value = true;
  593. };
  594. const clickCancel = (status) => {
  595. openQuick.value = false;
  596. if (status) {
  597. getList();
  598. getNum();
  599. }
  600. };
  601. </script>
  602. <style lang="scss" scoped>
  603. ::v-deep(.el-input-number .el-input__inner) {
  604. text-align: left;
  605. }
  606. .printBomList {
  607. width: 100%;
  608. font-size: 12px !important;
  609. .t {
  610. text-align: center;
  611. font-size: 26px;
  612. font-weight: 700;
  613. margin: 10px 0px;
  614. }
  615. .time {
  616. margin-bottom: 10px;
  617. }
  618. .table {
  619. width: 100%;
  620. td {
  621. padding: 4px;
  622. }
  623. }
  624. }
  625. :deep(.el-dialog) {
  626. margin-top: 10px !important;
  627. margin-bottom: 10px !important;
  628. }
  629. .table-class {
  630. width: 100%;
  631. font-size: 14px;
  632. border: 1px solid #eeeeee;
  633. }
  634. .table-class th {
  635. height: 35px;
  636. line-height: 35px;
  637. padding: 0 12px;
  638. text-align: left;
  639. background-color: #eeeeee !important;
  640. border-right: 1px solid #eeeeee;
  641. }
  642. .table-class td {
  643. height: 35px;
  644. line-height: 35px;
  645. padding: 8px 12px;
  646. text-align: left;
  647. border-bottom: 1px solid #eeeeee;
  648. border-right: 1px solid #eeeeee;
  649. }
  650. </style>