index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. <template>
  2. <div class="tenant">
  3. <!-- <Banner /> -->
  4. <div class="content">
  5. <byTable
  6. :source="sourceList.data"
  7. :pagination="sourceList.pagination"
  8. :config="config"
  9. :loading="loading"
  10. highlight-current-row
  11. :selectConfig="selectConfig"
  12. :table-events="{
  13. //element talbe事件都能传
  14. }"
  15. :action-list="[
  16. {
  17. text: 'Excel导入',
  18. action: () => openExcel(),
  19. disabled: false,
  20. },
  21. {
  22. text: '添加退货',
  23. action: () => openModal(),
  24. },
  25. ]"
  26. @get-list="getList"
  27. >
  28. <template #fileSlot="{ item }">
  29. <div
  30. style="cursor: pointer; color: #409eff"
  31. @click="handleClickFile(item)"
  32. >
  33. {{ item.fileName }}
  34. </div>
  35. </template>
  36. </byTable>
  37. </div>
  38. <el-dialog
  39. :title="
  40. modalType === 'add'
  41. ? '添加退货'
  42. : modalType === 'edit'
  43. ? '编辑退货'
  44. : '退货详情'
  45. "
  46. v-model="dialogVisible"
  47. width="800"
  48. v-loading="loading"
  49. destroy-on-close
  50. >
  51. <byForm
  52. :formConfig="formConfig"
  53. :formOption="formOption"
  54. v-model="formData.data"
  55. :rules="rules"
  56. ref="byform"
  57. >
  58. <template #detailSlot>
  59. <div style="width: 100%">
  60. <el-button
  61. type="primary"
  62. @click="openProduct = true"
  63. style="margin-bottom: 10px"
  64. v-if="modalType != 'detail'"
  65. >
  66. 添加产品
  67. </el-button>
  68. <el-table :data="formData.data.jdBackDetailsList">
  69. <el-table-column prop="productCode" label="产品编码" />
  70. <el-table-column prop="productName" label="产品名称" />
  71. <el-table-column prop="quantity" label="退货数量" min-width="150">
  72. <template #default="{ row, $index }">
  73. <el-form-item
  74. :prop="'jdBackDetailsList.' + $index + '.quantity'"
  75. :rules="rules.quantity"
  76. :inline-message="true"
  77. >
  78. <el-input-number
  79. v-model="row.quantity"
  80. :precision="4"
  81. :controls="false"
  82. :min="0"
  83. />
  84. </el-form-item>
  85. </template>
  86. </el-table-column>
  87. <el-table-column
  88. prop="zip"
  89. label="操作"
  90. width="100"
  91. v-if="modalType != 'detail'"
  92. >
  93. <template #default="{ $index }">
  94. <el-button type="primary" link @click="handleRemove($index)"
  95. >删除</el-button
  96. >
  97. </template>
  98. </el-table-column>
  99. </el-table>
  100. </div>
  101. </template>
  102. </byForm>
  103. <template #footer v-if="modalType != 'detail'">
  104. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  105. <el-button
  106. type="primary"
  107. @click="submitForm()"
  108. size="large"
  109. :loading="submitLoading"
  110. >
  111. 确 定
  112. </el-button>
  113. </template>
  114. </el-dialog>
  115. <el-dialog
  116. v-model="openProduct"
  117. title="选择产品"
  118. width="70%"
  119. append-to-body
  120. >
  121. <SelectProduct @handleSelect="handleSelect"></SelectProduct>
  122. <template #footer>
  123. <span class="dialog-footer">
  124. <el-button @click="openProduct = false">取消</el-button>
  125. </span>
  126. </template>
  127. </el-dialog>
  128. <el-dialog
  129. title="Excel导入"
  130. v-model="openExcelDialog"
  131. width="400"
  132. v-loading="excelLoading"
  133. >
  134. <div style="margin-bottom: 10px">导入前请先选择仓库</div>
  135. <el-select v-model="importData.warehouseId" placeholder="请选择仓库">
  136. <el-option
  137. v-for="item in warehouseList"
  138. :key="item.id"
  139. :label="item.name"
  140. :value="item.id"
  141. />
  142. </el-select>
  143. <div style="margin-top: 20px" v-show="importData.warehouseId">
  144. <el-upload
  145. :action="actionUrl + '/jdBack/excelImport'"
  146. :data="importData"
  147. :headers="headers"
  148. :on-success="handleSuccess"
  149. :on-progress="handleProgress"
  150. :show-file-list="false"
  151. :on-error="handleError"
  152. accept=".xlsx"
  153. >
  154. <el-button type="primary">点击导入</el-button>
  155. </el-upload>
  156. </div>
  157. <template #footer>
  158. <el-button @click="openExcelDialog = false" size="large"
  159. >取 消</el-button
  160. >
  161. <!-- <el-button
  162. type="primary"
  163. @click="submitExcel()"
  164. size="large"
  165. :loading="submitLoading"
  166. >
  167. 确 定
  168. </el-button> -->
  169. </template>
  170. </el-dialog>
  171. </div>
  172. </template>
  173. <script setup>
  174. import { ElMessage, ElMessageBox } from "element-plus";
  175. import byTable from "@/components/byTable/index";
  176. import byForm from "@/components/byForm/index";
  177. import { watch } from "vue";
  178. import SelectProduct from "@/components/WDLY/product/SelectProduct";
  179. import { getToken } from "@/utils/auth";
  180. const uploadData = ref({});
  181. const headers = ref({ Authorization: "Bearer " + getToken() });
  182. const actionUrl = import.meta.env.VITE_APP_BASE_API;
  183. const loading = ref(false);
  184. const submitLoading = ref(false);
  185. const sourceList = ref({
  186. data: [],
  187. pagination: {
  188. total: 3,
  189. pageNum: 1,
  190. pageSize: 10,
  191. },
  192. });
  193. let dialogVisible = ref(false);
  194. let openProduct = ref(false);
  195. let openExcelDialog = ref(false);
  196. let excelLoading = ref(false);
  197. let modalType = ref("add");
  198. let rules = ref({
  199. warehouseId: [{ required: true, message: "请选择仓库", trigger: "change" }],
  200. logisticsCompanyCode: [
  201. { required: true, message: "请选择物流公司", trigger: "change" },
  202. ],
  203. logisticsCode: [
  204. { required: true, message: "请输入物流/快递单号", trigger: "blur" },
  205. ],
  206. quantity: [{ required: true, message: "请输入退货数量", trigger: "blur" }],
  207. });
  208. const { proxy } = getCurrentInstance();
  209. const selectConfig = reactive([
  210. {
  211. label: "数据来源",
  212. prop: "type",
  213. data: [
  214. {
  215. label: "手动创建",
  216. value: "1",
  217. },
  218. {
  219. label: "批量导入",
  220. value: "2",
  221. },
  222. ],
  223. },
  224. {
  225. label: "退货状态",
  226. prop: "status",
  227. data: [
  228. {
  229. label: "新建",
  230. value: "1",
  231. },
  232. {
  233. label: "运输中",
  234. value: "2",
  235. },
  236. {
  237. label: "待质检",
  238. value: "3",
  239. },
  240. ],
  241. },
  242. ]);
  243. const config = computed(() => {
  244. return [
  245. {
  246. attrs: {
  247. label: "数据来源",
  248. prop: "type",
  249. },
  250. render(type) {
  251. return type == 1 ? "手动创建" : "批量导入";
  252. },
  253. },
  254. {
  255. attrs: {
  256. label: "仓库名称",
  257. prop: "warehouseName",
  258. },
  259. },
  260. {
  261. attrs: {
  262. label: "物流/快递公司",
  263. prop: "logisticsCompanyName",
  264. },
  265. },
  266. {
  267. attrs: {
  268. label: "物流/快递单号",
  269. prop: "logisticsCode",
  270. },
  271. },
  272. {
  273. attrs: {
  274. label: "创建时间",
  275. prop: "createTime",
  276. },
  277. },
  278. {
  279. attrs: {
  280. label: "退货状态",
  281. prop: "status",
  282. },
  283. render(status) {
  284. return status == 1 ? "新建" : status == 2 ? "运输中 " : "待质检";
  285. },
  286. },
  287. {
  288. attrs: {
  289. label: "操作",
  290. width: "240",
  291. align: "right",
  292. },
  293. renderHTML(row) {
  294. return [
  295. row.status < 2
  296. ? {
  297. attrs: {
  298. label: "修改",
  299. type: "primary",
  300. text: true,
  301. },
  302. el: "button",
  303. click() {
  304. getDtl(row, "edit");
  305. },
  306. }
  307. : {},
  308. row.status < 2
  309. ? {
  310. attrs: {
  311. label: "删除",
  312. type: "primary",
  313. text: true,
  314. },
  315. el: "button",
  316. click() {
  317. // 弹窗提示是否删除
  318. ElMessageBox.confirm(
  319. "此操作将永久删除该数据, 是否继续?",
  320. "提示",
  321. {
  322. confirmButtonText: "确定",
  323. cancelButtonText: "取消",
  324. type: "warning",
  325. }
  326. ).then(() => {
  327. // 删除
  328. proxy
  329. .post("/jdBack/delete", {
  330. id: row.id,
  331. })
  332. .then((res) => {
  333. ElMessage({
  334. message: "删除成功",
  335. type: "success",
  336. });
  337. getList();
  338. });
  339. });
  340. },
  341. }
  342. : {},
  343. {
  344. attrs: {
  345. label: "查看",
  346. type: "primary",
  347. text: true,
  348. },
  349. el: "button",
  350. click() {
  351. getDtl(row, "detail");
  352. },
  353. },
  354. ];
  355. },
  356. },
  357. ];
  358. });
  359. let formData = reactive({
  360. data: {},
  361. });
  362. const formOption = reactive({
  363. inline: true,
  364. labelWidth: 100,
  365. itemWidth: 100,
  366. });
  367. const byform = ref(null);
  368. let formConfig = reactive([
  369. {
  370. type: "title",
  371. title: "退货信息",
  372. },
  373. {
  374. type: "select",
  375. prop: "warehouseId",
  376. label: "仓库名称",
  377. itemWidth: 100,
  378. disabled: false,
  379. data: [],
  380. },
  381. {
  382. type: "select",
  383. label: "物流/快递信息",
  384. prop: "logisticsCompanyCode",
  385. itemWidth: 50,
  386. placeholder: "物流/快递公司",
  387. filterable: true,
  388. data: [],
  389. style: {
  390. width: "100%",
  391. },
  392. },
  393. {
  394. type: "input",
  395. label: " ",
  396. prop: "logisticsCode",
  397. itemWidth: 50,
  398. placeholder: "物流/快递单号",
  399. },
  400. {
  401. type: "slot",
  402. slotName: "detailSlot",
  403. label: "退货明细",
  404. },
  405. ]);
  406. const configData = [
  407. [
  408. {
  409. type: "input",
  410. prop: "supplyName",
  411. label: "供应商",
  412. disabled: true,
  413. itemWidth: 50,
  414. },
  415. {
  416. type: "input",
  417. prop: "purchaseCode",
  418. label: "采购单号",
  419. disabled: true,
  420. itemWidth: 50,
  421. },
  422. {
  423. type: "select",
  424. label: "物流信息",
  425. prop: "logisticsCompanyCode",
  426. itemWidth: 50,
  427. style: {
  428. width: "100%",
  429. },
  430. },
  431. {
  432. type: "input",
  433. label: " ",
  434. prop: "code",
  435. itemWidth: 50,
  436. },
  437. {
  438. type: "slot",
  439. slotName: "detailSlot",
  440. label: "发货明细",
  441. },
  442. ],
  443. [
  444. {
  445. type: "input",
  446. prop: "supplyName",
  447. label: "供应商",
  448. disabled: true,
  449. itemWidth: 50,
  450. },
  451. {
  452. type: "input",
  453. prop: "purchaseCode",
  454. label: "采购单号",
  455. disabled: true,
  456. itemWidth: 50,
  457. },
  458. {
  459. type: "select",
  460. label: "物流/快递单号",
  461. prop: "deliverGoodsId",
  462. itemWidth: 50,
  463. style: {
  464. width: "100%",
  465. },
  466. },
  467. {
  468. type: "slot",
  469. slotName: "detailSlot",
  470. label: "发货明细",
  471. },
  472. ],
  473. ];
  474. const deliverData = ref([]);
  475. const getList = async (req) => {
  476. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  477. loading.value = true;
  478. proxy.post("/jdBack/page", sourceList.value.pagination).then((message) => {
  479. console.log(message);
  480. sourceList.value.data = message.rows;
  481. sourceList.value.pagination.total = message.total;
  482. setTimeout(() => {
  483. loading.value = false;
  484. }, 200);
  485. });
  486. };
  487. const submitForm = () => {
  488. byform.value.handleSubmit((valid) => {
  489. const list = formData.data.jdBackDetailsList;
  490. if (!list.length > 0) {
  491. return ElMessage({
  492. message: `请添加退货明细`,
  493. type: "info",
  494. });
  495. }
  496. for (let i = 0; i < list.length; i++) {
  497. const e = list[i];
  498. if (e.quantity == 0) {
  499. return ElMessage({
  500. message: `退货数量不能为0!`,
  501. type: "info",
  502. });
  503. }
  504. }
  505. loading.value = true;
  506. submitLoading.value = true;
  507. proxy.post("/jdBack/" + modalType.value, formData.data).then(
  508. (res) => {
  509. ElMessage({
  510. message: `操作成功!`,
  511. type: "success",
  512. });
  513. dialogVisible.value = false;
  514. submitLoading.value = false;
  515. loading.value = false;
  516. getList();
  517. },
  518. (err) => (submitLoading.value = false)
  519. );
  520. });
  521. };
  522. const getDtl = (row, type) => {
  523. modalType.value = type;
  524. proxy.post("/jdBack/detail", { id: row.id }).then((res) => {
  525. formData.data = res;
  526. dialogVisible.value = true;
  527. });
  528. };
  529. const importData = reactive({});
  530. const handleEdit = (row, status) => {
  531. let purchaseStatusName = status == 88 ? "作废" : "终止";
  532. const data = { ...row, purchaseStatus: status };
  533. // 弹窗提示是否删除
  534. ElMessageBox.confirm(
  535. `此操作将${purchaseStatusName}该数据, 是否继续?`,
  536. "提示",
  537. {
  538. confirmButtonText: "确定",
  539. cancelButtonText: "取消",
  540. type: "warning",
  541. }
  542. ).then(() => {
  543. // 删除
  544. proxy.post("/purchase/edit", data).then((res) => {
  545. ElMessage({
  546. message: `${purchaseStatusName}成功`,
  547. type: "success",
  548. });
  549. getList();
  550. });
  551. });
  552. };
  553. const logisticsData = ref([]);
  554. const getLogisticsData = (row) => {
  555. proxy.post("/companyInfo/list", { pageNum: 1, pageSize: 999 }).then((res) => {
  556. // logisticsData.value = res.reverse().slice(0, 100); //截取前100
  557. logisticsData.value = res.reverse();
  558. formConfig[2].data = logisticsData.value.map((x) => ({
  559. label: x.name,
  560. value: x.code,
  561. }));
  562. });
  563. };
  564. watch(modalType, (val) => {
  565. if (val) {
  566. formConfig[1].disabled = val == "detail" ? true : false;
  567. formConfig[2].disabled = val == "detail" ? true : false;
  568. formConfig[3].disabled = val == "detail" ? true : false;
  569. }
  570. });
  571. const openModal = () => {
  572. dialogVisible.value = true;
  573. modalType.value = "add";
  574. formData.data = {
  575. type: "1",
  576. status: "1",
  577. jdBackDetailsList: [],
  578. };
  579. };
  580. const warehouseList = ref([]);
  581. const warehouseListData = () => {
  582. // // 币种数据
  583. proxy
  584. .post("/warehouse/page", {
  585. pageNum: 1,
  586. pageSize: 10,
  587. })
  588. .then((message) => {
  589. warehouseList.value = message.rows;
  590. formConfig[1].data = message.rows.map((x) => ({
  591. label: x.name,
  592. value: x.id,
  593. }));
  594. });
  595. };
  596. getList();
  597. getLogisticsData();
  598. warehouseListData();
  599. const handleSelect = (row) => {
  600. const flag = formData.data.jdBackDetailsList.some(
  601. (x) => x.productId === row.id
  602. );
  603. if (flag)
  604. return ElMessage({
  605. message: "该物品已选择",
  606. type: "info",
  607. });
  608. formData.data.jdBackDetailsList.push({
  609. quantity: null,
  610. productName: row.name,
  611. productCode: row.code,
  612. productId: row.id,
  613. });
  614. return ElMessage({
  615. message: "选择成功",
  616. type: "success",
  617. });
  618. };
  619. const handleRemove = (index) => {
  620. formData.data.jdBackDetailsList.splice(index, 1);
  621. return ElMessage({
  622. message: "删除成功",
  623. type: "success",
  624. });
  625. };
  626. const openExcel = () => {
  627. openExcelDialog.value = true;
  628. importData.warehouseId = "";
  629. };
  630. const handleProgress = () => {
  631. excelLoading.value = true;
  632. };
  633. const handleError = (err) => {
  634. console.log(res);
  635. ElMessage({
  636. message: `${err},请重试!`,
  637. type: "info",
  638. });
  639. openExcelDialog.value = false;
  640. excelLoading.value = false;
  641. };
  642. const handleSuccess = (res) => {
  643. if (res.code != 200) {
  644. return ElMessage({
  645. message: `${res.msg},请重试!`,
  646. type: "info",
  647. });
  648. } else {
  649. ElMessage({
  650. message: "导入成功!",
  651. type: "success",
  652. });
  653. openExcelDialog.value = false;
  654. excelLoading.value = false;
  655. getList();
  656. }
  657. };
  658. </script>
  659. <style lang="scss" scoped>
  660. .tenant {
  661. padding: 20px;
  662. }
  663. </style>