inventoryTable.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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. :datasource="form.datasource"
  9. cache-key="systemRoleTable17"
  10. class="time-form"
  11. >
  12. <!-- 表头工具栏 -->
  13. <template v-slot:toolbar>
  14. <div class="headbox">
  15. <el-button
  16. size="small"
  17. type="primary"
  18. icon="el-icon-plus"
  19. class="ele-btn-icon"
  20. @click="handlAdd"
  21. >
  22. 新增
  23. </el-button>
  24. </div>
  25. </template>
  26. <template v-slot:technicalDrawings="{ row, $index }">
  27. <el-form-item
  28. style="margin-bottom: 20px"
  29. :prop="'datasource.' + $index + '.technicalDrawings'"
  30. >
  31. <div v-if="row.technicalDrawings && row.technicalDrawings?.length">
  32. <el-link
  33. v-for="link in row.technicalDrawings"
  34. :key="link.id"
  35. type="primary"
  36. :underline="false"
  37. @click="downloadFile(link)"
  38. >
  39. {{ link.name }}</el-link
  40. >
  41. </div>
  42. </el-form-item>
  43. </template>
  44. <template v-slot:remark="{ row, $index }">
  45. <el-form-item
  46. style="margin-bottom: 20px"
  47. :prop="'datasource.' + $index + '.remark'"
  48. >
  49. <el-input
  50. clearable
  51. v-model="row.remark"
  52. type="textarea"
  53. placeholder="请输入"
  54. />
  55. </el-form-item>
  56. </template>
  57. <template v-slot:totalCount="scope">
  58. <el-form-item
  59. style="margin-bottom: 20px"
  60. :prop="'datasource.' + scope.$index + '.totalCount'"
  61. :rules="[
  62. { required: true, message: '请输入数字', trigger: 'blur' },
  63. { validator: validateTotalCount(scope.row), trigger: 'blur' }
  64. ]"
  65. >
  66. <el-input
  67. v-model="scope.row.totalCount"
  68. @input="(val) => changeNum(val, scope.$index)"
  69. ></el-input>
  70. </el-form-item>
  71. </template>
  72. <template v-slot:warehouseId="scope">
  73. <el-form-item
  74. style="margin-bottom: 20px"
  75. :prop="'datasource.' + scope.$index + '.warehouseId'"
  76. :rules="[{ required: true, message: '请选择仓库', trigger: 'blur' }]"
  77. >
  78. <el-select
  79. v-model="scope.row.warehouseId"
  80. placeholder="请选择"
  81. @change="warehouseChange(scope.$index, scope.row)"
  82. >
  83. <el-option
  84. v-for="item in warehouseList"
  85. :key="item.id"
  86. :label="item.name"
  87. :value="item.id"
  88. >
  89. </el-option>
  90. </el-select>
  91. </el-form-item>
  92. </template>
  93. <template v-slot:warehouseNum="scope">
  94. <el-form-item style="margin-bottom: 20px">
  95. {{ scope.row.warehouseNum }}
  96. </el-form-item>
  97. </template>
  98. <template v-slot:headerWarehouseId="{ column }">
  99. <span class="is-required">{{ column.label }}</span>
  100. </template>
  101. <template v-slot:headerTotalCount="{ column }">
  102. <span class="is-required">{{ column.label }}</span>
  103. </template>
  104. <!-- 操作列 -->
  105. <template v-slot:action="scope">
  106. <el-popconfirm
  107. class="ele-action"
  108. title="确定要删除吗?"
  109. @confirm="remove(scope.$index)"
  110. >
  111. <template v-slot:reference>
  112. <el-link type="danger" :underline="false" icon="el-icon-delete">
  113. 删除
  114. </el-link>
  115. </template>
  116. </el-popconfirm>
  117. </template>
  118. </ele-pro-table>
  119. <product-list
  120. ref="productListRef"
  121. :orderId="orderId"
  122. type="purchase"
  123. @changeParent="changeParent"
  124. ></product-list>
  125. </el-form>
  126. </template>
  127. <script>
  128. import { numberReg } from 'ele-admin';
  129. import productList from '@/views/saleManage/saleOrder/invoice/components/product-list.vue';
  130. import dictMixins from '@/mixins/dictMixins';
  131. import { getWarehouseList } from '@/api/saleManage/saleorder';
  132. import store from '@/store';
  133. import { copyObj } from '@/utils/util';
  134. export default {
  135. mixins: [dictMixins],
  136. props: {
  137. orderId: String
  138. },
  139. components: {
  140. productList
  141. },
  142. data() {
  143. const defaultForm = {
  144. key: null,
  145. endTime: '',
  146. isFirst: 0,
  147. name: '',
  148. startTime: '',
  149. workHour: '',
  150. technicalDrawings: []
  151. // warehouseCode:"",
  152. // warehouseId:'',
  153. // warehouseName:'',
  154. };
  155. return {
  156. discountTotalPrice: 0.0,
  157. allPrice: 0.0,
  158. numberReg,
  159. defaultForm,
  160. warehouseList: [],
  161. form: {
  162. datasource: []
  163. },
  164. rules: {},
  165. columns: [
  166. {
  167. width: 45,
  168. type: 'index',
  169. columnKey: 'index',
  170. align: 'center',
  171. fixed: 'left'
  172. },
  173. {
  174. width: 200,
  175. prop: 'productName',
  176. label: '名称',
  177. slot: 'productName'
  178. },
  179. {
  180. width: 120,
  181. prop: 'productCode',
  182. label: '编码',
  183. slot: 'productCode'
  184. },
  185. {
  186. width: 200,
  187. prop: 'productCategoryName',
  188. label: '类型',
  189. slot: 'productCategoryName'
  190. },
  191. {
  192. width: 160,
  193. prop: 'productBrand',
  194. label: '牌号',
  195. slot: 'productBrand'
  196. },
  197. {
  198. width: 120,
  199. prop: 'modelType',
  200. label: '型号',
  201. slot: 'modelType'
  202. },
  203. {
  204. width: 120,
  205. prop: 'specification',
  206. label: '规格',
  207. slot: 'specification'
  208. },
  209. {
  210. width: 200,
  211. prop: 'warehouseId',
  212. label: '仓库名称',
  213. slot: 'warehouseId',
  214. headerSlot: 'headerWarehouseId'
  215. },
  216. {
  217. width: 120,
  218. prop: 'totalCount',
  219. label: '进货数量',
  220. slot: 'totalCount',
  221. headerSlot: 'headerTotalCount'
  222. },
  223. {
  224. width: 120,
  225. prop: 'orderTotalCount',
  226. label: '总数量',
  227. slot: 'orderTotalCount'
  228. },
  229. {
  230. width: 80,
  231. prop: 'measuringUnit',
  232. label: '计量单位',
  233. slot: 'measuringUnit'
  234. },
  235. {
  236. width: 160,
  237. prop: 'singlePrice',
  238. label: '单价',
  239. slot: 'singlePrice'
  240. },
  241. {
  242. width: 120,
  243. prop: 'totalPrice',
  244. label: '合计',
  245. slot: 'totalPrice'
  246. },
  247. {
  248. width: 80,
  249. prop: 'deliveryDays',
  250. label: '交期(天)',
  251. slot: 'deliveryDays'
  252. },
  253. {
  254. width: 160,
  255. prop: 'deliveryDeadline',
  256. label: '交期截止日期',
  257. slot: 'deliveryDeadline'
  258. },
  259. {
  260. width: 200,
  261. prop: 'guaranteePeriod',
  262. label: '质保期',
  263. slot: 'guaranteePeriod'
  264. },
  265. {
  266. width: 160,
  267. prop: 'guaranteePeriodDeadline',
  268. label: '质保截止日期',
  269. slot: 'guaranteePeriodDeadline'
  270. },
  271. {
  272. width: 130,
  273. prop: 'technicalAnswerName',
  274. label: '技术答疑人',
  275. slot: 'technicalAnswerName'
  276. },
  277. {
  278. width: 220,
  279. prop: 'technicalParams',
  280. label: '技术参数',
  281. slot: 'technicalParams'
  282. },
  283. {
  284. width: 240,
  285. prop: 'technicalDrawings',
  286. label: '技术图纸',
  287. slot: 'technicalDrawings'
  288. },
  289. {
  290. width: 220,
  291. prop: 'remark',
  292. label: '备注',
  293. slot: 'remark'
  294. },
  295. {
  296. columnKey: 'action',
  297. label: '操作',
  298. width: 120,
  299. align: 'center',
  300. resizable: false,
  301. slot: 'action',
  302. fixed: 'right',
  303. showOverflowTooltip: true
  304. }
  305. ]
  306. };
  307. },
  308. created() {
  309. getWarehouseList().then((res) => {
  310. this.warehouseList = res;
  311. });
  312. },
  313. computed: {},
  314. methods: {
  315. async warehouseChange(index, row) {
  316. let warehouseIds =
  317. this.form.datasource
  318. .filter(
  319. (item, i) => row.productCode == item.productCode && index != i
  320. )
  321. .map((item) => item.warehouseId) || [];
  322. const data = this.warehouseList.find(
  323. (item) => item.id == row.warehouseId
  324. );
  325. if (warehouseIds.length > 0 && warehouseIds.includes(row.warehouseId)) {
  326. row.warehouseId = '';
  327. return this.$message.error('同一个产品不能选择相同的仓库');
  328. }
  329. this.$set(this.form.datasource[index], 'warehouseName', data.name);
  330. this.$set(this.form.datasource[index], 'warehouseCode', data.code);
  331. },
  332. //修改数量更新合计
  333. changeNum(val, index) {
  334. this.$set(
  335. this.form.datasource[index],
  336. 'totalPrice',
  337. (Number(this.form.datasource[index].singlePrice) * val).toFixed(2)
  338. );
  339. },
  340. //选择产品回调
  341. changeParent(obj, idx) {
  342. obj.orderTotalCount = obj.orderTotalCount || obj.totalCount;
  343. obj.id = '';
  344. this.$set(
  345. this.form.datasource,
  346. this.form.datasource.length,
  347. copyObj(obj)
  348. );
  349. },
  350. validateTotalCount(row) {
  351. return (rule, value, callback) => {
  352. if (isNaN(value) || Number(value) <= 0) {
  353. this.$message.error('请输入大于0的数');
  354. callback(new Error('请输入大于0的数字'));
  355. } else if (this.getTotalCount(row) > row.orderTotalCount) {
  356. this.$message.error('进货数量不能大于总数量');
  357. callback(new Error('进货数量不能大于总数量'));
  358. } else {
  359. callback();
  360. }
  361. };
  362. },
  363. getTotalCount(row) {
  364. let num = 0;
  365. this.form.datasource
  366. .filter((item) => item.productCode == row.productCode)
  367. .forEach((item) => {
  368. num += Number(item.totalCount);
  369. });
  370. console.log(num);
  371. return num;
  372. },
  373. // 返回列表数据
  374. getTableValue() {
  375. let comitDatasource = this.form.datasource;
  376. if (comitDatasource.length === 0) return [];
  377. comitDatasource.forEach(async (v) => {
  378. v.totalCount = Number(v.totalCount);
  379. v.technicalDrawings = Array.isArray(v.technicalDrawings)
  380. ? v.technicalDrawings
  381. : [];
  382. });
  383. return comitDatasource;
  384. },
  385. getPrice() {
  386. return [this.allPrice];
  387. },
  388. //修改回显
  389. putTableValue(data) {
  390. if (data) {
  391. this.form.datasource = data;
  392. console.log(data);
  393. }
  394. },
  395. remove(i) {
  396. this.form.datasource.splice(i, 1);
  397. this.setSort();
  398. },
  399. // 清空表格
  400. restTable() {
  401. this.form.datasource = [];
  402. },
  403. // 重新排序
  404. setSort() {
  405. this.form.datasource.forEach((n, index) => {
  406. n.key = index + 1;
  407. });
  408. },
  409. // 添加
  410. handlAdd() {
  411. if (!this.orderId) return this.$message.error('请先选择订单');
  412. this.$refs.productListRef.open(this.form.datasource);
  413. },
  414. validateForm(callback) {
  415. //开始表单校验
  416. this.$refs.form.validate((valid) => {
  417. callback(valid);
  418. });
  419. }
  420. }
  421. };
  422. </script>
  423. <style lang="scss" scoped>
  424. .headbox {
  425. display: flex;
  426. justify-content: space-between;
  427. align-items: center;
  428. .amount {
  429. font-size: 14px;
  430. font-weight: bold;
  431. padding-right: 30px;
  432. }
  433. }
  434. .time-form .el-form-item {
  435. margin-bottom: 0 !important;
  436. }
  437. ::v-deep .period {
  438. display: flex;
  439. .borderleftnone {
  440. .el-input--medium .el-input__inner {
  441. border-top-right-radius: 0;
  442. border-bottom-right-radius: 0;
  443. }
  444. }
  445. .borderrightnone {
  446. .el-input--medium .el-input__inner {
  447. border-top-left-radius: 0;
  448. border-bottom-left-radius: 0;
  449. }
  450. }
  451. }
  452. ::v-deep .time-form tbody > tr:hover > td {
  453. background-color: transparent !important;
  454. }
  455. ::v-deep .time-form .el-table tr {
  456. background-color: #ffffff;
  457. }
  458. .pricebox {
  459. display: flex;
  460. justify-content: flex-start;
  461. align-items: center;
  462. font-weight: bold;
  463. }
  464. </style>