material.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. <template>
  2. <div>
  3. <header-title title="物料清单"></header-title>
  4. <ele-pro-table
  5. ref="table"
  6. row-key="id"
  7. :columns="materialColumns"
  8. :datasource="materialList"
  9. cache-key="prenatal-examination-material-list-table-2511031522"
  10. autoAmendPage
  11. :needPage="false"
  12. @refresh="$emit('refresh')"
  13. >
  14. <template v-slot:toolbar> </template>
  15. <template v-slot:selectColumn="{ row }">
  16. <el-checkbox
  17. v-model="row.selected"
  18. @change="selectedChange(row)"
  19. ></el-checkbox>
  20. </template>
  21. </ele-pro-table>
  22. <header-title title="产出清单" style="margin-top: 20px"></header-title>
  23. <ele-pro-table
  24. ref="table"
  25. row-key="id"
  26. :columns="outputDetailsColumns"
  27. :datasource="localOutputDetails"
  28. cache-key="prenatal-examination-output-list-table-2511031523"
  29. autoAmendPage
  30. :needPage="false"
  31. @refresh="localOutputDetailsRefresh"
  32. >
  33. <template v-slot:reportQuantity="{ row }">
  34. <div>
  35. <el-input-number
  36. size="small"
  37. v-model.number="row.reportQuantity"
  38. controls-position="right"
  39. :min="0"
  40. :max="reportQuantitymax(row)"
  41. @change="reportQuantityChange(row)"
  42. ></el-input-number>
  43. </div>
  44. </template>
  45. <template v-slot:qualifiedQuantity="{ row }">
  46. <el-input-number
  47. size="small"
  48. v-model.number="row.qualifiedQuantity"
  49. controls-position="right"
  50. :min="0"
  51. :max="qualifiedQuantityMax(row)"
  52. @change="qualifiedQuantityChange(row)"
  53. ></el-input-number>
  54. </template>
  55. <template v-slot:noQualifiedQuantity="{ row }">
  56. <el-input-number
  57. size="small"
  58. v-model.number="row.noQualifiedQuantity"
  59. controls-position="right"
  60. :min="0"
  61. :max="noQualifiedQuantityMax(row)"
  62. @change="noQualifiedQuantityChange(row)"
  63. ></el-input-number>
  64. </template>
  65. <template v-slot:msg="{ row }">
  66. <el-input
  67. v-model="row.msg"
  68. type="textarea"
  69. rows="1"
  70. autosize
  71. @change="$emit('update:outputDetails', localOutputDetails)"
  72. ></el-input>
  73. </template>
  74. </ele-pro-table>
  75. </div>
  76. </template>
  77. <script>
  78. import {
  79. getMaterialQuotaInfo,
  80. getCategoryAndLevelByCategoryId
  81. } from '@/api/producetaskrecordrulesrecord/index';
  82. export default {
  83. components: {},
  84. props: {
  85. // 物料明细
  86. pickDetails: {
  87. type: Array,
  88. default: () => []
  89. },
  90. // 本次产出明细
  91. outputDetails: {
  92. type: Array,
  93. default: () => []
  94. },
  95. // 上到工序产出明细
  96. preOutputDetails: {
  97. type: Array,
  98. default: () => []
  99. },
  100. sumOutputDetails: {
  101. type: Array,
  102. default: () => []
  103. },
  104. // 工单id
  105. workOrderId: {
  106. type: [String, Number],
  107. required: true
  108. },
  109. // 规则id
  110. ruleId: {
  111. type: [String, Number],
  112. required: false
  113. },
  114. // 工序id
  115. produceTaskId: {
  116. type: [String, Number],
  117. required: true
  118. },
  119. // 工序实例id
  120. produceTaskInstanceId: {
  121. type: [String, Number],
  122. required: true
  123. },
  124. // 工序名称
  125. produceTaskName: {
  126. type: String,
  127. required: true
  128. },
  129. // BOM产品分类id
  130. bomCategoryId: {
  131. type: [String, Number],
  132. required: true
  133. },
  134. // 产出类型 1-物料本身 2-在制品 3-BOM标准产出
  135. outputType: {
  136. type: [Number],
  137. required: true
  138. },
  139. // 产品分类id
  140. categoryId: {
  141. type: [String, Number],
  142. required: false
  143. },
  144. // 执行状态
  145. executeStatus: {
  146. type: [Number],
  147. required: false
  148. }
  149. },
  150. watch: {
  151. pickDetails: {
  152. handler(newVal) {
  153. this.localPickDetails = JSON.parse(JSON.stringify(newVal)).map(
  154. (i) => {
  155. i.ruleId = this.ruleId;
  156. i.bomCategoryId = this.bomCategoryId;
  157. return i;
  158. }
  159. );
  160. },
  161. deep: true,
  162. immediate: true
  163. },
  164. outputDetails: {
  165. handler(newVal) {
  166. this.localOutputDetails = JSON.parse(JSON.stringify(newVal)).map(
  167. (i) => {
  168. i.ruleId = this.ruleId;
  169. i.outputType = this.outputType;
  170. i.bomCategoryId = this.bomCategoryId;
  171. i.id = null;
  172. return i;
  173. }
  174. );
  175. },
  176. deep: true,
  177. immediate: true
  178. },
  179. outputType: {
  180. handler() {
  181. // 重置产出明细
  182. this.localOutputDetails = [];
  183. this.localPickDetails = this.localPickDetails.map((item) => {
  184. return {
  185. ...item,
  186. selected: false
  187. };
  188. });
  189. // 根据不同的类型,重置物料明细
  190. if (this.outputType == 1) {
  191. this.$emit('update:outputDetails', this.localOutputDetails);
  192. // 1-物料本身
  193. } else if (this.outputType == 2) {
  194. // 2-在制品
  195. this.categoryInfoSetOutput();
  196. } else {
  197. // 3 BOM标准产出
  198. this.setMaterialQuotaInfo();
  199. }
  200. }
  201. },
  202. ruleId: {
  203. handler() {
  204. // 更新物料明细的ruleId
  205. this.localPickDetails = this.localPickDetails.map((item) => {
  206. return {
  207. ...item,
  208. ruleId: this.ruleId
  209. };
  210. });
  211. // 更新产出明细的ruleId
  212. this.localOutputDetails = this.localOutputDetails.map((item) => {
  213. return {
  214. ...item,
  215. ruleId: this.ruleId
  216. };
  217. });
  218. // 通知父组件更新
  219. this.$emit('update:pickDetails', this.localPickDetails);
  220. this.$emit('update:outputDetails', this.localOutputDetails);
  221. }
  222. },
  223. produceTaskId: {
  224. handler() {
  225. this.getMaterialQuotaInfo();
  226. this.getCategoryAndLevelByCategoryId();
  227. },
  228. immediate: true
  229. }
  230. },
  231. computed: {
  232. // 物料清单(包含上到工序产出明细)
  233. materialList() {
  234. return [...this.preOutputDetails, ...this.localPickDetails];
  235. },
  236. // 物料清单表头
  237. materialColumns() {
  238. const list = [
  239. {
  240. width: 45,
  241. type: 'index',
  242. columnKey: 'index',
  243. align: 'center'
  244. },
  245. {
  246. label: '类型',
  247. prop: 'categoryLevelNamePath',
  248. minWidth: 120
  249. },
  250. {
  251. label: '编码',
  252. prop: 'categoryCode',
  253. minWidth: 120
  254. },
  255. {
  256. label: '名称',
  257. prop: 'categoryName',
  258. minWidth: 120
  259. },
  260. {
  261. prop: 'model',
  262. label: '型号',
  263. align: 'center',
  264. showOverflowTooltip: true
  265. },
  266. {
  267. prop: 'specifications',
  268. label: '规格',
  269. align: 'center',
  270. width: 160,
  271. showOverflowTooltip: true
  272. },
  273. {
  274. prop: 'brandNo',
  275. label: '牌号',
  276. align: 'center'
  277. },
  278. {
  279. label: '工序名称',
  280. prop: 'produceTaskName',
  281. minWidth: 120
  282. },
  283. {
  284. label: '数量',
  285. prop: 'feedQuantity',
  286. minWidth: 120,
  287. formatter: (row) => {
  288. return (row.quantity || 0) + (row.unit || '');
  289. }
  290. },
  291. {
  292. label: '当次消耗数量',
  293. prop: '',
  294. minWidth: 120,
  295. formatter: (row) => {
  296. // 产出为物料
  297. if (this.outputType == 1) {
  298. // 取值产出清单
  299. const outputItem = this.localOutputDetails.find(
  300. (item) => item.categoryCode === row.categoryCode
  301. );
  302. return (
  303. (outputItem ? outputItem.reportQuantity : 0) +
  304. (row.unit || '')
  305. );
  306. } else {
  307. // 产出为在制品 或 BOM标准产出
  308. // 查询基数
  309. if (!this.materialQuotaInfo) {
  310. return '0' + (row.unit || '');
  311. }
  312. // 当前行为在制品 和 BOM标准产出
  313. const preOutputItem = this.localOutputDetails.find(
  314. (item) => item.categoryCode === row.categoryCode
  315. );
  316. if (preOutputItem) {
  317. return (preOutputItem.reportQuantity || 0) + (row.unit || '');
  318. }
  319. // 当前行为原材料
  320. const materialItem = this.materialQuotaInfo.materialQuota.find(
  321. (item) => item.categoryCode === row.categoryCode
  322. );
  323. if (!materialItem) {
  324. return '0' + (row.unit || '');
  325. }
  326. // 需要的物料数量比例
  327. let count =
  328. materialItem.count / this.materialQuotaInfo.baseCount;
  329. // 产出清单的报工数量 当次报工+累计报工
  330. const outputItem = this.localOutputDetails[0];
  331. if (!outputItem) {
  332. return '0' + (row.unit || '');
  333. }
  334. // 当次消耗
  335. let needQuantity = outputItem.reportQuantity * count;
  336. return needQuantity + (row.unit || '');
  337. }
  338. }
  339. },
  340. {
  341. label: '累计消耗数量',
  342. prop: '',
  343. minWidth: 120,
  344. formatter: (row) => {
  345. if (this.outputType == 1) {
  346. const outputItem = this.localOutputDetails.find(
  347. (item) => item.categoryCode == row.categoryCode
  348. );
  349. // 查询其他工单sumOutputDetails中已产生的bom标准产出和在制品的累计消耗数量
  350. let preCount = 0;
  351. if (this.materialQuotaInfo) {
  352. const materialQuotaItem =
  353. this.materialQuotaInfo.materialQuota.find(
  354. (item) => item.categoryCode === row.categoryCode
  355. );
  356. if (!materialQuotaItem) {
  357. return 0 + (row.unit || '');
  358. }
  359. // 计算比例
  360. const proportion =
  361. materialQuotaItem.count / this.materialQuotaInfo.baseCount;
  362. if (this.materialQuotaInfo.standardOutput) {
  363. // BOM标准产出
  364. const preItem = this.sumOutputDetails.find(
  365. (item) =>
  366. item.categoryCode ===
  367. this.materialQuotaInfo.standardOutput.categoryCode
  368. );
  369. if (preItem) {
  370. preCount += preItem.sumReportQuantity * proportion;
  371. }
  372. }
  373. if (this.categoryInfo) {
  374. // 在制品
  375. const preItem = this.sumOutputDetails.find(
  376. (item) =>
  377. item.categoryCode === this.categoryInfo.categoryCode
  378. );
  379. if (preItem) {
  380. preCount += preItem.sumReportQuantity * proportion;
  381. }
  382. }
  383. }
  384. let count = 0;
  385. if (outputItem) {
  386. if (this.executeStatus === 2) {
  387. // 已执行,处理重新一键报工时,sumReportQuantity包含了当前报工数量
  388. count =
  389. row.sumReportQuantity -
  390. (outputItem.reportQuantityCopy -
  391. outputItem.reportQuantity);
  392. } else {
  393. count = row.sumReportQuantity + outputItem.reportQuantity;
  394. }
  395. } else {
  396. count = row.sumReportQuantity;
  397. }
  398. return count + preCount + (row.unit || '');
  399. } else {
  400. // 当前行为在制品 和 BOM标准产出
  401. const output = this.localOutputDetails.find(
  402. (item) => item.categoryCode === row.categoryCode
  403. );
  404. if (output) {
  405. // 区分已执行状态
  406. if (this.executeStatus === 2) {
  407. // 已执行,处理重新一键报工时,sumReportQuantity包含了当前报工数量
  408. return (
  409. output.sumReportQuantity -
  410. (output.reportQuantityCopy - output.reportQuantity) +
  411. (row.unit || '')
  412. );
  413. }
  414. return (
  415. (output.sumReportQuantity || 0) +
  416. output.reportQuantity +
  417. (row.unit || '')
  418. );
  419. }
  420. // 产出为在制品 或 BOM标准产出 累计消耗数量
  421. if (!this.materialQuotaInfo) {
  422. return row.sumReportQuantity + (row.unit || '');
  423. }
  424. const materialItem = this.materialQuotaInfo.materialQuota.find(
  425. (item) => item.categoryCode === row.categoryCode
  426. );
  427. if (!materialItem) {
  428. return row.sumReportQuantity + (row.unit || '');
  429. }
  430. // 计算在制 标准产出消耗原材料
  431. const outputItem = this.localOutputDetails[0];
  432. if (!outputItem) {
  433. return row.sumReportQuantity + (row.unit || '');
  434. }
  435. // 单位产出所需物料比例
  436. const proportion =
  437. materialItem.count / this.materialQuotaInfo.baseCount;
  438. // 查询其他工单sumOutputDetails中已产生的bom标准产出和在制品的累计消耗数量
  439. let preCount = 0;
  440. // 如果当前物料不是BOM标准产出,则需要加上BOM标准产出的消耗数量
  441. if (
  442. outputItem.categoryCode !=
  443. this.materialQuotaInfo.standardOutput.categoryCode
  444. ) {
  445. // BOM标准产出
  446. const preItem = this.sumOutputDetails.find(
  447. (item) =>
  448. item.categoryCode ===
  449. this.materialQuotaInfo.standardOutput.categoryCode
  450. );
  451. if (preItem) {
  452. preCount += preItem.sumReportQuantity * proportion;
  453. }
  454. }
  455. // 在制品
  456. if (this.categoryInfo) {
  457. if (
  458. this.categoryInfo.categoryCode != outputItem.categoryCode
  459. ) {
  460. const preItem = this.sumOutputDetails.find(
  461. (item) =>
  462. item.categoryCode === this.categoryInfo.categoryCode
  463. );
  464. if (preItem) {
  465. preCount += preItem.sumReportQuantity * proportion;
  466. }
  467. }
  468. }
  469. let cumulativeOutputQuantity = 0;
  470. if (this.executeStatus === 2) {
  471. // 已执行,处理重新一键报工时,sumReportQuantity包含了当前报工数量
  472. cumulativeOutputQuantity =
  473. outputItem.sumReportQuantity -
  474. (outputItem.reportQuantityCopy - outputItem.reportQuantity);
  475. } else {
  476. cumulativeOutputQuantity =
  477. outputItem.sumReportQuantity + outputItem.reportQuantity;
  478. }
  479. const needQuantity = cumulativeOutputQuantity * proportion;
  480. // 已消耗数量转换
  481. // const sumReportQuantity = row.sumReportQuantity * proportion;
  482. const sumReportQuantity = row.sumReportQuantity;
  483. return (
  484. needQuantity + preCount + sumReportQuantity + (row.unit || '')
  485. );
  486. }
  487. }
  488. }
  489. ];
  490. if (this.outputType == 1) {
  491. list.push({
  492. prop: '',
  493. label: '选择',
  494. slot: 'selectColumn',
  495. align: 'center',
  496. fixed: 'right'
  497. });
  498. }
  499. return list;
  500. }
  501. },
  502. data() {
  503. return {
  504. localPickDetails: [],
  505. localOutputDetails: [],
  506. // bom配置的 标准产出信息
  507. materialQuotaInfo: null,
  508. // 在制品信息
  509. categoryInfo: null,
  510. // 产出清单表头
  511. outputDetailsColumns: [
  512. {
  513. width: 45,
  514. type: 'index',
  515. columnKey: 'index',
  516. align: 'center'
  517. },
  518. {
  519. label: '类型',
  520. prop: 'categoryLevelNamePath',
  521. minWidth: 120
  522. },
  523. {
  524. label: '编码',
  525. prop: 'categoryCode',
  526. minWidth: 120
  527. },
  528. {
  529. label: '名称',
  530. prop: 'categoryName',
  531. minWidth: 120
  532. },
  533. {
  534. prop: 'model',
  535. label: '型号',
  536. align: 'center',
  537. showOverflowTooltip: true
  538. },
  539. {
  540. prop: 'specifications',
  541. label: '规格',
  542. align: 'center',
  543. width: 160,
  544. showOverflowTooltip: true
  545. },
  546. {
  547. prop: 'brandNo',
  548. label: '牌号',
  549. align: 'center'
  550. },
  551. {
  552. label: '工序名称',
  553. prop: 'produceTaskName',
  554. minWidth: 120
  555. },
  556. {
  557. label: '当次报工数量',
  558. prop: 'reportQuantity',
  559. minWidth: 160,
  560. slot: 'reportQuantity'
  561. },
  562. {
  563. label: '当次合格数量',
  564. prop: 'qualifiedQuantity',
  565. minWidth: 160,
  566. slot: 'qualifiedQuantity'
  567. },
  568. {
  569. label: '当次不合格数量',
  570. prop: 'noQualifiedQuantity',
  571. minWidth: 160,
  572. slot: 'noQualifiedQuantity'
  573. },
  574. {
  575. label: '不合格原因',
  576. prop: 'msg',
  577. minWidth: 160,
  578. slot: 'msg'
  579. },
  580. {
  581. label: '已报工数量',
  582. prop: 'sumReportQuantity',
  583. minWidth: 120,
  584. formatter(row) {
  585. return (row.sumReportQuantity || 0) + row.unit;
  586. }
  587. },
  588. {
  589. label: '合格总数',
  590. prop: 'sumQualifiedQuantity',
  591. minWidth: 120,
  592. formatter(row) {
  593. return (row.sumQualifiedQuantity || 0) + (row.unit || '');
  594. }
  595. },
  596. {
  597. label: '不合格总数',
  598. prop: 'sumNoQualifiedQuantity',
  599. minWidth: 120,
  600. formatter(row) {
  601. return (row.sumNoQualifiedQuantity || 0) + (row.unit || '');
  602. }
  603. }
  604. ]
  605. };
  606. },
  607. methods: {
  608. // 选择物料
  609. openMaterialModal() {
  610. this.$refs.materialModalRef.open(
  611. {
  612. workOrderId: this.workOrderId,
  613. ruleId: this.ruleId,
  614. produceTaskId: this.produceTaskId
  615. },
  616. // ...this.localPickDetails, ...this.preOutputDetails
  617. []
  618. );
  619. },
  620. materialConfirm(data) {
  621. // 选择物料后添加
  622. console.log('data', data);
  623. data.forEach((newItem) => {
  624. const index = this.localPickDetails.findIndex(
  625. (item) => item.categoryCode === newItem.categoryCode
  626. );
  627. if (index !== -1) {
  628. // 存在则替换数量
  629. this.localPickDetails[index].quantity = newItem.quantity;
  630. } else {
  631. const sumItem = this.sumOutputDetails.find(
  632. (item) => item.categoryCode === newItem.categoryCode
  633. );
  634. let sumQualifiedQuantity = 0;
  635. let sumNoQualifiedQuantity = 0;
  636. let sumReportQuantity = 0;
  637. if (sumItem) {
  638. sumQualifiedQuantity = sumItem.sumQualifiedQuantity;
  639. sumNoQualifiedQuantity = sumItem.sumNoQualifiedQuantity;
  640. sumReportQuantity = sumItem.sumReportQuantity;
  641. }
  642. // 不存在则添加
  643. this.localPickDetails.push({
  644. ...newItem,
  645. reportQuantity: 0,
  646. ruleId: this.ruleId,
  647. bomCategoryId: this.bomCategoryId,
  648. produceTaskId: this.produceTaskId,
  649. produceTaskInstanceId: this.produceTaskInstanceId,
  650. produceTaskName: this.produceTaskName,
  651. workOrderId: this.workOrderId,
  652. sumQualifiedQuantity,
  653. sumNoQualifiedQuantity,
  654. sumReportQuantity
  655. });
  656. }
  657. });
  658. this.$emit('update:pickDetails', this.localPickDetails);
  659. },
  660. // bom标准产出赋值
  661. setMaterialQuotaInfo() {
  662. console.log('this.materialQuotaInfo', this.materialQuotaInfo);
  663. if (this.materialQuotaInfo && this.materialQuotaInfo.standardOutput) {
  664. const sumItem = this.sumOutputDetails.find(
  665. (i) =>
  666. i.categoryCode ===
  667. this.materialQuotaInfo.standardOutput.categoryCode
  668. );
  669. let sumQualifiedQuantity = 0;
  670. let sumNoQualifiedQuantity = 0;
  671. let sumReportQuantity = 0;
  672. if (sumItem) {
  673. sumQualifiedQuantity = sumItem.sumQualifiedQuantity;
  674. sumNoQualifiedQuantity = sumItem.sumNoQualifiedQuantity;
  675. sumReportQuantity = sumItem.sumReportQuantity;
  676. }
  677. // 赋值产出
  678. this.localOutputDetails = [
  679. {
  680. ...this.materialQuotaInfo.standardOutput,
  681. id: null,
  682. reportQuantity: 0,
  683. reportQuantityCopy: 0,
  684. qualifiedQuantity: 0,
  685. noQualifiedQuantity: 0,
  686. msg: '',
  687. sumReportQuantity,
  688. sumQualifiedQuantity,
  689. sumNoQualifiedQuantity,
  690. ruleId: this.ruleId,
  691. outputType: this.outputType,
  692. produceTaskId: this.produceTaskId,
  693. produceTaskInstanceId: this.produceTaskInstanceId,
  694. produceTaskName: this.produceTaskName,
  695. workOrderId: this.workOrderId
  696. }
  697. ];
  698. this.$emit('update:outputDetails', this.localOutputDetails);
  699. } else {
  700. this.$message.warning('未配置BOM标准产出信息');
  701. }
  702. },
  703. // 获取bom的产出清单
  704. async getMaterialQuotaInfo() {
  705. if (this.bomCategoryId && this.produceTaskId) {
  706. const data = await getMaterialQuotaInfo(
  707. this.bomCategoryId,
  708. this.produceTaskId
  709. );
  710. console.log('this.materialQuotaInfo', data);
  711. if (JSON.stringify(data) === '{}') {
  712. this.materialQuotaInfo = null;
  713. return;
  714. }
  715. this.materialQuotaInfo = data;
  716. console.log('this.materialQuotaInfo', this.materialQuotaInfo);
  717. }
  718. },
  719. // qualifiedQuantityMax 最大合格数量
  720. qualifiedQuantityMax(row) {
  721. return row.reportQuantity;
  722. },
  723. noQualifiedQuantityMax(row) {
  724. return row.reportQuantity;
  725. },
  726. selectedChange(row) {
  727. console.log('row', row);
  728. if (this.outputType != 1) return;
  729. if (row.selected) {
  730. // 判断是否存在
  731. const index = this.localOutputDetails.findIndex(
  732. (item) => item.categoryId === row.categoryId
  733. );
  734. if (index === -1) {
  735. const sumItem = this.sumOutputDetails.find(
  736. (i) => i.categoryCode === row.categoryCode
  737. );
  738. let sumQualifiedQuantity = 0;
  739. let sumNoQualifiedQuantity = 0;
  740. let sumReportQuantity = 0;
  741. if (sumItem) {
  742. sumQualifiedQuantity = sumItem.sumQualifiedQuantity;
  743. sumNoQualifiedQuantity = sumItem.sumNoQualifiedQuantity;
  744. sumReportQuantity = sumItem.sumReportQuantity;
  745. }
  746. // 不存在则添加
  747. this.localOutputDetails.push({
  748. ...row,
  749. id: null,
  750. reportQuantity: 0,
  751. reportQuantityCopy: 0,
  752. qualifiedQuantity: 0,
  753. noQualifiedQuantity: 0,
  754. msg: '',
  755. sumReportQuantity,
  756. sumQualifiedQuantity,
  757. sumNoQualifiedQuantity,
  758. ruleId: this.ruleId,
  759. outputType: this.outputType,
  760. bomCategoryId: this.bomCategoryId,
  761. produceTaskId: this.produceTaskId,
  762. produceTaskInstanceId: this.produceTaskInstanceId,
  763. produceTaskName: this.produceTaskName,
  764. workOrderId: this.workOrderId
  765. });
  766. } else {
  767. this.$message.warning('该物料已存在于产出清单中');
  768. }
  769. } else {
  770. // 取消选择则删除
  771. this.localOutputDetails = this.localOutputDetails.filter(
  772. (item) => !(item.categoryId === row.categoryId)
  773. );
  774. }
  775. this.$emit('update:outputDetails', this.localOutputDetails);
  776. },
  777. // getCategoryAndLevelByCategoryId 获取产品 在制品信息
  778. async getCategoryAndLevelByCategoryId() {
  779. const data = await getCategoryAndLevelByCategoryId(this.categoryId);
  780. this.categoryInfo = data;
  781. console.log('this.categoryInfo 在制品信息', this.categoryInfo);
  782. },
  783. // 在制品信息 设置产出物
  784. categoryInfoSetOutput() {
  785. if (this.categoryInfo) {
  786. const sumItem = this.sumOutputDetails.find(
  787. (i) => i.categoryCode == this.categoryInfo.categoryCode
  788. );
  789. let sumQualifiedQuantity = 0;
  790. let sumNoQualifiedQuantity = 0;
  791. let sumReportQuantity = 0;
  792. if (sumItem) {
  793. sumQualifiedQuantity = sumItem.sumQualifiedQuantity;
  794. sumNoQualifiedQuantity = sumItem.sumNoQualifiedQuantity;
  795. sumReportQuantity = sumItem.sumReportQuantity;
  796. }
  797. this.localOutputDetails = [
  798. {
  799. ...this.categoryInfo,
  800. id: null,
  801. reportQuantity: 0,
  802. reportQuantityCopy: 0,
  803. qualifiedQuantity: 0,
  804. noQualifiedQuantity: 0,
  805. msg: '',
  806. sumReportQuantity,
  807. sumQualifiedQuantity,
  808. sumNoQualifiedQuantity,
  809. ruleId: this.ruleId,
  810. outputType: this.outputType,
  811. produceTaskId: this.produceTaskId,
  812. produceTaskInstanceId: this.produceTaskInstanceId,
  813. produceTaskName: this.produceTaskName,
  814. workOrderId: this.workOrderId
  815. }
  816. ];
  817. }
  818. this.$emit('update:outputDetails', this.localOutputDetails);
  819. console.log('this.localOutputDetails', this.localOutputDetails);
  820. },
  821. // 计算报工数量最大值
  822. reportQuantitymax(row) {
  823. if (this.outputType == 1) {
  824. // 查询物料本身
  825. const pickItem = this.localPickDetails.find(
  826. (item) => item.categoryCode === row.categoryCode
  827. );
  828. // 查询其他工单sumOutputDetails中已产生的bom标准产出和在制品的累计消耗数量
  829. let preCount = 0;
  830. if (this.materialQuotaInfo) {
  831. const materialQuotaItem = this.materialQuotaInfo.materialQuota.find(
  832. (item) => item.categoryCode === row.categoryCode
  833. );
  834. if (materialQuotaItem) {
  835. // 计算比例
  836. const proportion =
  837. materialQuotaItem.count / this.materialQuotaInfo.baseCount;
  838. if (this.materialQuotaInfo.standardOutput) {
  839. // BOM标准产出
  840. const preItem = this.sumOutputDetails.find(
  841. (item) =>
  842. item.categoryCode ===
  843. this.materialQuotaInfo.standardOutput.categoryCode
  844. );
  845. if (preItem) {
  846. preCount += preItem.sumReportQuantity * proportion;
  847. }
  848. }
  849. if (this.categoryInfo) {
  850. // 在制品
  851. const preItem = this.sumOutputDetails.find(
  852. (item) => item.categoryCode === this.categoryInfo.categoryCode
  853. );
  854. if (preItem) {
  855. preCount += preItem.sumReportQuantity * proportion;
  856. }
  857. }
  858. }
  859. }
  860. // 未找到物料,则返回剩余数量
  861. if (!pickItem) return pickItem.quantity - preCount;
  862. // 已执行,处理重新一键报工时,sumReportQuantity包含了当前报工数量
  863. if (this.executeStatus === 2) {
  864. return (
  865. pickItem.quantity -
  866. (pickItem.sumReportQuantity - row.reportQuantityCopy) -
  867. preCount
  868. );
  869. } else {
  870. return pickItem.quantity - pickItem.sumReportQuantity - preCount;
  871. }
  872. }
  873. if (row.outputType == 2 || row.outputType == 3) {
  874. // 当前行为在制品 和 BOM标准产出
  875. const preOutputItem = this.preOutputDetails.find(
  876. (item) => item.categoryCode === row.categoryCode
  877. );
  878. // 存在则当前row为在制品或BOM标准产出
  879. if (preOutputItem) {
  880. // 区分已执行状态
  881. if (this.executeStatus === 2) {
  882. return (
  883. preOutputItem.quantity -
  884. (row.sumReportQuantity - row.reportQuantityCopy)
  885. );
  886. }
  887. return preOutputItem.quantity - row.sumReportQuantity;
  888. }
  889. // 基于物料配额限制最大可报工数量(兼容已缓存/已保存一次的编辑场景,并区分已执行状态)
  890. if (!this.materialQuotaInfo) return Infinity;
  891. const quota = this.materialQuotaInfo.materialQuota || [];
  892. if (!quota.length) return Infinity;
  893. const isExecuted = this.executeStatus === 2;
  894. const { baseCount } = this.materialQuotaInfo;
  895. if (!baseCount) return Infinity;
  896. // 计算每个物料的最大可报工数量
  897. const maxQuantities = quota.map((item) => {
  898. const pickItem = this.localPickDetails.find(
  899. (p) => p.categoryCode === item.categoryCode
  900. );
  901. if (!pickItem) {
  902. return Infinity;
  903. }
  904. // 单位产出所需物料比例
  905. const proportion = item.count / baseCount;
  906. // 查询其他工单 sumOutputDetails 中已产生的 BOM 标准产出和在制品的累计消耗数量
  907. let preOutputConsumedProportion = 0;
  908. // BOM标准产出
  909. if (
  910. this.materialQuotaInfo &&
  911. this.materialQuotaInfo.standardOutput &&
  912. row.categoryCode !==
  913. this.materialQuotaInfo.standardOutput.categoryCode
  914. ) {
  915. const preStd = this.sumOutputDetails.find(
  916. (s) =>
  917. s.categoryCode ===
  918. this.materialQuotaInfo.standardOutput.categoryCode
  919. );
  920. if (preStd) {
  921. preOutputConsumedProportion +=
  922. preStd.sumReportQuantity * proportion;
  923. }
  924. }
  925. // 在制品
  926. if (
  927. this.categoryInfo &&
  928. row.categoryCode !== this.categoryInfo.categoryCode
  929. ) {
  930. const preWip = this.sumOutputDetails.find(
  931. (s) => s.categoryCode === this.categoryInfo.categoryCode
  932. );
  933. if (preWip) {
  934. preOutputConsumedProportion +=
  935. preWip.sumReportQuantity * proportion;
  936. }
  937. }
  938. // 已执行,处理重新一键报工时,sumReportQuantity包含了当前报工数量
  939. let consumedQuantity = isExecuted
  940. ? row.sumReportQuantity - row.reportQuantityCopy
  941. : row.sumReportQuantity;
  942. // 已执行的比例换算,换算为需要多少物料数量
  943. const consumedProportion = consumedQuantity * proportion;
  944. // 最大可报工数量
  945. let maxQuantity =
  946. (pickItem.quantity -
  947. consumedProportion -
  948. preOutputConsumedProportion) /
  949. proportion;
  950. // 向下取整
  951. return Math.floor(maxQuantity);
  952. });
  953. // 返回最小的那个物料的最大可报工数量
  954. return Math.min(...maxQuantities);
  955. }
  956. return Infinity;
  957. },
  958. // 判断生成产出清单的物料数量是合格
  959. async validateOutputQuantities() {
  960. if (this.localOutputDetails.length == 0) {
  961. this.$message.warning(`产出清单不能为空`);
  962. return false;
  963. }
  964. for (const item of this.localOutputDetails) {
  965. if (!item.reportQuantity) {
  966. this.$message.warning(
  967. `请填写产出清单【${item.categoryName}】的当次报工数量`
  968. );
  969. return false;
  970. }
  971. }
  972. if (this.outputType == 1) {
  973. if (
  974. this.localPickDetails.length == 0 &&
  975. this.preOutputDetails.length == 0
  976. ) {
  977. this.$message.warning(`物料清单不能为空`);
  978. return false;
  979. }
  980. for (const item of this.localOutputDetails) {
  981. const pickitem = this.localPickDetails.find(
  982. (pick) => pick.categoryCode == item.categoryCode
  983. );
  984. const prePickitem = this.preOutputDetails.find(
  985. (pick) => pick.categoryCode == item.categoryCode
  986. );
  987. if (pickitem == null && prePickitem == null) {
  988. this.$message.warning(
  989. `所需物料【${item.categoryName}】未在物料清单中找到`
  990. );
  991. return false;
  992. }
  993. if (item.reportQuantity > item.quantity) {
  994. this.$message.error(
  995. `物料【${item.categoryName}】的报工数量不能超过领料数量`
  996. );
  997. return false;
  998. }
  999. }
  1000. }
  1001. return true;
  1002. },
  1003. // 当次报工修改
  1004. reportQuantityChange(row) {
  1005. // 同步当前合格数量 和 不合格数量为0
  1006. // 默认全部合格
  1007. row.qualifiedQuantity = row.reportQuantity;
  1008. row.noQualifiedQuantity = 0;
  1009. this.$emit('update:outputDetails', this.localOutputDetails);
  1010. },
  1011. // qualifiedQuantityChange 当次合格数量变化 计算 noQualifiedQuantity不合格数量
  1012. qualifiedQuantityChange(row) {
  1013. row.noQualifiedQuantity = row.reportQuantity - row.qualifiedQuantity;
  1014. this.$emit('update:outputDetails', this.localOutputDetails);
  1015. },
  1016. // 不合格数量变化
  1017. noQualifiedQuantityChange(row) {
  1018. row.qualifiedQuantity = row.reportQuantity - row.noQualifiedQuantity;
  1019. this.$emit('update:outputDetails', this.localOutputDetails);
  1020. },
  1021. localOutputDetailsRefresh() {
  1022. if (this.outputType == 1) {
  1023. this.$emit('refresh', 'output');
  1024. } else if (this.outputType == 2) {
  1025. this.getCategoryAndLevelByCategoryId();
  1026. } else {
  1027. this.setMaterialQuotaInfo();
  1028. }
  1029. }
  1030. }
  1031. };
  1032. </script>
  1033. <style></style>