inventoryTable.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. <template>
  2. <el-form ref="form" :model="form" :rules="rules">
  3. <ele-pro-table
  4. ref="table"
  5. :needPage="false"
  6. :columns="columns"
  7. :toolkit="[]"
  8. max-height="500px"
  9. :datasource="form.datasource"
  10. cache-key="systemRoleTable17"
  11. class="time-form"
  12. :selection.sync="selection"
  13. >
  14. <template v-slot:files="scope">
  15. <el-form-item prop="files">
  16. <fileMain v-model="scope.row.files" type="view"></fileMain>
  17. </el-form-item>
  18. </template>
  19. <template v-slot:taskName="scope">
  20. <el-form-item
  21. style="margin-bottom: 20px"
  22. :prop="'datasource.' + scope.$index + '.taskName'"
  23. >
  24. <el-input
  25. v-model="scope.row.taskName"
  26. placeholder="请选择"
  27. style="width: 60%; margin-right: 10px"
  28. disabled
  29. ></el-input>
  30. <el-button
  31. v-if="scope.row.productCode"
  32. size="small"
  33. type="primary"
  34. @click.native="handleTaskinstance(scope.row, scope.$index)"
  35. >选择
  36. </el-button>
  37. </el-form-item>
  38. </template>
  39. <template v-slot:supplierIds="scope">
  40. <el-form-item prop="supplierIds">
  41. <el-select
  42. v-model="scope.row['supplierIds']"
  43. clearable
  44. filterable
  45. multiple
  46. collapse-tags
  47. >
  48. <el-option
  49. v-for="i in scope.row.supplierList"
  50. :key="i.id"
  51. :value="i.id"
  52. :label="i.name"
  53. ></el-option>
  54. </el-select>
  55. </el-form-item>
  56. </template>
  57. <!-- 操作列 -->
  58. <!-- <template v-slot:[item.slot]="scope" v-for="item in supplierList">
  59. <el-form-item
  60. style="margin-bottom: 20px"
  61. :prop="'datasource.' + scope.$index + '.' + item.prop"
  62. :rules="{
  63. required: true,
  64. message: '请输入',
  65. trigger: 'blur'
  66. }"
  67. >
  68. <el-input
  69. type="input"
  70. v-model="scope.row[item.prop]"
  71. placeholder="请输入"
  72. ></el-input>
  73. </el-form-item>
  74. </template>
  75. <template v-slot:[item.headerSlot]="scope" v-for="item in supplierList">
  76. <el-form-item style="margin-bottom: 20px">
  77. <span>{{ item.label }}</span>
  78. <fileUpload
  79. v-model="item.files"
  80. module="main"
  81. :showLib="false"
  82. :limit="1"
  83. />
  84. </el-form-item>
  85. </template> -->
  86. <template v-slot:add="scope">
  87. <el-form-item style="margin-bottom: 20px">
  88. <el-button type="primary" @click="openSupplier(scope.row)"
  89. >新增报价单</el-button
  90. >
  91. </el-form-item>
  92. </template>
  93. <template v-slot:action="scope">
  94. <el-popconfirm
  95. class="ele-action"
  96. title="确定要删除吗?"
  97. @confirm="remove(scope.$index, scope.row.productCode)"
  98. >
  99. <template v-slot:reference>
  100. <el-link type="danger" :underline="false" icon="el-icon-delete">
  101. 删除
  102. </el-link>
  103. </template>
  104. </el-popconfirm>
  105. </template>
  106. </ele-pro-table>
  107. <taskinstance-dialog
  108. ref="taskinstanceDialogRef"
  109. v-if="taskinstanceDialogFlag"
  110. @saveTaskInstance="saveTaskInstance"
  111. :visible.sync="taskinstanceDialogFlag"
  112. ></taskinstance-dialog>
  113. </el-form>
  114. </template>
  115. <script>
  116. import { numberReg } from 'ele-admin';
  117. import dictMixins from '@/mixins/dictMixins';
  118. import fileUpload from '@/components/upload/fileUpload';
  119. import { getFile } from '@/api/system/file';
  120. import { getInventoryTotalAPI } from '@/api/wms';
  121. import { getByCode } from '@/api/system/dictionary-data';
  122. import fileMain from '@/components/addDoc/index.vue';
  123. import taskinstanceDialog from '@/BIZComponents/procedure/taskinstanceDialog.vue';
  124. export default {
  125. mixins: [dictMixins],
  126. components: {
  127. fileMain,
  128. fileUpload,
  129. taskinstanceDialog
  130. },
  131. props: {
  132. acceptUnpack: {
  133. default: ''
  134. },
  135. isSupplier: {
  136. default: true
  137. }
  138. },
  139. data() {
  140. const defaultForm = {
  141. key: null,
  142. endTime: '',
  143. isFirst: 0,
  144. name: ''
  145. };
  146. return {
  147. taskinstanceDialogFlag: false,
  148. numberReg,
  149. defaultForm,
  150. supplierList: [],
  151. selection: [],
  152. // resultList:'',
  153. form: {
  154. datasource: []
  155. },
  156. dictList: {},
  157. files: [],
  158. rules: {}
  159. };
  160. },
  161. computed: {
  162. canHandl() {
  163. return this.form.datasource.length;
  164. },
  165. columns() {
  166. return [
  167. {
  168. width: 50,
  169. label: '序号',
  170. type: 'index',
  171. columnKey: 'index',
  172. align: 'center',
  173. fixed: 'left'
  174. },
  175. {
  176. width: 45,
  177. type: 'selection',
  178. columnKey: 'selection',
  179. align: 'center',
  180. fixed: 'left',
  181. show: this.isSupplier
  182. },
  183. {
  184. minWidth: 180,
  185. slot: 'add',
  186. label: '新增报价',
  187. showOverflowTooltip: true,
  188. fixed: 'left',
  189. align: 'center'
  190. },
  191. {
  192. minWidth: 100,
  193. label: '状态',
  194. fixed: 'left',
  195. filters: [
  196. { value: 0, text: '未核价' },
  197. { value: 1, text: '部分核价' },
  198. { value: 2, text: '全部核价完成' }
  199. ],
  200. filterMethod: this.isInquiryFn,
  201. // sortable: true,
  202. formatter: (row, column) => {
  203. return row.isInquiry == 1
  204. ? '部分核价'
  205. : row.isInquiry == 2
  206. ? '全部核价完成'
  207. : '未核价';
  208. },
  209. align: 'center'
  210. },
  211. {
  212. minWidth: 100,
  213. prop: 'productCategoryName',
  214. label: '分类',
  215. slot: 'productCategoryName',
  216. showOverflowTooltip: true,
  217. fixed: 'left',
  218. align: 'center'
  219. },
  220. {
  221. minWidth: 100,
  222. prop: 'productCode',
  223. label: '编码',
  224. fixed: 'left',
  225. slot: 'productCode',
  226. showOverflowTooltip: true,
  227. align: 'center'
  228. },
  229. {
  230. minWidth: 140,
  231. prop: 'productName',
  232. fixed: 'left',
  233. label: '名称',
  234. slot: 'productName',
  235. headerSlot: 'productNameHeader',
  236. showOverflowTooltip: true,
  237. align: 'center'
  238. },
  239. {
  240. minWidth: 200,
  241. prop: 'supplierIds',
  242. label: '供应商选择',
  243. slot: 'supplierIds',
  244. showOverflowTooltip: true,
  245. align: 'center',
  246. filters: this.supplierList,
  247. filterMethod: this.filterMethod
  248. },
  249. {
  250. minWidth: 100,
  251. prop: 'productBrand',
  252. label: '牌号',
  253. slot: 'productBrand',
  254. showOverflowTooltip: true,
  255. align: 'center'
  256. },
  257. {
  258. minWidth: 80,
  259. prop: 'totalCount',
  260. label: '数量',
  261. slot: 'totalCount',
  262. showOverflowTooltip: true,
  263. align: 'center'
  264. },
  265. {
  266. width: 150,
  267. prop: 'inquiryNum',
  268. label: '已核价数量',
  269. align: 'center'
  270. },
  271. {
  272. minWidth: 80,
  273. prop: 'availableCountBase',
  274. label: '库存数量',
  275. slot: 'availableCountBase',
  276. align: 'center'
  277. },
  278. {
  279. width: 120,
  280. prop: 'totalWeight',
  281. label: '重量',
  282. slot: 'totalWeight',
  283. align: 'center'
  284. },
  285. {
  286. width: 150,
  287. prop: 'inquiryWeight',
  288. label: '已核价重量',
  289. align: 'center'
  290. },
  291. {
  292. minWidth: 220,
  293. prop: 'taskName',
  294. label: '工序',
  295. slot: 'taskName',
  296. align: 'center'
  297. },
  298. {
  299. width: 110,
  300. prop: 'batchNo',
  301. label: '批次号',
  302. slot: 'batchNo',
  303. align: 'center'
  304. },
  305. {
  306. prop: 'provenance',
  307. label: '产地',
  308. slot: 'provenance',
  309. align: 'center',
  310. minWidth: 200,
  311. showOverflowTooltip: true,
  312. formatter: (row, column) => {
  313. return row.provenance && row.provenance.length
  314. ? row.provenance
  315. .map((item) => this.getDictValue('产地', item ))
  316. .join(',')
  317. : '';
  318. }
  319. },
  320. {
  321. minWidth: 80,
  322. prop: 'measuringUnit',
  323. label: '单位',
  324. slot: 'measuringUnit',
  325. showOverflowTooltip: true,
  326. align: 'center'
  327. },
  328. {
  329. minWidth: 130,
  330. prop: 'modelType',
  331. label: '型号',
  332. slot: 'modelType',
  333. showOverflowTooltip: true,
  334. align: 'center'
  335. },
  336. {
  337. minWidth: 120,
  338. prop: 'specification',
  339. label: '规格',
  340. slot: 'specification',
  341. showOverflowTooltip: true,
  342. align: 'center'
  343. },
  344. // {
  345. // width: 120,
  346. // prop: 'singleWeight',
  347. // label: '单重',
  348. // slot: 'singleWeight',
  349. // align: 'center'
  350. // },
  351. {
  352. minWidth: 120,
  353. prop: 'imgCode',
  354. align: 'center',
  355. label: '图号/件号',
  356. showOverflowTooltip: true
  357. },
  358. {
  359. minWidth: 120,
  360. prop: 'produceType',
  361. align: 'center',
  362. label: '属性类型',
  363. showOverflowTooltip: true,
  364. formatter: (row, column) => {
  365. return row.produceType && row.produceType.length
  366. ? row.produceType
  367. .map((item) => this.getDictV('productionType', item))
  368. .join(',')
  369. : '';
  370. }
  371. },
  372. {
  373. minWidth: 120,
  374. prop: 'approvalNumber',
  375. align: 'center',
  376. label: '批准文号',
  377. showOverflowTooltip: true
  378. },
  379. {
  380. minWidth: 120,
  381. prop: 'packingSpecification',
  382. align: 'center',
  383. label: '包装规格',
  384. showOverflowTooltip: true
  385. },
  386. // {
  387. // width: 130,
  388. // prop: 'brand',
  389. // label: '品牌',
  390. // slot: 'brand'
  391. // },
  392. {
  393. minWidth: 170,
  394. prop: 'expectReceiveDate',
  395. label: '到货日期',
  396. slot: 'expectReceiveDate',
  397. showOverflowTooltip: true,
  398. align: 'center'
  399. },
  400. {
  401. minWidth: 140,
  402. prop: 'files',
  403. label: '附件',
  404. slot: 'files',
  405. align: 'center'
  406. },
  407. {
  408. minWidth: 220,
  409. prop: 'remark',
  410. label: '备注',
  411. slot: 'remark',
  412. showOverflowTooltip: true,
  413. align: 'center'
  414. }
  415. // {
  416. // columnKey: 'action',
  417. // label: '操作',
  418. // width: 120,
  419. // align: 'center',
  420. // resizable: false,
  421. // slot: 'action',
  422. // fixed: 'right',
  423. // showOverflowTooltip: true
  424. // }
  425. ];
  426. }
  427. },
  428. created() {
  429. this.requestDict('产地');
  430. this.getDictList('productionType');
  431. },
  432. methods: {
  433. getDictV(code, val) {
  434. if (!this.dictList[code]) return '';
  435. return this.dictList[code].find((item) => item.value == val)?.label;
  436. },
  437. async getDictList(code) {
  438. let { data: res } = await getByCode(code);
  439. this.dictList[code] = res.map((item) => {
  440. let values = Object.keys(item);
  441. return {
  442. value: values[0],
  443. label: item[values[0]]
  444. };
  445. });
  446. },
  447. setIsInquiry(list) {
  448. // return;
  449. this.form.datasource.forEach((productItem, index) => {
  450. //产品清单
  451. let isInquiry = 0,
  452. totalCountS = [];
  453. list.forEach((item) => {
  454. //供应商列表
  455. item.resultList.forEach((val) => {
  456. //供应商产品
  457. if (val.productCode == productItem.productCode&&val.batchNo == productItem.batchNo&&val.taskId == productItem.taskId) {
  458. totalCountS.push(
  459. Number(val.totalCount || 0) +
  460. Number(productItem.doneTotalCount || 0)
  461. );
  462. }
  463. });
  464. });
  465. if (totalCountS.length > 0) {
  466. this.$set(
  467. this.form.datasource[index],
  468. 'isInquiry',
  469. Math.max(...totalCountS) >= productItem.totalCount ? 2 : 1
  470. );
  471. } else {
  472. this.$set(this.form.datasource[index], 'isInquiry', 0);
  473. }
  474. console.log(totalCountS, 'codeS');
  475. });
  476. },
  477. downloadFile(file) {
  478. getFile({ objectName: file.storePath }, file.name);
  479. },
  480. // 返回列表数据
  481. getTableValue() {
  482. let comitDatasource = this.form.datasource;
  483. if (comitDatasource.length === 0) return [];
  484. comitDatasource.forEach((v) => {
  485. v.totalPrice = (v.totalCount * v.singlePrice)?.toFixed(2) || 0;
  486. v.files = v.files || null;
  487. });
  488. return comitDatasource;
  489. },
  490. filterMethod(value, row, column) {
  491. console.log(value);
  492. console.log(row);
  493. let ids = row.supplierIds;
  494. if (ids.length > 0 && ids.includes(value)) {
  495. return row;
  496. }
  497. },
  498. isInquiryFn(value, row, column) {
  499. if (value == row.isInquiry) {
  500. return row;
  501. }
  502. },
  503. //修改回显
  504. async putTableValue(data) {
  505. if (data && data?.length) {
  506. let supplierList = [],
  507. supplierIds = [];
  508. this.form.datasource = data;
  509. let codeList = this.form.datasource.filter((item) => item.productCode).map((item) => item.productCode);
  510. //获取仓库库存
  511. let inventoryTotalList = await getInventoryTotalAPI(codeList);
  512. this.form.datasource.filter((item) => item.productCode).forEach((item, index) => {
  513. let find =
  514. inventoryTotalList.find((key) => key.code == item.productCode) ||
  515. {};
  516. // item.availableCountBase = find.availableCountBase;
  517. this.$set(
  518. this.form.datasource[index],
  519. 'availableCountBase',
  520. find.availableCountBase
  521. );
  522. supplierList.push(...item.supplierList);
  523. });
  524. supplierIds = Array.from(
  525. new Set(supplierList.map((item) => item.id))
  526. );
  527. this.supplierList = supplierIds.map((id) => {
  528. let data = supplierList.find((item) => item.id == id);
  529. return {
  530. text: data.name,
  531. value: data.id
  532. };
  533. });
  534. console.log(this.supplierList, 'supplierList');
  535. this.$refs.table.reload();
  536. }
  537. },
  538. handleTaskinstance(row, index) {
  539. this.taskinstanceDialogFlag = true;
  540. this.$nextTick(() => {
  541. this.$refs.taskinstanceDialogRef.open(row, index);
  542. });
  543. },
  544. saveTaskInstance(row = {}) {
  545. this.$set(this.form.datasource[row.index], 'taskId', row.id);
  546. this.$set(this.form.datasource[row.index], 'taskName', row.name);
  547. this.$set(
  548. this.form.datasource[row.index],
  549. 'routingId',
  550. row.produceRoutingId
  551. );
  552. },
  553. handleSupplierSelect(row) {
  554. this.$emit('supplierSelect', row);
  555. },
  556. //选择产品
  557. handParent() {
  558. this.$refs.productListRef.open();
  559. },
  560. //选择产品回调
  561. changeParent(obj, idx) {
  562. obj['productBrand'] = obj.brandNum;
  563. obj['productCode'] = obj.code;
  564. obj['productName'] = obj.name;
  565. obj['productCategoryName'] = obj.categoryLevelPath;
  566. obj['productCategoryId'] = obj.categoryLevelId;
  567. this.form.datasource.push(obj);
  568. },
  569. remove(i, productCode) {
  570. if (!this.acceptUnpack) {
  571. this.$message.warning('本采购计划不能拆单');
  572. return;
  573. }
  574. this.form.datasource.splice(i, 1);
  575. this.$emit('delList', productCode);
  576. },
  577. // 清空表格
  578. restTable() {
  579. this.form.datasource = [];
  580. },
  581. openSupplier(row) {
  582. this.$emit('supplierSelect', row);
  583. },
  584. // 添加
  585. handlAdd() {
  586. let item = JSON.parse(JSON.stringify(this.defaultForm));
  587. item.key = this.form.datasource.length + 1;
  588. this.form.datasource.push(item);
  589. },
  590. validateForm(callback) {
  591. //开始表单校验
  592. this.$refs.form.validate((valid) => {
  593. callback(valid);
  594. });
  595. }
  596. }
  597. };
  598. </script>
  599. <style lang="scss" scoped>
  600. .headbox {
  601. display: flex;
  602. justify-content: space-between;
  603. align-items: center;
  604. .amount {
  605. font-size: 14px;
  606. font-weight: bold;
  607. }
  608. }
  609. .time-form .el-form-item {
  610. margin-bottom: 0 !important;
  611. }
  612. ::v-deep .period {
  613. display: flex;
  614. .borderleftnone {
  615. .el-input--medium .el-input__inner {
  616. border-top-right-radius: 0;
  617. border-bottom-right-radius: 0;
  618. }
  619. }
  620. .borderrightnone {
  621. .el-input--medium .el-input__inner {
  622. border-top-left-radius: 0;
  623. border-bottom-left-radius: 0;
  624. }
  625. }
  626. }
  627. ::v-deep .time-form tbody > tr:hover > td {
  628. background-color: transparent !important;
  629. }
  630. ::v-deep .time-form .el-table tr {
  631. background-color: #ffffff;
  632. }
  633. </style>