inventoryTable.vue 18 KB

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