homogeneityInspectDialog.vue 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. <template>
  2. <div>
  3. <ele-modal
  4. width="90vw"
  5. :visible.sync="visible"
  6. :close-on-click-modal="false"
  7. row-key="code"
  8. custom-class="ele-dialog-form"
  9. :title="'齐套性检查'"
  10. :maxable="true"
  11. >
  12. <el-form
  13. :inline="true"
  14. class="demo-form-inline"
  15. label-width="107px"
  16. style="margin-bottom: 16px"
  17. >
  18. <el-form-item label="选择日期:">
  19. <!-- <el-date-picker
  20. v-model="startTime"
  21. type="date"
  22. placeholder="选择日期"
  23. value-format="yyyy-MM-dd"
  24. size="large"
  25. :picker-options="pickerOptions"
  26. >
  27. </el-date-picker> -->
  28. <el-date-picker
  29. v-model="startTime"
  30. type="daterange"
  31. value-format="yyyy-MM-dd"
  32. start-placeholder="开始日期"
  33. end-placeholder="结束日期"
  34. :clearable="false"
  35. :picker-options="pickerOptions"
  36. >
  37. </el-date-picker>
  38. </el-form-item>
  39. <el-form-item>
  40. <el-button type="primary" @click="onSubmit">查询</el-button>
  41. </el-form-item>
  42. </el-form>
  43. <div v-loading="loading">
  44. <el-form label-width="107px" :model="planInfo" class="plan_form">
  45. <el-row :gutter="20" type="flex" style="flex-wrap: wrap">
  46. <el-col :span="6">
  47. <el-form-item label="名称:">
  48. <el-input readonly v-model="planInfo.productName"></el-input>
  49. </el-form-item>
  50. </el-col>
  51. <el-col :span="6">
  52. <el-form-item label="计划编号:">
  53. <el-input readonly v-model="planInfo.code"></el-input>
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="6">
  57. <el-form-item label="规格:">
  58. <el-input readonly v-model="planInfo.specification"></el-input>
  59. </el-form-item>
  60. </el-col>
  61. <el-col :span="6">
  62. <el-form-item label="型号:">
  63. <el-input readonly v-model="planInfo.model"></el-input>
  64. </el-form-item>
  65. </el-col>
  66. </el-row>
  67. <el-row>
  68. <el-col :span="6">
  69. <el-form-item label="编码:">
  70. <el-input readonly v-model="planInfo.productCode"></el-input>
  71. </el-form-item>
  72. </el-col>
  73. <el-col :span="6">
  74. <el-form-item label="牌号:">
  75. <el-input readonly v-model="planInfo.brandNo"></el-input>
  76. </el-form-item>
  77. </el-col>
  78. <el-col :span="6">
  79. <el-form-item label="计划数量:">
  80. <el-input readonly v-model="planInfo.productNum"></el-input>
  81. </el-form-item>
  82. </el-col>
  83. <el-col :span="6">
  84. <el-form-item label="未发总数:">
  85. <el-input
  86. readonly
  87. v-model="kitComInfo.totalUnshippedQuantity"
  88. ></el-input>
  89. </el-form-item>
  90. </el-col>
  91. </el-row>
  92. <el-row>
  93. <el-col :span="6">
  94. <el-form-item label="库存数量:">
  95. <el-input
  96. readonly
  97. v-model="kitComInfo.inventoryQuantity"
  98. ></el-input>
  99. </el-form-item>
  100. </el-col>
  101. <el-col :span="6">
  102. <el-form-item label="在制总数:">
  103. <el-input
  104. readonly
  105. v-model="kitComInfo.totalNumberProduction"
  106. ></el-input>
  107. </el-form-item>
  108. </el-col>
  109. <el-col :span="6">
  110. <el-form-item label="最终缺料数量:">
  111. <el-input
  112. readonly
  113. v-model="kitComInfo.finalFilledShortCount"
  114. ></el-input>
  115. </el-form-item>
  116. </el-col>
  117. <el-col :span="6">
  118. <el-form-item label="最终状态:">
  119. <el-input
  120. readonly
  121. v-model="kitComInfo.finalFilledShortState"
  122. ></el-input>
  123. </el-form-item>
  124. </el-col>
  125. </el-row>
  126. </el-form>
  127. <div class="form-wrapper">
  128. <div
  129. class="left_tree"
  130. v-show="leftShow"
  131. :style="{ width: leftWidth }"
  132. >
  133. <el-tree
  134. ref="treeRef"
  135. :expand-on-click-node="false"
  136. :data="cardList"
  137. :props="treeProps"
  138. node-key="id"
  139. highlight-current
  140. @node-click="handleNodeClick"
  141. ></el-tree>
  142. </div>
  143. <div :style="{ width: rightWidth }">
  144. <div>
  145. <ele-pro-table
  146. ref="table"
  147. :needPage="false"
  148. :columns="columns"
  149. :init-load="false"
  150. :datasource="datasourceList"
  151. row-key="code"
  152. :cache-key="`ProductionPlanTable`"
  153. border
  154. height="40vh"
  155. key="id"
  156. :selection.sync="selection"
  157. >
  158. <template v-slot:default>
  159. <div class="tool">
  160. <div class="tool_l">
  161. <el-button
  162. v-if="produceType == 2"
  163. type="primary"
  164. @click="bulkPurchase"
  165. size="medium"
  166. >下发采购计划</el-button
  167. >
  168. <el-button
  169. v-if="produceType == 1&&formInline.bomType!=1"
  170. type="primary"
  171. @click="issuePlan"
  172. size="medium"
  173. >下发生产计划</el-button
  174. >
  175. </div>
  176. <div class="tool_r">
  177. <el-form
  178. :inline="true"
  179. :model="formInline"
  180. class="demo-form-inline"
  181. >
  182. <el-form-item label="BOM类型">
  183. <el-select
  184. size="medium"
  185. v-model="formInline.bomType"
  186. placeholder="BOM类型"
  187. class="select-type"
  188. @change="bomTypeChange"
  189. >
  190. <el-option
  191. v-for="item in bomListType"
  192. :key="item.bomType"
  193. :label="item.bomName"
  194. :value="item.bomType"
  195. >
  196. </el-option>
  197. </el-select>
  198. </el-form-item>
  199. <el-form-item label="BOM版本">
  200. <el-select
  201. class="select-type"
  202. size="medium"
  203. v-model="formInline.bomId"
  204. placeholder="BOM版本"
  205. @change="bomVChange"
  206. >
  207. <el-option
  208. v-for="item in bomListV"
  209. :key="item.bomId"
  210. :label="item.versions"
  211. :value="item.bomId"
  212. >
  213. </el-option>
  214. </el-select>
  215. </el-form-item>
  216. <el-form-item label="属性类型" v-if="produceType == 2">
  217. <el-select
  218. size="medium"
  219. v-model="formInline.attributeType"
  220. placeholder="属性类型"
  221. class="select-type"
  222. @change="attributeChange"
  223. >
  224. <el-option
  225. v-for="item in attributeList"
  226. :key="item.value"
  227. :label="item.label"
  228. :value="item.value"
  229. >
  230. </el-option>
  231. </el-select>
  232. </el-form-item>
  233. <el-form-item label="最终状态">
  234. <el-select
  235. class="select-type"
  236. size="medium"
  237. v-model="formInline.finalState"
  238. placeholder="最终状态"
  239. @change="finalChange"
  240. >
  241. <el-option
  242. v-for="item in finalStateList"
  243. :key="item.value"
  244. :label="item.label"
  245. :value="item.value"
  246. >
  247. </el-option>
  248. </el-select>
  249. </el-form-item>
  250. </el-form>
  251. </div>
  252. </div>
  253. </template>
  254. <!-- <template v-slot:toolbar>
  255. <el-button
  256. v-if="produceType == 2"
  257. type="primary"
  258. @click="bulkPurchase"
  259. size="medium"
  260. >下发采购计划</el-button
  261. >
  262. <el-button
  263. v-if="produceType == 1"
  264. type="primary"
  265. @click="issuePlan"
  266. size="medium"
  267. >下发生产计划</el-button
  268. >
  269. </template> -->
  270. <!-- 默认按订单 -->
  271. <template v-slot:toolbar v-if="produceType == 1">
  272. <el-form :inline="true">
  273. <el-form-item label="定额计算方法:">
  274. <el-radio-group
  275. v-model="quota_calculation"
  276. @change="selectCalculate"
  277. >
  278. <el-radio :label="1">按订单数量</el-radio>
  279. <el-radio :label="2">按缺料数量</el-radio>
  280. </el-radio-group>
  281. </el-form-item>
  282. </el-form>
  283. </template>
  284. <template v-slot:toolkit>
  285. <!-- 定额计算方法: 按订单数量 按缺料数量 -->
  286. <el-form :inline="true">
  287. <el-form-item label="基本数量">
  288. <el-input size="medium" v-model="baseCount" disabled>
  289. <template slot="append">{{ baseUnit }}</template>
  290. </el-input>
  291. </el-form-item>
  292. </el-form>
  293. </template>
  294. <template v-slot:inventoryQuantity="{ row }">
  295. <el-link
  296. type="primary"
  297. :underline="false"
  298. @click="stockDetail(row)"
  299. >
  300. {{ row.inventoryQuantity }}
  301. </el-link>
  302. </template>
  303. <template v-slot:inTransitNum="{ row }">
  304. <el-link
  305. type="primary"
  306. :underline="false"
  307. @click="currentDetail(row)"
  308. >
  309. {{ row.inTransitNum }}
  310. </el-link>
  311. </template>
  312. <template v-slot:inventoryStatusText="{ row }">
  313. <div
  314. :class="
  315. row.inventoryStatusText == '缺料'
  316. ? 'statusRed'
  317. : 'statusGreen'
  318. "
  319. >
  320. {{ row.inventoryStatusText }}
  321. </div>
  322. </template>
  323. <template v-slot:inTransitStatusText="{ row }">
  324. <div
  325. :class="
  326. row.inTransitStatusText == '缺料'
  327. ? 'statusRed'
  328. : 'statusGreen'
  329. "
  330. >
  331. {{ row.inTransitStatusText }}
  332. </div>
  333. </template>
  334. <template v-slot:finalStateText="{ row }">
  335. <div
  336. :class="
  337. row.finalStateText == '缺料' ? 'statusRed' : 'statusGreen'
  338. "
  339. >
  340. {{ row.finalStateText }}
  341. </div>
  342. </template>
  343. <template v-slot:numberProductionStateText="{ row }">
  344. <div
  345. :class="
  346. row.numberProductionStateText == '缺料'
  347. ? 'statusRed'
  348. : 'statusGreen'
  349. "
  350. >
  351. {{ row.numberProductionStateText }}
  352. </div>
  353. </template>
  354. <template v-slot:productFinalStateText="{ row }">
  355. <div
  356. :class="
  357. row.productFinalStateText == '缺料'
  358. ? 'statusRed'
  359. : 'statusGreen'
  360. "
  361. >
  362. {{ row.productFinalStateText }}
  363. </div>
  364. </template>
  365. <template v-slot:finishCount="{ row }">
  366. <div>
  367. <div v-if="row.finishCount > 0">{{ row.finishCount }}</div>
  368. <div v-else>-</div>
  369. </div>
  370. </template>
  371. <!-- <template v-slot:action="{ row }">
  372. <el-link
  373. type="primary"
  374. :underline="false"
  375. @click="issuePlan(row)"
  376. >
  377. 下发生产计划
  378. </el-link>
  379. </template> -->
  380. </ele-pro-table>
  381. </div>
  382. </div>
  383. </div>
  384. </div>
  385. <div slot="footer">
  386. <el-button plain @click="cancel">取消</el-button>
  387. <!-- <el-button type="primary" @click="confirm">确定</el-button> -->
  388. </div>
  389. </ele-modal>
  390. <stockDetailDialog ref="stockDetailDialog" />
  391. <currentDetailDialog ref="currentDetailDialog" />
  392. <purchaseDialog ref="purchaseDialogRef" :orderType="2" @success="success" />
  393. <factoryAdd
  394. ref="factoryAddRef"
  395. :isAdd="false"
  396. :factoryType="3"
  397. @close="factoryClose"
  398. ></factoryAdd>
  399. </div>
  400. </template>
  401. <script>
  402. import {
  403. findMaterialInfoByPlanId,
  404. findBomCategoryByCategoryId,
  405. findBomCategoryByCategoryIdV2,
  406. bomVersionList,
  407. listBomType,
  408. getProductKitting
  409. } from '@/api/productionPlan/index.js';
  410. import factoryAdd from './factoryAdd';
  411. import stockDetailDialog from './stockDetailDialog.vue';
  412. import currentDetailDialog from './currentDetailDialog.vue';
  413. import producePlan from '@/views/materialPlan/components/producePlan.vue';
  414. import purchaseDialog from './purchaseDialog.vue';
  415. import { issueProductionPlan } from '@/api/productionPlan/index.js';
  416. export default {
  417. components: {
  418. stockDetailDialog,
  419. currentDetailDialog,
  420. producePlan,
  421. purchaseDialog,
  422. factoryAdd
  423. },
  424. computed: {
  425. fieldShow() {
  426. return this.produceType == 1 && this.quota_calculation === 2;
  427. },
  428. columns() {
  429. return [
  430. {
  431. width: 45,
  432. type: 'selection',
  433. columnKey: 'selection',
  434. align: 'center',
  435. slot: 'selection',
  436. fixed: 'left'
  437. },
  438. {
  439. columnKey: 'index',
  440. label: '序号',
  441. type: 'index',
  442. width: 55,
  443. align: 'center',
  444. fixed: 'left'
  445. },
  446. {
  447. prop: 'batchNo',
  448. label: '批次号',
  449. align: 'center',
  450. minWidth: 100,
  451. showOverflowTooltip: true
  452. },
  453. {
  454. prop: 'bomCode',
  455. label: 'BOM编码',
  456. align: 'center',
  457. minWidth: 100,
  458. showOverflowTooltip: true
  459. },
  460. {
  461. prop: 'code',
  462. label: '物料编码',
  463. align: 'center',
  464. minWidth: 100,
  465. showOverflowTooltip: true
  466. },
  467. {
  468. prop: 'name',
  469. label: '物料名称',
  470. align: 'center',
  471. minWidth: 100,
  472. showOverflowTooltip: true
  473. },
  474. {
  475. prop: 'level',
  476. label: '层级',
  477. align: 'center',
  478. minWidth: 50
  479. },
  480. {
  481. prop: 'supplierName',
  482. label: '供应商',
  483. align: 'center',
  484. showOverflowTooltip: true,
  485. minWidth: 140
  486. },
  487. {
  488. prop: 'demandQuantity',
  489. label: '定额数量',
  490. showOverflowTooltip: true,
  491. align: 'center'
  492. },
  493. {
  494. prop: 'unit',
  495. label: '单位',
  496. showOverflowTooltip: true,
  497. align: 'center',
  498. width: 60
  499. },
  500. {
  501. prop: 'totalUnshippedQuantity',
  502. label: '未发总数',
  503. showOverflowTooltip: true,
  504. align: 'center',
  505. show: this.fieldShow
  506. // show: this.produceType == 1
  507. },
  508. {
  509. slot: 'inventoryQuantity',
  510. prop: 'inventoryQuantity',
  511. label: '库存数量',
  512. showOverflowTooltip: true,
  513. align: 'center'
  514. },
  515. {
  516. prop: 'secureInventory',
  517. label: '安全库存',
  518. showOverflowTooltip: true,
  519. align: 'center'
  520. },
  521. {
  522. prop: 'lockQuantity',
  523. label: '锁库数量',
  524. showOverflowTooltip: true,
  525. align: 'center'
  526. },
  527. {
  528. slot: 'inventoryStatusText',
  529. prop: 'inventoryStatusText',
  530. label: '库存状态',
  531. align: 'center',
  532. minWidth: 80
  533. },
  534. {
  535. slot: 'inTransitNum',
  536. prop: 'inTransitNum',
  537. label: '在途数量',
  538. align: 'center',
  539. minWidth: 80
  540. },
  541. {
  542. prop: 'inTransitOrdersNum',
  543. label: '在途已关联数量 ',
  544. align: 'center',
  545. minWidth: 120
  546. },
  547. {
  548. slot: 'inTransitStatusText',
  549. prop: 'inTransitStatusText',
  550. label: '在途状态',
  551. align: 'center',
  552. minWidth: 80
  553. },
  554. {
  555. prop: 'totalNumberProduction',
  556. label: '在制总数',
  557. showOverflowTooltip: true,
  558. align: 'center',
  559. // show: this.produceType == 1
  560. show: this.fieldShow
  561. },
  562. {
  563. prop: 'numberProductionStateText',
  564. slot: 'numberProductionStateText',
  565. label: '在制齐套',
  566. showOverflowTooltip: true,
  567. align: 'center',
  568. // show: this.produceType == 1
  569. show: this.fieldShow
  570. },
  571. // {
  572. // prop: 'productFinalStateText',
  573. // slot: 'productFinalStateText',
  574. // label: '成品的最终齐套',
  575. // showOverflowTooltip: true,
  576. // align: 'center',
  577. // minWidth: 160,
  578. // show: this.produceType == 1
  579. // },
  580. {
  581. label: '最终可用数量',
  582. prop: 'finalAvailableQuantity',
  583. align: 'center',
  584. minWidth: 110
  585. },
  586. {
  587. label: '最终缺料数量',
  588. prop: 'finalShortageQuantity',
  589. align: 'center',
  590. minWidth: 120
  591. },
  592. {
  593. label: '下发状态',
  594. align: 'center',
  595. minWidth: 90,
  596. fixed: 'right',
  597. formatter: (row) => {
  598. return row.hasIssued ? '已下发' : '未下发';
  599. }
  600. },
  601. {
  602. slot: 'finalStateText',
  603. prop: 'finalStateText',
  604. label: '最终状态',
  605. align: 'center',
  606. minWidth: 80,
  607. fixed: 'right'
  608. }
  609. // {
  610. // columnKey: 'action',
  611. // label: '操作',
  612. // width: 120,
  613. // align: 'center',
  614. // resizable: false,
  615. // fixed: 'right',
  616. // show: this.produceType == 1,
  617. // slot: 'action'
  618. // }
  619. ];
  620. }
  621. },
  622. data() {
  623. return {
  624. visible: false,
  625. kitComInfo: {},
  626. // requiredFormingNum: 0,
  627. formInline: {
  628. finalState: 0,
  629. attributeType: 2,
  630. bomId: '',
  631. time: ''
  632. },
  633. finalStateList: [
  634. {
  635. label: '全部',
  636. value: 0
  637. },
  638. {
  639. label: '齐套',
  640. value: 1
  641. },
  642. {
  643. label: '缺料',
  644. value: 2
  645. }
  646. ],
  647. ids: [],
  648. leftShow: false,
  649. leftWidth: '0%',
  650. rightWidth: '100%',
  651. cardList: [],
  652. treeProps: {
  653. label: 'code',
  654. children: 'children'
  655. },
  656. planInfo: {
  657. salesCode: ''
  658. },
  659. datasourceAllList: [], // 表格物料全部数据
  660. datasourceList: [], // 表格物料数据
  661. bomListV: [], // BOM版本
  662. bomListType: [], // BOM 类型
  663. planId: '',
  664. selectNodeId: '',
  665. loading: false,
  666. produceType: 1,
  667. selection: [],
  668. attributeList: [
  669. {
  670. value: 'all',
  671. label: '全部'
  672. },
  673. {
  674. value: 2,
  675. label: '采购件'
  676. },
  677. {
  678. value: 3,
  679. label: '外协件'
  680. }
  681. ],
  682. baseCount: '',
  683. baseUnit: '',
  684. quota_calculation: 1,
  685. pickerOptions: {
  686. // 限制最大可选日期为今天
  687. disabledDate(time) {
  688. const today = new Date(2025, 7, 29);
  689. return time.getTime() > today.getTime();
  690. }
  691. },
  692. startTime: []
  693. };
  694. },
  695. watch: {
  696. leftShow(newVal, oldVal) {
  697. if (newVal) {
  698. this.leftWidth = '230px';
  699. this.rightWidth = 'calc(100% - 240px)';
  700. } else {
  701. this.leftWidth = '0';
  702. this.rightWidth = '100%';
  703. }
  704. }
  705. },
  706. mounted() {},
  707. methods: {
  708. onSubmit() {},
  709. async handleNodeClick(data) {
  710. this.planInfo = data;
  711. try {
  712. await this.getKitting();
  713. await this.getBomData(data);
  714. this.selectNodeId = data.id;
  715. } catch (e) {
  716. console.log(e, '错误');
  717. }
  718. },
  719. async getKitting() {
  720. let { startTime, endTime } = this.getTimeData();
  721. let params = {
  722. categoryId: this.planInfo.categoryId,
  723. startTime,
  724. endTime
  725. };
  726. const res = await getProductKitting(params);
  727. if (res) {
  728. this.kitComInfo = res;
  729. }
  730. },
  731. getTimeData() {
  732. let startTime = '';
  733. let endTime = '';
  734. if (this.startTime.length > 0) {
  735. startTime = this.startTime[0];
  736. endTime = this.startTime[1];
  737. }
  738. return { startTime, endTime };
  739. },
  740. initTime() {
  741. // 获取当前日期(今天)
  742. const today = new Date(2025, 7, 29); // 注意:月份是0-based,8月对应7
  743. // 计算三个月前的日期
  744. const threeMonthsAgo = new Date(today);
  745. threeMonthsAgo.setMonth(today.getMonth() - 3);
  746. let start = this.formatDate(threeMonthsAgo);
  747. let end = this.formatDate(today);
  748. this.startTime = [start, end];
  749. },
  750. formatDate(date) {
  751. const year = date.getFullYear();
  752. const month = String(date.getMonth() + 1).padStart(2, '0');
  753. const day = String(date.getDate()).padStart(2, '0');
  754. return `${year}-${month}-${day}`;
  755. },
  756. selectCalculate(val) {
  757. this.attributeChange(this.formInline.attributeType);
  758. },
  759. reload(where) {
  760. this.$nextTick(() => {
  761. this.$refs.table.reload({ page: 1, where });
  762. });
  763. },
  764. stockDetail(row) {
  765. this.$refs.stockDetailDialog.open({ bomCode: row.code });
  766. },
  767. currentDetail(row) {
  768. this.$refs.currentDetailDialog.open({ bomCode: row.code });
  769. },
  770. // 选择BOM类型
  771. async bomTypeChange(e, type) {
  772. this.formInline.bomType = e;
  773. const params = {
  774. categoryId: this.planInfo.categoryId,
  775. bomType: e,
  776. isTemp: 0
  777. };
  778. const res = await bomVersionList(params);
  779. if (!res || res.length == 0) {
  780. this.bomListV = [];
  781. return;
  782. }
  783. let list = [];
  784. res.forEach((el) => {
  785. if (el.status != 1) return;
  786. let obj = {
  787. bomId: el.id,
  788. id: el.id,
  789. versions: `V${el.versions}.0`
  790. };
  791. list.push(obj);
  792. });
  793. this.bomListV = list;
  794. if (type == 'init') {
  795. let obj = list.find((el) => el.bomId == this.planInfo.bomCategoryId);
  796. let id = obj ? obj.bomId : list[0].bomId;
  797. this.formInline.bomId = id;
  798. this.bomVChange(id);
  799. } else {
  800. let id = list[0].bomId;
  801. this.formInline.bomId = id;
  802. this.bomVChange(id);
  803. }
  804. // let data = this.bomListType.find((el) => el.id === e);
  805. // if (!data) return;
  806. // this.bomListV = data.bomList;
  807. // let idx = 0;
  808. // if (type == 'init') {
  809. // idx = data.bomList.findIndex(
  810. // (item) => item.bomId == this.planInfo.bomCategoryId
  811. // );
  812. // }
  813. // const index = idx != -1 ? idx : 0;
  814. // await this.bomVChange(data.bomList[index].bomId);
  815. },
  816. // 选择BOM版本
  817. async bomVChange(e) {
  818. this.formInline.bomId = e;
  819. // return
  820. // let bomData = list.find((el) => el.bomId == e);
  821. // if (!bomData) return;
  822. // let data = this.bomListV.find((el) => el.bomId === e);
  823. this.getMaterialData({ bomId: e }, this.formInline.attributeType);
  824. },
  825. // 查询采购价跟外协件两个类型数据
  826. async dataMerging() {
  827. if (!this.formInline.bomId) {
  828. return;
  829. }
  830. let kitting = this.quota_calculation == 1 ? false : true;
  831. let { startTime, endTime } = this.getTimeData();
  832. let params1 = {
  833. planId: this.planId,
  834. bomVersionId: this.formInline.bomId,
  835. produceType: 2,
  836. startTime,
  837. endTime,
  838. kitting: kitting
  839. };
  840. let params2 = {
  841. planId: this.planId,
  842. bomVersionId: this.formInline.bomId,
  843. produceType: 3,
  844. startTime,
  845. endTime,
  846. kitting: kitting
  847. };
  848. this.loading = true;
  849. try {
  850. // 直接调用接口函数,因为其返回Promise,无需额外包装
  851. let p1 = findMaterialInfoByPlanId(params1);
  852. let p2 = findMaterialInfoByPlanId(params2);
  853. // 使用Promise.all并行执行多个Promise
  854. let results = await Promise.all([p1, p2]);
  855. this.loading = false;
  856. // 这里可以继续对results做后续处理,比如解构等
  857. const [result1, result2] = results;
  858. // 示例:可以接着处理result1和result2,比如合并数据等
  859. const mergeData = this.handleMergedData(result1, result2);
  860. this.resultProcess(mergeData);
  861. } catch (error) {
  862. this.loading = false;
  863. console.error('接口请求出错:', error);
  864. }
  865. },
  866. handleMergedData(result1, result2) {
  867. // 处理合并后的数据逻辑
  868. return [...result1, ...result2];
  869. },
  870. // 切换属性
  871. async attributeChange(e) {
  872. if (e == 'all') {
  873. this.dataMerging();
  874. return;
  875. }
  876. let data = this.bomListV.find(
  877. (el) => el.bomId === this.formInline.bomId
  878. );
  879. if (!data) return;
  880. await this.getMaterialData(data, e);
  881. },
  882. // 获取物料数据信息
  883. async getMaterialData(data, attributeType) {
  884. if (attributeType == 'all') {
  885. this.dataMerging();
  886. return;
  887. }
  888. let kitting = this.quota_calculation == 1 ? false : true;
  889. let produceType =
  890. this.produceType == 1 ? 1 : attributeType == 2 ? 2 : 3;
  891. let { startTime, endTime } = this.getTimeData();
  892. let params = {
  893. planId: this.planId,
  894. bomVersionId: data.bomId,
  895. produceType: produceType,
  896. startTime,
  897. endTime,
  898. kitting: kitting
  899. };
  900. this.loading = true;
  901. try {
  902. const result = await findMaterialInfoByPlanId(params);
  903. this.resultProcess(result);
  904. this.loading = false;
  905. } catch (err) {
  906. this.loading = false;
  907. }
  908. },
  909. // 结果数据处理
  910. resultProcess(result) {
  911. this.datasourceList=[]
  912. if (!result || result.length == 0) {
  913. this.baseCount = '';
  914. this.baseUnit = '';
  915. return;
  916. }
  917. let first = result[0];
  918. this.baseCount = first.baseCount;
  919. this.baseUnit = first.measuringUnit;
  920. result.forEach((item) => {
  921. item.batchNo = this.planInfo.batchNo;
  922. item.salesCode = this.planInfo.salesCode;
  923. item.finalState =
  924. item.finalStateText == '齐套'
  925. ? 1
  926. : item.finalStateText == '缺料'
  927. ? 2
  928. : '';
  929. });
  930. this.datasourceAllList = result;
  931. this.finalChange(this.formInline.finalState);
  932. },
  933. // 选择状态
  934. finalChange(e) {
  935. if (e === 0 || !e) {
  936. this.datasourceList = this.datasourceAllList;
  937. return;
  938. }
  939. this.datasourceList = this.datasourceAllList.filter(
  940. (item) => item.finalState === e
  941. );
  942. },
  943. // 批量采购
  944. async bulkPurchase() {
  945. if (this.selection.length == 0) {
  946. return this.$message.warning('请至少选择一条数据');
  947. }
  948. for (let i = 0; i < this.selection.length; i++) {
  949. let el = this.selection[i];
  950. if (el.finalState == 1) {
  951. return this.$message.warning('必须选择最终状态为缺料的数据');
  952. }
  953. if (el.hasIssued) {
  954. return this.$message.warning('必须选择下发状态为未下发的数据');
  955. }
  956. }
  957. let arr = JSON.parse(JSON.stringify(this.selection));
  958. let obj = this.bomListType.find(
  959. (el) => el.bomType === this.formInline.bomType
  960. );
  961. let data = {
  962. ...this.planInfo,
  963. bomId: this.formInline.bomId,
  964. bomType: obj.bomType
  965. };
  966. this.$refs.purchaseDialogRef.open(arr, data);
  967. },
  968. success() {
  969. this.bomVChange(this.formInline.bomId);
  970. },
  971. async open(dataList, produceType) {
  972. this.initTime();
  973. this.produceType = produceType;
  974. this.visible = true;
  975. this.$nextTick(() => {
  976. this.$refs.table.reRenderTable();
  977. });
  978. // this.$refs.table.reRenderTable();
  979. this.cardList = dataList;
  980. if (dataList.length === 1) {
  981. this.leftShow = false;
  982. } else {
  983. this.leftShow = true;
  984. const firstNodeKey = dataList[0].id;
  985. this.$nextTick(() => {
  986. this.$refs.treeRef.setCurrentKey(firstNodeKey);
  987. });
  988. }
  989. this.handleNodeClick(dataList[0]);
  990. },
  991. cancel() {
  992. this.clearData();
  993. this.visible = false;
  994. },
  995. clearData() {
  996. this.formInline = {
  997. finalState: 0,
  998. attributeType: 2,
  999. bomId: ''
  1000. };
  1001. this.baseCount = '';
  1002. this.baseUnit = '';
  1003. this.bomListV = [];
  1004. this.bomListType = [];
  1005. this.datasourceList = [];
  1006. this.datasourceAllList = [];
  1007. },
  1008. // 获取bom 数据
  1009. async getBomData(data) {
  1010. // this.loading = true;
  1011. try {
  1012. this.planId = data.id;
  1013. let params = { categoryId: data.categoryId };
  1014. const res = await listBomType(params);
  1015. if (!res || res.length === 0) return;
  1016. let bomMap = {
  1017. 1: 'PBOM',
  1018. 2: 'MBOM',
  1019. 3: 'ABOM'
  1020. };
  1021. let list = res.map((item) => {
  1022. return {
  1023. bomType: item.bomType,
  1024. id: item.id,
  1025. bomId: item.id,
  1026. bomName: bomMap[item.bomType]
  1027. };
  1028. });
  1029. let bom = list.find((el) => el.bomType == data.produceType);
  1030. let bomType = bom ? bom.bomType : list[0].bomType;
  1031. this.bomListType = list;
  1032. this.formInline.bomType = bomType;
  1033. this.bomTypeChange(bomType, 'init');
  1034. // console.log(res, 'res 333');
  1035. // const params = {
  1036. // categoryId: data.categoryId,
  1037. // bomType: data.produceType,
  1038. // isTemp: 0
  1039. // };
  1040. // const res = bomVersionList(params);
  1041. return;
  1042. // const res = await findBomCategoryByCategoryIdV2(
  1043. // data.bomCategoryId,
  1044. // this.produceType
  1045. // );
  1046. // this.loading = false;
  1047. // if (!res || res.length == 0) {
  1048. // this.bomListD = [];
  1049. // this.datasourceList = [];
  1050. // return;
  1051. // }
  1052. // let obj = {};
  1053. // let bomMap = {
  1054. // 1: 'PBOM',
  1055. // 2: 'MBOM',
  1056. // 3: 'ABOM'
  1057. // };
  1058. // if (this.produceType == 1) {
  1059. // delete bomMap[1];
  1060. // }
  1061. // let result = res.filter((item) => item.bomType != 1);
  1062. // result.map((el) => {
  1063. // el.bomName = bomMap[el.bomType];
  1064. // let OBMINFO = {
  1065. // bomId: el.bomId,
  1066. // bomType: el.type,
  1067. // versions: `V${el.versions}.0`
  1068. // };
  1069. // if (obj[el.bomType]) {
  1070. // obj[el.bomType].bomList.unshift(OBMINFO);
  1071. // } else {
  1072. // obj[el.bomType] = { ...el, bomList: [OBMINFO] };
  1073. // }
  1074. // });
  1075. // let list = Object.values(obj);
  1076. // if (list.length == 0) return;
  1077. // this.bomListType = list;
  1078. // let bomObj = res.find(
  1079. // (item) => item.bomId == this.planInfo.bomCategoryId
  1080. // );
  1081. // console.log(bomObj, 'bomObj');
  1082. // let idx = 0;
  1083. // if (bomObj && bomObj.bomId) {
  1084. // idx = list.findIndex((item) => item.bomType == bomObj.bomType);
  1085. // }
  1086. // const index = idx != -1 ? idx : 0;
  1087. // await this.bomTypeChange(list[index].id, 'init');
  1088. // this.loading = false;
  1089. } catch (err) {
  1090. this.$message.error(err.message);
  1091. this.loading = false;
  1092. }
  1093. },
  1094. issuePlan() {
  1095. if (this.selection.length == 0) {
  1096. return this.$message.warning('请至少选择一条数据');
  1097. }
  1098. for (let i = 0; i < this.selection.length; i++) {
  1099. let el = this.selection[i];
  1100. if (el.finalState == 1) {
  1101. return this.$message.warning('必须选择最终状态为缺料的数据');
  1102. }
  1103. // if (el.hasIssued) {
  1104. // return this.$message.warning('必须选择下发状态为未下发的数据');
  1105. // }
  1106. }
  1107. let obj = this.bomListType.find(
  1108. (el) => el.bomType === this.formInline.bomType
  1109. );
  1110. const addPOList = this.fieldProcessing(this.selection);
  1111. // this.$alert('确定要将所选的数据下发生产计划吗', {
  1112. // confirmButtonText: '确定',
  1113. // callback: (action) => {
  1114. // let param = {
  1115. // addPOList: addPOList,
  1116. // produceType: obj.bomType,
  1117. // id: this.planInfo.id
  1118. // };
  1119. // batchSave(param).then((res) => {
  1120. // this.$message.success('操作成功');
  1121. // this.bomVChange(this.formInline.bomId);
  1122. // });
  1123. // }
  1124. // });
  1125. this.$confirm('确定要将所选的数据下发生产计划吗?', '提示', {
  1126. confirmButtonText: '确定',
  1127. cancelButtonText: '取消'
  1128. })
  1129. .then(() => {
  1130. let param = {
  1131. addPOList: addPOList,
  1132. produceType: obj.bomType,
  1133. id: this.planInfo.id
  1134. };
  1135. issueProductionPlan(param).then((res) => {
  1136. this.$message.success('操作成功');
  1137. this.bomVChange(this.formInline.bomId);
  1138. });
  1139. })
  1140. .catch(() => {});
  1141. // this.$refs.factoryAddRef.open();
  1142. // this.$refs.factoryAddRef.confirmChoose([row]);
  1143. },
  1144. // 字段处理
  1145. fieldProcessing(arr) {
  1146. // return;
  1147. let list = arr.map((item) => {
  1148. return {
  1149. id: item.resourceBomId,
  1150. categoryId: item.categoryId,
  1151. productCode: item.code,
  1152. productName: item.name,
  1153. specification: item.specification,
  1154. produceRoutingId: item.produceRoutingId || '',
  1155. produceRoutingName: item.produceRoutingName || '',
  1156. requiredFormingNum: item.finalShortageQuantity,
  1157. startTime: this.planInfo.startTime,
  1158. endTime: this.planInfo.endTime,
  1159. unit: item.unit,
  1160. brandNo: item.brandNo || '',
  1161. batchNo: this.planInfo.batchNo,
  1162. model: item.model,
  1163. resourceType: 0
  1164. };
  1165. });
  1166. return list || [];
  1167. },
  1168. factoryClose(val) {
  1169. // this.factoryObj = {};
  1170. },
  1171. onSubmit() {
  1172. this.getKitting();
  1173. this.attributeChange(this.formInline.attributeType);
  1174. }
  1175. // confirm() {
  1176. // this.visible = false;
  1177. // },
  1178. // async merge() {
  1179. // this.reload({ planIds: this.ids, productType: 1, merge: 2 });
  1180. // },
  1181. // tabClick() {
  1182. // this.reload({ planIds: this.ids, productType: 1 });
  1183. // }
  1184. }
  1185. };
  1186. </script>
  1187. <style lang="scss" scoped>
  1188. .mt20 {
  1189. margin-top: 20px;
  1190. }
  1191. .el-form-item {
  1192. margin-bottom: 0 !important;
  1193. }
  1194. .optionButton {
  1195. display: flex;
  1196. justify-content: flex-end;
  1197. padding-bottom: 3px;
  1198. }
  1199. .statusRed {
  1200. color: red;
  1201. }
  1202. .statusGreen {
  1203. color: green;
  1204. }
  1205. .planInfo {
  1206. }
  1207. .form-wrapper {
  1208. display: flex;
  1209. }
  1210. .planInfo {
  1211. // display: flex;
  1212. font-size: 16px;
  1213. }
  1214. .plan_form {
  1215. .el-col {
  1216. margin-bottom: 16px;
  1217. }
  1218. }
  1219. .left_tree {
  1220. max-height: 600px;
  1221. min-height: 300px;
  1222. overflow: auto;
  1223. border: 1px solid #ccc;
  1224. margin-right: 10px;
  1225. }
  1226. .tool {
  1227. display: flex;
  1228. align-items: center;
  1229. justify-content: space-between;
  1230. padding: 5px 10px;
  1231. border-left: 1px solid #ededed;
  1232. border-right: 1px solid #ededed;
  1233. }
  1234. </style>