material.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  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', 'material')"
  13. >
  14. <template v-slot:toolbar>
  15. <el-button type="primary" @click="openMaterialModal"
  16. >添加物料</el-button
  17. >
  18. </template>
  19. <template v-slot:selectColumn="{ row }">
  20. <el-checkbox
  21. v-model="row.selected"
  22. @change="selectedChange(row)"
  23. ></el-checkbox>
  24. </template>
  25. </ele-pro-table>
  26. <header-title title="产出清单" style="margin-top: 20px"></header-title>
  27. <ele-pro-table
  28. ref="table"
  29. row-key="id"
  30. :columns="outputDetailsColumns"
  31. :datasource="localOutputDetails"
  32. cache-key="prenatal-examination-output-list-table-2511031523"
  33. autoAmendPage
  34. :needPage="false"
  35. @refresh="$emit('refresh', 'output')"
  36. >
  37. <template v-slot:reportQuantity="{ row }">
  38. <el-input-number
  39. size="small"
  40. v-model.number="row.reportQuantity"
  41. controls-position="right"
  42. :min="0"
  43. :max="row.feedQuantity"
  44. ></el-input-number>
  45. </template>
  46. <template v-slot:qualifiedQuantity="{ row }">
  47. <el-input-number
  48. size="small"
  49. v-model.number="row.qualifiedQuantity"
  50. controls-position="right"
  51. :min="0"
  52. :max="qualifiedQuantityMax(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. ></el-input-number>
  63. </template>
  64. <template v-slot:msg="{ row }">
  65. <el-input
  66. v-model="row.msg"
  67. type="textarea"
  68. rows="1"
  69. autosize
  70. ></el-input>
  71. </template>
  72. </ele-pro-table>
  73. <materialModal ref="materialModalRef" @confirm="materialConfirm" />
  74. </div>
  75. </template>
  76. <script>
  77. import materialModal from './materialModal.vue';
  78. import {
  79. getMaterialQuotaInfo,
  80. getCategoryAndLevelByCategoryId
  81. } from '@/api/producetaskrecordrulesrecord/index';
  82. export default {
  83. components: {
  84. materialModal
  85. },
  86. props: {
  87. // 物料明细
  88. pickDetails: {
  89. type: Array,
  90. default: () => []
  91. },
  92. // 本次产出明细
  93. outputDetails: {
  94. type: Array,
  95. default: () => []
  96. },
  97. // 上到工序产出明细
  98. preOutputDetails: {
  99. type: Array,
  100. default: () => []
  101. },
  102. // 工单id
  103. workOrderId: {
  104. type: [String, Number],
  105. required: true
  106. },
  107. // 规则id
  108. ruleId: {
  109. type: [String, Number],
  110. required: true
  111. },
  112. // 工序id
  113. produceTaskId: {
  114. type: [String, Number],
  115. required: true
  116. },
  117. // BOM产品分类id
  118. bomCategoryId: {
  119. type: [String, Number],
  120. required: true
  121. },
  122. // 产出类型 1-物料本身 2-在制品 3-BOM标准产出
  123. outputType: {
  124. type: [Number],
  125. required: true
  126. },
  127. // 产品分类id
  128. categoryId: {
  129. type: [String, Number],
  130. required: false
  131. }
  132. },
  133. watch: {
  134. pickDetails: {
  135. handler(newVal) {
  136. this.localPickDetails = JSON.parse(JSON.stringify(newVal));
  137. },
  138. deep: true
  139. },
  140. outputDetails: {
  141. handler(newVal) {
  142. this.localOutputDetails = JSON.parse(JSON.stringify(newVal));
  143. },
  144. deep: true
  145. },
  146. bomCategoryId: {
  147. handler() {
  148. this.getMaterialQuotaInfo();
  149. }
  150. },
  151. produceTaskId: {
  152. handler() {
  153. this.getMaterialQuotaInfo();
  154. }
  155. },
  156. outputType: {
  157. handler() {
  158. // 重置产出明细
  159. this.localOutputDetails = [];
  160. // 根据不同的类型,重置物料明细
  161. if (this.outputType == 1) {
  162. this.$emit('update:outputDetails', this.localOutputDetails);
  163. // 1-物料本身
  164. } else if (this.outputType == 2) {
  165. // 2-在制品
  166. this.getCategoryAndLevelByCategoryId();
  167. } else {
  168. // 3 BOM标准产出
  169. this.getMaterialQuotaInfo();
  170. }
  171. }
  172. }
  173. },
  174. computed: {
  175. // 物料清单(包含上到工序产出明细)
  176. materialList() {
  177. return [...this.preOutputDetails, ...this.localPickDetails];
  178. },
  179. // 物料清单表头
  180. materialColumns() {
  181. const list = [
  182. {
  183. width: 45,
  184. type: 'index',
  185. columnKey: 'index',
  186. align: 'center'
  187. },
  188. {
  189. label: '类型',
  190. prop: 'categoryLevelNamePath',
  191. minWidth: 120
  192. },
  193. {
  194. label: '编码',
  195. prop: 'categoryCode',
  196. minWidth: 120
  197. },
  198. {
  199. label: '名称',
  200. prop: 'categoryName',
  201. minWidth: 120
  202. },
  203. {
  204. prop: 'model',
  205. label: '型号',
  206. align: 'center',
  207. showOverflowTooltip: true
  208. },
  209. {
  210. prop: 'specifications',
  211. label: '规格',
  212. align: 'center',
  213. width: 160,
  214. showOverflowTooltip: true
  215. },
  216. {
  217. prop: 'brandNo',
  218. label: '牌号',
  219. align: 'center'
  220. },
  221. {
  222. label: '工序名称',
  223. prop: 'produceTaskName',
  224. minWidth: 120
  225. },
  226. {
  227. label: '数量',
  228. prop: 'feedQuantity',
  229. minWidth: 120,
  230. formatter: (row) => {
  231. return (row.quantity || '') + (row.unit || '');
  232. }
  233. }
  234. ];
  235. if (this.outputType == 1) {
  236. list.push({
  237. prop: '',
  238. label: '选择',
  239. slot: 'selectColumn',
  240. align: 'center',
  241. fixed: 'right'
  242. });
  243. }
  244. return list;
  245. }
  246. },
  247. data() {
  248. return {
  249. localPickDetails: JSON.parse(JSON.stringify(this.pickDetails)),
  250. localOutputDetails: JSON.parse(JSON.stringify(this.outputDetails)),
  251. materialQuotaInfo: null,
  252. // 产出清单表头
  253. outputDetailsColumns: [
  254. {
  255. width: 45,
  256. type: 'index',
  257. columnKey: 'index',
  258. align: 'center'
  259. },
  260. {
  261. label: '类型',
  262. prop: 'categoryLevelNamePath',
  263. minWidth: 120
  264. },
  265. {
  266. label: '编码',
  267. prop: 'categoryCode',
  268. minWidth: 120
  269. },
  270. {
  271. label: '名称',
  272. prop: 'categoryName',
  273. minWidth: 120
  274. },
  275. {
  276. prop: 'model',
  277. label: '型号',
  278. align: 'center',
  279. showOverflowTooltip: true
  280. },
  281. {
  282. prop: 'specifications',
  283. label: '规格',
  284. align: 'center',
  285. width: 160,
  286. showOverflowTooltip: true
  287. },
  288. {
  289. prop: 'brandNo',
  290. label: '牌号',
  291. align: 'center'
  292. },
  293. {
  294. label: '工序名称',
  295. prop: 'produceTaskName',
  296. minWidth: 120
  297. },
  298. {
  299. label: '当次报工数量',
  300. prop: 'reportQuantity',
  301. minWidth: 160,
  302. slot: 'reportQuantity',
  303. formatter: (row) => {
  304. return (
  305. (row.reportQuantity == null ? '' : row.unit) +
  306. (row.feedUnit || '')
  307. );
  308. }
  309. },
  310. {
  311. label: '当次合格数量',
  312. prop: 'qualifiedQuantity',
  313. minWidth: 160,
  314. slot: 'qualifiedQuantity',
  315. formatter: (row) => {
  316. return (
  317. (row.qualifiedQuantity == null ? '' : row.unit) +
  318. (row.feedUnit || '')
  319. );
  320. }
  321. },
  322. {
  323. label: '当次不合格数量',
  324. prop: 'noQualifiedQuantity',
  325. minWidth: 160,
  326. slot: 'noQualifiedQuantity',
  327. formatter: (row) => {
  328. return (row.noQualifiedQuantity || 0) + (row.unit || '');
  329. }
  330. },
  331. {
  332. label: '不合格原因',
  333. prop: 'msg',
  334. minWidth: 160,
  335. slot: 'msg'
  336. },
  337. {
  338. label: '已报工数量',
  339. prop: 'sumReportQuantity',
  340. minWidth: 120,
  341. formatter(row) {
  342. return (row.sumReportQuantity || 0) + row.unit;
  343. }
  344. },
  345. {
  346. label: '合格总数',
  347. prop: 'sumQualifiedQuantity',
  348. minWidth: 120,
  349. formatter(row) {
  350. return (row.sumQualifiedQuantity || 0) + (row.unit || '');
  351. }
  352. },
  353. {
  354. label: '不合格总数',
  355. prop: 'sumNoQualifiedQuantity',
  356. minWidth: 120,
  357. formatter(row) {
  358. return (row.sumNoQualifiedQuantity || 0) + (row.unit || '');
  359. }
  360. }
  361. ]
  362. };
  363. },
  364. mounted() {
  365. if (this.outputType == 2) {
  366. this.getCategoryAndLevelByCategoryId();
  367. }
  368. if (this.outputType == 3) {
  369. this.getMaterialQuotaInfo();
  370. }
  371. },
  372. methods: {
  373. // 选择物料
  374. openMaterialModal() {
  375. this.$refs.materialModalRef.open(
  376. {
  377. workOrderId: this.workOrderId,
  378. ruleId: this.ruleId,
  379. produceTaskId: this.produceTaskId
  380. },
  381. []
  382. );
  383. },
  384. materialConfirm(data) {
  385. // 选择物料后添加
  386. console.log('data', data);
  387. data.forEach((newItem) => {
  388. const index = this.localPickDetails.findIndex(
  389. (item) =>
  390. item.categoryCode === newItem.categoryCode &&
  391. item.produceTaskInstanceId === newItem.produceTaskInstanceId
  392. );
  393. if (index !== -1) {
  394. // 存在则替换数量
  395. this.localPickDetails[index].quantity = newItem.quantity;
  396. } else {
  397. // 不存在则添加
  398. this.localPickDetails.push({ ...newItem });
  399. }
  400. });
  401. this.$emit('update:pickDetails', this.localPickDetails);
  402. },
  403. // 获取bom的产出
  404. async getMaterialQuotaInfo() {
  405. if (this.bomCategoryId && this.produceTaskId) {
  406. const data = await getMaterialQuotaInfo(
  407. this.bomCategoryId,
  408. this.produceTaskId
  409. );
  410. console.log('this.materialQuotaInfo', data);
  411. if (!data.standardOutput) {
  412. return this.$message.warning('未配置标准产出物料');
  413. }
  414. // 赋值产出
  415. this.localOutputDetails = [
  416. {
  417. ...data.standardOutput,
  418. reportQuantity: 0,
  419. qualifiedQuantity: 0,
  420. noQualifiedQuantity: 0,
  421. msg: '',
  422. sumReportQuantity: 0,
  423. sumQualifiedQuantity: 0,
  424. sumNoQualifiedQuantity: 0
  425. }
  426. ];
  427. this.$emit('update:outputDetails', this.localOutputDetails);
  428. console.log('this.localOutputDetails', this.localOutputDetails);
  429. }
  430. },
  431. // qualifiedQuantityMax 最大合格数量
  432. qualifiedQuantityMax(row) {
  433. return row.reportQuantity - row.noQualifiedQuantity;
  434. },
  435. noQualifiedQuantityMax(row) {
  436. return row.reportQuantity - row.qualifiedQuantity;
  437. },
  438. selectedChange(row) {
  439. console.log('row', row);
  440. if (row.selected) {
  441. // 判断是否存在
  442. const index = this.localOutputDetails.findIndex(
  443. (item) =>
  444. item.categoryId === row.categoryId &&
  445. item.produceTaskInstanceId === row.produceTaskInstanceId
  446. );
  447. if (index === -1) {
  448. // 不存在则添加
  449. this.localOutputDetails.push({
  450. ...row,
  451. reportQuantity: 0,
  452. qualifiedQuantity: 0,
  453. noQualifiedQuantity: 0,
  454. msg: '',
  455. sumReportQuantity: 0,
  456. sumQualifiedQuantity: 0,
  457. sumNoQualifiedQuantity: 0
  458. });
  459. } else {
  460. this.$message.warning('该物料已存在于产出清单中');
  461. }
  462. this.$emit('update:outputDetails', this.localOutputDetails);
  463. }
  464. },
  465. // getCategoryAndLevelByCategoryId 获取产品
  466. async getCategoryAndLevelByCategoryId() {
  467. const data = await getCategoryAndLevelByCategoryId(this.categoryId);
  468. this.localOutputDetails = [
  469. {
  470. ...data,
  471. reportQuantity: 0,
  472. qualifiedQuantity: 0,
  473. noQualifiedQuantity: 0,
  474. msg: '',
  475. sumReportQuantity: 0,
  476. sumQualifiedQuantity: 0,
  477. sumNoQualifiedQuantity: 0
  478. }
  479. ];
  480. this.$emit('update:outputDetails', this.localOutputDetails);
  481. console.log('this.localOutputDetails', this.localOutputDetails);
  482. }
  483. }
  484. };
  485. </script>
  486. <style></style>