index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. <template>
  2. <div>
  3. <el-card :class="props.selectStatus ? 'select-card' : 'box-card'">
  4. <byTable
  5. :source="sourceList.data"
  6. :pagination="sourceList.pagination"
  7. :config="config"
  8. :loading="loading"
  9. :searchConfig="searchConfig"
  10. highlight-current-row
  11. :action-list="[
  12. props.selectStatus
  13. ? {}
  14. : {
  15. text: '操作日志',
  16. action: () => viewLogs(),
  17. },
  18. props.selectStatus
  19. ? {}
  20. : {
  21. text: '复制万里牛单号',
  22. action: () => clickCopyWLNCode(),
  23. },
  24. ]"
  25. @get-list="getList"
  26. @clickReset="clickReset">
  27. <template #code="{ item }">
  28. <div>
  29. <a style="color: #409eff; cursor: pointer; word-break: break-all" @click="clickCode(item)">{{ item.code }}</a>
  30. </div>
  31. </template>
  32. <template #totalAmount="{ item }">
  33. <div style="color: #409eff">{{ moneyFormat(item.totalAmount) }}</div>
  34. </template>
  35. <template #address="{ item }">
  36. <div>{{ item.province }}, {{ item.city }}, {{ item.county }}, {{ item.detailedAddress }}</div>
  37. </template>
  38. </byTable>
  39. </el-card>
  40. <el-dialog title="操作日志" v-if="openLogs" v-model="openLogs" width="50%">
  41. <byTable
  42. :source="logsList.data"
  43. :pagination="logsList.pagination"
  44. :config="configLogs"
  45. :loading="loadingLogs"
  46. highlight-current-row
  47. @get-list="getLogsList">
  48. </byTable>
  49. <template #footer>
  50. <el-button @click="openLogs = false" size="large">关 闭</el-button>
  51. </template>
  52. </el-dialog>
  53. <el-dialog title="修改税率" v-if="openChangeTaxRate" v-model="openChangeTaxRate" width="500" style="margin-top: 20vh !important">
  54. <el-form :model="details.data" label-width="120px" ref="taxRate">
  55. <el-form-item label="税率" prop="taxRate" :rules="[{ required: true, message: '请输入税率', trigger: 'blur' }]">
  56. <el-input-number
  57. onmousewheel="return false;"
  58. v-model="details.data.taxRate"
  59. placeholder="请输入税率"
  60. style="width: 100%"
  61. :controls="false"
  62. :min="0"
  63. :precision="2"
  64. :max="100" />
  65. </el-form-item>
  66. </el-form>
  67. <template #footer>
  68. <el-button @click="openChangeTaxRate = false" size="large">取 消</el-button>
  69. <el-button type="primary" @click="submitChangeTaxRate()" size="large" v-preReClick>确 定</el-button>
  70. </template>
  71. </el-dialog>
  72. <el-dialog title="售后类型" v-if="openAfterSale" v-model="openAfterSale" width="300px" style="margin-top: 20vh !important">
  73. <template #footer>
  74. <el-button type="primary" @click="applyForAfterSale(1)" size="large" v-preReClick>退 货</el-button>
  75. <el-button @click="applyForAfterSale(2)" size="large" v-preReClick>换 货</el-button>
  76. </template>
  77. </el-dialog>
  78. <el-dialog title="送货单" v-if="openDeliveryNote" v-model="openDeliveryNote" width="1000px">
  79. <DeliveryNote :rowData="rowData" @clickCancel="clickCancel"></DeliveryNote>
  80. </el-dialog>
  81. </div>
  82. </template>
  83. <script setup>
  84. import byTable from "/src/components/byTable/index";
  85. import { ElMessage, ElMessageBox } from "element-plus";
  86. import { copyText } from "vue3-clipboard";
  87. import DeliveryNote from "/src/components/order/deliveryNote/index";
  88. const { proxy } = getCurrentInstance();
  89. const props = defineProps({
  90. selectStatus: Boolean,
  91. departmentId: String,
  92. });
  93. const departmentList = ref([{ dictKey: "0", dictValue: "胜德体育" }]);
  94. const sourceList = ref({
  95. data: [],
  96. pagination: {
  97. total: 0,
  98. pageNum: 1,
  99. pageSize: 10,
  100. departmentId: "",
  101. code: "",
  102. wlnCode: "",
  103. status: "",
  104. settlementStatus: "",
  105. exception: "0",
  106. },
  107. });
  108. const loading = ref(false);
  109. const searchConfig = computed(() => {
  110. return [
  111. {
  112. type: "input",
  113. prop: "code",
  114. label: "订单号",
  115. },
  116. {
  117. type: "input",
  118. prop: "wlnCode",
  119. label: "万里牛单号",
  120. },
  121. props.departmentId
  122. ? {}
  123. : {
  124. type: "select",
  125. prop: "departmentId",
  126. data: departmentList.value,
  127. label: "事业部",
  128. },
  129. props.departmentId
  130. ? {}
  131. : {
  132. type: "select",
  133. prop: "status",
  134. dictKey: "order_status",
  135. label: "订单状态",
  136. },
  137. {
  138. type: "select",
  139. prop: "settlementStatus",
  140. label: "结算状态",
  141. data: proxy.useUserStore().allDict["settlement_status"],
  142. },
  143. ];
  144. });
  145. const config = computed(() => {
  146. return [
  147. {
  148. attrs: {
  149. label: "事业部",
  150. prop: "departmentName",
  151. width: 120,
  152. },
  153. },
  154. {
  155. attrs: {
  156. label: "订单号",
  157. slot: "code",
  158. width: 200,
  159. },
  160. },
  161. {
  162. attrs: {
  163. label: "万里牛单号",
  164. prop: "wlnCode",
  165. width: 160,
  166. },
  167. },
  168. {
  169. attrs: {
  170. label: "快递单号",
  171. prop: "expressDeliveryCode",
  172. width: 140,
  173. },
  174. },
  175. {
  176. attrs: {
  177. label: "订单状态",
  178. prop: "status",
  179. width: 120,
  180. },
  181. render(val) {
  182. return proxy.dictKeyValue(val, proxy.useUserStore().allDict["order_status"]);
  183. },
  184. },
  185. {
  186. attrs: {
  187. label: "结算状态",
  188. prop: "settlementStatus",
  189. width: 120,
  190. },
  191. render(val) {
  192. return proxy.dictKeyValue(val, proxy.useUserStore().allDict["settlement_status"]);
  193. },
  194. },
  195. {
  196. attrs: {
  197. label: "税率",
  198. prop: "taxRate",
  199. width: 80,
  200. },
  201. render(val) {
  202. return val + "%";
  203. },
  204. },
  205. {
  206. attrs: {
  207. label: "订单总金额 ¥",
  208. slot: "totalAmount",
  209. width: 120,
  210. align: "right",
  211. },
  212. },
  213. {
  214. attrs: {
  215. label: "产品总金额 ¥",
  216. prop: "productTotalAmount",
  217. width: 120,
  218. align: "right",
  219. },
  220. render(val) {
  221. return proxy.moneyFormat(val);
  222. },
  223. },
  224. {
  225. attrs: {
  226. label: "定制加工费 ¥",
  227. prop: "customProcessingFee",
  228. width: 120,
  229. align: "right",
  230. },
  231. render(val) {
  232. return proxy.moneyFormat(val);
  233. },
  234. },
  235. {
  236. attrs: {
  237. label: "代发费 ¥",
  238. prop: "lssueFee",
  239. width: 120,
  240. align: "right",
  241. },
  242. render(val) {
  243. return proxy.moneyFormat(val);
  244. },
  245. },
  246. {
  247. attrs: {
  248. label: "快递包材费 ¥",
  249. prop: "deliveryMaterialsFee",
  250. width: 120,
  251. align: "right",
  252. },
  253. render(val) {
  254. return proxy.moneyFormat(val);
  255. },
  256. },
  257. {
  258. attrs: {
  259. label: "包装人工费 ¥",
  260. prop: "packingLabor",
  261. width: 120,
  262. align: "right",
  263. },
  264. render(val) {
  265. return proxy.moneyFormat(val);
  266. },
  267. },
  268. {
  269. attrs: {
  270. label: "包材费 ¥",
  271. prop: "packagingMaterialCost",
  272. width: 120,
  273. align: "right",
  274. },
  275. render(val) {
  276. return proxy.moneyFormat(val);
  277. },
  278. },
  279. {
  280. attrs: {
  281. label: "管理费 ¥",
  282. prop: "managementFee",
  283. width: 120,
  284. align: "right",
  285. },
  286. render(val) {
  287. return proxy.moneyFormat(val);
  288. },
  289. },
  290. {
  291. attrs: {
  292. label: "外箱包装费 ¥",
  293. prop: "outerBoxPackingFee",
  294. width: 120,
  295. align: "right",
  296. },
  297. render(val) {
  298. return proxy.moneyFormat(val);
  299. },
  300. },
  301. {
  302. attrs: {
  303. label: "交期",
  304. prop: "deliveryTime",
  305. width: 160,
  306. align: "center",
  307. },
  308. },
  309. {
  310. attrs: {
  311. label: "发货时间",
  312. prop: "shippingTime",
  313. width: 160,
  314. align: "center",
  315. },
  316. },
  317. {
  318. attrs: {
  319. label: "收货人",
  320. prop: "consignee",
  321. width: 140,
  322. },
  323. },
  324. {
  325. attrs: {
  326. label: "收货人电话",
  327. prop: "consigneeNumber",
  328. width: 140,
  329. },
  330. },
  331. {
  332. attrs: {
  333. label: "收货人地址",
  334. slot: "address",
  335. width: 400,
  336. },
  337. },
  338. {
  339. attrs: {
  340. label: "操作",
  341. width: 180,
  342. align: "center",
  343. fixed: "right",
  344. },
  345. renderHTML(row) {
  346. return [
  347. props.selectStatus
  348. ? {
  349. attrs: {
  350. label: "选择",
  351. type: "primary",
  352. text: true,
  353. },
  354. el: "button",
  355. click() {
  356. clickSelect(row);
  357. },
  358. }
  359. : [40, 50].includes(row.status)
  360. ? {
  361. attrs: {
  362. label: "售后",
  363. type: "primary",
  364. text: true,
  365. },
  366. el: "button",
  367. click() {
  368. clickAfterSale(row);
  369. },
  370. }
  371. : {},
  372. !props.selectStatus && row.type === 1 && row.status == 40
  373. ? {
  374. attrs: {
  375. label: "送货单",
  376. type: "primary",
  377. text: true,
  378. },
  379. el: "button",
  380. click() {
  381. clickDeliveryNote(row);
  382. },
  383. }
  384. : {},
  385. !props.selectStatus && row.status == 20
  386. ? {
  387. attrs: {
  388. label: "挂起",
  389. type: "primary",
  390. text: true,
  391. },
  392. el: "button",
  393. click() {
  394. clickHangUp(row);
  395. },
  396. }
  397. : {},
  398. !props.selectStatus && row.status == 60
  399. ? {
  400. attrs: {
  401. label: "取消挂起",
  402. type: "primary",
  403. text: true,
  404. },
  405. el: "button",
  406. click() {
  407. clickCancelHangUp(row);
  408. },
  409. }
  410. : {},
  411. !props.selectStatus && row.status && row.status != 0
  412. ? {
  413. attrs: {
  414. label: "税率",
  415. type: "primary",
  416. text: true,
  417. },
  418. el: "button",
  419. click() {
  420. clickChangeTaxRate(row);
  421. },
  422. }
  423. : {},
  424. !props.selectStatus && [0, 10, 20].includes(row.status) && proxy.useUserStore().user.userId === "1"
  425. ? {
  426. attrs: {
  427. label: "删除",
  428. type: "danger",
  429. text: true,
  430. },
  431. el: "button",
  432. click() {
  433. clickDelete(row);
  434. },
  435. }
  436. : {},
  437. !props.selectStatus && [30, 40].includes(row.status) && proxy.useUserStore().user.userId === "1"
  438. ? {
  439. attrs: {
  440. label: "删除",
  441. type: "danger",
  442. text: true,
  443. },
  444. el: "button",
  445. click() {
  446. clickDeleteTwo(row);
  447. },
  448. }
  449. : {},
  450. ];
  451. },
  452. },
  453. ];
  454. });
  455. const getDemandData = () => {
  456. proxy.post("/department/page", { pageNum: 1, pageSize: 999 }).then((res) => {
  457. if (res.rows && res.rows.length > 0) {
  458. departmentList.value = departmentList.value.concat(
  459. res.rows.map((item) => {
  460. return {
  461. dictKey: item.id,
  462. dictValue: item.name,
  463. };
  464. })
  465. );
  466. }
  467. });
  468. };
  469. getDemandData();
  470. const getList = async (req, status) => {
  471. if (status) {
  472. sourceList.value.pagination = {
  473. pageNum: sourceList.value.pagination.pageNum,
  474. pageSize: sourceList.value.pagination.pageSize,
  475. exception: "0",
  476. };
  477. } else {
  478. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  479. }
  480. if (props.selectStatus) {
  481. sourceList.value.pagination.linkedStatementOfAccount = 0;
  482. }
  483. if (props.departmentId) {
  484. sourceList.value.pagination.departmentId = props.departmentId;
  485. }
  486. loading.value = true;
  487. proxy.post("/orderInfo/page", sourceList.value.pagination).then((res) => {
  488. sourceList.value.data = res.rows;
  489. sourceList.value.pagination.total = res.total;
  490. setTimeout(() => {
  491. loading.value = false;
  492. }, 200);
  493. });
  494. };
  495. getList();
  496. const clickReset = () => {
  497. getList("", true);
  498. };
  499. const clickCode = (row) => {
  500. proxy.$router.replace({
  501. path: "/platform_manage/process/processApproval",
  502. query: {
  503. flowKey: "order",
  504. flowName: "订单详情",
  505. processType: "20",
  506. id: row.id,
  507. flowId: row.flowId,
  508. random: proxy.random(),
  509. },
  510. });
  511. };
  512. const clickDelete = (row) => {
  513. ElMessageBox.confirm("你是否确认此操作", "提示", {
  514. confirmButtonText: "确定",
  515. cancelButtonText: "取消",
  516. type: "warning",
  517. })
  518. .then(() => {
  519. proxy.post("/orderInfo/delete", { id: row.id }).then(() => {
  520. ElMessage({ message: "删除成功", type: "success" });
  521. getList();
  522. });
  523. })
  524. .catch(() => {});
  525. };
  526. const clickDeleteTwo = (row) => {
  527. ElMessageBox.confirm("你是否确认此操作", "提示", {
  528. confirmButtonText: "确定",
  529. cancelButtonText: "取消",
  530. type: "warning",
  531. })
  532. .then(() => {
  533. proxy.post("/orderInfo/deleteAndStore", { id: row.id }).then(() => {
  534. ElMessage({ message: "删除成功", type: "success" });
  535. getList();
  536. });
  537. })
  538. .catch(() => {});
  539. };
  540. const clickHangUp = (row) => {
  541. ElMessageBox.confirm("你是否确认此操作", "提示", {
  542. confirmButtonText: "确定",
  543. cancelButtonText: "取消",
  544. type: "warning",
  545. })
  546. .then(() => {
  547. proxy.post("/orderInfo/suspendOrder", { id: row.id }).then(() => {
  548. ElMessage({ message: "操作成功", type: "success" });
  549. getList();
  550. });
  551. })
  552. .catch(() => {});
  553. };
  554. const clickCancelHangUp = (row) => {
  555. ElMessageBox.confirm("你是否确认此操作", "提示", {
  556. confirmButtonText: "确定",
  557. cancelButtonText: "取消",
  558. type: "warning",
  559. })
  560. .then(() => {
  561. proxy.post("/orderInfo/cancelSuspendOrder", { id: row.id }).then(() => {
  562. ElMessage({ message: "操作成功", type: "success" });
  563. getList();
  564. });
  565. })
  566. .catch(() => {});
  567. };
  568. const openLogs = ref(false);
  569. const loadingLogs = ref(false);
  570. const logsList = ref({
  571. data: [],
  572. pagination: {
  573. total: 0,
  574. pageNum: 1,
  575. pageSize: 10,
  576. },
  577. });
  578. const type = ref([
  579. { dictKey: "10", dictValue: "新增订单" },
  580. { dictKey: "20", dictValue: "图稿上传" },
  581. { dictKey: "21", dictValue: "修改税率" },
  582. { dictKey: "30", dictValue: "删除订单" },
  583. ]);
  584. const configLogs = computed(() => {
  585. return [
  586. {
  587. attrs: {
  588. label: "操作时间",
  589. prop: "createTime",
  590. width: 160,
  591. align: "center",
  592. },
  593. },
  594. {
  595. attrs: {
  596. label: "操作人",
  597. prop: "userName",
  598. align: "center",
  599. },
  600. },
  601. {
  602. attrs: {
  603. label: "订单号",
  604. prop: "orderCode",
  605. align: "center",
  606. },
  607. },
  608. {
  609. attrs: {
  610. label: "行为",
  611. prop: "type",
  612. width: 100,
  613. align: "center",
  614. },
  615. render(val) {
  616. return proxy.dictKeyValue(val, type.value);
  617. },
  618. },
  619. ];
  620. });
  621. const viewLogs = () => {
  622. logsList.value.data = [];
  623. logsList.value.pagination.total = 0;
  624. openLogs.value = true;
  625. getLogsList({ pageNum: 1, pageSize: 10 });
  626. };
  627. const getLogsList = async (req) => {
  628. logsList.value.pagination = { ...logsList.value.pagination, ...req };
  629. loadingLogs.value = true;
  630. proxy.post("/orderOperatingLog/page", logsList.value.pagination).then((res) => {
  631. logsList.value.data = res.rows;
  632. logsList.value.pagination.total = res.total;
  633. setTimeout(() => {
  634. loadingLogs.value = false;
  635. }, 200);
  636. });
  637. };
  638. const details = reactive({
  639. data: {},
  640. });
  641. const openChangeTaxRate = ref(false);
  642. const clickChangeTaxRate = (item) => {
  643. proxy.post("/orderInfo/detail", { id: item.id }).then((res) => {
  644. details.data = res;
  645. openChangeTaxRate.value = true;
  646. });
  647. };
  648. const submitChangeTaxRate = () => {
  649. proxy.$refs.taxRate.validate((valid) => {
  650. if (valid) {
  651. details.data.updateType = "21";
  652. proxy.post("/orderInfo/edit", details.data).then(() => {
  653. ElMessage({ message: "修改完成", type: "success" });
  654. openChangeTaxRate.value = false;
  655. getList();
  656. });
  657. }
  658. });
  659. };
  660. const emit = defineEmits(["selectOrder"]);
  661. const clickSelect = (item) => {
  662. emit("selectOrder", item);
  663. };
  664. const clickCopyWLNCode = () => {
  665. ElMessage("复制数据中,请稍后");
  666. proxy.post("/orderInfo/getOrderWlnCodeStr", sourceList.value.pagination).then((res) => {
  667. copyText(res, undefined, (error) => {
  668. if (error) {
  669. ElMessage.error(`复制失败: ${error} !`);
  670. } else {
  671. ElMessage.success(`复制成功!`);
  672. }
  673. });
  674. });
  675. };
  676. const openAfterSale = ref(false);
  677. const rowData = ref({});
  678. const clickAfterSale = (row) => {
  679. rowData.value = row;
  680. openAfterSale.value = true;
  681. };
  682. const applyForAfterSale = (type) => {
  683. openAfterSale.value = false;
  684. proxy.$router.replace({
  685. path: "/order/after-sale/initiate",
  686. query: {
  687. orderInfoId: rowData.value.id,
  688. type: type,
  689. random: proxy.random(),
  690. },
  691. });
  692. };
  693. const openDeliveryNote = ref(false);
  694. const clickDeliveryNote = (row) => {
  695. rowData.value = row;
  696. openDeliveryNote.value = true;
  697. };
  698. const clickCancel = (status) => {
  699. openDeliveryNote.value = false;
  700. if (status) {
  701. getList();
  702. }
  703. };
  704. </script>
  705. <style lang="scss" scoped>
  706. ::v-deep(.el-input-number .el-input__inner) {
  707. text-align: left;
  708. }
  709. :deep(.el-dialog) {
  710. margin-top: 10px !important;
  711. margin-bottom: 10px !important;
  712. }
  713. .select-card {
  714. height: calc(100vh - 184px);
  715. overflow-y: auto;
  716. overflow-x: hidden;
  717. }
  718. </style>