index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. <template>
  2. <el-card shadow="always" :body-style="{ padding: '10px' }">
  3. <div class="app-container">
  4. <el-row :gutter="10">
  5. <el-col :span="10">
  6. <div class="table-area">
  7. <el-button
  8. class="mb10"
  9. type="success"
  10. size="small"
  11. @click="handleRefresh"
  12. :icon="loading ? 'el-icon-loading' : 'el-icon-refresh'"
  13. :disabled="loading"
  14. >刷新
  15. </el-button>
  16. <el-table
  17. :data="leftTableData"
  18. border
  19. stripe
  20. @selection-change="handleSelectionChange"
  21. @cell-click="cellClick"
  22. highlight-current-row
  23. >
  24. <!-- <el-table-column type="selection" width="55" /> -->
  25. <el-table-column type="index" label="序号" width="50" />
  26. <el-table-column
  27. align="center"
  28. prop="customerName"
  29. label="客户名称"
  30. >
  31. </el-table-column>
  32. <el-table-column
  33. align="center"
  34. prop="saleOrderNo"
  35. label="销售单号"
  36. >
  37. </el-table-column>
  38. <el-table-column
  39. align="center"
  40. prop="noticeNumber"
  41. label="通知单号"
  42. >
  43. </el-table-column>
  44. <el-table-column
  45. align="center"
  46. prop="noticeDate"
  47. label="开单日期"
  48. >
  49. </el-table-column>
  50. </el-table></div
  51. ></el-col>
  52. <el-col :span="14">
  53. <div class="form-area">
  54. <el-row :gutter="20">
  55. <el-form
  56. :model="form"
  57. ref="form"
  58. label-width="80px"
  59. :inline="true"
  60. size="mini"
  61. :rules="rules"
  62. >
  63. <el-col :span="16">
  64. <el-form-item label="通知单号" prop="noticeNumber">
  65. <div class="text-area">
  66. <span class="mr10">{{ form.noticeNumber }}</span>
  67. <span>{{ form.documentTypeName }}</span>
  68. </div>
  69. </el-form-item>
  70. </el-col>
  71. <el-col :span="8">
  72. <el-form-item label="销售员" prop="salesman">
  73. {{ form.salesman }}
  74. </el-form-item>
  75. </el-col>
  76. <el-col :span="16">
  77. <el-form-item label="客户名称" prop="customerName">
  78. {{ form.customerName }}
  79. </el-form-item>
  80. </el-col>
  81. <el-col :span="8">
  82. <el-form-item label="售货单位" prop="sellingUnit">
  83. {{ form.sellingUnit }}
  84. </el-form-item>
  85. </el-col>
  86. <el-col :span="16">
  87. <el-form-item label="货车信息" prop="truckRegistration">
  88. {{ form.truckRegistration }}
  89. </el-form-item>
  90. </el-col>
  91. <el-col :span="8">
  92. <el-form-item label="发货员" prop="deliveryClerk">
  93. {{ form.deliveryClerk }}
  94. </el-form-item>
  95. </el-col>
  96. <el-col :span="24">
  97. <el-form-item label="备注" prop="dispatchNoteRemark">
  98. {{ form.dispatchNoteRemark }}
  99. </el-form-item>
  100. </el-col>
  101. <el-col :span="12">
  102. <el-form-item label="发货日期" prop="deliveryDate">
  103. <el-date-picker
  104. v-model="form.deliveryDate"
  105. type="date"
  106. size="mini"
  107. placeholder="选择日期"
  108. >
  109. </el-date-picker>
  110. </el-form-item>
  111. </el-col>
  112. <el-col :span="12">
  113. <el-form-item label="发货仓库" prop="deliveryWarehouse">
  114. <el-select
  115. v-model="form.deliveryWarehouse"
  116. clearable
  117. filterable
  118. >
  119. <el-option
  120. v-for="item in warehouseList"
  121. :key="item.id"
  122. :label="item.warehouseName"
  123. :value="item.id"
  124. >
  125. </el-option>
  126. </el-select>
  127. </el-form-item>
  128. </el-col>
  129. <!-- <el-col :span="12">
  130. <el-form-item label="调拨仓库" prop="transferWarehouse">
  131. <el-select
  132. v-model="form.transferWarehouse"
  133. clearable
  134. filterable
  135. >
  136. <el-option
  137. v-for="item in warehouseList"
  138. :key="item.id"
  139. :label="item.warehouseName"
  140. :value="item.id"
  141. >
  142. </el-option>
  143. </el-select>
  144. </el-form-item>
  145. </el-col> -->
  146. <el-col :span="24">
  147. <el-form-item>
  148. <el-button type="primary" @click="outStockHandler"
  149. >出库
  150. </el-button>
  151. <el-button @click="refreshHandler">刷新</el-button>
  152. </el-form-item>
  153. </el-col>
  154. </el-form>
  155. </el-row>
  156. <el-table
  157. :data="saleProductInfoList"
  158. border
  159. stripe
  160. :span-method="objectSpanMethod"
  161. :row-class-name="tableRowClassName"
  162. >
  163. <el-table-column align="center" label="编码" prop="productCode">
  164. </el-table-column>
  165. <el-table-column align="center" label="品名" prop="productName">
  166. </el-table-column>
  167. <el-table-column align="center" label="批号" prop="lotNum" v-if="this.dlotNum">
  168. </el-table-column>
  169. <el-table-column
  170. align="center"
  171. label="规格"
  172. prop="productSpecifications"
  173. >
  174. </el-table-column>
  175. <el-table-column align="center" label="颜色" prop="productColor">
  176. </el-table-column>
  177. <!-- <el-table-column align="center" label="批号" prop="lotNum">
  178. </el-table-column>
  179. <el-table-column align="center" label="等级" prop="levels">
  180. </el-table-column> -->
  181. <el-table-column align="center" label="通知">
  182. <el-table-column
  183. align="center"
  184. label="重量"
  185. prop="actualWeight"
  186. >
  187. </el-table-column>
  188. </el-table-column>
  189. <el-table-column align="center" label="实发">
  190. <!-- <el-table-column
  191. align="center"
  192. label="总箱数"
  193. prop="coutBoxNum"
  194. >
  195. <template slot-scope="scope">
  196. <el-input
  197. v-model="scope.row.coutBoxNum"
  198. size="mini"
  199. @input="iptChange"
  200. ></el-input>
  201. </template>
  202. </el-table-column> -->
  203. <el-table-column
  204. align="center"
  205. label="箱数"
  206. prop="oldActualBoxNum"
  207. >
  208. <template slot-scope="scope">
  209. <el-input
  210. v-model="scope.row.oldActualBoxNum"
  211. size="mini"
  212. @input="iptChange"
  213. ></el-input>
  214. </template>
  215. </el-table-column>
  216. <!-- <el-table-column
  217. align="center"
  218. label="总重量"
  219. prop="coutweight"
  220. >
  221. <template slot-scope="scope">
  222. <el-input
  223. v-model="scope.row.coutweight"
  224. size="mini"
  225. @input="iptChange"
  226. ></el-input>
  227. </template>
  228. </el-table-column> -->
  229. <el-table-column
  230. align="center"
  231. label="重量"
  232. prop="oldActualWeight"
  233. >
  234. <template slot-scope="scope">
  235. <el-input
  236. v-model="scope.row.oldActualWeight"
  237. size="mini"
  238. @input="iptChange"
  239. ></el-input>
  240. </template>
  241. </el-table-column>
  242. </el-table-column>
  243. </el-table>
  244. </div>
  245. </el-col>
  246. </el-row>
  247. </div>
  248. </el-card>
  249. </template>
  250. <script>
  251. import {
  252. productInvoiceList,
  253. saleStorageDetails,
  254. queryDropDownBoxData,
  255. noticeOutStorage,
  256. oldNoticeOutStorage, checkOldInventory,
  257. } from "@/api/tablelist/commonTable";
  258. import { mapState } from "vuex";
  259. export default {
  260. name: "OutStock",
  261. props: [],
  262. dicts: ["billing_type", "document_type"],
  263. components: {},
  264. data() {
  265. return {
  266. spanArr: [], // 用于记录每个 productCode 的跨行信息
  267. loading: false,
  268. dlotNum: false,
  269. currentIndex: "",
  270. form: {
  271. noticeNumber: "", //通知单号
  272. documentType: "", //通知单类型
  273. documentTypeName: "",
  274. salesman: "", //销售员
  275. sellingUnit: "", //售货单位
  276. truckRegistration: "", //货车信息
  277. drawer: "", //开票员
  278. deliveryClerk: "", // 发货员
  279. dispatchNoteRemark: "", //备注
  280. customerName: "", //客户名称
  281. deliveryDate: new Date(), //发货日期
  282. deliveryWarehouse: "", //发货仓库
  283. transferWarehouse: "", //调拨仓库
  284. id: "",
  285. },
  286. leftTableData: [],
  287. warehouseList: [],
  288. saleProductInfoList: [],
  289. rules: {
  290. deliveryDate: [
  291. { required: true, message: "请选择发货日期", trigger: "change" },
  292. ],
  293. deliveryWarehouse: [
  294. { required: true, message: "请选择发货仓库", trigger: "change" },
  295. ],
  296. transferWarehouse: [
  297. { required: true, message: "请选择调拨仓库", trigger: "change" },
  298. ],
  299. },
  300. };
  301. },
  302. methods: {
  303. iptChange(value) {
  304. console.log(value);
  305. this.$forceUpdate(); //强制刷新
  306. },
  307. tableRowClassName({ row, rowIndex }) {
  308. if (!row.actualWeight && row.actualWeight != 0) {
  309. return "warning-row";
  310. }
  311. },
  312. objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  313. // 重量
  314. if (columnIndex === 6 || columnIndex === 7 || columnIndex === 9) {
  315. const prevRow2 = this.saleProductInfoList[rowIndex - 1]; //上一行数据
  316. let nextRow2 = this.saleProductInfoList[rowIndex + 1]; //下一行数据
  317. // 当上一行的数据等于当前行数据时,当前行单元格隐藏
  318. if (
  319. prevRow2 &&
  320. prevRow2.productCode == row.productCode &&
  321. prevRow2.productColor == row.productColor
  322. ) {
  323. return { rowspan: 0, colspan: 0 };
  324. } else {
  325. // 反之,则循环判断若下一行数据等于当前行数据,则当前行开始进行合并单元格
  326. let countRowspan2 = 1; //用于合并计数多少单元格
  327. while (
  328. nextRow2 &&
  329. nextRow2.productCode == row.productCode &&
  330. nextRow2.productColor == row.productColor
  331. ) {
  332. nextRow2 = this.saleProductInfoList[++countRowspan2 + rowIndex];
  333. }
  334. if (countRowspan2 > 1) {
  335. // this.saleProductInfoList[rowIndex].coutBoxNum = 9;
  336. return { rowspan: countRowspan2, colspan: 1 };
  337. }
  338. }
  339. }
  340. },
  341. // 刷新回调
  342. async handleRefresh() {
  343. this.loading = true;
  344. await this.initData();
  345. await this.initWarehouse();
  346. this.loading = false;
  347. },
  348. // 左侧表格点击回调
  349. cellClick(row, column, cell, event) {
  350. this.currentIndex = this.leftTableData.findIndex(
  351. (item) => item.id == row.id
  352. );
  353. this.initFormData();
  354. },
  355. // 刷新回调
  356. refreshHandler() {
  357. this.initFormData();
  358. },
  359. // 出库回调
  360. outStockHandler() {
  361. this.$refs.form.validate(async (valid) => {
  362. if (valid) {
  363. this.$confirm("是否确认出库?", "提示", {
  364. confirmButtonText: "确定",
  365. cancelButtonText: "取消",
  366. type: "warning",
  367. })
  368. .then(async () => {
  369. let payLoad = { ...this.form };
  370. payLoad.oldProductInvoiceList = this.saleProductInfoList;
  371. payLoad.transferWarehouse = payLoad.deliveryWarehouse;
  372. payLoad.saleOrderNo =
  373. this.leftTableData[this.currentIndex || 0].saleOrderNo;
  374. if (!this.form.id) {
  375. return;
  376. }
  377. delete payLoad.documentTypeName;
  378. //校验库存是否足够
  379. let res1 = await checkOldInventory(payLoad);
  380. //等于200 可以进行老库存出库
  381. if (res1.code == 200) {
  382. if(res1.isG==1){
  383. this.$confirm(res1.msg, "库存不足提示", {
  384. confirmButtonText: "确定",
  385. cancelButtonText: "取消",
  386. type: "warning",
  387. })
  388. .then(async () => {
  389. this.$message.success("出库成功");
  390. let res = await oldNoticeOutStorage(payLoad);
  391. if (res.code == 200) {
  392. this.$message.success("出库成功");
  393. this.currentIndex = 0;
  394. await this.initData();
  395. this.refreshHandler();
  396. } else {
  397. this.$message.error(res.msg);
  398. }
  399. }).catch(() => {
  400. this.$message({
  401. type: "info",
  402. message: "已取消出库",
  403. });
  404. });
  405. }else {
  406. let res = await oldNoticeOutStorage(payLoad);
  407. if (res.code == 200) {
  408. this.$message.success("出库成功");
  409. this.currentIndex = 0;
  410. await this.initData();
  411. this.refreshHandler();
  412. } else {
  413. this.$message.error(res.msg);
  414. }
  415. }
  416. } else {
  417. console.log("当前code",res1);
  418. }
  419. })
  420. .catch(() => {
  421. this.$message({
  422. type: "info",
  423. message: "已取消出库",
  424. });
  425. });
  426. } else {
  427. return false;
  428. }
  429. });
  430. },
  431. handleSelectionChange() {},
  432. // 初始化仓库选项数据
  433. async initWarehouse() {
  434. try {
  435. let payload = [
  436. {
  437. basicMap: {
  438. tableName: "warehouse",
  439. },
  440. conditionMap: {
  441. warehouse_type: ["1"],
  442. },
  443. },
  444. ];
  445. let res = await queryDropDownBoxData(payload);
  446. if (res.code == 200) {
  447. this.warehouseList = res.data.resultMap?.warehouse || [];
  448. } else {
  449. throw new Error(res.msg);
  450. }
  451. } catch (error) {}
  452. },
  453. // 初始化数据
  454. async initData() {
  455. try {
  456. let payload = {
  457. isEnablePaging: false,
  458. status: 1,
  459. };
  460. let res = await productInvoiceList(payload);
  461. if (res.code == 200) {
  462. this.leftTableData = res.rows;
  463. if (this.leftTableData.length > 0) {
  464. this.currentIndex = 0;
  465. this.initFormData();
  466. }
  467. } else {
  468. throw new Error(res.msg);
  469. }
  470. } catch (error) {}
  471. },
  472. // 根据字典获取文件类型
  473. getdocumentTypeName(value) {
  474. return (
  475. this.dict.type.document_type.find((item) => {
  476. return item.value === value;
  477. })?.label || ""
  478. );
  479. },
  480. // 加载表单数据
  481. async initFormData() {
  482. // let { id, customerName } = this.leftTableData[this.currentIndex];
  483. let id = false,
  484. customerName;
  485. if (this.leftTableData[this.currentIndex]) {
  486. id = this.leftTableData[this.currentIndex].id;
  487. customerName = this.leftTableData[this.currentIndex].customerName;
  488. }
  489. if (!id) {
  490. //重置表单数据
  491. Object.assign(this.form, {
  492. noticeNumber: "", //通知单号
  493. documentType: "", //通知单类型
  494. documentTypeName: "", //通知单类型 名
  495. salesman: "", //销售员
  496. sellingUnit: "", //售货单位
  497. truckRegistration: "", //货车信息
  498. dispatchNoteRemark: "", //备注
  499. customerName: "", //客户名称
  500. deliveryClerk: "", //发货员
  501. id: "",
  502. });
  503. return;
  504. }
  505. try {
  506. let res = await saleStorageDetails(id);
  507. if (res.code == 200) {
  508. let {
  509. noticeNumber, //通知单号
  510. documentType, //通知单类型
  511. salesman, //销售员
  512. sellingUnit, //售货单位
  513. truckRegistration, //货车信息
  514. drawer, //开票员
  515. dispatchNoteRemark, //备注
  516. saleProductInfoList, //产品信息
  517. id,
  518. } = res.data;
  519. let documentTypeName = this.getdocumentTypeName(documentType);
  520. // let list = saleProductInfoList.sort( (a,b)=>{
  521. // let {productColor : colorA,productCode :codeA}=a
  522. // let {productColor : colorB,productCode : codeB}=b
  523. // return (colorA+codeA)-(colorB-codeB)
  524. // })
  525. this.saleProductInfoList = saleProductInfoList;
  526. // 使用 reduce 方法来累加相同 productCode 和 productColor 的第一条数据的 boxNum
  527. const codeColorSums = this.saleProductInfoList.reduce(
  528. (acc, curr, index) => {
  529. // 创建一个用于组合 productCode 和 productColor 的键
  530. const key = `${curr.productCode}-${curr.productColor}`;
  531. // 检查当前 key 是否已经存在
  532. if (!acc[key]) {
  533. // 如果不存在,添加 key 作为键,并将 boxNum 设置为当前值
  534. acc[key] = {
  535. firstIndex: index,
  536. sum: curr.boxNum,
  537. weight: curr.weight,
  538. count: 1,
  539. };
  540. } else {
  541. acc[key].count++; // 增加计数
  542. acc[key].sum += curr.boxNum;
  543. acc[key].weight += curr.weight;
  544. }
  545. return acc;
  546. },
  547. {}
  548. );
  549. this.saleProductInfoList.forEach((item, index) => {
  550. if (codeColorSums[`${item.productCode}-${item.productColor}`]) {
  551. item.coutBoxNum =
  552. codeColorSums[`${item.productCode}-${item.productColor}`].sum;
  553. item.coutweight =
  554. codeColorSums[
  555. `${item.productCode}-${item.productColor}`
  556. ].weight.toFixed(2);
  557. }
  558. });
  559. if(this.saleProductInfoList.length > 0){
  560. if(this.saleProductInfoList[0].lotNum == null || this.saleProductInfoList[0].lotNum == '' || this.saleProductInfoList[0].lotNum == undefined){
  561. this.dlotNum = false;
  562. }else{
  563. this.dlotNum = true;
  564. }
  565. }else{
  566. this.dlotNum = false;
  567. }
  568. Object.assign(this.form, {
  569. noticeNumber, //通知单号
  570. documentType, //通知单类型
  571. documentTypeName, //通知单类型 名
  572. salesman, //销售员
  573. sellingUnit, //售货单位
  574. truckRegistration, //货车信息
  575. dispatchNoteRemark, //备注
  576. customerName, //客户名称
  577. id,
  578. });
  579. this.form.deliveryClerk = this.nickName;
  580. } else {
  581. console.log(res);
  582. this.$message.error("网络异常");
  583. }
  584. } catch (error) {
  585. console.log(error);
  586. }
  587. },
  588. },
  589. computed: {
  590. ...mapState({
  591. nickName: (state) => state.user.nickName,
  592. }),
  593. },
  594. mounted() {
  595. this.initData();
  596. this.initWarehouse();
  597. },
  598. };
  599. </script>
  600. <style scoped lang="scss">
  601. .app-container {
  602. display: flex;
  603. width: 100%;
  604. .table-area {
  605. // width: 600px;
  606. }
  607. .form-area {
  608. // flex: 1;
  609. }
  610. }
  611. ::v-deep .el-table__body tr.current-row > td.el-table__cell {
  612. background-color: #55e905 !important;
  613. }
  614. .table-data > .gutter {
  615. display: table-cell !important;
  616. }
  617. ::v-deep .el-table .warning-row {
  618. color: red;
  619. }
  620. </style>