index.vue 15 KB

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