dodo hold 1 rok temu
rodzic
commit
52090a7b84

+ 1 - 1
config/vite.config.dev.ts

@@ -7,7 +7,7 @@ export default mergeConfig(
         mode: 'development',
         server: {
             open: true,
-            port: 7173,
+            port: 7174,
             fs: {
                 strict: true,
             },

+ 10 - 15
src/api/app.ts

@@ -1,5 +1,5 @@
 import axios from 'axios';
-import type { ListRes } from './base';
+import type { ListRes, FormRes } from './base';
 
 /*
 daily_logs
@@ -47,6 +47,7 @@ export interface DailyLogRecord {
 export interface DailyLogParams extends Partial<DailyLogRecord> {
     query_date?: string[]; // 覆盖 report_date 的类型为字符串数组
     accountName?: string;
+    query_channel?: string;
     current: number;
     pageSize: number;
     sort?: string;
@@ -60,9 +61,6 @@ export function queryDailyLog(data: DailyLogParams) {
     return axios.post<DailyLogRes>('/api/report/daily_list', data);
 }
 
-
-
-
 export interface ReportParams extends Partial<DailyLogRecord> {
     accountId?: number;
     total_key?: string;
@@ -84,18 +82,15 @@ export interface ReportChartRes {
     data2: ChartDataResponse[];
 }
 
-
 export function queryReportChartData(data: ReportParams) {
     return axios.post<ReportChartRes>('/api/report/chartData', data);
 }
 
-// export function queryTkReport(data: TkReportParams) {
-//     const url = ForwardAPI('/api/report/report_list');
-//     return axios.post<TkReportRes>(url, data);
-// }
-
-// queryTkReport,
-// queryTkReportDailys,
-// queryTkReportHourtrend,
-// TkReportRecord,
-// TkReportParams,
+export interface UpdateAccountModel {
+    id: number;
+    name: string;
+    val: any;
+}
+export function UpdateAccount(path: string, data: UpdateAccountModel) {
+    return axios.post<FormRes>(path, data);
+}

+ 11 - 11
src/api/base.ts

@@ -1,14 +1,14 @@
-
-
 export interface ListRes {
-  msg: string;
-  code: number;
-  page: number;
-  pageCount: number;
-  size: number;
-  count: number;
+    msg: string;
+    code: number;
+    page: number;
+    pageCount: number;
+    size: number;
+    count: number;
 }
 
-
-
-
+export interface FormRes {
+    msg: string;
+    code: number;
+    success: boolean;
+}

+ 43 - 17
src/api/jd.ts

@@ -1,21 +1,5 @@
 import axios from 'axios';
-import type { ListRes } from './base';
-
-export interface FormRes {
-    msg: string;
-    code: number;
-    success: boolean;
-}
-
-export interface JdUpdateAccountModel {
-    id: number;
-    name: string;
-    val: any;
-}
-
-export function JdUpdateAccount(data: JdUpdateAccountModel) {
-    return axios.post<FormRes>('/api/JdUnion/update', data);
-}
+import type { ListRes, FormRes } from './base';
 
 export interface UpdateCookieModel {
     cookie: string;
@@ -63,6 +47,7 @@ export interface JdPoolRecord {
     app_secret: string;
     user_agent: string;
     cookies: string;
+
     time_range: number;
 }
 
@@ -81,3 +66,44 @@ export interface JdPoolRes extends ListRes {
 export function queryJdPool(data: JdPoolParams) {
     return axios.post<JdPoolRes>('/api/JdUnion/list', data);
 }
+
+export interface JdSettleBillRecord {
+    id: number;
+    accountName: string;
+    report_date: Date;
+    create_time: Date;
+    last_time: Date;
+
+    clickNum: number;
+    cosFee: number;
+
+    cosPrice: number;
+    finishCosFee: number;
+
+    finishCosPrice: number;
+    finishOrderNum: number;
+
+    orderNum: number;
+}
+
+export interface JdSettleBillsParams extends Partial<JdSettleBillRecord> {
+    keyword?: string;
+    query_date?: string[]; // 覆盖 report_date 的类型为字符串数组
+    current: number;
+    pageSize: number;
+    sort?: string;
+    order?: string;
+}
+
+export interface JdSettleBillsRes extends ListRes {
+    list: JdSettleBillRecord[];
+}
+export function queryJdSettleBillsTotal(data: JdSettleBillsParams) {
+    return axios.post<JdSettleBillsRes>(
+        '/api/JdUnion/settle_bills_total',
+        data
+    );
+}
+export function queryJdSettleBills(data: JdSettleBillsParams) {
+    return axios.post<JdSettleBillsRes>('/api/JdUnion/settle_bills', data);
+}

+ 9 - 1
src/api/taobao.ts

@@ -7,6 +7,7 @@ function ForwardAPI(url: string) {
 
 export interface UpdateConfigModel {
     cookie: string;
+    blacklist_oaid: string;
     ignorePercentage: number;
     jdIgnorePercentage: number;
     pass_salt: string;
@@ -57,7 +58,6 @@ export interface TkPoolRecord {
     phone: string;
     cookies: string;
     create_time: Date;
-    daily_income_limit: number;
     current_amt: number;
     description: string;
     floorId: string;
@@ -80,6 +80,14 @@ export interface TkPoolRecord {
     appkey: string;
     appSecret: string;
     open_pid: string;
+
+    
+    daily_income_limit: number;
+    daily_calls_limit: number;
+    current_hourly_calls: number;
+    hourly_calls_limit: number;
+    current_daily_calls: number;
+    time_range: number;
 }
 
 export interface FormRes {

+ 5 - 3
src/views/jd/components/WorkHourModel.vue → src/components/WorkHourModel.vue

@@ -20,13 +20,14 @@
 
 import useLoading from '@/hooks/loading';
 import { defineProps, ref, reactive, defineEmits } from 'vue';
-import { JdUpdateAccountModel, JdUpdateAccount } from '@/api/jd';
+import { UpdateAccountModel, UpdateAccount } from '@/api/app';
 import { Message } from '@arco-design/web-vue';
 
 const { loading, setLoading } = useLoading(true);
 
 const props = defineProps<{
     record: any;
+    path: string;
 }>();
 
 const emits = defineEmits(['change']);
@@ -131,12 +132,13 @@ const handleOk = async () => {
         id: props.record.id,
         name: "time_range",
         val: timeRange
-    } as JdUpdateAccountModel;
+    } as UpdateAccountModel;
 
     setLoading(true);
     try {
 
-        const { data } = await JdUpdateAccount(args);
+        const { data } = await UpdateAccount(props.path, args);
+        // const { data } = await UpdateAccount('/api/JdUnion/update', args);
         console.log(data, data.msg);
         const msg = data.msg || '更新成功!';
         if (data.success) {

+ 2 - 0
src/locale/en-US/taoke.ts

@@ -30,6 +30,8 @@ export default {
     'menu.taobao.bill_dailys': 'Expected revenue',
     'menu.taobao.orders': 'Orders',
 
+    'menu.jd.bill_dailys': '效果统计-推广效果',
+    
     'menu.list.searchTable': 'Search Table',
     'searchTable.form.number': 'Set Number',
     'searchTable.form.number.placeholder': 'Please enter Set Number',

+ 3 - 0
src/locale/zh-CN/taoke.ts

@@ -32,6 +32,9 @@ export default {
   'menu.taobao.bill_dailys': '联盟预计收益',
   'menu.taobao.orders': '联盟推广订单',
 
+  'menu.jd.bill_dailys': '效果统计-推广效果',
+
+
   'menu.list.searchTable': '查询表格',
   'searchTable.form.number': '集合编号',
   'searchTable.form.number.placeholder': '请输入集合编号',

+ 29 - 29
src/router/routes/modules/dashboard.ts

@@ -2,37 +2,37 @@ import { DEFAULT_LAYOUT } from '../base';
 import { AppRouteRecordRaw } from '../types';
 
 const DASHBOARD: AppRouteRecordRaw = {
-  path: '/dashboard',
-  name: 'dashboard',
-  component: DEFAULT_LAYOUT,
-  meta: {
-    locale: 'menu.dashboard',
-    requiresAuth: true,
-    icon: 'icon-dashboard',
-    order: 0,
-  },
-  children: [
-    {
-      path: 'workplace',
-      name: 'Workplace',
-      component: () => import('@/views/dashboard/workplace/index.vue'),
-      meta: {
-        locale: 'menu.dashboard.workplace',
+    path: '/dashboard',
+    name: 'dashboard',
+    component: DEFAULT_LAYOUT,
+    meta: {
+        locale: 'menu.dashboard',
         requiresAuth: true,
-        roles: ['*'],
-      },
+        icon: 'icon-dashboard',
+        order: 0,
     },
-    {
-      path: 'dailyLog',
-      name: 'dailyLog',
-      component: () => import('@/views/dashboard/dailyLog/index.vue'),
-      meta: {
-        locale: 'menu.dashboard.dailyLog',
-        requiresAuth: true,
-        roles: ['*'],
-      },
-    },
-  ],
+    children: [
+        {
+            path: 'workplace',
+            name: 'Workplace',
+            component: () => import('@/views/dashboard/workplace/index.vue'),
+            meta: {
+                locale: 'menu.dashboard.workplace',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+        {
+            path: 'dailyLog',
+            name: 'dailyLog',
+            component: () => import('@/views/dashboard/dailyLog/index.vue'),
+            meta: {
+                locale: 'menu.dashboard.dailyLog',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+    ],
 };
 
 export default DASHBOARD;

+ 10 - 0
src/router/routes/modules/jd.ts

@@ -32,6 +32,16 @@ const TBCOUPON: AppRouteRecordRaw = {
                 roles: ['*'],
             },
         },
+        {
+            path: 'bill_dailys',
+            name: 'jd_bill_dailys',
+            component: () => import('@/views/jd/bill_dailys.vue'),
+            meta: {
+                locale: 'menu.jd.bill_dailys',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
     ],
 };
 

+ 751 - 0
src/views/dashboard/dailyLog/components/all.vue

@@ -0,0 +1,751 @@
+<template>
+    <a-row>
+        <a-col :flex="1">
+            <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
+                label-align="left">
+                <a-row :gutter="16">
+                    <a-col :span="8">
+                        <a-form-item field="query_date" :label="$t('searchTable.form.report_date')">
+                            <a-range-picker v-model="formModel.query_date" style="width: 100%" @change="search" />
+                        </a-form-item>
+                    </a-col>
+                </a-row>
+            </a-form>
+        </a-col>
+        <a-divider style="height: 32px" direction="vertical" />
+        <a-col :flex="'86px'" style="text-align: right">
+            <a-space direction="vertical" :size="18">
+                <a-button type="primary" @click="search">
+                    <template #icon>
+                        <icon-search />
+                    </template>
+                    {{ $t('searchTable.form.search') }}
+                </a-button>
+            </a-space>
+        </a-col>
+    </a-row>
+    <a-divider style="margin-top: 0" />
+    <a-row style="margin-bottom: 16px">
+        <a-col :span="12"> </a-col>
+        <a-col :span="12" style="
+                        display: flex;
+                        align-items: center;
+                        justify-content: end;
+                    ">
+            <a-tooltip :content="$t('searchTable.actions.refresh')">
+                <div class="action-icon" @click="search"><icon-refresh size="18" /></div>
+            </a-tooltip>
+            <a-dropdown @select="handleSelectDensity">
+                <a-tooltip :content="$t('searchTable.actions.density')">
+                    <div class="action-icon"><icon-line-height size="18" /></div>
+                </a-tooltip>
+                <template #content>
+                    <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
+                        :class="{ active: item.value === size }">
+                        <span>{{ item.name }}</span>
+                    </a-doption>
+                </template>
+            </a-dropdown>
+            <a-tooltip :content="$t('searchTable.actions.columnSetting')">
+                <a-popover trigger="click" position="bl" @popup-visible-change="popupVisibleChange">
+                    <div class="action-icon"><icon-settings size="18" /></div>
+                    <template #content>
+                        <div id="tableSetting">
+                            <div v-for="(item, index) in showColumns" :key="item.dataIndex" class="setting">
+                                <div style="
+                                                margin-right: 4px;
+                                                cursor: move;
+                                            ">
+                                    <icon-drag-arrow />
+                                </div>
+                                <div>
+                                    <a-checkbox v-model="item.checked" @change="
+                                        handleChange(
+                                            $event,
+                                            item as TableColumnData,
+                                            index
+                                        )
+                                        ">
+                                    </a-checkbox>
+                                </div>
+                                <div class="title">
+                                    {{
+                                        item.title === '#'
+                                            ? '序列号'
+                                            : item.title
+                                    }}
+                                </div>
+                            </div>
+                        </div>
+                    </template>
+                </a-popover>
+            </a-tooltip>
+        </a-col>
+    </a-row>
+
+    <a-table row-key="id" :loading="loading" :pagination="pagination" :summary="true" summary-text="汇总"
+        :columns="(cloneColumns as TableColumnData[])" :scroll="scroll" :scrollbar="scrollbar" :data="renderData"
+        :bordered="{ headerCell: true }" :size="size" :load-more="loadMore" @page-change="onPageChange"
+        @page-size-change="onPageSizeChange">
+
+        <template #index="{ rowIndex }">
+            {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
+        </template>
+        <template #xAxis="{ record }">
+            <template v-if="record.isLeaf">
+                {{ record.accountName }}
+            </template>
+            <template v-else>
+                {{ dayjs(record.log_date).format('YYYY-MM-DD') }}
+            </template>
+        </template>
+
+        <template #total_count="{ record }">
+            <a-popover v-if="record.total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #parse_total_count="{ record }">
+            <a-popover v-if="record.parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #jd_parse_total_count="{ record }">
+            <a-popover v-if="record.jd_parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.jd_parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="jd_parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #coupon_total_count="{ record }">
+            <a-popover v-if="record.coupon_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.coupon_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="coupon_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+        <template #tool_total_count="{ record }">
+            <a-popover v-if="record.tool_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.tool_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="tool_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+        <template #ks_parse_total_count="{ record }">
+            <a-popover v-if="record.ks_parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.ks_parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="ks_parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #pdd_parse_total_count="{ record }">
+            <a-popover v-if="record.pdd_parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.pdd_parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="pdd_parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+
+        <template #summary-cell="{ column, record }">
+            <template v-if="column.slotName == 'total_count'">
+                <a-tag v-if="record.total_count > 0" color="green">{{ record.total_count }}</a-tag>
+            </template>
+            <template v-else-if="column.slotName == 'parse_total_count'">
+                <a-tag v-if="record.parse_total_count > 0" color="green">
+                    {{ record.parse_total_count }}</a-tag>
+            </template>
+            <template v-else-if="column.slotName == 'coupon_total_count'">
+                <a-tag v-if="record.coupon_total_count > 0" color="green">
+                    {{ record.coupon_total_count }}</a-tag>
+            </template>
+
+            <template v-else-if="column.slotName == 'jd_parse_total_count'">
+                <a-tag v-if="record.jd_parse_total_count > 0" color="green">
+                    {{ record.jd_parse_total_count }}</a-tag>
+            </template>
+
+            <template v-else-if="column.slotName == 'ks_parse_total_count'">
+                <a-tag v-if="record.ks_parse_total_count > 0" color="green">
+                    {{ record.ks_parse_total_count }}</a-tag>
+            </template>
+
+            <template v-else-if="column.slotName == 'pdd_parse_total_count'">
+                <a-tag v-if="record.pdd_parse_total_count > 0" color="green">
+                    {{ record.pdd_parse_total_count }}</a-tag>
+            </template>
+            <template v-else>
+                <div>{{ toAmount(record[column.dataIndex]) }}</div>
+            </template>
+
+        </template>
+
+
+
+    </a-table>
+</template>
+
+<script lang="ts" setup>
+import { useRouter } from 'vue-router';
+import { computed, ref, reactive, watch, nextTick } from 'vue';
+import { useI18n } from 'vue-i18n';
+import dayjs from 'dayjs';
+import useLoading from '@/hooks/loading';
+import { queryDailyLog, DailyLogRecord, DailyLogParams } from '@/api/app';
+import { Pagination } from '@/types/global';
+import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
+import type { TableData, TableColumnData } from '@arco-design/web-vue/es/table/interface';
+import cloneDeep from 'lodash/cloneDeep';
+import Sortable from 'sortablejs';
+import CategoriesPercent from './categories-percent.vue';
+
+type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+type Column = TableColumnData & { checked?: true };
+
+const generateFormModel = () => {
+    return {
+        accountName: 'all',
+        current: 1,
+        pageSize: 31,
+        sort: 'log_date',
+        order: 'descending'
+
+    };
+};
+const router = useRouter();
+
+const { loading, setLoading } = useLoading(true);
+const { t } = useI18n();
+const renderData = ref<DailyLogRecord[]>([]);
+const formModel = ref(generateFormModel());
+const cloneColumns = ref<Column[]>([]);
+const showColumns = ref<Column[]>([]);
+
+const size = ref<SizeProps>('medium');
+
+const scrollbar = ref(true);
+const scroll = {
+    x: '100%',
+    y: '100%',
+    maxHeight: 'calc( 100vh - 420px)',
+};
+
+const basePagination: Pagination = {
+    current: 1,
+    pageSize: 31,
+};
+const pagination = reactive({
+    ...basePagination,
+    showTotal: true,
+    showJumper: true,
+    showMore: true,
+    showPageSize: true,
+    pageSizeOptions: [10, 20, 30, 31, 50, 100, 200],
+    sizePageSize: true,
+
+});
+const densityList = computed(() => [
+    {
+        name: t('searchTable.size.mini'),
+        value: 'mini',
+    },
+    {
+        name: t('searchTable.size.small'),
+        value: 'small',
+    },
+    {
+        name: t('searchTable.size.medium'),
+        value: 'medium',
+    },
+    {
+        name: t('searchTable.size.large'),
+        value: 'large',
+    },
+]);
+
+
+const toAmount = (val: any): any => {
+    console.log(val);
+    if (typeof val === 'number' && !Number.isNaN(val)) {
+        return parseFloat(val.toFixed(2));
+    }
+    return val;
+}
+
+const columns = computed<TableColumnData[]>(() => [
+    {
+        title: '日期',
+        dataIndex: 'xAxis',
+        slotName: 'xAxis',
+        width: 250,
+        fixed: 'left',
+    },
+    {
+        title: '转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'parse_total_count',
+                dataIndex: 'parse_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'parse_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'parse_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'parse_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'parse_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+    {
+        title: '优惠券API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'coupon_total_count',
+                dataIndex: 'coupon_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'coupon_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'coupon_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'coupon_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'coupon_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+    {
+        title: '京东转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'jd_parse_total_count',
+                dataIndex: 'jd_parse_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'jd_parse_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'jd_parse_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'jd_parse_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'jd_parse_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+    {
+        title: '拼多多转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'pdd_parse_total_count',
+                dataIndex: 'pdd_parse_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'pdd_parse_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'pdd_parse_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'pdd_parse_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'pdd_parse_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+    {
+        title: '快手转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'ks_parse_total_count',
+                dataIndex: 'ks_parse_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'ks_parse_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'ks_parse_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'ks_parse_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'ks_parse_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+
+    {
+        title: '工具API调用',
+        children: [
+            {
+                title: '调用',
+                dataIndex: 'tool_total_count',
+                slotName: 'tool_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'tool_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'tool_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'tool_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'tool_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+    {
+        title: '第三方API调用',
+        children: [
+            {
+                title: '调用',
+                dataIndex: 'total_count',
+                slotName: 'total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+]);
+
+
+const onPageSizeChange = (current: number) => {
+    basePagination.pageSize = current;
+    pagination.pageSize = current;
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current: 1,
+    });
+};
+const fetchData = async (
+    params: DailyLogParams = {
+        accountName: 'all',
+        pageSize: basePagination.pageSize,
+        current: 1,
+        sort: 'log_date',
+        order: 'descending'
+    }
+) => {
+    setLoading(true);
+    try {
+
+        const { data } = await queryDailyLog(params);
+        console.log(data);
+        if (!data) return;
+        // const { data } = await queryDailyLog(params);
+        renderData.value = data.list;
+        pagination.current = data.page;
+        pagination.total = data.count;
+        console.log(data)
+    } catch (err) {
+
+        console.log(err)
+        // you can report use errorHandler or other
+    } finally {
+        setLoading(false);
+    }
+};
+
+const loadMore = async (row: TableData, done: (data: TableData[]) => void) => {
+    setLoading(true);
+    try {
+
+        const params: DailyLogParams = {
+            query_date: [row.log_date, row.log_date],
+            current: 1, pageSize: 999, sort: 'id', order: 'descending'
+        };
+
+        const { data } = await queryDailyLog(params);
+        console.log(data);
+        if (!data) return;
+
+        const list: TableData[] = data.list.map((item: DailyLogRecord) => ({
+            ...item,
+            isLeaf: true
+        }));
+        done(list);
+    } catch (err) {
+        console.log(err)
+    } finally {
+        setLoading(false);
+    }
+};
+
+
+
+
+const changeItem = async (
+    data: DailyLogRecord
+) => {
+    router.push({ name: 'updateCookies' });
+};
+
+
+
+const search = () => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+    } as unknown as DailyLogParams);
+};
+const onPageChange = (current: number) => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current
+    });
+};
+
+fetchData();
+const reset = () => {
+    formModel.value = generateFormModel();
+};
+
+const handleSelectDensity = (
+    val: string | number | Record<string, any> | undefined,
+    e: Event
+) => {
+    size.value = val as SizeProps;
+};
+
+const handleChange = (
+    checked: boolean | (string | boolean | number)[],
+    column: Column,
+    index: number
+) => {
+    if (!checked) {
+        cloneColumns.value = showColumns.value.filter(
+            (item) => item.dataIndex !== column.dataIndex
+        );
+    } else {
+        cloneColumns.value.splice(index, 0, column);
+    }
+};
+
+const exchangeArray = <T extends Array<any>>(
+    array: T,
+    beforeIdx: number,
+    newIdx: number,
+    isDeep = false
+): T => {
+    const newArray = isDeep ? cloneDeep(array) : array;
+    if (beforeIdx > -1 && newIdx > -1) {
+        // 先替换后面的,然后拿到替换的结果替换前面的
+        newArray.splice(
+            beforeIdx,
+            1,
+            newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
+        );
+    }
+    return newArray;
+};
+
+const popupVisibleChange = (val: boolean) => {
+    if (val) {
+        nextTick(() => {
+            const el = document.getElementById('tableSetting') as HTMLElement;
+            const sortable = new Sortable(el, {
+                onEnd(e: any) {
+                    const { oldIndex, newIndex } = e;
+                    exchangeArray(cloneColumns.value, oldIndex, newIndex);
+                    exchangeArray(showColumns.value, oldIndex, newIndex);
+                },
+            });
+        });
+    }
+};
+
+watch(
+    () => columns.value,
+    (val) => {
+        cloneColumns.value = cloneDeep(val);
+        cloneColumns.value.forEach((item, index) => {
+            item.checked = true;
+        });
+        showColumns.value = cloneDeep(cloneColumns.value);
+    },
+    { deep: true, immediate: true }
+);
+</script>
+
+<script lang="ts">
+export default {
+    name: 'SearchTable',
+};
+</script>
+
+<style scoped lang="less">
+.container {
+    padding: 0 20px 20px 20px;
+}
+
+:deep(.arco-table-th) {
+    &:last-child {
+        .arco-table-th-item-title {
+            margin-left: 16px;
+        }
+    }
+}
+
+.action-icon {
+    margin-left: 12px;
+    cursor: pointer;
+}
+
+.active {
+    color: #0960bd;
+    background-color: #e3f4fc;
+}
+
+.setting {
+    display: flex;
+    align-items: center;
+    width: 200px;
+
+    .title {
+        margin-left: 12px;
+        cursor: pointer;
+    }
+}
+</style>

+ 613 - 0
src/views/dashboard/dailyLog/components/jd.vue

@@ -0,0 +1,613 @@
+<template>
+    <a-row>
+        <a-col :flex="1">
+            <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
+                label-align="left">
+                <a-row :gutter="16">
+                    <a-col :span="8">
+                        <a-form-item field="query_date" :label="$t('searchTable.form.report_date')">
+                            <a-range-picker v-model="formModel.query_date" style="width: 100%" @change="search" />
+                        </a-form-item>
+                    </a-col>
+                </a-row>
+            </a-form>
+        </a-col>
+        <a-divider style="height: 32px" direction="vertical" />
+        <a-col :flex="'86px'" style="text-align: right">
+            <a-space direction="vertical" :size="18">
+                <a-button type="primary" @click="search">
+                    <template #icon>
+                        <icon-search />
+                    </template>
+                    {{ $t('searchTable.form.search') }}
+                </a-button>
+            </a-space>
+        </a-col>
+    </a-row>
+    <a-divider style="margin-top: 0" />
+    <a-row style="margin-bottom: 16px">
+        <a-col :span="12"> </a-col>
+        <a-col :span="12" style="
+                        display: flex;
+                        align-items: center;
+                        justify-content: end;
+                    ">
+            <a-tooltip :content="$t('searchTable.actions.refresh')">
+                <div class="action-icon" @click="search"><icon-refresh size="18" /></div>
+            </a-tooltip>
+            <a-dropdown @select="handleSelectDensity">
+                <a-tooltip :content="$t('searchTable.actions.density')">
+                    <div class="action-icon"><icon-line-height size="18" /></div>
+                </a-tooltip>
+                <template #content>
+                    <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
+                        :class="{ active: item.value === size }">
+                        <span>{{ item.name }}</span>
+                    </a-doption>
+                </template>
+            </a-dropdown>
+            <a-tooltip :content="$t('searchTable.actions.columnSetting')">
+                <a-popover trigger="click" position="bl" @popup-visible-change="popupVisibleChange">
+                    <div class="action-icon"><icon-settings size="18" /></div>
+                    <template #content>
+                        <div id="tableSetting">
+                            <div v-for="(item, index) in showColumns" :key="item.dataIndex" class="setting">
+                                <div style="
+                                                margin-right: 4px;
+                                                cursor: move;
+                                            ">
+                                    <icon-drag-arrow />
+                                </div>
+                                <div>
+                                    <a-checkbox v-model="item.checked" @change="
+                                        handleChange(
+                                            $event,
+                                            item as TableColumnData,
+                                            index
+                                        )
+                                        ">
+                                    </a-checkbox>
+                                </div>
+                                <div class="title">
+                                    {{
+                                        item.title === '#'
+                                            ? '序列号'
+                                            : item.title
+                                    }}
+                                </div>
+                            </div>
+                        </div>
+                    </template>
+                </a-popover>
+            </a-tooltip>
+        </a-col>
+    </a-row>
+
+    <a-table row-key="id" :loading="loading" :pagination="pagination" :summary="true" summary-text="汇总"
+        :columns="(cloneColumns as TableColumnData[])" :scroll="scroll" :scrollbar="scrollbar" :data="renderData"
+        :bordered="{ headerCell: true }" :size="size" :load-more="loadMore" @page-change="onPageChange"
+        @page-size-change="onPageSizeChange">
+
+        <template #index="{ rowIndex }">
+            {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
+        </template>
+        <template #xAxis="{ record }">
+            <template v-if="record.isLeaf">
+                {{ record.accountName }}
+            </template>
+            <template v-else>
+                {{ dayjs(record.log_date).format('YYYY-MM-DD') }}
+            </template>
+        </template>
+
+        <template #total_count="{ record }">
+            <a-popover v-if="record.total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #parse_total_count="{ record }">
+            <a-popover v-if="record.parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #jd_parse_total_count="{ record }">
+            <a-popover v-if="record.jd_parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.jd_parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="jd_parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #coupon_total_count="{ record }">
+            <a-popover v-if="record.coupon_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.coupon_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="coupon_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+        <template #tool_total_count="{ record }">
+            <a-popover v-if="record.tool_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.tool_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="tool_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+
+        <template #summary-cell="{ column, record }">
+            <template v-if="column.slotName == 'total_count'">
+                <a-tag v-if="record.total_count > 0" color="green">{{ record.total_count }}</a-tag>
+            </template>
+            <template v-else-if="column.slotName == 'parse_total_count'">
+                <a-tag v-if="record.parse_total_count > 0" color="green">
+                    {{ record.parse_total_count }}</a-tag>
+            </template>
+            <template v-else-if="column.slotName == 'coupon_total_count'">
+                <a-tag v-if="record.coupon_total_count > 0" color="green">
+                    {{ record.coupon_total_count }}</a-tag>
+            </template>
+
+            <template v-else-if="column.slotName == 'jd_parse_total_count'">
+                <a-tag v-if="record.jd_parse_total_count > 0" color="green">
+                    {{ record.jd_parse_total_count }}</a-tag>
+            </template>
+            <template v-else>
+                <div>{{ toAmount(record[column.dataIndex]) }}</div>
+            </template>
+
+        </template>
+    </a-table>
+</template>
+
+<script lang="ts" setup>
+import { useRouter } from 'vue-router';
+import { computed, ref, reactive, watch, nextTick } from 'vue';
+import { useI18n } from 'vue-i18n';
+import dayjs from 'dayjs';
+import useLoading from '@/hooks/loading';
+import { queryDailyLog, DailyLogRecord, DailyLogParams } from '@/api/app';
+import { Pagination } from '@/types/global';
+import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
+import type { TableData, TableColumnData } from '@arco-design/web-vue/es/table/interface';
+import cloneDeep from 'lodash/cloneDeep';
+import Sortable from 'sortablejs';
+import CategoriesPercent from './categories-percent.vue';
+
+type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+type Column = TableColumnData & { checked?: true };
+
+const generateFormModel = () => {
+    return {
+        accountName: 'all',
+        current: 1,
+        pageSize: 31,
+        sort: 'log_date',
+        order: 'descending'
+
+    };
+};
+const router = useRouter();
+
+const { loading, setLoading } = useLoading(true);
+const { t } = useI18n();
+const renderData = ref<DailyLogRecord[]>([]);
+const formModel = ref(generateFormModel());
+const cloneColumns = ref<Column[]>([]);
+const showColumns = ref<Column[]>([]);
+
+const size = ref<SizeProps>('medium');
+
+const scrollbar = ref(true);
+const scroll = {
+    x: '100%',
+    y: '100%',
+    maxHeight: 'calc( 100vh - 420px)',
+};
+
+const basePagination: Pagination = {
+    current: 1,
+    pageSize: 31,
+};
+const pagination = reactive({
+    ...basePagination,
+    showTotal: true,
+    showJumper: true,
+    showMore: true,
+    showPageSize: true,
+    pageSizeOptions: [10, 20, 30, 31, 50, 100, 200],
+    sizePageSize: true,
+
+});
+const densityList = computed(() => [
+    {
+        name: t('searchTable.size.mini'),
+        value: 'mini',
+    },
+    {
+        name: t('searchTable.size.small'),
+        value: 'small',
+    },
+    {
+        name: t('searchTable.size.medium'),
+        value: 'medium',
+    },
+    {
+        name: t('searchTable.size.large'),
+        value: 'large',
+    },
+]);
+
+
+const toAmount = (val: any): any => {
+    console.log(val);
+    if (typeof val === 'number' && !Number.isNaN(val)) {
+        return parseFloat(val.toFixed(2));
+    }
+    return val;
+}
+
+const columns = computed<TableColumnData[]>(() => [
+    {
+        title: '日期',
+        dataIndex: 'xAxis',
+        slotName: 'xAxis',
+        width: 250,
+        fixed: 'left',
+    },
+    {
+        title: '转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'parse_total_count',
+                dataIndex: 'parse_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'parse_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'parse_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'parse_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'parse_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    }, 
+    {
+        title: '京东转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'jd_parse_total_count',
+                dataIndex: 'jd_parse_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'jd_parse_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'jd_parse_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'jd_parse_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'jd_parse_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+
+    {
+        title: '工具API调用',
+        children: [
+            {
+                title: '调用',
+                dataIndex: 'tool_total_count',
+                slotName: 'tool_total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'tool_success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'tool_success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'tool_abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'tool_abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+    {
+        title: '第三方API调用',
+        children: [
+            {
+                title: '调用',
+                dataIndex: 'total_count',
+                slotName: 'total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    },
+]);
+
+
+const onPageSizeChange = (current: number) => {
+    basePagination.pageSize = current;
+    pagination.pageSize = current;
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current: 1,
+    });
+};
+const fetchData = async (
+    params: DailyLogParams = {
+        accountName: 'all',
+        pageSize: basePagination.pageSize,
+        current: 1,
+        sort: 'log_date',
+        order: 'descending'
+    }
+) => {
+    setLoading(true);
+    try {
+
+        const { data } = await queryDailyLog(params);
+        console.log(data);
+        if (!data) return;
+        // const { data } = await queryDailyLog(params);
+        renderData.value = data.list;
+        pagination.current = data.page;
+        pagination.total = data.count;
+        console.log(data)
+    } catch (err) {
+
+        console.log(err)
+        // you can report use errorHandler or other
+    } finally {
+        setLoading(false);
+    }
+};
+
+const loadMore = async (row: TableData, done: (data: TableData[]) => void) => {
+    setLoading(true);
+    try {
+
+        const params: DailyLogParams = {
+            query_date: [row.log_date, row.log_date],
+            current: 1, pageSize: 999, sort: 'id', order: 'descending'
+        };
+
+        const { data } = await queryDailyLog(params);
+        console.log(data);
+        if (!data) return;
+
+        const list: TableData[] = data.list.map((item: DailyLogRecord) => ({
+            ...item,
+            isLeaf: true
+        }));
+        done(list);
+    } catch (err) {
+        console.log(err)
+    } finally {
+        setLoading(false);
+    }
+};
+
+
+
+
+const changeItem = async (
+    data: DailyLogRecord
+) => {
+    router.push({ name: 'updateCookies' });
+};
+
+
+
+const search = () => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+    } as unknown as DailyLogParams);
+};
+const onPageChange = (current: number) => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current
+    });
+};
+
+fetchData();
+const reset = () => {
+    formModel.value = generateFormModel();
+};
+
+const handleSelectDensity = (
+    val: string | number | Record<string, any> | undefined,
+    e: Event
+) => {
+    size.value = val as SizeProps;
+};
+
+const handleChange = (
+    checked: boolean | (string | boolean | number)[],
+    column: Column,
+    index: number
+) => {
+    if (!checked) {
+        cloneColumns.value = showColumns.value.filter(
+            (item) => item.dataIndex !== column.dataIndex
+        );
+    } else {
+        cloneColumns.value.splice(index, 0, column);
+    }
+};
+
+const exchangeArray = <T extends Array<any>>(
+    array: T,
+    beforeIdx: number,
+    newIdx: number,
+    isDeep = false
+): T => {
+    const newArray = isDeep ? cloneDeep(array) : array;
+    if (beforeIdx > -1 && newIdx > -1) {
+        // 先替换后面的,然后拿到替换的结果替换前面的
+        newArray.splice(
+            beforeIdx,
+            1,
+            newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
+        );
+    }
+    return newArray;
+};
+
+const popupVisibleChange = (val: boolean) => {
+    if (val) {
+        nextTick(() => {
+            const el = document.getElementById('tableSetting') as HTMLElement;
+            const sortable = new Sortable(el, {
+                onEnd(e: any) {
+                    const { oldIndex, newIndex } = e;
+                    exchangeArray(cloneColumns.value, oldIndex, newIndex);
+                    exchangeArray(showColumns.value, oldIndex, newIndex);
+                },
+            });
+        });
+    }
+};
+
+watch(
+    () => columns.value,
+    (val) => {
+        cloneColumns.value = cloneDeep(val);
+        cloneColumns.value.forEach((item, index) => {
+            item.checked = true;
+        });
+        showColumns.value = cloneDeep(cloneColumns.value);
+    },
+    { deep: true, immediate: true }
+);
+</script>
+
+<script lang="ts">
+export default {
+    name: 'SearchTable',
+};
+</script>
+
+<style scoped lang="less">
+.container {
+    padding: 0 20px 20px 20px;
+}
+
+:deep(.arco-table-th) {
+    &:last-child {
+        .arco-table-th-item-title {
+            margin-left: 16px;
+        }
+    }
+}
+
+.action-icon {
+    margin-left: 12px;
+    cursor: pointer;
+}
+
+.active {
+    color: #0960bd;
+    background-color: #e3f4fc;
+}
+
+.setting {
+    display: flex;
+    align-items: center;
+    width: 200px;
+
+    .title {
+        margin-left: 12px;
+        cursor: pointer;
+    }
+}
+</style>

+ 504 - 0
src/views/dashboard/dailyLog/components/ks.vue

@@ -0,0 +1,504 @@
+<template>
+    <a-row>
+        <a-col :flex="1">
+            <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
+                label-align="left">
+                <a-row :gutter="16">
+                    <a-col :span="8">
+                        <a-form-item field="query_date" :label="$t('searchTable.form.report_date')">
+                            <a-range-picker v-model="formModel.query_date" style="width: 100%" @change="search" />
+                        </a-form-item>
+                    </a-col>
+                </a-row>
+            </a-form>
+        </a-col>
+        <a-divider style="height: 32px" direction="vertical" />
+        <a-col :flex="'86px'" style="text-align: right">
+            <a-space direction="vertical" :size="18">
+                <a-button type="primary" @click="search">
+                    <template #icon>
+                        <icon-search />
+                    </template>
+                    {{ $t('searchTable.form.search') }}
+                </a-button>
+            </a-space>
+        </a-col>
+    </a-row>
+    <a-divider style="margin-top: 0" />
+    <a-row style="margin-bottom: 16px">
+        <a-col :span="12"> </a-col>
+        <a-col :span="12" style="
+                        display: flex;
+                        align-items: center;
+                        justify-content: end;
+                    ">
+            <a-tooltip :content="$t('searchTable.actions.refresh')">
+                <div class="action-icon" @click="search"><icon-refresh size="18" /></div>
+            </a-tooltip>
+            <a-dropdown @select="handleSelectDensity">
+                <a-tooltip :content="$t('searchTable.actions.density')">
+                    <div class="action-icon"><icon-line-height size="18" /></div>
+                </a-tooltip>
+                <template #content>
+                    <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
+                        :class="{ active: item.value === size }">
+                        <span>{{ item.name }}</span>
+                    </a-doption>
+                </template>
+            </a-dropdown>
+            <a-tooltip :content="$t('searchTable.actions.columnSetting')">
+                <a-popover trigger="click" position="bl" @popup-visible-change="popupVisibleChange">
+                    <div class="action-icon"><icon-settings size="18" /></div>
+                    <template #content>
+                        <div id="tableSetting">
+                            <div v-for="(item, index) in showColumns" :key="item.dataIndex" class="setting">
+                                <div style="
+                                                margin-right: 4px;
+                                                cursor: move;
+                                            ">
+                                    <icon-drag-arrow />
+                                </div>
+                                <div>
+                                    <a-checkbox v-model="item.checked" @change="
+                                        handleChange(
+                                            $event,
+                                            item as TableColumnData,
+                                            index
+                                        )
+                                        ">
+                                    </a-checkbox>
+                                </div>
+                                <div class="title">
+                                    {{
+                                        item.title === '#'
+                                            ? '序列号'
+                                            : item.title
+                                    }}
+                                </div>
+                            </div>
+                        </div>
+                    </template>
+                </a-popover>
+            </a-tooltip>
+        </a-col>
+    </a-row>
+
+    <a-table row-key="id" :loading="loading" :pagination="pagination" :summary="true" summary-text="汇总"
+        :columns="(cloneColumns as TableColumnData[])" :scroll="scroll" :scrollbar="scrollbar" :data="renderData"
+        :bordered="{ headerCell: true }" :size="size" :load-more="loadMore" @page-change="onPageChange"
+        @page-size-change="onPageSizeChange">
+
+        <template #index="{ rowIndex }">
+            {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
+        </template>
+        <template #xAxis="{ record }">
+            <template v-if="record.isLeaf">
+                {{ record.accountName }}
+            </template>
+            <template v-else>
+                {{ dayjs(record.log_date).format('YYYY-MM-DD') }}
+            </template>
+        </template>
+
+        <template #total_count="{ record }">
+            <a-popover v-if="record.total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #parse_total_count="{ record }">
+            <a-popover v-if="record.parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #jd_parse_total_count="{ record }">
+            <a-popover v-if="record.jd_parse_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.jd_parse_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="jd_parse_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+        <template #coupon_total_count="{ record }">
+            <a-popover v-if="record.coupon_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.coupon_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="coupon_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+        <template #tool_total_count="{ record }">
+            <a-popover v-if="record.tool_total_count > 0" popup-container="body" trigger="click">
+                <a-tag color="green">{{ record.tool_total_count }}</a-tag>
+                <template #content>
+                    <CategoriesPercent total_key="tool_total" :record="record" />
+                </template>
+            </a-popover>
+        </template>
+
+
+        <template #summary-cell="{ column, record }">
+            <template v-if="column.slotName == 'total_count'">
+                <a-tag v-if="record.total_count > 0" color="green">{{ record.total_count }}</a-tag>
+            </template>
+            <template v-else-if="column.slotName == 'parse_total_count'">
+                <a-tag v-if="record.parse_total_count > 0" color="green">
+                    {{ record.parse_total_count }}</a-tag>
+            </template>
+            <template v-else-if="column.slotName == 'coupon_total_count'">
+                <a-tag v-if="record.coupon_total_count > 0" color="green">
+                    {{ record.coupon_total_count }}</a-tag>
+            </template>
+
+            <template v-else-if="column.slotName == 'jd_parse_total_count'">
+                <a-tag v-if="record.jd_parse_total_count > 0" color="green">
+                    {{ record.jd_parse_total_count }}</a-tag>
+            </template>
+            <template v-else>
+                <div>{{ toAmount(record[column.dataIndex]) }}</div>
+            </template>
+
+        </template>
+    </a-table>
+</template>
+
+<script lang="ts" setup>
+import { useRouter } from 'vue-router';
+import { computed, ref, reactive, watch, nextTick } from 'vue';
+import { useI18n } from 'vue-i18n';
+import dayjs from 'dayjs';
+import useLoading from '@/hooks/loading';
+import { queryDailyLog, DailyLogRecord, DailyLogParams } from '@/api/app';
+import { Pagination } from '@/types/global';
+import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
+import type { TableData, TableColumnData } from '@arco-design/web-vue/es/table/interface';
+import cloneDeep from 'lodash/cloneDeep';
+import Sortable from 'sortablejs';
+import CategoriesPercent from './categories-percent.vue';
+
+type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+type Column = TableColumnData & { checked?: true };
+
+const generateFormModel = () => {
+    return {
+        accountName: 'all',
+        query_channel: 'all',
+        current: 1,
+        pageSize: 31,
+        sort: 'log_date',
+        order: 'descending'
+
+    };
+};
+const router = useRouter();
+
+const { loading, setLoading } = useLoading(true);
+const { t } = useI18n();
+const renderData = ref<DailyLogRecord[]>([]);
+const formModel = ref(generateFormModel());
+const cloneColumns = ref<Column[]>([]);
+const showColumns = ref<Column[]>([]);
+
+const size = ref<SizeProps>('medium');
+const scrollbar = ref(true);
+const scroll = {
+    x: '100%',
+    y: '100%',
+    maxHeight: 'calc( 100vh - 420px)',
+};
+
+const basePagination: Pagination = {
+    current: 1,
+    pageSize: 31,
+};
+const pagination = reactive({
+    ...basePagination,
+    showTotal: true,
+    showJumper: true,
+    showMore: true,
+    showPageSize: true,
+    pageSizeOptions: [10, 20, 30, 31, 50, 100, 200],
+    sizePageSize: true,
+
+});
+const densityList = computed(() => [
+    {
+        name: t('searchTable.size.mini'),
+        value: 'mini',
+    },
+    {
+        name: t('searchTable.size.small'),
+        value: 'small',
+    },
+    {
+        name: t('searchTable.size.medium'),
+        value: 'medium',
+    },
+    {
+        name: t('searchTable.size.large'),
+        value: 'large',
+    },
+]);
+
+
+const toAmount = (val: any): any => {
+    console.log(val);
+    if (typeof val === 'number' && !Number.isNaN(val)) {
+        return parseFloat(val.toFixed(2));
+    }
+    return val;
+}
+
+const columns = computed<TableColumnData[]>(() => [
+    {
+        title: '日期',
+        dataIndex: 'xAxis',
+        slotName: 'xAxis',
+        width: 250,
+        fixed: 'left',
+    },
+    {
+        title: '转链API调用',
+        children: [
+            {
+                title: '调用',
+                slotName: 'total_count',
+                dataIndex: 'total_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功',
+                dataIndex: 'success_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '成功(%)',
+                dataIndex: 'success_percentage',
+                width: 90,
+                align: 'right'
+            },
+            {
+                title: '放弃',
+                dataIndex: 'abandon_count',
+                width: 100,
+                align: 'right'
+            },
+            {
+                title: '放弃(%)',
+                dataIndex: 'abandon_percentage',
+                width: 90,
+                align: 'right'
+            },
+        ]
+    }
+]);
+
+
+const onPageSizeChange = (current: number) => {
+    basePagination.pageSize = current;
+    pagination.pageSize = current;
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current: 1,
+    });
+};
+const fetchData = async (
+    params: DailyLogParams = {
+        accountName: 'all',
+        query_channel: 'ks',
+        pageSize: basePagination.pageSize,
+        current: 1,
+        sort: 'log_date',
+        order: 'descending'
+    }
+) => {
+    setLoading(true);
+    try {
+
+        const { data } = await queryDailyLog(params);
+        console.log(data);
+        if (!data) return;
+        renderData.value = data.list;
+        pagination.current = data.page;
+        pagination.total = data.count;
+        console.log(data)
+    } catch (err) {
+
+        console.log(err)
+        // you can report use errorHandler or other
+    } finally {
+        setLoading(false);
+    }
+};
+
+const loadMore = async (row: TableData, done: (data: TableData[]) => void) => {
+    setLoading(true);
+    try {
+        const params: DailyLogParams = {
+            query_channel: 'ks',
+            query_date: [row.log_date, row.log_date],
+            current: 1, pageSize: 999, sort: 'id', order: 'descending'
+        };
+
+        const { data } = await queryDailyLog(params);
+        console.log(data);
+        if (!data) return;
+
+        const list: TableData[] = data.list.map((item: DailyLogRecord) => ({
+            ...item,
+            isLeaf: true
+        }));
+        done(list);
+    } catch (err) {
+        console.log(err)
+    } finally {
+        setLoading(false);
+    }
+};
+
+
+
+
+const changeItem = async (
+    data: DailyLogRecord
+) => {
+    router.push({ name: 'updateCookies' });
+};
+
+
+
+const search = () => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+    } as unknown as DailyLogParams);
+};
+const onPageChange = (current: number) => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current
+    });
+};
+
+fetchData();
+const reset = () => {
+    formModel.value = generateFormModel();
+};
+
+const handleSelectDensity = (
+    val: string | number | Record<string, any> | undefined,
+    e: Event
+) => {
+    size.value = val as SizeProps;
+};
+
+const handleChange = (
+    checked: boolean | (string | boolean | number)[],
+    column: Column,
+    index: number
+) => {
+    if (!checked) {
+        cloneColumns.value = showColumns.value.filter(
+            (item) => item.dataIndex !== column.dataIndex
+        );
+    } else {
+        cloneColumns.value.splice(index, 0, column);
+    }
+};
+
+const exchangeArray = <T extends Array<any>>(
+    array: T,
+    beforeIdx: number,
+    newIdx: number,
+    isDeep = false
+): T => {
+    const newArray = isDeep ? cloneDeep(array) : array;
+    if (beforeIdx > -1 && newIdx > -1) {
+        // 先替换后面的,然后拿到替换的结果替换前面的
+        newArray.splice(
+            beforeIdx,
+            1,
+            newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
+        );
+    }
+    return newArray;
+};
+
+const popupVisibleChange = (val: boolean) => {
+    if (val) {
+        nextTick(() => {
+            const el = document.getElementById('tableSetting') as HTMLElement;
+            const sortable = new Sortable(el, {
+                onEnd(e: any) {
+                    const { oldIndex, newIndex } = e;
+                    exchangeArray(cloneColumns.value, oldIndex, newIndex);
+                    exchangeArray(showColumns.value, oldIndex, newIndex);
+                },
+            });
+        });
+    }
+};
+
+watch(
+    () => columns.value,
+    (val) => {
+        cloneColumns.value = cloneDeep(val);
+        cloneColumns.value.forEach((item, index) => {
+            item.checked = true;
+        });
+        showColumns.value = cloneDeep(cloneColumns.value);
+    },
+    { deep: true, immediate: true }
+);
+</script>
+
+<script lang="ts">
+export default {
+    name: 'SearchTable',
+};
+</script>
+
+<style scoped lang="less">
+.container {
+    padding: 0 20px 20px 20px;
+}
+
+:deep(.arco-table-th) {
+    &:last-child {
+        .arco-table-th-item-title {
+            margin-left: 16px;
+        }
+    }
+}
+
+.action-icon {
+    margin-left: 12px;
+    cursor: pointer;
+}
+
+.active {
+    color: #0960bd;
+    background-color: #e3f4fc;
+}
+
+.setting {
+    display: flex;
+    align-items: center;
+    width: 200px;
+
+    .title {
+        margin-left: 12px;
+        cursor: pointer;
+    }
+}
+</style>

+ 11 - 642
src/views/dashboard/dailyLog/index.vue

@@ -1,178 +1,15 @@
 <template>
     <div class="container">
         <Breadcrumb :items="['menu.dashboard', 'menu.dashboard.dailyLog']" />
-        <a-card class="general-card" :title="$t('menu.dashboard.dailyLog')">
-            <a-row>
-                <a-col :flex="1">
-                    <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
-                        label-align="left">
-                        <a-row :gutter="16">
-                            <a-col :span="8">
-                                <a-form-item field="query_date" :label="$t('searchTable.form.report_date')">
-                                    <a-range-picker v-model="formModel.query_date" style="width: 100%"
-                                        @change="search" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                    </a-form>
-                </a-col>
-                <a-divider style="height: 32px" direction="vertical" />
-                <a-col :flex="'86px'" style="text-align: right">
-                    <a-space direction="vertical" :size="18">
-                        <a-button type="primary" @click="search">
-                            <template #icon>
-                                <icon-search />
-                            </template>
-                            {{ $t('searchTable.form.search') }}
-                        </a-button>
-                    </a-space>
-                </a-col>
-            </a-row>
-            <a-divider style="margin-top: 0" />
-            <a-row style="margin-bottom: 16px">
-                <a-col :span="12"> </a-col>
-                <a-col :span="12" style="
-                        display: flex;
-                        align-items: center;
-                        justify-content: end;
-                    ">
-                    <a-tooltip :content="$t('searchTable.actions.refresh')">
-                        <div class="action-icon" @click="search"><icon-refresh size="18" /></div>
-                    </a-tooltip>
-                    <a-dropdown @select="handleSelectDensity">
-                        <a-tooltip :content="$t('searchTable.actions.density')">
-                            <div class="action-icon"><icon-line-height size="18" /></div>
-                        </a-tooltip>
-                        <template #content>
-                            <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
-                                :class="{ active: item.value === size }">
-                                <span>{{ item.name }}</span>
-                            </a-doption>
-                        </template>
-                    </a-dropdown>
-                    <a-tooltip :content="$t('searchTable.actions.columnSetting')">
-                        <a-popover trigger="click" position="bl" @popup-visible-change="popupVisibleChange">
-                            <div class="action-icon"><icon-settings size="18" /></div>
-                            <template #content>
-                                <div id="tableSetting">
-                                    <div v-for="(item, index) in showColumns" :key="item.dataIndex" class="setting">
-                                        <div style="
-                                                margin-right: 4px;
-                                                cursor: move;
-                                            ">
-                                            <icon-drag-arrow />
-                                        </div>
-                                        <div>
-                                            <a-checkbox v-model="item.checked" @change="
-                                                handleChange(
-                                                    $event,
-                                                    item as TableColumnData,
-                                                    index
-                                                )
-                                                ">
-                                            </a-checkbox>
-                                        </div>
-                                        <div class="title">
-                                            {{
-                                                item.title === '#'
-                                                    ? '序列号'
-                                                    : item.title
-                                            }}
-                                        </div>
-                                    </div>
-                                </div>
-                            </template>
-                        </a-popover>
-                    </a-tooltip>
-                </a-col>
-            </a-row>
-
-            <a-table row-key="id" :loading="loading" :pagination="pagination" :summary="true" summary-text="汇总"
-                :columns="(cloneColumns as TableColumnData[])" :scroll="scroll" :scrollbar="scrollbar"
-                :data="renderData" :bordered="{ headerCell: true }" :size="size" :load-more="loadMore"
-                @page-change="onPageChange" @page-size-change="onPageSizeChange">
-
-                <template #index="{ rowIndex }">
-                    {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
-                </template>
-                <template #xAxis="{ record }">
-                    <template v-if="record.isLeaf">
-                        {{ record.accountName }}
-                    </template>
-                    <template v-else>
-                        {{ dayjs(record.log_date).format('YYYY-MM-DD') }}
-                    </template>
-                </template>
-
-                <template #total_count="{ record }">
-                    <a-popover v-if="record.total_count > 0" popup-container="body" trigger="click">
-                        <a-tag color="green">{{ record.total_count }}</a-tag>
-                        <template #content>
-                            <CategoriesPercent total_key="total" :record="record" />
-                        </template>
-                    </a-popover>
-                </template>
-                <template #parse_total_count="{ record }">
-                    <a-popover v-if="record.parse_total_count > 0" popup-container="body" trigger="click">
-                        <a-tag color="green">{{ record.parse_total_count }}</a-tag>
-                        <template #content>
-                            <CategoriesPercent total_key="parse_total" :record="record" />
-                        </template>
-                    </a-popover>
-                </template>
-                <template #jd_parse_total_count="{ record }">
-                    <a-popover v-if="record.jd_parse_total_count > 0" popup-container="body" trigger="click">
-                        <a-tag color="green">{{ record.jd_parse_total_count }}</a-tag>
-                        <template #content>
-                            <CategoriesPercent total_key="jd_parse_total" :record="record" />
-                        </template>
-                    </a-popover>
-                </template>
-                <template #coupon_total_count="{ record }">
-                    <a-popover v-if="record.coupon_total_count > 0" popup-container="body" trigger="click">
-                        <a-tag color="green">{{ record.coupon_total_count }}</a-tag>
-                        <template #content>
-                            <CategoriesPercent total_key="coupon_total" :record="record" />
-                        </template>
-                    </a-popover>
-                </template>
-
-                <template #tool_total_count="{ record }">
-                    <a-popover v-if="record.tool_total_count > 0" popup-container="body" trigger="click">
-                        <a-tag color="green">{{ record.tool_total_count }}</a-tag>
-                        <template #content>
-                            <CategoriesPercent total_key="tool_total" :record="record" />
-                        </template>
-                    </a-popover>
-                </template>
-
-
-                <template #summary-cell="{ column, record }">
-                    <template v-if="column.slotName == 'total_count'">
-                        <a-tag v-if="record.total_count > 0" color="green">{{ record.total_count }}</a-tag>
-                    </template>
-                    <template v-else-if="column.slotName == 'parse_total_count'">
-                        <a-tag v-if="record.parse_total_count > 0" color="green">
-                            {{ record.parse_total_count }}</a-tag>
-                    </template>
-                    <template v-else-if="column.slotName == 'coupon_total_count'">
-                        <a-tag v-if="record.coupon_total_count > 0" color="green">
-                            {{ record.coupon_total_count }}</a-tag>
-                    </template>
-
-                    <template v-else-if="column.slotName == 'jd_parse_total_count'">
-                        <a-tag v-if="record.jd_parse_total_count > 0" color="green">
-                            {{ record.jd_parse_total_count }}</a-tag>
-                    </template>
-                    <template v-else>
-                        <div>{{ toAmount(record[column.dataIndex]) }}</div>
-                    </template>
-
-                </template>
-
-
-
-            </a-table>
+        <a-card class="general-card">
+            <a-tabs default-active-key="all" lazy-load>
+                <a-tab-pane key="all" :title="$t('menu.dashboard.dailyLog')">
+                    <AllReport />
+                </a-tab-pane>
+                <!-- <a-tab-pane key="ks" title="快手">
+                    <KsReport />
+                </a-tab-pane> -->
+            </a-tabs>
         </a-card>
     </div>
 </template>
@@ -181,478 +18,10 @@
 import { useRouter } from 'vue-router';
 import { computed, ref, reactive, watch, nextTick } from 'vue';
 import { useI18n } from 'vue-i18n';
-import dayjs from 'dayjs';
-import useLoading from '@/hooks/loading';
-import { queryDailyLog, DailyLogRecord, DailyLogParams } from '@/api/app';
-import { Pagination } from '@/types/global';
-import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
-import type { TableData, TableColumnData } from '@arco-design/web-vue/es/table/interface';
-import cloneDeep from 'lodash/cloneDeep';
-import Sortable from 'sortablejs';
-import CategoriesPercent from './components/categories-percent.vue';
-
-type SizeProps = 'mini' | 'small' | 'medium' | 'large';
-type Column = TableColumnData & { checked?: true };
-
-const generateFormModel = () => {
-    return {
-        accountName: 'all',
-        current: 1,
-        pageSize: 31,
-        sort: 'log_date',
-        order: 'descending'
+import AllReport from './components/all.vue';
+import KsReport from './components/ks.vue';
 
-    };
-};
 const router = useRouter();
 
-const { loading, setLoading } = useLoading(true);
 const { t } = useI18n();
-const renderData = ref<DailyLogRecord[]>([]);
-const formModel = ref(generateFormModel());
-const cloneColumns = ref<Column[]>([]);
-const showColumns = ref<Column[]>([]);
-
-const size = ref<SizeProps>('medium');
-
-const scrollbar = ref(true);
-const scroll = {
-    x: '100%',
-    y: '100%',
-    maxHeight: 'calc( 100vh - 420px)',
-};
-
-const basePagination: Pagination = {
-    current: 1,
-    pageSize: 31,
-};
-const pagination = reactive({
-    ...basePagination,
-    showTotal: true,
-    showJumper: true,
-    showMore: true,
-    showPageSize: true,
-    pageSizeOptions: [10, 20, 30, 31, 50, 100, 200],
-    sizePageSize: true,
-
-});
-const densityList = computed(() => [
-    {
-        name: t('searchTable.size.mini'),
-        value: 'mini',
-    },
-    {
-        name: t('searchTable.size.small'),
-        value: 'small',
-    },
-    {
-        name: t('searchTable.size.medium'),
-        value: 'medium',
-    },
-    {
-        name: t('searchTable.size.large'),
-        value: 'large',
-    },
-]);
-
-
-const toAmount = (val: any): any => {
-    console.log(val);
-    if (typeof val === 'number' && !Number.isNaN(val)) {
-        return parseFloat(val.toFixed(2));
-    }
-    return val;
-}
-
-const columns = computed<TableColumnData[]>(() => [
-    {
-        title: '日期',
-        dataIndex: 'xAxis',
-        slotName: 'xAxis',
-        width: 250,
-        fixed: 'left',
-    },
-    {
-        title: '转链API调用',
-        children: [
-            {
-                title: '调用',
-                slotName: 'parse_total_count',
-                dataIndex: 'parse_total_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功',
-                dataIndex: 'parse_success_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功(%)',
-                dataIndex: 'parse_success_percentage',
-                width: 90,
-                align: 'right'
-            },
-            {
-                title: '放弃',
-                dataIndex: 'parse_abandon_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '放弃(%)',
-                dataIndex: 'parse_abandon_percentage',
-                width: 90,
-                align: 'right'
-            },
-        ]
-    },
-    {
-        title: '优惠券API调用',
-        children: [
-            {
-                title: '调用',
-                slotName: 'coupon_total_count',
-                dataIndex: 'coupon_total_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功',
-                dataIndex: 'coupon_success_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功(%)',
-                dataIndex: 'coupon_success_percentage',
-                width: 90,
-                align: 'right'
-            },
-            {
-                title: '放弃',
-                dataIndex: 'coupon_abandon_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '放弃(%)',
-                dataIndex: 'coupon_abandon_percentage',
-                width: 90,
-                align: 'right'
-            },
-        ]
-    },
-    {
-        title: '京东转链API调用',
-        children: [
-            {
-                title: '调用',
-                slotName: 'jd_parse_total_count',
-                dataIndex: 'jd_parse_total_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功',
-                dataIndex: 'jd_parse_success_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功(%)',
-                dataIndex: 'jd_parse_success_percentage',
-                width: 90,
-                align: 'right'
-            },
-            {
-                title: '放弃',
-                dataIndex: 'jd_parse_abandon_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '放弃(%)',
-                dataIndex: 'jd_parse_abandon_percentage',
-                width: 90,
-                align: 'right'
-            },
-        ]
-    },
-
-    {
-        title: '工具API调用',
-        children: [
-            {
-                title: '调用',
-                dataIndex: 'tool_total_count',
-                slotName: 'tool_total_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功',
-                dataIndex: 'tool_success_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功(%)',
-                dataIndex: 'tool_success_percentage',
-                width: 90,
-                align: 'right'
-            },
-            {
-                title: '放弃',
-                dataIndex: 'tool_abandon_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '放弃(%)',
-                dataIndex: 'tool_abandon_percentage',
-                width: 90,
-                align: 'right'
-            },
-        ]
-    },
-    {
-        title: '第三方API调用',
-        children: [
-            {
-                title: '调用',
-                dataIndex: 'total_count',
-                slotName: 'total_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功',
-                dataIndex: 'success_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '成功(%)',
-                dataIndex: 'success_percentage',
-                width: 90,
-                align: 'right'
-            },
-            {
-                title: '放弃',
-                dataIndex: 'abandon_count',
-                width: 100,
-                align: 'right'
-            },
-            {
-                title: '放弃(%)',
-                dataIndex: 'abandon_percentage',
-                width: 90,
-                align: 'right'
-            },
-        ]
-    },
-]);
-
-
-const onPageSizeChange = (current: number) => {
-    basePagination.pageSize = current;
-    pagination.pageSize = current;
-    fetchData({
-        ...basePagination,
-        ...formModel.value,
-        current: 1,
-    });
-};
-const fetchData = async (
-    params: DailyLogParams = {
-        accountName: 'all',
-        pageSize: basePagination.pageSize,
-        current: 1,
-        sort: 'log_date',
-        order: 'descending'
-    }
-) => {
-    setLoading(true);
-    try {
-
-        const { data } = await queryDailyLog(params);
-        console.log(data);
-        if (!data) return;
-        // const { data } = await queryDailyLog(params);
-        renderData.value = data.list;
-        pagination.current = data.page;
-        pagination.total = data.count;
-        console.log(data)
-    } catch (err) {
-
-        console.log(err)
-        // you can report use errorHandler or other
-    } finally {
-        setLoading(false);
-    }
-};
-
-const loadMore = async (row: TableData, done: (data: TableData[]) => void) => {
-    setLoading(true);
-    try {
-
-        const params: DailyLogParams = {
-            query_date: [row.log_date, row.log_date],
-            current: 1, pageSize: 999, sort: 'id', order: 'descending'
-        };
-
-        const { data } = await queryDailyLog(params);
-        console.log(data);
-        if (!data) return;
-
-        const list: TableData[] = data.list.map((item: DailyLogRecord) => ({
-            ...item,
-            isLeaf: true
-        }));
-        done(list);
-    } catch (err) {
-        console.log(err)
-    } finally {
-        setLoading(false);
-    }
-};
-
-
-
-
-const changeItem = async (
-    data: DailyLogRecord
-) => {
-    router.push({ name: 'updateCookies' });
-};
-
-
-
-const search = () => {
-    fetchData({
-        ...basePagination,
-        ...formModel.value,
-    } as unknown as DailyLogParams);
-};
-const onPageChange = (current: number) => {
-    fetchData({
-        ...basePagination,
-        ...formModel.value,
-        current
-    });
-};
-
-fetchData();
-const reset = () => {
-    formModel.value = generateFormModel();
-};
-
-const handleSelectDensity = (
-    val: string | number | Record<string, any> | undefined,
-    e: Event
-) => {
-    size.value = val as SizeProps;
-};
-
-const handleChange = (
-    checked: boolean | (string | boolean | number)[],
-    column: Column,
-    index: number
-) => {
-    if (!checked) {
-        cloneColumns.value = showColumns.value.filter(
-            (item) => item.dataIndex !== column.dataIndex
-        );
-    } else {
-        cloneColumns.value.splice(index, 0, column);
-    }
-};
-
-const exchangeArray = <T extends Array<any>>(
-    array: T,
-    beforeIdx: number,
-    newIdx: number,
-    isDeep = false
-): T => {
-    const newArray = isDeep ? cloneDeep(array) : array;
-    if (beforeIdx > -1 && newIdx > -1) {
-        // 先替换后面的,然后拿到替换的结果替换前面的
-        newArray.splice(
-            beforeIdx,
-            1,
-            newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
-        );
-    }
-    return newArray;
-};
-
-const popupVisibleChange = (val: boolean) => {
-    if (val) {
-        nextTick(() => {
-            const el = document.getElementById('tableSetting') as HTMLElement;
-            const sortable = new Sortable(el, {
-                onEnd(e: any) {
-                    const { oldIndex, newIndex } = e;
-                    exchangeArray(cloneColumns.value, oldIndex, newIndex);
-                    exchangeArray(showColumns.value, oldIndex, newIndex);
-                },
-            });
-        });
-    }
-};
-
-watch(
-    () => columns.value,
-    (val) => {
-        cloneColumns.value = cloneDeep(val);
-        cloneColumns.value.forEach((item, index) => {
-            item.checked = true;
-        });
-        showColumns.value = cloneDeep(cloneColumns.value);
-    },
-    { deep: true, immediate: true }
-);
-</script>
-
-<script lang="ts">
-export default {
-    name: 'SearchTable',
-};
 </script>
-
-<style scoped lang="less">
-.container {
-    padding: 0 20px 20px 20px;
-}
-
-:deep(.arco-table-th) {
-    &:last-child {
-        .arco-table-th-item-title {
-            margin-left: 16px;
-        }
-    }
-}
-
-.action-icon {
-    margin-left: 12px;
-    cursor: pointer;
-}
-
-.active {
-    color: #0960bd;
-    background-color: #e3f4fc;
-}
-
-.setting {
-    display: flex;
-    align-items: center;
-    width: 200px;
-
-    .title {
-        margin-left: 12px;
-        cursor: pointer;
-    }
-}
-</style>

+ 518 - 0
src/views/jd/bill_dailys.vue

@@ -0,0 +1,518 @@
+<template>
+    <div class="container">
+        <Breadcrumb :items="['menu.jd', 'menu.jd.bill_dailys']" />
+        <a-card class="general-card" :title="$t('menu.jd.bill_dailys')">
+            <a-row>
+                <a-col :flex="1">
+                    <a-form :model="formModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }"
+                        label-align="left">
+                        <a-row :gutter="16">
+                            <a-col :span="8">
+                                <a-form-item field="keyword" label="账号名">
+                                    <selectAccount v-model="formModel.keyword" @change="changeCompany" />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="8">
+                                <a-form-item field="query_date" :label="$t('searchTable.form.report_date')">
+                                    <a-range-picker v-model="formModel.query_date" style="width: 100%"
+                                        @change="search" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                    </a-form>
+                </a-col>
+                <a-divider style="height: 32px" direction="vertical" />
+                <a-col :flex="'86px'" style="text-align: right">
+                    <a-space direction="vertical" :size="18">
+                        <a-button type="primary" @click="search">
+                            <template #icon>
+                                <icon-search />
+                            </template>
+                            {{ $t('searchTable.form.search') }}
+                        </a-button>
+                    </a-space>
+                </a-col>
+            </a-row>
+            <a-divider style="margin-top: 0" />
+            <a-row style="margin-bottom: 16px">
+                <a-col :span="12"> </a-col>
+                <a-col :span="12" style="
+                        display: flex;
+                        align-items: center;
+                        justify-content: end;
+                    ">
+                    <a-tooltip :content="$t('searchTable.actions.refresh')">
+                        <div class="action-icon" @click="search"><icon-refresh size="18" /></div>
+                    </a-tooltip>
+                    <a-dropdown @select="handleSelectDensity">
+                        <a-tooltip :content="$t('searchTable.actions.density')">
+                            <div class="action-icon"><icon-line-height size="18" /></div>
+                        </a-tooltip>
+                        <template #content>
+                            <a-doption v-for="item in densityList" :key="item.value" :value="item.value"
+                                :class="{ active: item.value === size }">
+                                <span>{{ item.name }}</span>
+                            </a-doption>
+                        </template>
+                    </a-dropdown>
+                    <a-tooltip :content="$t('searchTable.actions.columnSetting')">
+                        <a-popover trigger="click" position="bl" @popup-visible-change="popupVisibleChange">
+                            <div class="action-icon"><icon-settings size="18" /></div>
+                            <template #content>
+                                <div id="tableSetting">
+                                    <div v-for="(item, index) in showColumns" :key="item.dataIndex" class="setting">
+                                        <div style="
+                                                margin-right: 4px;
+                                                cursor: move;
+                                            ">
+                                            <icon-drag-arrow />
+                                        </div>
+                                        <div>
+                                            <a-checkbox v-model="item.checked" @change="
+                                                handleChange(
+                                                    $event,
+                                                    item as TableColumnData,
+                                                    index
+                                                )
+                                                ">
+                                            </a-checkbox>
+                                        </div>
+                                        <div class="title">
+                                            {{
+                                                item.title === '#'
+                                                    ? '序列号'
+                                                    : item.title
+                                            }}
+                                        </div>
+                                    </div>
+                                </div>
+                            </template>
+                        </a-popover>
+                    </a-tooltip>
+                </a-col>
+            </a-row>
+
+
+            <a-table row-key="id" :loading="loading" :pagination="pagination" :summary="true" summary-text="汇总"
+                :columns="(cloneColumns as TableColumnData[])" :scroll="scroll" :scrollbar="scrollbar"
+                :data="renderData" :bordered="false" :size="size" :load-more="loadMore" @page-change="onPageChange"
+                @page-size-change="onPageSizeChange">
+
+
+                <template #xAxis="{ record }">
+                    {{ dayjs(record.report_date).format('YYYY-MM-DD') }}
+                </template>
+                <template #summary-cell="{ column, record }">
+                    <div>{{ toAmount(record[column.dataIndex]) }}</div>
+                </template>
+ 
+            </a-table>
+        </a-card>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { useRouter } from 'vue-router';
+import dayjs from 'dayjs';
+import { computed, ref, reactive, watch, nextTick } from 'vue';
+import { useI18n } from 'vue-i18n';
+import useLoading from '@/hooks/loading';
+import {
+    JdSettleBillRecord,
+    JdSettleBillsParams,
+    queryJdSettleBills,
+    queryJdSettleBillsTotal,
+
+} from '@/api/jd';
+
+
+
+import { Pagination } from '@/types/global';
+import type {
+    TableData,
+    TableColumnData,
+} from '@arco-design/web-vue/es/table/interface';
+import cloneDeep from 'lodash/cloneDeep';
+import Sortable from 'sortablejs';
+import selectAccount from './components/selectAccount.vue';
+
+
+type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+type Column = TableColumnData & { checked?: true };
+
+const generateFormModel = () => {
+    let keyword = ''
+    if (router.currentRoute.value.query.name) {
+        keyword = router.currentRoute.value.query.name.toString()
+    }
+
+    return {
+        keyword,
+        query_date: [],
+        current: 1,
+        pageSize: 30,
+        sort: 'report_date',
+        order: 'descending',
+    };
+};
+
+
+const router = useRouter();
+
+const { loading, setLoading } = useLoading(true);
+const { t } = useI18n();
+const renderData = ref<JdSettleBillRecord[]>([]);
+const formModel = ref(generateFormModel());
+const cloneColumns = ref<Column[]>([]);
+const showColumns = ref<Column[]>([]);
+const size = ref<SizeProps>('medium');
+
+const scrollbar = ref(true);
+const scroll = {
+    x: '100%',
+    y: '100%',
+    maxHeight: 'calc( 100vh - 420px)',
+};
+
+const basePagination: Pagination = {
+    current: 1,
+    pageSize: 30,
+};
+const pagination = reactive({
+    ...basePagination,
+    showTotal: true,
+    showJumper: true,
+    showMore: true,
+    showPageSize: true,
+    pageSizeOptions: [10, 20, 30, 31, 50, 100, 200, 500],
+    sizePageSize: true,
+
+});
+const densityList = computed(() => [
+    {
+        name: t('searchTable.size.mini'),
+        value: 'mini',
+    },
+    {
+        name: t('searchTable.size.small'),
+        value: 'small',
+    },
+    {
+        name: t('searchTable.size.medium'),
+        value: 'medium',
+    },
+    {
+        name: t('searchTable.size.large'),
+        value: 'large',
+    },
+]);
+
+const columns = computed<TableColumnData[]>(() => [
+    {
+        title: '日期',
+        dataIndex: 'xAxis',
+        slotName: 'xAxis',
+        fixed: 'left',
+        width: 150,
+    },
+    {
+        title: '所属账号',
+        dataIndex: 'accountName',
+        width: 150,
+    },
+    {
+        title: '点击量',
+        dataIndex: 'clickNum',
+        slotName: 'clickNum',
+        width: 140,
+        align: "right",
+    },
+    {
+        title: '预估收入',
+        dataIndex: 'cosFee',
+        slotName: 'cosFee',
+        width: 140,
+        align: "right",
+    },
+    {
+        title: '有效订单金额',
+        dataIndex: 'cosPrice',
+        slotName: 'cosPrice',
+        width: 140,
+        align: "right",
+    },
+
+    {
+        title: '完成订单佣金',
+        dataIndex: 'finishCosFee',
+        slotName: 'finishCosFee',
+        width: 140,
+        align: "right",
+    },
+    {
+        title: '完成订单金额',
+        dataIndex: 'finishCosPrice',
+        slotName: 'finishCosPrice',
+        width: 140,
+        align: "right",
+    },
+    {
+        title: '完成订单数',
+        dataIndex: 'finishOrderNum',
+        slotName: 'finishOrderNum',
+        width: 140,
+        align: "right",
+    },
+    {
+        title: '有效订单量',
+        dataIndex: 'orderNum',
+        slotName: 'orderNum',
+        width: 140,
+        align: "right",
+    },
+    {
+        title: '最后更新时间',
+        dataIndex: 'last_time',
+        width: 180,
+    },
+]);
+
+
+const toAmount = (val: any): any => {
+    console.log(val);
+    if (typeof val === 'number' && !Number.isNaN(val)) {
+        return parseFloat(val.toFixed(2));
+    }
+    return val;
+}
+
+
+const fetchData = async (
+    params: JdSettleBillsParams = {
+        current: 1,
+        pageSize: basePagination.pageSize,
+        sort: 'report_date',
+        order: 'descending',
+    }
+) => {
+    console.log(basePagination, params)
+    setLoading(true);
+
+    try {
+        console.log(params)
+        if (params.keyword) {
+            const { data } = await queryJdSettleBills(params);
+            if (!data) return;
+
+            const list = data.list.map((item: JdSettleBillRecord) => ({
+                ...item,
+                isLeaf: true,
+            }));
+            renderData.value = list;
+            pagination.current = data.page;
+            pagination.total = data.count;
+        } else {
+            const { data } = await queryJdSettleBillsTotal(params);
+            if (!data) return;
+            renderData.value = data.list;
+            pagination.current = data.page;
+            pagination.total = data.count;
+        }
+    } catch (err) {
+        console.log(err);
+        // you can report use errorHandler or other
+    } finally {
+        setLoading(false);
+    }
+};
+
+
+const loadMore = async (
+    row: TableData,
+    done: (data: TableData[]) => void
+) => {
+    setLoading(true);
+    try {
+        let list: TableData[] = [];
+
+        if (row.accountName === '') {
+            console.log(row.report_date)
+            const params: JdSettleBillsParams = {
+                query_date: [row.report_date, row.report_date],
+                current: 1,
+                pageSize: 30,
+                sort: 'report_date',
+                order: 'descending',
+            };
+
+            const { data } = await queryJdSettleBills(params);
+            console.log(data);
+            if (!data) return;
+            list = data.list.map((item: JdSettleBillRecord) => ({
+                ...item,
+                isLeaf: true,
+            }));
+
+            console.log(list)
+        }
+        done(list);
+    } catch (err) {
+        console.log(err);
+        // you can report use errorHandler or other
+    } finally {
+        setLoading(false);
+    }
+};
+
+const search = () => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+    } as unknown as JdSettleBillsParams);
+};
+const changeCompany = (value: any) => {
+    const reset = () => {
+        formModel.value = generateFormModel();
+    };
+    formModel.value.keyword = value
+
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+    } as unknown as JdSettleBillsParams);
+};
+
+
+
+const onPageChange = (current: number) => {
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current
+    });
+};
+const onPageSizeChange = (current: number) => {
+    basePagination.pageSize = current;
+    pagination.pageSize = current;
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        pageSize: current,
+        current: 1,
+    });
+};
+
+fetchData({ ...formModel.value } as unknown as JdSettleBillsParams);
+const reset = () => {
+    formModel.value = generateFormModel();
+};
+
+const handleSelectDensity = (
+    val: string | number | Record<string, any> | undefined,
+    e: Event
+) => {
+    size.value = val as SizeProps;
+};
+
+const handleChange = (
+    checked: boolean | (string | boolean | number)[],
+    column: Column,
+    index: number
+) => {
+    if (!checked) {
+        cloneColumns.value = showColumns.value.filter(
+            (item) => item.dataIndex !== column.dataIndex
+        );
+    } else {
+        cloneColumns.value.splice(index, 0, column);
+    }
+};
+
+const exchangeArray = <T extends Array<any>>(
+    array: T,
+    beforeIdx: number,
+    newIdx: number,
+    isDeep = false
+): T => {
+    const newArray = isDeep ? cloneDeep(array) : array;
+    if (beforeIdx > -1 && newIdx > -1) {
+        // 先替换后面的,然后拿到替换的结果替换前面的
+        newArray.splice(
+            beforeIdx,
+            1,
+            newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
+        );
+    }
+    return newArray;
+};
+
+const popupVisibleChange = (val: boolean) => {
+    if (val) {
+        nextTick(() => {
+            const el = document.getElementById(
+                'tableSetting'
+            ) as HTMLElement;
+            const sortable = new Sortable(el, {
+                onEnd(e: any) {
+                    const { oldIndex, newIndex } = e;
+                    exchangeArray(cloneColumns.value, oldIndex, newIndex);
+                    exchangeArray(showColumns.value, oldIndex, newIndex);
+                },
+            });
+        });
+    }
+};
+
+watch(
+    () => columns.value,
+    (val) => {
+        cloneColumns.value = cloneDeep(val);
+        cloneColumns.value.forEach((item, index) => {
+            item.checked = true;
+        });
+        showColumns.value = cloneDeep(cloneColumns.value);
+    },
+    { deep: true, immediate: true }
+);
+</script>
+
+<script lang="ts">
+export default {
+    name: 'bill_dailys',
+};
+</script>
+
+<style scoped lang="less">
+.container {
+    padding: 0 20px 20px 20px;
+}
+
+:deep(.arco-table-th) {
+    &:last-child {
+        .arco-table-th-item-title {
+            margin-left: 16px;
+        }
+    }
+}
+
+.action-icon {
+    margin-left: 12px;
+    cursor: pointer;
+}
+
+.active {
+    color: #0960bd;
+    background-color: #e3f4fc;
+}
+
+.setting {
+    display: flex;
+    align-items: center;
+    width: 200px;
+
+    .title {
+        margin-left: 12px;
+        cursor: pointer;
+    }
+}
+</style>

+ 47 - 0
src/views/jd/components/selectAccount.vue

@@ -0,0 +1,47 @@
+<template>
+
+    <a-select v-model="model" placeholder="指定账号名" @change="changeCompany">
+        <a-option value="">所有账号</a-option>
+        <a-option :key="item.id" v-for="item of accounts" :value="item.company" :label="item.company" />
+    </a-select>
+
+</template>
+
+<script lang="ts" setup>
+import { defineEmits, ref } from 'vue';
+import {
+    JdPoolParams,
+    queryJdPool,
+    JdPoolRecord,
+} from '@/api/jd';
+
+const model = defineModel()
+const accounts = ref<JdPoolRecord[]>([]);
+
+const loadAccounts = async (
+    params: JdPoolParams = {
+        current: 1,
+        pageSize: 9999,
+        sort: 'status',
+        order: 'descending',
+        getTotal: false,
+    }
+) => {
+    try {
+        const { data } = await queryJdPool(params);
+        console.log(data);
+        if (!data) return;
+        accounts.value = data.list;
+    } catch (err) {
+        console.log(err);
+    }
+};
+
+const emits = defineEmits(['change'])
+
+const changeCompany = (value: any) => {
+    emits('change', value)
+}
+loadAccounts();
+
+</script>

+ 26 - 44
src/views/jd/list.vue

@@ -125,21 +125,6 @@
                         </template>
                     </a-list-item-meta>
                 </template>
-                <template #hourly_calls_limit="{ record }">
-                    <a-tag bordered
-                        :color="record.current_hourly_calls > record.hourly_calls_limit && record.hourly_calls_limit > 0 ? 'red' : ''">
-                        {{ record.current_hourly_calls }} /
-                        {{ record.hourly_calls_limit }}
-                    </a-tag>
-                </template>
-
-                <template #daily_calls_limit="{ record }">
-                    <a-tag bordered
-                        :color="record.current_daily_calls > record.daily_calls_limit && record.daily_calls_limit > 0 ? 'red' : ''">
-                        {{ record.current_daily_calls }} /
-                        {{ record.daily_calls_limit }}
-                    </a-tag>
-                </template>
                 <template #nodeName="{ record }">
                     <a-tag color="gray">{{ record.end_point }} - {{ record.nodeName }} </a-tag>
                 </template>
@@ -215,7 +200,22 @@
 
                 </template>
                 <template #time_range="{ record }">
-                    <WorkHourModel :record="record" @change="search" />
+                    <WorkHourModel :path="updatePath" :record="record" @change="search" />
+                </template>
+                <template #hourly_calls_limit="{ record }">
+                    <a-tag bordered
+                        :color="record.current_hourly_calls > record.hourly_calls_limit && record.hourly_calls_limit > 0 ? 'red' : ''">
+                        {{ record.current_hourly_calls }} /
+                        {{ record.hourly_calls_limit }}
+                    </a-tag>
+                </template>
+
+                <template #daily_calls_limit="{ record }">
+                    <a-tag bordered
+                        :color="record.current_daily_calls > record.daily_calls_limit && record.daily_calls_limit > 0 ? 'red' : ''">
+                        {{ record.current_daily_calls }} /
+                        {{ record.daily_calls_limit }}
+                    </a-tag>
                 </template>
 
             </a-table>
@@ -229,7 +229,8 @@ import { computed, ref, reactive, watch, nextTick } from 'vue';
 import { useI18n } from 'vue-i18n';
 import dayjs from 'dayjs';
 import useLoading from '@/hooks/loading';
-import { queryJdPool, JdPoolRecord, JdPoolParams, JdUpdateAccountModel, JdUpdateAccount } from '@/api/jd';
+import { queryJdPool, JdPoolRecord, JdPoolParams } from '@/api/jd';
+
 import { Pagination } from '@/types/global';
 import { Message } from '@arco-design/web-vue';
 import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
@@ -237,11 +238,14 @@ import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
 import cloneDeep from 'lodash/cloneDeep';
 import Sortable from 'sortablejs';
 import { numberFormat, amountFormat } from '@/utils/util';
-import WorkHourModel from './components/WorkHourModel.vue';
+import { UpdateAccountModel, UpdateAccount } from '@/api/app';
+import WorkHourModel from '@/components/WorkHourModel.vue';
 
+const updatePath = '/api/JdUnion/update';
 type SizeProps = 'mini' | 'small' | 'medium' | 'large';
 type Column = TableColumnData & { checked?: true };
 
+
 const generateFormModel = () => {
     return {
         name: '',
@@ -332,27 +336,6 @@ const columns = computed<TableColumnData[]>(() => [
                 align: 'right',
                 render: (e: any) => amountFormat(e.record.today_cosPrice)
             },
-            // {
-            //     title: '完成收益',
-            //     dataIndex: 'today_finishCosFee',
-            //     width: 100,
-            //     align: 'right',
-            //     render: (e: any) => amountFormat(e.record.today_finishCosFee)
-            // },
-            // {
-            //     title: '完成订单量',
-            //     dataIndex: 'today_finishOrderNum',
-            //     width: 100,
-            //     align: 'right',
-            //     render: (e: any) => numberFormat(e.record.today_finishOrderNum)
-            // },
-            // {
-            //     title: '完成订单量',
-            //     dataIndex: 'today_finishCosPrice',
-            //     width: 100,
-            //     align: 'right',
-            //     render: (e: any) => numberFormat(e.record.today_finishCosPrice)
-            // },
             {
                 title: '预估收入',
                 dataIndex: 'today_cosFee',
@@ -456,12 +439,12 @@ const changeStatus = async (id: number, val: any) => {
         id,
         name: 'status',
         val
-    } as JdUpdateAccountModel;
+    } as UpdateAccountModel;
 
     setLoading(true);
 
     try {
-        const { data } = await JdUpdateAccount(args);
+        const { data } = await UpdateAccount(updatePath, args);
         console.log(data, data.msg);
         const msg = data.msg || '更新成功!';
         if (data.success) {
@@ -481,12 +464,11 @@ const changeAttr = async (id: number, name: string, val: any) => {
         id,
         name,
         val
-    } as JdUpdateAccountModel;
+    } as UpdateAccountModel;
 
     setLoading(true);
     try {
-
-        const { data } = await JdUpdateAccount(args);
+        const { data } = await UpdateAccount(updatePath, args);
         console.log(data, data.msg);
         const msg = data.msg || '更新成功!';
         if (data.success) {

+ 15 - 51
src/views/pdd/list.vue

@@ -125,21 +125,6 @@
                         </template>
                     </a-list-item-meta>
                 </template>
-                <template #hourly_calls_limit="{ record }">
-                    <a-tag bordered
-                        :color="record.current_hourly_calls > record.hourly_calls_limit && record.hourly_calls_limit > 0 ? 'red' : ''">
-                        {{ record.current_hourly_calls }} /
-                        {{ record.hourly_calls_limit }}
-                    </a-tag>
-                </template>
-
-                <template #daily_calls_limit="{ record }">
-                    <a-tag bordered
-                        :color="record.current_daily_calls > record.daily_calls_limit && record.daily_calls_limit > 0 ? 'red' : ''">
-                        {{ record.current_daily_calls }} /
-                        {{ record.daily_calls_limit }}
-                    </a-tag>
-                </template>
                 <template #nodeName="{ record }">
                     <a-tag color="gray">{{ record.end_point }} - {{ record.nodeName }} </a-tag>
                 </template>
@@ -217,6 +202,21 @@
                 <template #time_range="{ record }">
                     <WorkHourModel :record="record" @change="search" />
                 </template>
+                <template #hourly_calls_limit="{ record }">
+                    <a-tag bordered
+                        :color="record.current_hourly_calls > record.hourly_calls_limit && record.hourly_calls_limit > 0 ? 'red' : ''">
+                        {{ record.current_hourly_calls }} /
+                        {{ record.hourly_calls_limit }}
+                    </a-tag>
+                </template>
+
+                <template #daily_calls_limit="{ record }">
+                    <a-tag bordered
+                        :color="record.current_daily_calls > record.daily_calls_limit && record.daily_calls_limit > 0 ? 'red' : ''">
+                        {{ record.current_daily_calls }} /
+                        {{ record.daily_calls_limit }}
+                    </a-tag>
+                </template>
 
             </a-table>
         </a-card>
@@ -308,42 +308,6 @@ const columns = computed<TableColumnData[]>(() => [
         align: 'right',
         width: 200,
     },
-    // {
-    //     title: '当日推广效果',
-    //     children: [
-    //         {
-    //             title: '点击量',
-    //             dataIndex: 'today_clickNum',
-    //             width: 100,
-    //             align: 'right',
-    //             render: (e: any) => numberFormat(e.record.today_clickNum)
-    //         },
-    //         {
-    //             title: '有效订单',
-    //             dataIndex: 'today_orderNum',
-    //             width: 100,
-    //             align: 'right',
-    //             render: (e: any) => numberFormat(e.record.today_orderNum)
-    //         },
-    //         {
-    //             title: '订单金额',
-    //             dataIndex: 'today_cosPrice',
-    //             width: 150,
-    //             align: 'right',
-    //             render: (e: any) => amountFormat(e.record.today_cosPrice)
-    //         },
-    //         {
-    //             title: '预估收入',
-    //             dataIndex: 'today_cosFee',
-    //             width: 150,
-    //             align: 'right',
-    //             render: (e: any) => amountFormat(e.record.today_cosFee)
-    //         },
-
-    //         // 
-
-    //     ]
-    // },
     {
         title: '小时调用',
         slotName: 'hourly_calls_limit',

+ 12 - 6
src/views/settings/config.vue

@@ -47,6 +47,11 @@
                                     </a-form-item>
 
 
+                                    <a-form-item field="blacklist_oaid" label="OAID黑名单">
+                                        <a-textarea v-model="formData.blacklist_oaid" auto-size
+                                            placeholder="OAID黑名单" />
+                                    </a-form-item>
+
                                 </a-tab-pane>
                                 <a-tab-pane key="cps" title="CPS">
 
@@ -55,7 +60,7 @@
                                     </a-form-item>
 
 
-                                    <a-form-item field="cps_limit_per_ip_24h" label="24小时转链次数(CPS)"
+                                    <a-form-item field="cps_limit_per_ip_24h" label="(IP) 24小时转链次数"
                                         :rules="[{ required: true }]">
                                         <a-input-number v-model="formData.cps_limit_per_ip_24h" :min="0"
                                             placeholder="同ip在24小时内可转链的次数。" />
@@ -105,7 +110,7 @@
                                     </a-form-item>
 
 
-                                    <a-form-item field="tk_limit_per_ip_24h" label="24小时转链次数(TK)"
+                                    <a-form-item field="tk_limit_per_ip_24h" label="(IP) 24小时转链次数"
                                         :rules="[{ required: true }]">
                                         <a-input-number v-model="formData.tk_limit_per_ip_24h" :min="0"
                                             placeholder="同ip在24小时内可转链的次数。" />
@@ -126,12 +131,12 @@
                                         <a-input v-model="formData.jdIgnorePercentageCity" />
                                     </a-form-item>
 
-                                    <a-form-item field="jd_limit_per_ip_24h" label="24小时转链次数"
+                                    <a-form-item field="jd_limit_per_ip_24h" label="(IP) 24小时转链次数"
                                         :rules="[{ required: true }]">
                                         <a-input-number v-model="formData.jd_limit_per_ip_24h" :min="0"
                                             placeholder="同ip在24小时内可转链的次数。" />
                                     </a-form-item>
-                                    
+
                                     <a-form-item field="jd_limit_per_oaid_24h" label="(OAID) 24小时转链次数"
                                         :rules="[{ required: true }]">
                                         <a-input-number v-model="formData.jd_limit_per_oaid_24h" :min="0"
@@ -172,12 +177,12 @@
                                         <a-input v-model="formData.ksIgnorePercentageCity" />
                                     </a-form-item>
 
-                                    <a-form-item field="ks_limit_per_ip_24h" label="24小时转链次数"
+                                    <a-form-item field="ks_limit_per_ip_24h" label="(IP) 24小时转链次数"
                                         :rules="[{ required: true }]">
                                         <a-input-number v-model="formData.ks_limit_per_ip_24h" :min="0"
                                             placeholder="同ip在24小时内可转链的次数。" />
                                     </a-form-item>
-                                    
+
                                     <a-form-item field="ks_limit_per_oaid_24h" label="(OAID) 24小时转链次数"
                                         :rules="[{ required: true }]">
                                         <a-input-number v-model="formData.ks_limit_per_oaid_24h" :min="0"
@@ -241,6 +246,7 @@ const router = useRouter();
 const formRef = ref<FormInstance>();
 const formData = ref<UpdateConfigModel>({
     cookie: '',
+    blacklist_oaid: '',
     ignorePercentage: 0,
     jdIgnorePercentage: 0,
     pass_salt: '',

+ 1 - 10
src/views/taobao/bill_dailys.vue

@@ -105,15 +105,7 @@
                 <template #summary-cell="{ column, record }">
                     <div>{{ toAmount(record[column.dataIndex]) }}</div>
                 </template>
-
-                <template #total_count="{ record }">
-                    <a-popover v-if="record.total_count > 0" popup-container="body" trigger="click">
-                        <a-tag color="green">{{ record.total_count }}</a-tag>
-                        <template #content>
-                            <CategoriesPercent :record="record" />
-                        </template>
-                    </a-popover>
-                </template>
+ 
             </a-table>
         </a-card>
     </div>
@@ -146,7 +138,6 @@ import type {
 } from '@arco-design/web-vue/es/table/interface';
 import cloneDeep from 'lodash/cloneDeep';
 import Sortable from 'sortablejs';
-import CategoriesPercent from './components/categories-percent.vue';
 import selectAccount from './components/selectAccount.vue';
 
 

+ 52 - 6
src/views/taobao/list.vue

@@ -128,13 +128,13 @@
                 </template>
 
                 <template #suspended_endpoint="{ record }">
-                        <a-tag v-if="record.suspended_endpoint" size="small" bordered color="red"
-                            @click="changeAttr(record.id, 'check_status', true)">
-                            暂停:{{ record.suspended_endpoint }}</a-tag>
+                    <a-tag v-if="record.suspended_endpoint" size="small" bordered color="red"
+                        @click="changeAttr(record.id, 'check_status', true)">
+                        暂停:{{ record.suspended_endpoint }}</a-tag>
 
-                        <a-tag v-else size="small" bordered color="gray"
-                            @click="changeAttr(record.id, 'check_status', true)">
-                            正常</a-tag>
+                    <a-tag v-else size="small" bordered color="gray"
+                        @click="changeAttr(record.id, 'check_status', true)">
+                        正常</a-tag>
 
                 </template>
                 <template #status="{ record }">
@@ -241,6 +241,25 @@
                     </div>
                 </template>
 
+                <template #time_range="{ record }">
+                    <WorkHourModel :path="updatePath" :record="record" @change="search" />
+                </template>
+                <template #hourly_calls_limit="{ record }">
+                    <a-tag bordered
+                        :color="record.current_hourly_calls > record.hourly_calls_limit && record.hourly_calls_limit > 0 ? 'red' : ''">
+                        {{ record.current_hourly_calls }} /
+                        {{ record.hourly_calls_limit }}
+                    </a-tag>
+                </template>
+
+                <template #daily_calls_limit="{ record }">
+                    <a-tag bordered
+                        :color="record.current_daily_calls > record.daily_calls_limit && record.daily_calls_limit > 0 ? 'red' : ''">
+                        {{ record.current_daily_calls }} /
+                        {{ record.daily_calls_limit }}
+                    </a-tag>
+                </template>
+
             </a-table>
         </a-card>
     </div>
@@ -260,6 +279,11 @@ import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
 import cloneDeep from 'lodash/cloneDeep';
 import Sortable from 'sortablejs';
 import { numberFormat, amountFormat } from '@/utils/util';
+import { UpdateAccountModel, UpdateAccount } from '@/api/app';
+import WorkHourModel from '@/components/WorkHourModel.vue';
+
+const updatePath = '/api/taobao/update';
+
 
 type SizeProps = 'mini' | 'small' | 'medium' | 'large';
 type Column = TableColumnData & { checked?: true };
@@ -323,10 +347,32 @@ const columns = computed<TableColumnData[]>(() => [
         slotName: 'name',
         width: 200,
     },
+    {
+        title: '工作时间',
+        dataIndex: 'time_range',
+        slotName: 'time_range',
+        align: 'right',
+        width: 200,
+    },
+    {
+        title: '小时调用',
+        slotName: 'hourly_calls_limit',
+        dataIndex: 'current_hourly_calls',
+        align: 'right',
+        width: 120,
+    },
+    {
+        title: '当日调用',
+        slotName: 'daily_calls_limit',
+        dataIndex: 'current_daily_calls',
+        align: 'right',
+        width: 150,
+    },
     {
         title: '每日收益限额',
         slotName: 'daily_income_limit',
         dataIndex: 'current_amt',
+        align: 'right',
         width: 180,
     },
     {