index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. <script setup lang="tsx">
  2. import { nextTick, onMounted, ref, watch } from 'vue';
  3. import { useRoute, useRouter } from 'vue-router';
  4. import { NTag, useDialog } from 'naive-ui';
  5. import type { InternalRowData } from 'naive-ui/es/data-table/src/interface';
  6. import {
  7. // fetchAudit,
  8. fetchBreakDownload,
  9. fetchExportList,
  10. fetchExportOrderList,
  11. fetchGetDeliveryOrderList,
  12. fetchGetDeliveryStatusNum
  13. } from '@/service/api/order-manage/normal-order';
  14. // import { fetchGetLoginUserList } from '@/service/api/common';
  15. import { useAuth } from '@/hooks/business/auth';
  16. // import { copyTextToClipboard } from '@/utils/zt';
  17. import { commonExport } from '@/utils/common';
  18. import { useModal } from '@/components/zt/Modal/hooks/useModal';
  19. import { useTable } from '@/components/zt/Table/hooks/useTable';
  20. // import { type } from '../../../../packages/axios/src/index';
  21. import { DJKOrderStatus, SearchForm, businessType, orderStatus } from './normal-order';
  22. const router = useRouter();
  23. const route = useRoute();
  24. const activeTab = ref('all');
  25. const statusList = ref<{ label: string; value: string; num?: number }[]>([]);
  26. // const ShipmentModal = useTemplateRef('Shipment');
  27. const channelIdList = ref([]);
  28. const orderNumber = route.query.orderNumber;
  29. const columns: NaiveUI.TableColumn<Api.delivery.deliveryOrder>[] = [
  30. {
  31. key: 'orderNumber',
  32. title: '订单编号',
  33. align: 'center',
  34. width: 220
  35. },
  36. {
  37. key: 'consigneeAddress',
  38. title: '业务类型',
  39. align: 'center',
  40. width: 120,
  41. render: row => {
  42. return <NTag>{businessType[row.businessType as keyof typeof businessType] || row.businessType}</NTag>;
  43. }
  44. },
  45. {
  46. key: 'info',
  47. title: '客户信息',
  48. align: 'center',
  49. width: 220,
  50. render: row => {
  51. return (
  52. <div>
  53. <div>
  54. {row.consigneeName}
  55. {row.consigneeMobile}
  56. </div>
  57. <div>{row.consigneeAddress}</div>
  58. </div>
  59. );
  60. }
  61. },
  62. {
  63. key: 'status',
  64. title: '订单状态',
  65. align: 'center',
  66. width: 120,
  67. render: row => {
  68. const statusKey = row.hbOrderStatus as keyof typeof orderStatus;
  69. let statusText;
  70. if (row.businessType == 'XNSP') {
  71. if (row.hbOrderStatus == 60 || row.hbOrderStatus == 50 || row.hbOrderStatus == 0) {
  72. statusText = '订单取消';
  73. } else {
  74. statusText = '订单完成';
  75. }
  76. } else if (row.businessType == 'DJK') {
  77. statusText = DJKOrderStatus[statusKey as keyof typeof DJKOrderStatus] || '未知状态';
  78. } else {
  79. statusText = orderStatus[statusKey] || '未知状态';
  80. }
  81. return <NTag>{statusText}</NTag>;
  82. }
  83. },
  84. {
  85. key: 'createTime',
  86. title: '下单时间',
  87. align: 'center',
  88. width: 180,
  89. render: row => {
  90. return <div>{row.createTime?.replace('T', ' ')}</div>;
  91. }
  92. }
  93. ];
  94. const [registerTable, { refresh, setTableLoading, getSeachForm, getTableData, setFieldsValue }] = useTable({
  95. searchFormConfig: {
  96. schemas: [...SearchForm]
  97. },
  98. tableConfig: {
  99. keyField: 'id',
  100. title: '',
  101. showAddButton: false,
  102. showTableHeaderAction: true,
  103. fieldMapToTime: [['createTime', ['startTime', 'endTime']]]
  104. }
  105. });
  106. const exportColumns: NaiveUI.TableColumn<InternalRowData>[] = [
  107. {
  108. key: 'index',
  109. title: '序号',
  110. align: 'center',
  111. width: 100,
  112. render(_, rowIndex) {
  113. return rowIndex + 1;
  114. }
  115. },
  116. {
  117. key: 'taskName',
  118. title: '任务名称',
  119. align: 'center',
  120. minWidth: 100
  121. },
  122. {
  123. key: 'updateTime',
  124. title: '时间',
  125. align: 'center',
  126. minWidth: 100,
  127. render: row => {
  128. return (
  129. <div>
  130. <div>创建时间:{row.createTime}</div>
  131. <div>完成时间:{row.updateTime}</div>
  132. </div>
  133. );
  134. }
  135. },
  136. {
  137. key: 'operator',
  138. title: '操作人',
  139. align: 'center',
  140. minWidth: 100
  141. },
  142. {
  143. key: 'exportStatus',
  144. title: '状态',
  145. align: 'center',
  146. minWidth: 100,
  147. render: row => {
  148. if (row.exportStatus == 0) {
  149. return (
  150. <div>
  151. 请耐心等待,正在导出中...
  152. <n-button text type="info" onClick={() => handleBreak(row.id as string)}>
  153. 中断
  154. </n-button>
  155. </div>
  156. );
  157. } else if (row.exportStatus == 1) {
  158. return (
  159. <div>
  160. 未下载
  161. <n-button text type="info" onClick={() => handleDownload(row.id as string)}>
  162. 下载
  163. </n-button>
  164. </div>
  165. );
  166. } else if (row.exportStatus == 2) {
  167. return <div class={'text-gray-500'}>生成文件失败</div>;
  168. } else if (row.exportStatus == 3) {
  169. return (
  170. <div>
  171. 已下载&nbsp;
  172. <n-button text type="info" onClick={() => handleDownload(row.id as string)}>
  173. 下载
  174. </n-button>
  175. </div>
  176. );
  177. } else if (row.exportStatus == 4) {
  178. return <div>导出失败</div>;
  179. }
  180. return <div>进行中</div>;
  181. }
  182. }
  183. ];
  184. async function handleDownload(id: string) {
  185. setTableLoading(true);
  186. await commonExport('/platform/exportTask/download', { fileId: id }, '正常订单列表.xlsx');
  187. refresh();
  188. }
  189. async function handleBreak(id: string) {
  190. setTableLoading(true);
  191. await fetchBreakDownload(id);
  192. refresh();
  193. }
  194. const [registerModalPrice, { openModal }] = useModal({
  195. title: '导出记录',
  196. width: 1200,
  197. height: 600,
  198. showFooter: false
  199. });
  200. const dialog = useDialog();
  201. // async function handleDeivery(row: Api.delivery.deliveryOrder) {
  202. // if (!row.orderNumber) {
  203. // window.$message?.error('订单异常');
  204. // return;
  205. // }
  206. // ShipmentModal.value?.handleOpenOrder(row.orderNumber);
  207. // }
  208. function handleOrderDetail(row: Api.delivery.deliveryOrder) {
  209. if (!row.orderNumber) {
  210. window.$message?.error('订单异常');
  211. }
  212. router.push({
  213. path: '/order-manage/order-detail',
  214. query: {
  215. orderNumber: row.orderNumber
  216. }
  217. });
  218. // orderMoadl.value?.open(String(row.orderNumber));
  219. }
  220. // async function handleAudit(row: any) {
  221. // window.$dialog?.info({
  222. // title: '提示',
  223. // content: `此操作将核销该订单,且无法撤销,确定要核销吗?`,
  224. // positiveText: '确定',
  225. // negativeText: '取消',
  226. // onPositiveClick: async () => {
  227. // const { error } = await fetchAudit({ orderNumber: row.orderNumber });
  228. // if (!error) {
  229. // refresh();
  230. // }
  231. // }
  232. // });
  233. // }
  234. async function getNums() {
  235. const form = getSeachForm();
  236. const params = {
  237. ...form,
  238. channelIdList: channelIdList.value,
  239. startTime: form?.createTime && form.createTime[0],
  240. endTime: form?.createTime && form.createTime[1],
  241. createTime: null
  242. };
  243. const { data: keyData } = await fetchGetDeliveryStatusNum(params);
  244. if (!keyData) return;
  245. const orderStatusList = [
  246. {
  247. label: '全部',
  248. value: 'all'
  249. },
  250. {
  251. label: '待支付',
  252. value: 'paddingPay'
  253. },
  254. {
  255. label: '进行中',
  256. value: 'ing'
  257. },
  258. {
  259. label: '已完成',
  260. value: 'completed'
  261. },
  262. {
  263. label: '已取消',
  264. value: 'cancel'
  265. }
  266. ];
  267. const updatedOrderStatusList = orderStatusList.map(item => {
  268. const key = item.value as keyof typeof keyData;
  269. if (Object.hasOwn(keyData, key)) {
  270. return {
  271. ...item,
  272. num: keyData[key]
  273. };
  274. }
  275. return item;
  276. });
  277. // console.log(updatedOrderStatusList, 'updatedOrderStatusList');
  278. statusList.value = updatedOrderStatusList;
  279. }
  280. getNums();
  281. // async function handleCopy(row: Api.delivery.deliveryOrder, key: string) {
  282. // if (!row[key]) {
  283. // window.$message?.error('订单编号不存在');
  284. // return;
  285. // }
  286. // await copyTextToClipboard(row[key]);
  287. // }
  288. async function handleExport() {
  289. setTableLoading(true);
  290. try {
  291. // await commonExport(
  292. // '/platform/order/export',
  293. // { ...getFieldsValue(), orderStatus: activeTab.value },
  294. // '正常订单列表.xlsx'
  295. // );
  296. await fetchExportOrderList({ ...getSeachForm(), orderStatus: activeTab.value });
  297. dialog.success({
  298. title: '提示',
  299. content: () => {
  300. return (
  301. <div>
  302. <p>导出操作进行中......</p>
  303. <p>是否进入导出记录</p>
  304. </div>
  305. );
  306. },
  307. positiveText: '确定',
  308. negativeText: '取消',
  309. onPositiveClick: () => {
  310. openModal();
  311. },
  312. onNegativeClick: () => {}
  313. });
  314. } finally {
  315. setTableLoading(false);
  316. }
  317. }
  318. async function handleExportLog() {
  319. setTableLoading(true);
  320. try {
  321. openModal();
  322. } finally {
  323. setTableLoading(false);
  324. }
  325. }
  326. watch(
  327. () => [activeTab.value],
  328. () => {
  329. nextTick(() => {
  330. refresh();
  331. });
  332. }
  333. );
  334. onMounted(async () => {
  335. await setFieldsValue({ orderNumber });
  336. refresh();
  337. });
  338. </script>
  339. <template>
  340. <LayoutTable>
  341. <ZTable
  342. :columns="columns"
  343. :api="fetchGetDeliveryOrderList"
  344. :immediate="false"
  345. :default-params="{ orderStatus: activeTab }"
  346. @register="registerTable"
  347. @search="getNums"
  348. >
  349. <template #op="{ row }">
  350. <NButton size="small" type="primary" ghost @click="handleOrderDetail(row)">订单详情</NButton>
  351. <!--
  352. <NButton
  353. v-if="row.businessType === 'DJK' && row.isWriteOff == 1 && row.hbOrderStatus != 80"
  354. size="small"
  355. type="primary"
  356. ghost
  357. @click="handleAudit(row)"
  358. >
  359. 核销
  360. </NButton>
  361. -->
  362. </template>
  363. <template #header>
  364. <div class="flex items-center">
  365. <NScrollbar x-scrollable>
  366. <div class="flex items-center">
  367. <div class="max-w-800px">
  368. <NTabs v-model:value="activeTab" type="line" animated display-directive="show">
  369. <NTab
  370. v-for="item in statusList"
  371. :key="item.value"
  372. :name="item.value"
  373. :tab="`${item.label}(${item.num})`"
  374. ></NTab>
  375. </NTabs>
  376. </div>
  377. </div>
  378. </NScrollbar>
  379. </div>
  380. </template>
  381. <template #prefix="{ loading }">
  382. <div class="flex items-center">
  383. <NButton
  384. v-if="useAuth().hasAuth('order:user:export')"
  385. size="small"
  386. type="primary"
  387. class="ml20px mt30px"
  388. ghost
  389. :loading="loading"
  390. :disabled="getTableData().length == 0"
  391. @click="handleExport"
  392. >
  393. <template #icon>
  394. <SvgIcon icon="mingcute:file-export-line"></SvgIcon>
  395. </template>
  396. 导出
  397. </NButton>
  398. <NButton
  399. v-if="useAuth().hasAuth('order:user:export')"
  400. size="small"
  401. type="primary"
  402. class="ml20px mt30px"
  403. ghost
  404. :loading="loading"
  405. @click="handleExportLog"
  406. >
  407. 导出记录
  408. </NButton>
  409. </div>
  410. </template>
  411. </ZTable>
  412. <BasicModal @register="registerModalPrice" @after-leave="refresh">
  413. <LayoutTable>
  414. <ZTable
  415. :show-table-action="false"
  416. :columns="exportColumns"
  417. :api="fetchExportList"
  418. :default-params="{ exportType: 1, orderNumber }"
  419. @register="registerTable"
  420. ></ZTable>
  421. </LayoutTable>
  422. </BasicModal>
  423. </LayoutTable>
  424. </template>
  425. <style scoped></style>