report_daily.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. <template>
  2. <div class="container">
  3. <Breadcrumb :items="['menu.dashboard', 'menu.taobao.report_daily']" />
  4. <a-card class="general-card" :title="$t('menu.taobao.report_daily')">
  5. <a-row>
  6. <a-col :flex="1">
  7. <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
  8. label-align="left">
  9. <a-row :gutter="16">
  10. <a-col :span="8">
  11. <a-form-item field="query_date" :label="$t('searchTable.form.report_date')">
  12. <a-range-picker v-model="formModel.query_date" style="width: 100%"
  13. @change="search" />
  14. </a-form-item>
  15. </a-col>
  16. </a-row>
  17. </a-form>
  18. </a-col>
  19. <a-divider style="height: 32px" direction="vertical" />
  20. <a-col :flex="'86px'" style="text-align: right">
  21. <a-space direction="vertical" :size="18">
  22. <a-button type="primary" @click="search">
  23. <template #icon>
  24. <icon-search />
  25. </template>
  26. {{ $t('searchTable.form.search') }}
  27. </a-button>
  28. </a-space>
  29. </a-col>
  30. </a-row>
  31. <a-divider style="margin-top: 0" />
  32. <a-row style="margin-bottom: 16px">
  33. <a-col :span="12"> </a-col>
  34. <a-col :span="12" style="
  35. display: flex;
  36. align-items: center;
  37. justify-content: end;
  38. ">
  39. <a-tooltip :content="$t('searchTable.actions.refresh')">
  40. <div class="action-icon" @click="search"><icon-refresh size="18" /></div>
  41. </a-tooltip>
  42. <a-dropdown @select="handleSelectDensity">
  43. <a-tooltip :content="$t('searchTable.actions.density')">
  44. <div class="action-icon"><icon-line-height size="18" /></div>
  45. </a-tooltip>
  46. <template #content>
  47. <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
  48. :class="{ active: item.value === size }">
  49. <span>{{ item.name }}</span>
  50. </a-doption>
  51. </template>
  52. </a-dropdown>
  53. <a-tooltip :content="$t('searchTable.actions.columnSetting')">
  54. <a-popover trigger="click" position="bl" @popup-visible-change="popupVisibleChange">
  55. <div class="action-icon"><icon-settings size="18" /></div>
  56. <template #content>
  57. <div id="tableSetting">
  58. <div v-for="(item, index) in showColumns" :key="item.dataIndex" class="setting">
  59. <div style="
  60. margin-right: 4px;
  61. cursor: move;
  62. ">
  63. <icon-drag-arrow />
  64. </div>
  65. <div>
  66. <a-checkbox v-model="item.checked" @change="
  67. handleChange(
  68. $event,
  69. item as TableColumnData,
  70. index
  71. )
  72. ">
  73. </a-checkbox>
  74. </div>
  75. <div class="title">
  76. {{
  77. item.title === '#'
  78. ? '序列号'
  79. : item.title
  80. }}
  81. </div>
  82. </div>
  83. </div>
  84. </template>
  85. </a-popover>
  86. </a-tooltip>
  87. </a-col>
  88. </a-row>
  89. <a-table row-key="id" :loading="loading" :pagination="pagination" :summary="true" summary-text="汇总"
  90. :columns="(cloneColumns as TableColumnData[])" :scroll="scroll" :scrollbar="scrollbar"
  91. :data="renderData" :bordered="{ headerCell: true }" :size="size" :load-more="loadMore"
  92. @page-change="onPageChange" @page-size-change="onPageSizeChange">
  93. <template #xAxis="{ record }">
  94. <template v-if="record.accountName !== '' && !record.isLeaf">
  95. {{ record.accountName }}
  96. </template>
  97. <template v-else>
  98. {{ dayjs(record.report_date).format(record.isLeaf ? 'HH:mm' : 'YYYY-MM-DD') }}
  99. </template>
  100. </template>
  101. <template #accountName="{ record }">
  102. {{ record.isLeaf ? '' : record.accountName }}
  103. </template>
  104. <template #pay_ord_amt_56="{ record }">
  105. <viewOrdersModal filter-type='pay_ord_amt_56' :data="record">
  106. {{ amountFormat(record.pay_ord_amt_56) }}
  107. </viewOrdersModal>
  108. </template>
  109. <template #eff_ord_amt="{ record }">
  110. <viewOrdersModal filter-type='eff_ord_amt' :data="record">
  111. {{ amountFormat(record.eff_ord_amt) }}
  112. </viewOrdersModal>
  113. </template>
  114. <template #sett_ord_amt_56="{ record }">
  115. <viewOrdersModal filter-type='sett_ord_amt_56' :data="record">
  116. {{ amountFormat(record.sett_ord_amt_56) }}
  117. </viewOrdersModal>
  118. </template>
  119. <template #order_ord_amt="{ record }">
  120. <viewOrdersModal filter-type='order_ord_amt' :data="record">
  121. {{ amountFormat(record.order_ord_amt) }}
  122. </viewOrdersModal>
  123. </template>
  124. <template #order_ord_amt_12_14="{ record }">
  125. <a-popover popup-container="body">
  126. <viewOrdersModal filter-type='order_ord_amt_12_14' :data="record">
  127. {{ amountFormat(record.order_ord_amt_12_14) }}
  128. </viewOrdersModal>
  129. <template #content>
  130. <div style="min-width:400px;">
  131. <a-row>
  132. <a-col :span="8">已付款金额/收入: </a-col>
  133. <a-col :span="8"> {{ amountFormat(record.order_ord_amt_12) }} </a-col>
  134. <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_12) }} </a-col>
  135. </a-row>
  136. <a-row>
  137. <a-col :span="8">已收货金额/收入: </a-col>
  138. <a-col :span="8"> {{ amountFormat(record.order_ord_amt_14) }} </a-col>
  139. <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_14) }} </a-col>
  140. </a-row>
  141. <a-row>
  142. <a-col :span="8">已失效金额/收入: </a-col>
  143. <a-col :span="8"> {{ amountFormat(record.order_ord_amt_13) }} </a-col>
  144. <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_13) }} </a-col>
  145. </a-row>
  146. </div>
  147. </template>
  148. </a-popover>
  149. </template>
  150. <template #order_ord_tfee_12_14="{ record }">
  151. <a-popover popup-container="body">
  152. <div>{{ amountFormat(record.order_ord_tfee_12_14) }}</div>
  153. <template #content>
  154. <div style="min-width:400px;">
  155. <a-row>
  156. <a-col :span="8">已付款金额/收入: </a-col>
  157. <a-col :span="8"> {{ amountFormat(record.order_ord_amt_12) }} </a-col>
  158. <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_12) }} </a-col>
  159. </a-row>
  160. <a-row>
  161. <a-col :span="8">已收货金额/收入: </a-col>
  162. <a-col :span="8"> {{ amountFormat(record.order_ord_amt_14) }} </a-col>
  163. <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_14) }} </a-col>
  164. </a-row>
  165. <a-row>
  166. <a-col :span="8">已失效金额/收入: </a-col>
  167. <a-col :span="8"> {{ amountFormat(record.order_ord_amt_13) }} </a-col>
  168. <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_13) }} </a-col>
  169. </a-row>
  170. </div>
  171. </template>
  172. </a-popover>
  173. </template>
  174. <template #total_count="{ record }">
  175. <a-popover v-if="record.total_count > 0" popup-container="body" trigger="click">
  176. <a-tag color="green">{{ record.total_count }}</a-tag>
  177. <template #content>
  178. <CategoriesPercent :record="record" />
  179. </template>
  180. </a-popover>
  181. </template>
  182. <template #parse_total_count="{ record }">
  183. <a-popover v-if="record.parse_total_count > 0" popup-container="body" trigger="click">
  184. <a-tag color="green">{{ record.parse_total_count }}</a-tag>
  185. <template #content>
  186. <CategoriesPercent total_key="parse_total" :record="record" />
  187. </template>
  188. </a-popover>
  189. </template>
  190. <template #coupon_total_count="{ record }">
  191. <a-popover v-if="record.coupon_total_count > 0" popup-container="body" trigger="click">
  192. <a-tag color="green">{{ record.coupon_total_count }}</a-tag>
  193. <template #content>
  194. <CategoriesPercent total_key="coupon_total" :record="record" />
  195. </template>
  196. </a-popover>
  197. </template>
  198. <template #tool_total_count="{ record }">
  199. <a-popover v-if="record.tool_total_count > 0" popup-container="body" trigger="click">
  200. <a-tag color="green">{{ record.tool_total_count }}</a-tag>
  201. <template #content>
  202. <CategoriesPercent total_key="tool_total" :record="record" />
  203. </template>
  204. </a-popover>
  205. </template>
  206. <template #summary-cell="{ column, record }">
  207. <!--
  208. { "title": "点击人数", "dataIndex": "uclk_uv_56", "width": 100, "align": "right", "parent": { "title": "点击", "children": [ { "title": "点击人数", "dataIndex": "uclk_uv_56", "width": 100, "align": "right" }, { "title": "点击次数", "dataIndex": "uclk_pv_56", "width": 100, "align": "right" } ], "checked": true, "colSpan": 2 } }
  209. { "title": "付款金额", "slotName": "pay_ord_amt_56", "dataIndex": "pay_ord_amt_56", "width": 150, "align": "right", "parent": { "title": "付款", "children": [ { "title": "付款笔数", "dataIndex": "pay_ord_num_56", "width": 100, "align": "right" }, { "title": "付款金额", "slotName": "pay_ord_amt_56", "dataIndex": "pay_ord_amt_56", "width": 150, "align": "right" }, { "title": "付款预估收入", "dataIndex": "pay_tk_disp_tfee_56", "width": 150, "align": "right" }, { "title": "付款人数", "dataIndex": "pay_ord_uv_56", "width": 120, "align": "right" } ], "checked": true, "colSpan": 4 } } -->
  210. <template v-if="column.slotName == 'pay_ord_amt_56' ||
  211. column.slotName == 'eff_ord_amt' ||
  212. column.slotName == 'sett_ord_amt_56' ||
  213. column.slotName == 'order_ord_amt' ||
  214. column.slotName == 'order_ord_tfee' ||
  215. column.slotName == 'pay_tk_disp_tfee_56' ||
  216. column.slotName == 'eff_tk_disp_tfee' ||
  217. column.slotName == 'sett_tk_disp_tfee_56' ||
  218. column.slotName == 'order_ord_tfee_12_14' ||
  219. column.slotName == 'order_ord_amt_12_14' ||
  220. column.slotName == 'refund_order_ord_amt' ||
  221. column.slotName == 'refund_order_ord_tfee' ||
  222. column.slotName == 'refund_order_ord_amt_4' ||
  223. column.slotName == 'refund_order_ord_tfee_4' ||
  224. column.slotName == 'refund_order_ord_deduct_tfee' ||
  225. column.slotName == 'refund_order_ord_freeze_tfee' ||
  226. column.slotName == 'refund_order_ord_unfreeze_tfee'">
  227. <div>{{ amountFormat(record[column.dataIndex]) }}</div>
  228. </template>
  229. <template v-else-if="column.slotName == 'total_count'">
  230. <a-tag v-if="record.total_count > 0" color="green">{{ record.total_count }}</a-tag>
  231. </template>
  232. <template v-else-if="column.slotName == 'parse_total_count'">
  233. <a-tag v-if="record.parse_total_count > 0" color="green">{{ record.parse_total_count }}</a-tag>
  234. </template>
  235. <template v-else-if="column.slotName == 'coupon_total_count'">
  236. <a-tag v-if="record.coupon_total_count > 0" color="green">{{ record.coupon_total_count
  237. }}</a-tag>
  238. </template>
  239. <template v-else>
  240. <div>{{ toAmount(record[column.dataIndex]) }}</div>
  241. </template>
  242. </template>
  243. </a-table>
  244. </a-card>
  245. </div>
  246. </template>
  247. <script lang="ts" setup>
  248. import { useRouter } from 'vue-router';
  249. import dayjs from 'dayjs';
  250. import { computed, ref, reactive, watch, nextTick } from 'vue';
  251. import { useI18n } from 'vue-i18n';
  252. import useLoading from '@/hooks/loading';
  253. import { numberFormat, amountFormat } from '@/utils/util';
  254. import {
  255. queryTkReport,
  256. queryTkReportDailys,
  257. queryTkReportHourtrend,
  258. TkReportRecord,
  259. TkReportParams,
  260. } from '@/api/taobao';
  261. import { Pagination } from '@/types/global';
  262. import type {
  263. TableData,
  264. TableColumnData,
  265. } from '@arco-design/web-vue/es/table/interface';
  266. import cloneDeep from 'lodash/cloneDeep';
  267. import Sortable from 'sortablejs';
  268. import CategoriesPercent from './components/categories-percent.vue';
  269. import viewOrdersModal from './components/viewOrdersModal.vue';
  270. type SizeProps = 'mini' | 'small' | 'medium' | 'large';
  271. type Column = TableColumnData & { checked?: true };
  272. const generateFormModel = () => {
  273. return {
  274. accountName: '',
  275. query_date: [],
  276. current: 1,
  277. pageSize: 31,
  278. sort: 'report_date',
  279. order: 'descending',
  280. };
  281. };
  282. const router = useRouter();
  283. const { loading, setLoading } = useLoading(true);
  284. const { t } = useI18n();
  285. const renderData = ref<TkReportRecord[]>([]);
  286. const formModel = ref(generateFormModel());
  287. const cloneColumns = ref<Column[]>([]);
  288. const showColumns = ref<Column[]>([]);
  289. const size = ref<SizeProps>('medium');
  290. const scrollbar = ref(true);
  291. const scroll = {
  292. x: '100%',
  293. y: '100%',
  294. maxHeight: 'calc( 100vh - 420px)',
  295. };
  296. const basePagination: Pagination = {
  297. current: 1,
  298. pageSize: 31,
  299. };
  300. const pagination = reactive({
  301. ...basePagination,
  302. showTotal: true,
  303. showJumper: true,
  304. showMore: true,
  305. showPageSize: true,
  306. pageSizeOptions: [10, 20, 30, 31, 50, 100, 200, 500],
  307. sizePageSize: true,
  308. });
  309. const densityList = computed(() => [
  310. {
  311. name: t('searchTable.size.mini'),
  312. value: 'mini',
  313. },
  314. {
  315. name: t('searchTable.size.small'),
  316. value: 'small',
  317. },
  318. {
  319. name: t('searchTable.size.medium'),
  320. value: 'medium',
  321. },
  322. {
  323. name: t('searchTable.size.large'),
  324. value: 'large',
  325. },
  326. ]);
  327. const toAmount = (val: any): any => {
  328. console.log(val);
  329. if (typeof val === 'number' && !Number.isNaN(val)) {
  330. return parseFloat(val.toFixed(2));
  331. }
  332. return val;
  333. }
  334. const columns = computed<TableColumnData[]>(() => [
  335. {
  336. title: '日期',
  337. dataIndex: 'xAxis',
  338. slotName: 'xAxis',
  339. width: 250,
  340. fixed: 'left',
  341. },
  342. {
  343. title: '点击',
  344. children: [
  345. {
  346. title: '下单率',
  347. slotName: 'order_rate',
  348. render: ({ record }: { record: TkReportRecord }) => {
  349. if (record.uclk_pv_56 === 0) return `0%`;
  350. const rate = (record.eff_ord_num / record.uclk_pv_56) * 100;
  351. return `${rate.toFixed(2)}%`;
  352. },
  353. width: 100,
  354. align: 'right'
  355. },
  356. {
  357. title: '点击人数',
  358. dataIndex: 'uclk_uv_56',
  359. width: 100,
  360. align: 'right'
  361. },
  362. {
  363. title: '点击次数',
  364. dataIndex: 'uclk_pv_56',
  365. width: 100,
  366. align: 'right'
  367. },
  368. ]
  369. },
  370. {
  371. title: '付款',
  372. children: [
  373. {
  374. title: '付款笔数',
  375. dataIndex: 'pay_ord_num_56',
  376. width: 100,
  377. align: 'right',
  378. },
  379. {
  380. title: '订单付款数',
  381. dataIndex: 'order_ord_num',
  382. width: 110,
  383. },
  384. {
  385. title: '付款金额',
  386. slotName: 'pay_ord_amt_56',
  387. dataIndex: 'pay_ord_amt_56',
  388. width: 150,
  389. align: 'right',
  390. // render: (e: any) => amountFormat(e.record.pay_ord_amt_56)
  391. },
  392. {
  393. title: '付款预估收入',
  394. dataIndex: 'pay_tk_disp_tfee_56',
  395. slotName: 'pay_tk_disp_tfee_56',
  396. width: 150,
  397. align: 'right',
  398. render: (e: any) => amountFormat(e.record.pay_tk_disp_tfee_56)
  399. },
  400. {
  401. title: '付款人数',
  402. dataIndex: 'pay_ord_uv_56',
  403. width: 120,
  404. align: 'right',
  405. },
  406. ]
  407. },
  408. {
  409. title: '有效付款',
  410. children: [
  411. {
  412. title: '有效付款笔数',
  413. dataIndex: 'eff_ord_num',
  414. width: 150,
  415. align: 'right',
  416. },
  417. {
  418. title: '有效付款金额',
  419. slotName: 'eff_ord_amt',
  420. dataIndex: 'eff_ord_amt',
  421. width: 150,
  422. align: 'right',
  423. // render: (e: any) => amountFormat(e.record.eff_ord_amt)
  424. },
  425. {
  426. title: '有效付款预估收入',
  427. dataIndex: 'eff_tk_disp_tfee',
  428. slotName: 'eff_tk_disp_tfee',
  429. width: 150,
  430. align: 'right',
  431. render: (e: any) => amountFormat(e.record.eff_tk_disp_tfee)
  432. },
  433. ]
  434. },
  435. {
  436. title: '结算',
  437. children: [
  438. {
  439. title: '结算笔数',
  440. dataIndex: 'sett_ord_num_56',
  441. width: 100,
  442. align: 'right',
  443. },
  444. {
  445. title: '结算金额',
  446. slotName: 'sett_ord_amt_56',
  447. dataIndex: 'sett_ord_amt_56',
  448. width: 150,
  449. align: 'right',
  450. // render: (e: any) => amountFormat(e.record.sett_ord_amt_56)
  451. },
  452. {
  453. title: '结算预估收入',
  454. dataIndex: 'sett_tk_disp_tfee_56',
  455. slotName: 'sett_tk_disp_tfee_56',
  456. width: 150,
  457. align: 'right',
  458. render: (e: any) => amountFormat(e.record.sett_tk_disp_tfee_56)
  459. },
  460. ]
  461. },
  462. {
  463. title: '所属订单结算金额',
  464. children: [
  465. {
  466. title: '结算金额',
  467. slotName: 'order_ord_amt',
  468. dataIndex: 'order_ord_amt',
  469. width: 150,
  470. align: 'right',
  471. // render: (e: any) => amountFormat(e.record.order_ord_amt)
  472. },
  473. {
  474. title: '结算收入',
  475. width: 150,
  476. align: 'right',
  477. dataIndex: 'order_ord_tfee',
  478. slotName: 'order_ord_tfee',
  479. render: (e: any) => amountFormat(e.record.order_ord_tfee)
  480. },
  481. {
  482. title: '待结算金额',
  483. slotName: 'order_ord_amt_12_14',
  484. dataIndex: 'order_ord_amt_12_14',
  485. width: 150,
  486. align: 'right',
  487. },
  488. {
  489. title: '待结算收入',
  490. slotName: 'order_ord_tfee_12_14',
  491. dataIndex: 'order_ord_tfee_12_14',
  492. width: 120,
  493. align: 'right',
  494. },
  495. ]
  496. },
  497. {
  498. title: '订单维权',
  499. children: [
  500. {
  501. title: '扣款收入',
  502. width: 120,
  503. align: 'right',
  504. dataIndex: 'refund_order_ord_deduct_tfee',
  505. slotName: 'refund_order_ord_deduct_tfee',
  506. render: (e: any) => amountFormat(e.record.refund_order_ord_deduct_tfee)
  507. },
  508. {
  509. title: '冻结金额',
  510. slotName: 'refund_order_ord_freeze_tfee',
  511. dataIndex: 'refund_order_ord_freeze_tfee',
  512. width: 150,
  513. align: 'right',
  514. render: (e: any) => amountFormat(e.record.refund_order_ord_freeze_tfee)
  515. },
  516. {
  517. title: '解冻金额',
  518. width: 120,
  519. align: 'right',
  520. dataIndex: 'refund_order_ord_unfreeze_tfee',
  521. slotName: 'refund_order_ord_unfreeze_tfee',
  522. render: (e: any) => amountFormat(e.record.refund_order_ord_unfreeze_tfee)
  523. },
  524. ]
  525. },
  526. {
  527. title: '所属订单维权金额',
  528. children: [
  529. {
  530. title: '维权金额(扣款)',
  531. slotName: 'refund_order_ord_amt',
  532. dataIndex: 'refund_order_ord_amt',
  533. width: 150,
  534. align: 'right',
  535. render: (e: any) => amountFormat(e.record.refund_order_ord_amt)
  536. },
  537. {
  538. title: '扣款收入',
  539. width: 120,
  540. align: 'right',
  541. dataIndex: 'refund_order_ord_tfee',
  542. slotName: 'refund_order_ord_tfee',
  543. render: (e: any) => amountFormat(e.record.refund_order_ord_tfee)
  544. },
  545. {
  546. title: '维权金额(冻结)',
  547. slotName: 'refund_order_ord_amt_4',
  548. dataIndex: 'refund_order_ord_amt_4',
  549. width: 150,
  550. align: 'right',
  551. render: (e: any) => amountFormat(e.record.refund_order_ord_amt_4)
  552. },
  553. {
  554. title: '冻结收入',
  555. width: 120,
  556. align: 'right',
  557. dataIndex: 'refund_order_ord_tfee_4',
  558. slotName: 'refund_order_ord_tfee_4',
  559. render: (e: any) => amountFormat(e.record.refund_order_ord_tfee_4)
  560. },
  561. ]
  562. },
  563. {
  564. title: '转链API调用',
  565. children: [
  566. {
  567. title: '调用',
  568. slotName: 'parse_total_count',
  569. dataIndex: 'parse_total_count',
  570. width: 100,
  571. align: 'right'
  572. },
  573. {
  574. title: '成功',
  575. dataIndex: 'parse_success_count',
  576. width: 100,
  577. align: 'right'
  578. },
  579. {
  580. title: '成功(%)',
  581. dataIndex: 'parse_success_percentage',
  582. width: 90,
  583. align: 'right'
  584. },
  585. {
  586. title: '放弃',
  587. dataIndex: 'parse_abandon_count',
  588. width: 100,
  589. align: 'right'
  590. },
  591. {
  592. title: '放弃(%)',
  593. dataIndex: 'parse_abandon_percentage',
  594. width: 90,
  595. align: 'right'
  596. },
  597. ]
  598. },
  599. {
  600. title: '优惠券API调用',
  601. children: [
  602. {
  603. title: '调用',
  604. slotName: 'coupon_total_count',
  605. dataIndex: 'coupon_total_count',
  606. width: 100,
  607. align: 'right'
  608. },
  609. {
  610. title: '成功',
  611. dataIndex: 'coupon_success_count',
  612. width: 100,
  613. align: 'right'
  614. },
  615. {
  616. title: '成功(%)',
  617. dataIndex: 'coupon_success_percentage',
  618. width: 90,
  619. align: 'right'
  620. },
  621. {
  622. title: '放弃',
  623. dataIndex: 'coupon_abandon_count',
  624. width: 100,
  625. align: 'right'
  626. },
  627. {
  628. title: '放弃(%)',
  629. dataIndex: 'coupon_abandon_percentage',
  630. width: 90,
  631. align: 'right'
  632. },
  633. ]
  634. },
  635. {
  636. title: '工具API调用',
  637. children: [
  638. {
  639. title: '调用',
  640. dataIndex: 'tool_total_count',
  641. slotName: 'tool_total_count',
  642. width: 100,
  643. align: 'right'
  644. },
  645. {
  646. title: '成功',
  647. dataIndex: 'tool_success_count',
  648. width: 100,
  649. align: 'right'
  650. },
  651. {
  652. title: '成功(%)',
  653. dataIndex: 'tool_success_percentage',
  654. width: 90,
  655. align: 'right'
  656. },
  657. {
  658. title: '放弃',
  659. dataIndex: 'tool_abandon_count',
  660. width: 100,
  661. align: 'right'
  662. },
  663. {
  664. title: '放弃(%)',
  665. dataIndex: 'tool_abandon_percentage',
  666. width: 90,
  667. align: 'right'
  668. },
  669. ]
  670. },
  671. {
  672. title: '第三方API调用',
  673. children: [
  674. {
  675. title: '调用',
  676. dataIndex: 'total_count',
  677. slotName: 'total_count',
  678. width: 100,
  679. align: 'right'
  680. },
  681. {
  682. title: '成功',
  683. dataIndex: 'success_count',
  684. width: 100,
  685. align: 'right'
  686. },
  687. {
  688. title: '成功(%)',
  689. dataIndex: 'success_percentage',
  690. width: 90,
  691. align: 'right'
  692. },
  693. {
  694. title: '放弃',
  695. dataIndex: 'abandon_count',
  696. width: 100,
  697. align: 'right'
  698. },
  699. {
  700. title: '放弃(%)',
  701. dataIndex: 'abandon_percentage',
  702. width: 90,
  703. align: 'right'
  704. },
  705. ]
  706. },
  707. {
  708. title: '最后更新时间',
  709. dataIndex: 'last_time',
  710. width: 200,
  711. align: 'center'
  712. },
  713. {
  714. title: '收藏人数',
  715. dataIndex: 'uclt_uv_56',
  716. width: 100,
  717. },
  718. {
  719. title: '加购人数',
  720. dataIndex: 'ucart_uv_56',
  721. width: 100,
  722. },
  723. {
  724. title: '定金笔数',
  725. dataIndex: 'dep_ord_num_56',
  726. width: 100,
  727. },
  728. {
  729. title: '定金金额',
  730. dataIndex: 'dep_ord_dep_amt_56',
  731. width: 120,
  732. },
  733. ]);
  734. const fetchData = async (
  735. params: TkReportParams = {
  736. current: 1,
  737. pageSize: basePagination.pageSize,
  738. sort: 'report_date',
  739. order: 'descending',
  740. }
  741. ) => {
  742. setLoading(true);
  743. try {
  744. console.log(params)
  745. const { data } = await queryTkReportDailys(params);
  746. console.log(data);
  747. if (!data) return;
  748. let list: TableData[] = [];
  749. list = data.list.map((item: TkReportRecord) => ({
  750. ...item,
  751. order_ord_amt_12_14: item.order_ord_amt_12 + item.order_ord_amt_14,
  752. order_ord_tfee_12_14: item.order_ord_tfee_12 + item.order_ord_tfee_14,
  753. }));
  754. renderData.value = list;
  755. pagination.current = data.page;
  756. pagination.total = data.count;
  757. console.log(data);
  758. } catch (err) {
  759. console.log(err);
  760. // you can report use errorHandler or other
  761. } finally {
  762. setLoading(false);
  763. }
  764. };
  765. const loadMore = async (
  766. row: TableData,
  767. done: (data: TableData[]) => void
  768. ) => {
  769. setLoading(true);
  770. try {
  771. let list: TableData[] = [];
  772. if (row.accountName === '') {
  773. const params: TkReportParams = {
  774. query_date: [row.report_date, row.report_date],
  775. current: 1,
  776. pageSize: 999,
  777. sort: 'report_date',
  778. order: 'descending',
  779. };
  780. const { data } = await queryTkReport(params);
  781. console.log(data);
  782. if (!data) return;
  783. list = data.list.map((item: TkReportRecord) => ({
  784. ...item,
  785. order_ord_amt_12_14: item.order_ord_amt_12 + item.order_ord_amt_14,
  786. order_ord_tfee_12_14: item.order_ord_tfee_12 + item.order_ord_tfee_14,
  787. isLeaf: false,
  788. }));
  789. } else {
  790. const params: TkReportParams = {
  791. query_date: [row.report_date, row.report_date],
  792. accountId: row.accountId,
  793. current: 1,
  794. pageSize: 24,
  795. sort: 'report_date',
  796. order: 'descending',
  797. };
  798. const { data } = await queryTkReportHourtrend(params);
  799. console.log(data);
  800. if (!data) return;
  801. list = data.list.map((item: TkReportRecord) => ({
  802. ...item,
  803. order_ord_amt_12_14: item.order_ord_amt_12 + item.order_ord_amt_14,
  804. order_ord_tfee_12_14: item.order_ord_tfee_12 + item.order_ord_tfee_14,
  805. isLeaf: true,
  806. }));
  807. }
  808. done(list);
  809. } catch (err) {
  810. console.log(err);
  811. // you can report use errorHandler or other
  812. } finally {
  813. setLoading(false);
  814. }
  815. };
  816. const search = () => {
  817. fetchData({
  818. ...basePagination,
  819. ...formModel.value,
  820. } as unknown as TkReportParams);
  821. };
  822. const onPageChange = (current: number) => {
  823. fetchData({
  824. ...basePagination,
  825. ...formModel.value,
  826. current
  827. });
  828. };
  829. const onPageSizeChange = (current: number) => {
  830. basePagination.pageSize = current;
  831. pagination.pageSize = current;
  832. fetchData({
  833. ...basePagination,
  834. ...formModel.value,
  835. pageSize: current,
  836. current: 1,
  837. });
  838. };
  839. fetchData();
  840. const reset = () => {
  841. formModel.value = generateFormModel();
  842. };
  843. const handleSelectDensity = (
  844. val: string | number | Record<string, any> | undefined,
  845. e: Event
  846. ) => {
  847. size.value = val as SizeProps;
  848. };
  849. const handleChange = (
  850. checked: boolean | (string | boolean | number)[],
  851. column: Column,
  852. index: number
  853. ) => {
  854. if (!checked) {
  855. cloneColumns.value = showColumns.value.filter(
  856. (item) => item.dataIndex !== column.dataIndex
  857. );
  858. } else {
  859. cloneColumns.value.splice(index, 0, column);
  860. }
  861. };
  862. const exchangeArray = <T extends Array<any>>(
  863. array: T,
  864. beforeIdx: number,
  865. newIdx: number,
  866. isDeep = false
  867. ): T => {
  868. const newArray = isDeep ? cloneDeep(array) : array;
  869. if (beforeIdx > -1 && newIdx > -1) {
  870. // 先替换后面的,然后拿到替换的结果替换前面的
  871. newArray.splice(
  872. beforeIdx,
  873. 1,
  874. newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
  875. );
  876. }
  877. return newArray;
  878. };
  879. const popupVisibleChange = (val: boolean) => {
  880. if (val) {
  881. nextTick(() => {
  882. const el = document.getElementById(
  883. 'tableSetting'
  884. ) as HTMLElement;
  885. const sortable = new Sortable(el, {
  886. onEnd(e: any) {
  887. const { oldIndex, newIndex } = e;
  888. exchangeArray(cloneColumns.value, oldIndex, newIndex);
  889. exchangeArray(showColumns.value, oldIndex, newIndex);
  890. },
  891. });
  892. });
  893. }
  894. };
  895. watch(
  896. () => columns.value,
  897. (val) => {
  898. cloneColumns.value = cloneDeep(val);
  899. cloneColumns.value.forEach((item, index) => {
  900. item.checked = true;
  901. });
  902. showColumns.value = cloneDeep(cloneColumns.value);
  903. },
  904. { deep: true, immediate: true }
  905. );
  906. </script>
  907. <script lang="ts">
  908. export default {
  909. name: 'SearchTable',
  910. };
  911. </script>
  912. <style scoped lang="less">
  913. .container {
  914. padding: 0 20px 20px 20px;
  915. }
  916. :deep(.arco-table-th) {
  917. &:last-child {
  918. .arco-table-th-item-title {
  919. margin-left: 16px;
  920. }
  921. }
  922. }
  923. .action-icon {
  924. margin-left: 12px;
  925. cursor: pointer;
  926. }
  927. .active {
  928. color: #0960bd;
  929. background-color: #e3f4fc;
  930. }
  931. .setting {
  932. display: flex;
  933. align-items: center;
  934. width: 200px;
  935. .title {
  936. margin-left: 12px;
  937. cursor: pointer;
  938. }
  939. }
  940. </style>