index.vue 13 KB

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