plan-edit-dialog.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. <template>
  2. <ele-modal :visible.sync="visible" :closed="cancel" :title="`${type == 'add' ? '创建' : '编辑'}采购配料计划`"
  3. custom-class="ele-dialog-form" :close-on-click-modal="false" :close-on-press-escape="false" width="80%">
  4. <el-form :model="formData" ref="formRef" label-width="120px" class="ele-body" :rules="rules">
  5. <el-row :gutter="32">
  6. <el-col :span="12">
  7. <el-form-item label="配料计划名称" prop="name">
  8. <el-input placeholder="请选择" v-model="formData.name"></el-input>
  9. </el-form-item>
  10. </el-col>
  11. <el-col :span="12">
  12. <el-form-item label="备注" prop="remark">
  13. <el-input placeholder="备注" v-model="formData.remark"></el-input>
  14. </el-form-item>
  15. </el-col>
  16. </el-row>
  17. </el-form>
  18. <el-form :model="formData" ref="tableForm">
  19. <ele-pro-table ref="table" :needPage="false" :columns="columns" row-key="id">
  20. <template v-slot:toolbar>
  21. <el-button size="small" type="primary" icon="el-icon-plus" class="ele-btn-icon" @click="showAdd">
  22. 添加销售订单
  23. </el-button>
  24. </template>
  25. <template v-slot:code="{ row }">
  26. <el-input placeholder="请输入" readonly :value="row.code || row.salesOrderCode"></el-input>
  27. </template>
  28. <template v-slot:productionPlanId="{ row }">
  29. <el-link type="primary" v-if="!row.productionPlanId" :underline="false"
  30. @click.native="openVersion(row)">选择</el-link>
  31. </template>
  32. <template v-slot:action="{ row, $index }">
  33. <template>
  34. <el-link type="primary" :underline="false" @click="categorySelect(row)">
  35. 添加物料
  36. </el-link>
  37. <el-popconfirm class="ele-action" title="确定要删除此销售订单吗?" @confirm="remove(row, $index)">
  38. <template v-slot:reference>
  39. <el-link type="danger" :underline="false" icon="el-icon-delete">
  40. 删除
  41. </el-link>
  42. </template>
  43. </el-popconfirm>
  44. </template>
  45. </template>
  46. <!-- 展开内容 -->
  47. <template v-slot:expand="{ row }">
  48. <div style="width:calc(100% - 95px); min-height: 60px; margin-left: 95px;" v-if="row.materialList.length > 0">
  49. <ele-pro-table :toolbar="false" toolsTheme="none" ref="table2" :need-page="false"
  50. :datasource="row.materialList" :columns="columns2" row-key="id">
  51. <template v-slot:sort="{ $index }">
  52. {{ $index }}
  53. </template>
  54. <template v-slot:demandQuantity="{ row }">
  55. <el-input v-model="row.demandQuantity" placeholder="请输入" @input="(value) =>
  56. (row.demandQuantity = value.replace(
  57. /^(-)*(\d+)\.(\d\d\d\d\d\d).*$/,
  58. '$1$2.$3'
  59. ))
  60. "></el-input>
  61. </template>
  62. <template v-slot:purchaseQuantity="{ row }">
  63. <el-input v-model="row.purchaseQuantity" placeholder="请输入" @input="(value) =>
  64. (row.purchaseQuantity = value.replace(
  65. /^(-)*(\d+)\.(\d\d\d\d\d\d).*$/,
  66. '$1$2.$3'
  67. ))
  68. "></el-input>
  69. </template>
  70. <template v-slot:deliveryMethod="{ row }">
  71. <el-select clearable class="ele-block" v-model="row.deliveryMethod" placeholder="请选择">
  72. <el-option label="一次性到货" :value="1" />
  73. <el-option label="分批到货" :value="2" @click.native="handleMethod(row)" />
  74. </el-select>
  75. </template>
  76. <template v-slot:requireDeliveryTime="{ row }">
  77. <el-date-picker style="width: 100%" clearable v-model="row.requireDeliveryTime" type="date"
  78. v-if="row.deliveryMethod == 1" value-format="yyyy-MM-dd" placeholder="请选择日期">
  79. </el-date-picker>
  80. <el-link type="primary" :underline="false" v-if="row.deliveryMethod == 2"
  81. @click.native="handleMethod(row)">
  82. 设置分批时间
  83. </el-link>
  84. </template>
  85. <template v-slot:imgUrl="{ row }">
  86. <fileUpload v-model="row.imgUrl" module="main" :showLib="false" :limit="1" />
  87. </template>
  88. <template v-slot:annex="{ row }">
  89. <fileUpload v-model="row.annex" module="main" :showLib="false" :limit="1" />
  90. </template>
  91. <template v-slot:action="{ row }">
  92. <el-popconfirm class="ele-action" title="确定要删除当前物料吗?" @confirm="remove2(row)">
  93. <template v-slot:reference>
  94. <el-link type="danger" :underline="false" icon="el-icon-delete">
  95. 删除
  96. </el-link>
  97. </template>
  98. </el-popconfirm>
  99. </template>
  100. </ele-pro-table>
  101. </div>
  102. </template>
  103. </ele-pro-table>
  104. </el-form>
  105. <div slot="footer">
  106. <el-button @click="cancel">取消</el-button>
  107. <el-button type="primary" @click="confirm">保存</el-button>
  108. <el-button type="primary" @click="confirm">保存并提交</el-button>
  109. </div>
  110. <saleOrderPop ref="saleOrderRef" @chooseOrder="chooseOrder"></saleOrderPop>
  111. <ProductModal ref="productRefs" @chooseModal="chooseModal" />
  112. <ProductionVersion ref="versionRefs" @changeProduct="changeProduct"></ProductionVersion>
  113. <timeDialog ref="timeDialogRef" @chooseTime="chooseTime"></timeDialog>
  114. </ele-modal>
  115. </template>
  116. <script>
  117. import saleOrderPop from './saleOrderPop.vue'
  118. import ProductModal from './ProductModal.vue'
  119. import { listBomBySalesOrderIds, listBomBySalesOrderId, save, getById } from '@/api/materialPlan/index';
  120. import ProductionVersion from '@/components/CreatePlan/ProductionVersion2.vue';
  121. import fileUpload from '@/components/upload/fileUpload';
  122. import timeDialog from './timeDialog'
  123. export default {
  124. components: {
  125. saleOrderPop,
  126. ProductModal,
  127. ProductionVersion,
  128. fileUpload,
  129. timeDialog
  130. },
  131. data() {
  132. return {
  133. visible: false,
  134. type: 'add',
  135. tableData: [],
  136. xsId: null,
  137. // 表格列配置
  138. columns: [
  139. {
  140. width: 45,
  141. type: 'expand',
  142. columnKey: 'materialList',
  143. align: 'center',
  144. slot: 'expand'
  145. },
  146. {
  147. width: 50,
  148. label: '序号',
  149. type: 'index',
  150. align: 'center',
  151. slot: 'index'
  152. },
  153. {
  154. prop: 'code',
  155. label: '销售订单号',
  156. slot: 'code',
  157. showOverflowTooltip: true,
  158. align: 'center',
  159. minWidth: 170
  160. },
  161. {
  162. prop: 'customerName',
  163. label: '客户名称',
  164. align: 'center',
  165. showOverflowTooltip: true
  166. },
  167. {
  168. prop: 'deliveryNum',
  169. label: '客户代号',
  170. align: 'center',
  171. showOverflowTooltip: true
  172. },
  173. {
  174. prop: 'productCode',
  175. label: '产品编码',
  176. align: 'center',
  177. showOverflowTooltip: true,
  178. minWidth: 140
  179. },
  180. {
  181. prop: 'productName',
  182. label: '产品名称',
  183. align: 'center',
  184. minWidth: 120
  185. },
  186. {
  187. prop: 'model',
  188. label: '型号',
  189. align: 'center',
  190. minWidth: 120
  191. },
  192. {
  193. prop: 'brandNo',
  194. label: '牌号',
  195. align: 'center'
  196. },
  197. {
  198. prop: 'deliveryTime',
  199. label: '交付日期',
  200. align: 'center',
  201. showOverflowTooltip: true
  202. },
  203. {
  204. prop: 'contractNum',
  205. label: '合同数量',
  206. align: 'center'
  207. },
  208. {
  209. prop: 'lackNum',
  210. label: '欠交数量',
  211. align: 'center'
  212. },
  213. {
  214. prop: 'productionPlanId',
  215. label: '工艺路线',
  216. slot: 'productionPlanId',
  217. align: 'center',
  218. minWidth: 110
  219. },
  220. {
  221. columnKey: 'action',
  222. label: '操作',
  223. width: 150,
  224. align: 'center',
  225. resizable: false,
  226. slot: 'action',
  227. showOverflowTooltip: true
  228. }
  229. ],
  230. columns2: [
  231. {
  232. width: 50,
  233. label: '序号',
  234. prop: 'sort',
  235. slot: 'sort',
  236. align: 'center',
  237. },
  238. {
  239. label: '物料名称',
  240. prop: 'name',
  241. align: 'center',
  242. },
  243. {
  244. label: '物料编码',
  245. prop: 'code',
  246. align: 'center',
  247. },
  248. {
  249. label: '牌号',
  250. prop: 'brandNum',
  251. align: 'center',
  252. },
  253. {
  254. label: '型号',
  255. prop: 'modelType',
  256. align: 'center',
  257. },
  258. {
  259. prop: 'packingCountBase',
  260. label: '计量库存',
  261. sortable: 'custom',
  262. align: 'center',
  263. },
  264. {
  265. label: '计量单位',
  266. prop: 'unit',
  267. align: 'center',
  268. },
  269. {
  270. label: '需求数量',
  271. slot: 'demandQuantity',
  272. action: 'demandQuantity',
  273. align: 'center',
  274. },
  275. {
  276. label: '采购数量',
  277. slot: 'purchaseQuantity',
  278. action: 'purchaseQuantity',
  279. align: 'center',
  280. },
  281. {
  282. label: '到货方式',
  283. slot: 'deliveryMethod',
  284. action: 'deliveryMethod',
  285. align: 'center',
  286. minWidth: 140
  287. },
  288. {
  289. label: '要求到货时间',
  290. slot: 'requireDeliveryTime',
  291. action: 'requireDeliveryTime',
  292. align: 'center',
  293. minWidth: 140
  294. },
  295. {
  296. label: '图纸',
  297. slot: 'imgUrl',
  298. action: ' imgUrl',
  299. align: 'center',
  300. },
  301. {
  302. label: '附件',
  303. slot: 'annex',
  304. action: ' annex',
  305. align: 'center',
  306. },
  307. {
  308. columnKey: 'action',
  309. label: '操作',
  310. width: 70,
  311. align: 'center',
  312. resizable: false,
  313. slot: 'action',
  314. showOverflowTooltip: true
  315. }
  316. ],
  317. rules: {
  318. name: [
  319. {
  320. required: true,
  321. message: '请输入配料计划名称',
  322. trigger: ['blur', 'change']
  323. }
  324. ],
  325. },
  326. formData: {
  327. name: '',
  328. remark: '',
  329. detailRemoveIds: [],
  330. materialRemoveIds: []
  331. },
  332. };
  333. },
  334. methods: {
  335. async open(type, row) {
  336. this.type = type;
  337. if (row) {
  338. this.getDetail(row.id)
  339. }
  340. this.visible = true;
  341. },
  342. getDetail(id) {
  343. getById(id).then(res => {
  344. this.$set(this.formData, 'name', res.name)
  345. this.$set(this.formData, 'remark', res.remark)
  346. this.formData['id'] = res.id
  347. this.$refs.table.setData([...res.salesOrderList]);
  348. })
  349. },
  350. confirm() {
  351. this.$refs.formRef.validate(async (value) => {
  352. if (value) {
  353. let _arr = this.$refs.table.getData() ?? []
  354. if (_arr.length == 0) {
  355. this.$message.info('请添加销售订单');
  356. return false
  357. }
  358. let _arr2 = []
  359. _arr2 = _arr.map(m => {
  360. if (Object.prototype.hasOwnProperty.call(m, "salesOrderId") && m.salesOrderId) {
  361. } else {
  362. m.salesOrderId = m.id
  363. m.salesOrderCode = m.code
  364. delete m.id
  365. delete m.code
  366. }
  367. return {
  368. ...m,
  369. }
  370. })
  371. this.formData['type'] = 1
  372. this.formData['salesOrderList'] = _arr2
  373. await save(this.formData);
  374. this.$message.success('保存成功!');
  375. this.$emit('success');
  376. this.cancel();
  377. }
  378. });
  379. },
  380. cancel() {
  381. this.visible = false;
  382. this.formData = {};
  383. this.formData.detailRemoveIds = []
  384. this.formData.materialRemoveIds = []
  385. this.$refs.table.setData([]);
  386. this.$refs.formRef.resetFields();
  387. },
  388. datasource({ }) {
  389. return []
  390. },
  391. reload() {
  392. this.$refs.table.reload();
  393. },
  394. showAdd() {
  395. this.tableData = this.$refs.table.getData();
  396. this.$refs.saleOrderRef.open(this.tableData)
  397. },
  398. chooseOrder(list) {
  399. let salesOrderIds = []
  400. list.map((m => {
  401. salesOrderIds.push(m.id)
  402. return {
  403. ...m,
  404. }
  405. }))
  406. if (salesOrderIds.length > 0) {
  407. listBomBySalesOrderIds({ salesOrderIds: salesOrderIds }).then((res) => {
  408. this.$refs.table.setData([...this.tableData, ...res]);
  409. this.$refs.table.toggleRowExpansionAll()
  410. })
  411. }
  412. },
  413. remove(row, index) {
  414. this.formData.detailRemoveIds.push(row.id)
  415. let _arr = this.$refs.table.getData() || [];
  416. _arr.splice(index, 1);
  417. this.$refs.table.setData([..._arr]);
  418. },
  419. categorySelect(row) {
  420. this.$refs.productRefs.open(row.materialList, row)
  421. },
  422. chooseModal(data, current) {
  423. data.map((m => {
  424. m.detailId = current.id
  425. return {
  426. ...m,
  427. }
  428. }))
  429. let tableList = []
  430. tableList = this.$refs.table.getData()
  431. tableList.forEach(e => {
  432. if (e.id == current.id) {
  433. if (e.materialList.length == 0) {
  434. e.materialList = data
  435. } else {
  436. e.materialList = [...e.materialList, ...data]
  437. }
  438. }
  439. })
  440. this.$refs.table.setData([...tableList]);
  441. },
  442. remove2(row) {
  443. const data = this.$refs.table.getData() ?? [];
  444. this.formData.materialRemoveIds.push(row.id)
  445. data.forEach((e) => {
  446. if (row.detailId == e.id) {
  447. e.materialList = e.materialList.filter((d) => d.id !== row.id);
  448. }
  449. })
  450. this.$refs.table.setData([...data])
  451. this.$forceUpdate()
  452. },
  453. openVersion(row) {
  454. this.xsId = row.id
  455. this.$refs.versionRefs.open();
  456. },
  457. changeProduct(data) {
  458. let param = {
  459. salesOrderIds: [this.xsId],
  460. produceRoutingId: data.id
  461. }
  462. listBomBySalesOrderId(param).then((res) => {
  463. let tableList = []
  464. tableList = this.$refs.table.getData()
  465. tableList.forEach(e => {
  466. if (e.id == this.xsId) {
  467. res.map(m => {
  468. m.detailId = this.xsId
  469. return {
  470. ...m,
  471. }
  472. })
  473. e.materialList = res
  474. this.$nextTick(() => {
  475. this.$refs.table.setData([...tableList]);
  476. this.$refs.table.toggleRowExpansionAll()
  477. })
  478. }
  479. })
  480. })
  481. },
  482. handleMethod(row) {
  483. this.$refs.timeDialogRef.open(row)
  484. },
  485. chooseTime(current , timeList) {
  486. let tableList = []
  487. tableList = this.$refs.table.getData()
  488. tableList.forEach(e => {
  489. if (e.id == current.detailId) {
  490. console.log(e)
  491. e.materialList.forEach(m => {
  492. if(m.id == current.id) {
  493. m.timeList = timeList
  494. }
  495. })
  496. }
  497. })
  498. this.$refs.table.setData([...tableList]);
  499. }
  500. }
  501. };
  502. </script>
  503. <style lang="scss" scoped>
  504. :deep(.el-table__expanded-cell) {
  505. padding-bottom: 30px !important;
  506. border-bottom: 12px solid #CCFFCC !important;
  507. }
  508. </style>