inventoryTable.vue 15 KB

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