dodo hold 2 лет назад
Родитель
Сommit
720f79aad2
38 измененных файлов с 2916 добавлено и 1753 удалено
  1. 101 0
      src/api/app.ts
  2. 132 109
      src/api/interceptor.ts
  3. 73 0
      src/api/jd.ts
  4. 69 82
      src/api/taobao.ts
  5. 119 6
      src/components/navbar/index.vue
  6. 16 15
      src/config/settings.json
  7. 3 0
      src/locale/en-US/taoke.ts
  8. 5 1
      src/locale/zh-CN/taoke.ts
  9. 12 12
      src/router/routes/index.ts
  10. 21 21
      src/router/routes/modules/jd.ts
  11. 1 1
      src/router/routes/modules/taobao.ts
  12. 78 0
      src/router/routes/modules/tbcoupon.ts
  13. 13 13
      src/router/routes/types.ts
  14. 71 60
      src/store/modules/app/index.ts
  15. 17 16
      src/store/modules/app/types.ts
  16. 18 2
      src/utils/util.ts
  17. 134 0
      src/views/dashboard/dailyLog/components/categories-percent.vue
  18. 351 0
      src/views/dashboard/dailyLog/index copy 2.vue
  19. 1022 0
      src/views/dashboard/dailyLog/index copy.vue
  20. 549 241
      src/views/dashboard/dailyLog/index.vue
  21. 94 0
      src/views/jd/updateCookies.vue
  22. 0 71
      src/views/jd/workplace/components/announcement.vue
  23. 0 35
      src/views/jd/workplace/components/banner.vue
  24. 0 24
      src/views/jd/workplace/components/carousel.vue
  25. 0 114
      src/views/jd/workplace/components/categories-percent.vue
  26. 0 200
      src/views/jd/workplace/components/content-chart.vue
  27. 0 131
      src/views/jd/workplace/components/data-panel.vue
  28. 0 42
      src/views/jd/workplace/components/docs.vue
  29. 0 118
      src/views/jd/workplace/components/popular-content.vue
  30. 0 35
      src/views/jd/workplace/components/quick-operation.vue
  31. 0 44
      src/views/jd/workplace/components/recently-visited.vue
  32. 0 148
      src/views/jd/workplace/index.vue
  33. 0 38
      src/views/jd/workplace/locale/en-US.ts
  34. 0 37
      src/views/jd/workplace/locale/zh-CN.ts
  35. 0 129
      src/views/jd/workplace/mock.ts
  36. 15 3
      src/views/settings/config.vue
  37. 1 2
      src/views/taobao/report_daily.vue
  38. 1 3
      src/views/taobao/updateCookies.vue

+ 101 - 0
src/api/app.ts

@@ -0,0 +1,101 @@
+import axios from 'axios';
+import type { ListRes } from './base';
+
+/*
+daily_logs
+*/
+export interface DailyLogRecord {
+    id: number;
+    log_date: Date;
+    channel: number;
+    accountId: number;
+    accountName: string;
+    create_time: Date;
+    last_time: Date;
+
+    total_count: number;
+    abandon_count: number;
+    abandon_percentage: string;
+    success_count: number;
+    success_percentage: string;
+
+    coupon_total_count: number;
+    coupon_abandon_count: number;
+    coupon_abandon_percentage: string;
+    coupon_success_count: number;
+    coupon_success_percentage: string;
+
+    parse_total_count: number;
+    parse_abandon_count: number;
+    parse_abandon_percentage: string;
+    parse_success_count: number;
+    parse_success_percentage: string;
+
+    tool_total_count: number;
+    tool_abandon_count: number;
+    tool_abandon_percentage: string;
+    tool_success_count: number;
+    tool_success_percentage: string;
+
+    jd_parse_total_count: number;
+    jd_parse_abandon_count: number;
+    jd_parse_abandon_percentage: string;
+    jd_parse_success_count: number;
+    jd_parse_success_percentage: string;
+}
+
+export interface DailyLogParams extends Partial<DailyLogRecord> {
+    query_date?: string[]; // 覆盖 report_date 的类型为字符串数组
+    accountName?: string;
+    current: number;
+    pageSize: number;
+    sort?: string;
+    order?: string;
+}
+export interface DailyLogRes extends ListRes {
+    list: DailyLogRecord[];
+}
+
+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;
+    query_date?: string[]; // 覆盖 report_date 的类型为字符串数组
+    current: number;
+    pageSize: number;
+    sort?: string;
+    order?: string;
+}
+
+export interface ChartDataResponse {
+    name: string;
+    value: number;
+}
+
+export interface ReportChartRes {
+    code: number;
+    data: ChartDataResponse[];
+    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,

+ 132 - 109
src/api/interceptor.ts

@@ -1,135 +1,158 @@
 import axios from 'axios';
+
+import { listenerRouteChange } from '@/utils/route-listener';
+import type { RouteLocationNormalized } from 'vue-router';
+
 import type { AxiosRequestConfig, AxiosResponse } from 'axios';
 import { Message, Modal } from '@arco-design/web-vue';
 import { useUserStore } from '@/store';
 import { getToken } from '@/utils/auth';
 
+let currentRoute: RouteLocationNormalized | null = null;
+
+listenerRouteChange((route) => {
+    currentRoute = route;
+});
+
 export interface HttpResponse<T = unknown> {
-  status: number;
-  msg: string;
-  code: number;
-  data: T;
+    status: number;
+    msg: string;
+    code: number;
+    data: T;
 }
 
 if (import.meta.env.VITE_API_BASE_URL) {
-  axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL;
+    axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL;
 }
 
 let API_SCOPE = 'admin';
 if (import.meta.env.VITE_API_BASE_SCOPE) {
-  API_SCOPE = import.meta.env.VITE_API_BASE_SCOPE;
+    API_SCOPE = import.meta.env.VITE_API_BASE_SCOPE;
 }
 
 axios.interceptors.request.use(
-  (config: AxiosRequestConfig) => {
-    // let each request carry token
-    // this example using the JWT token
-    // Authorization is a custom headers key
-    // please modify it according to the actual situation
-
-    const token = getToken();
-    if (token) {
-      if (!config.headers) {
-        config.headers = {
-        };
-      }
-      if (API_SCOPE) {
-        config.headers.scope = API_SCOPE;
-      }
-      config.headers.Authorization = `Bearer ${token}`;
+    (config: AxiosRequestConfig) => {
+        // let each request carry token
+        // this example using the JWT token
+        // Authorization is a custom headers key
+        // please modify it according to the actual situation
+
+        // 判断 currentRoute.name 是否包含 "tbcoupon_"
+        if (
+            currentRoute &&
+            currentRoute.name &&
+            currentRoute.name.toString().includes('tbcoupon_')
+        ) {
+            if (config.url) {
+                config.url = config.url.replace('/api/taobao', '/coupon_api/taobao');
+            }
+        }
+
+        const token = getToken();
+        if (token) {
+            if (!config.headers) {
+                config.headers = {};
+            }
+            if (API_SCOPE) {
+                config.headers.scope = API_SCOPE;
+            }
+            config.headers.Authorization = `Bearer ${token}`;
+        }
+        return config;
+    },
+    (error) => {
+        // do something
+        return Promise.reject(error);
     }
-    return config;
-  },
-  (error) => {
-    // do something
-    return Promise.reject(error);
-  }
 );
 // add response interceptors
 axios.interceptors.response.use(
-  (response: AxiosResponse<HttpResponse>) => {
-    const res = response.data;
-    // if the custom code is not 20000, it is judged as an error.
-    if (res.code !== 200) {
-      Message.error({
-        content: res.msg || 'Error',
-        duration: 5 * 1000,
-      });
-      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
-      if (
-        [401].includes(res.code) &&
-        response.config.url !== '/api/user/info'
-      ) {
-        Modal.error({
-          title: 'Confirm logout',
-          content:
-            'You have been logged out, you can cancel to stay on this page, or log in again',
-          okText: 'Re-Login',
-          async onOk() {
-            const userStore = useUserStore();
-
-            await userStore.logout();
-            window.location.reload();
-          },
-        });
-      }
-      return Promise.reject(new Error(res.msg || 'Error'));
-    }
-    return res;
-  },
-  (error) => {
-    const result = error.response;
-
-    if (error.response) {
-      if (error.response.request.responseType === 'arraybuffer' && error.response.data.toString() === '[object ArrayBuffer]') {
-        const text = Buffer.from(error.response.data).toString('utf8');
-        result.data = JSON.parse(text);
-      }
-    } else {
-      Message.error({
-        content: error.msg || 'Request Error',
-        duration: 5 * 1000,
-      });
-      return Promise.reject(error);
-    }
+    (response: AxiosResponse<HttpResponse>) => {
+        const res = response.data;
+        // if the custom code is not 20000, it is judged as an error.
+        if (res.code !== 200) {
+            Message.error({
+                content: res.msg || 'Error',
+                duration: 5 * 1000,
+            });
+            // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
+            if (
+                [401].includes(res.code) &&
+                response.config.url !== '/api/user/info'
+            ) {
+                Modal.error({
+                    title: 'Confirm logout',
+                    content:
+                        'You have been logged out, you can cancel to stay on this page, or log in again',
+                    okText: 'Re-Login',
+                    async onOk() {
+                        const userStore = useUserStore();
+
+                        await userStore.logout();
+                        window.location.reload();
+                    },
+                });
+            }
+            return Promise.reject(new Error(res.msg || 'Error'));
+        }
+        return res;
+    },
+    (error) => {
+        const result = error.response;
+
+        if (error.response) {
+            if (
+                error.response.request.responseType === 'arraybuffer' &&
+                error.response.data.toString() === '[object ArrayBuffer]'
+            ) {
+                const text = Buffer.from(error.response.data).toString('utf8');
+                result.data = JSON.parse(text);
+            }
+        } else {
+            Message.error({
+                content: error.msg || 'Request Error',
+                duration: 5 * 1000,
+            });
+            return Promise.reject(error);
+        }
+
+        if (result.data.code !== 200) {
+            const url = result.data.config?.url;
+            // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
+            if (result.data.code === 401 && url !== '/api/user/info') {
+                Modal.error({
+                    title: 'Confirm logout',
+                    content:
+                        'You have been logged out, you can cancel to stay on this page, or log in again',
+                    okText: 'Re-Login',
+                    async onOk() {
+                        const userStore = useUserStore();
+
+                        await userStore.logout();
+                        window.location.reload();
+                    },
+                });
+            } else {
+                Message.error({
+                    content: result.data.msg || 'Error',
+                    duration: 5 * 1000,
+                });
+            }
+        }
+
+        if (result && typeof result.data.code !== 'undefined') {
+            const err = new Error(result.data.msg);
+            Message.error({
+                content: err.message || 'Request Error',
+                duration: 5 * 1000,
+            });
+            return Promise.reject(err);
+        }
 
-    if (result.data.code !== 200) {
-      const url = result.data.config?.url
-      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
-      if (result.data.code === 401 && url !== '/api/user/info') {
-        Modal.error({
-          title: 'Confirm logout',
-          content:
-            'You have been logged out, you can cancel to stay on this page, or log in again',
-          okText: 'Re-Login',
-          async onOk() {
-            const userStore = useUserStore();
-
-            await userStore.logout();
-            window.location.reload();
-          },
-        });
-      } else {
         Message.error({
-          content: result.data.msg || 'Error',
-          duration: 5 * 1000,
+            content: error.msg || 'Request Error',
+            duration: 5 * 1000,
         });
-      }
-    }
-
-    if (result && typeof (result.data.code) !== 'undefined') {
-      const err = new Error(result.data.msg);
-      Message.error({
-        content: err.message || 'Request Error',
-        duration: 5 * 1000,
-      });
-      return Promise.reject(err);
+        return Promise.reject(error);
     }
-
-    Message.error({
-      content: error.msg || 'Request Error',
-      duration: 5 * 1000,
-    });
-    return Promise.reject(error);
-  }
 );

+ 73 - 0
src/api/jd.ts

@@ -0,0 +1,73 @@
+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);
+}
+
+export interface UpdateCookieModel {
+    cookie: string;
+}
+  
+export function updateCookies(data: UpdateCookieModel) {
+    return axios.post<FormRes>('/api/JdUnion/updateCookies', data);
+}
+
+// list
+export interface JdPoolRecord {
+    id: number;
+    name: string;
+    company: string;
+    phone: string;
+    cookies: string;
+    create_time: Date;
+    daily_income_limit: number;
+    current_amt: number;
+    description: string;
+    floorId: string;
+    last_time: Date;
+    nodeName: string;
+    refpid: string;
+    status: boolean;
+    tb_token: string;
+    api: string;
+    end_point: string;
+    api_id: number;
+    enable_fake_click: boolean;
+    enable_parse: boolean;
+    enable_coupon: boolean;
+    enable_sync_order: boolean;
+    enable_promotionQuery: boolean;
+    appkey: string;
+    appSecret: string;
+    open_pid: string;
+}
+
+export interface JdPoolParams extends Partial<JdPoolRecord> {
+    current: number;
+    pageSize: number;
+    sort?: string;
+    order?: string;
+    getTotal: boolean;
+}
+
+export interface JdPoolRes extends ListRes {
+    list: JdPoolRecord[];
+} 
+
+export function queryJdPool(data: JdPoolParams) {
+    return axios.post<JdPoolRes>('/api/JdUnion/list', data);
+}
+  

+ 69 - 82
src/api/taobao.ts

@@ -1,8 +1,10 @@
 import axios from 'axios';
-import qs from 'query-string';
-import type { DescData } from '@arco-design/web-vue/es/descriptions/interface';
 import type { ListRes } from './base';
 
+function ForwardAPI(url: string) {
+    return url;
+}
+
 export interface UpdateConfigModel {
     cookie: string;
     ignorePercentage: number;
@@ -18,8 +20,13 @@ export interface UpdateConfigModel {
     tk_whitelist_regular: string;
     tk_blacklist_regular: string;
     multi_token_regular: string;
+    
+    jd_limit_per_ip_24h: number;
+    tk_limit_per_ip_24h: number;
 }
 
+
+
 export interface UpdateConfigRes {
     msg?: string;
     code: number;
@@ -61,30 +68,12 @@ export interface FormRes {
     success: boolean;
 }
 
-export function updateConfig(data: UpdateConfigModel) {
-    return axios.post<FormRes>('/api/config/update', data);
-}
-export function getConfig() {
-    return axios.get<UpdateConfigModel>('/api/config/get');
-}
-
-export interface UpdateCookieModel {
-    cookie: string;
-}
-export function updateCookies(data: UpdateCookieModel) {
-    return axios.post<FormRes>('/api/taobao/updateCookies', data);
-}
-
 export interface TkUpdateAccountModel {
     id: number;
     name: string;
     val: any;
 }
 
-export function TkUpdateAccount(data: TkUpdateAccountModel) {
-    return axios.post<UpdateConfigRes>('/api/taobao/update', data);
-}
-
 export interface TkPoolParams extends Partial<TkPoolRecord> {
     current: number;
     pageSize: number;
@@ -92,46 +81,6 @@ export interface TkPoolParams extends Partial<TkPoolRecord> {
     order?: string;
     getTotal: boolean;
 }
-
-export interface TkPoolRes extends ListRes {
-    list: TkPoolRecord[];
-}
-
-export function queryTkPool(data: TkPoolParams) {
-    return axios.post<TkPoolRes>('/api/taobao/list', data);
-}
-
-/*
-daily_logs
-*/
-export interface DailyLogRecord {
-    id: number;
-    log_date: Date;
-    channel: number;
-    total_count: number;
-    abandon_count: number;
-    abandon_percentage: string;
-    success_count: number;
-    success_percentage: string;
-    create_time: Date;
-    last_time: Date;
-}
-
-export interface DailyLogParams extends Partial<DailyLogRecord> {
-    query_date?: string[]; // 覆盖 report_date 的类型为字符串数组
-    accountName?: string;
-    current: number;
-    pageSize: number;
-    sort?: string;
-    order?: string;
-}
-export interface DailyLogRes extends ListRes {
-    list: DailyLogRecord[];
-}
-export function queryDailyLog(data: DailyLogParams) {
-    return axios.post<DailyLogRes>('/api/report/daily_list', data);
-}
-
 /*
 tk_report_hourtrend
 */
@@ -187,16 +136,10 @@ export interface TkReportParams extends Partial<TkReportRecord> {
 export interface TkReportRes extends ListRes {
     list: TkReportRecord[];
 }
-export function queryTkReport(data: TkReportParams) {
-    return axios.post<TkReportRes>('/api/taobao/report_list', data);
-}
-export function queryTkReportDailys(data: TkReportParams) {
-    return axios.post<TkReportRes>('/api/taobao/report_dailys', data);
-}
-export function queryTkReportHourtrend(data: TkReportParams) {
-    return axios.post<TkReportRes>('/api/taobao/report_hourtrend', data);
-}
 
+export interface TkPoolRes extends ListRes {
+    list: TkPoolRecord[];
+}
 export interface ChartDataResponse {
     name: string;
     value: number;
@@ -208,10 +151,6 @@ export interface TkReportChartRes {
     data2: ChartDataResponse[];
 }
 
-export function queryTkReportChartData(data: TkReportParams) {
-    return axios.post<TkReportChartRes>('/api/taobao/chartData', data);
-}
-
 export interface TkSettleBillRecord {
     id: number;
     accountName: string;
@@ -244,14 +183,8 @@ export interface TkSettleBillsParams extends Partial<TkSettleBillRecord> {
     order?: string;
 }
 
-export interface TkSettleBillsRes extends ListRes {
-    list: TkSettleBillRecord[];
-}
-export function queryTkSettleBillsTotal(data: TkSettleBillsParams) {
-    return axios.post<TkSettleBillsRes>('/api/taobao/settle_bills_total', data);
-}
-export function queryTkSettleBills(data: TkSettleBillsParams) {
-    return axios.post<TkSettleBillsRes>('/api/taobao/settle_bills', data);
+export interface UpdateCookieModel {
+    cookie: string;
 }
 
 export interface TkOrderRecord {
@@ -343,6 +276,60 @@ export interface TkOrdersParams {
 export interface TkOrdersRes extends ListRes {
     list: TkOrderRecord[];
 }
+
+export function updateConfig(data: UpdateConfigModel) {
+    const url = ForwardAPI('/api/config/update');
+    return axios.post<FormRes>(url, data);
+}
+export function getConfig() {
+    const url = ForwardAPI('/api/config/get');
+    return axios.get<UpdateConfigModel>(url);
+}
+export function updateCookies(data: UpdateCookieModel) {
+    const url = ForwardAPI('/api/taobao/updateCookies');
+    return axios.post<FormRes>(url, data);
+}
+
+export function TkUpdateAccount(data: TkUpdateAccountModel) {
+    const url = ForwardAPI('/api/taobao/update');
+    return axios.post<UpdateConfigRes>(url, data);
+}
+
+export function queryTkPool(data: TkPoolParams) {
+    const url = ForwardAPI('/api/taobao/list');
+    return axios.post<TkPoolRes>(url, data);
+}
+
+export function queryTkReport(data: TkReportParams) {
+    const url = ForwardAPI('/api/taobao/report_list');
+    return axios.post<TkReportRes>(url, data);
+}
+export function queryTkReportDailys(data: TkReportParams) {
+    const url = ForwardAPI('/api/taobao/report_dailys');
+    return axios.post<TkReportRes>(url, data);
+}
+export function queryTkReportHourtrend(data: TkReportParams) {
+    const url = ForwardAPI('/api/taobao/report_hourtrend');
+    return axios.post<TkReportRes>(url, data);
+}
+
+export function queryTkReportChartData(data: TkReportParams) {
+    const url = ForwardAPI('/api/taobao/chartData');
+    return axios.post<TkReportChartRes>(url, data);
+}
+export interface TkSettleBillsRes extends ListRes {
+    list: TkSettleBillRecord[];
+}
+export function queryTkSettleBillsTotal(data: TkSettleBillsParams) {
+    const url = ForwardAPI('/api/taobao/settle_bills_total');
+    return axios.post<TkSettleBillsRes>(url, data);
+}
+export function queryTkSettleBills(data: TkSettleBillsParams) {
+    const url = ForwardAPI('/api/taobao/settle_bills');
+    return axios.post<TkSettleBillsRes>(url, data);
+}
+
 export function queryTkOrders(data: TkOrdersParams) {
-    return axios.post<TkOrdersRes>('/api/taobaoOrder/list', data);
+    const url = ForwardAPI('/api/taobaoOrder/list');
+    return axios.post<TkOrdersRes>(url, data);
 }

+ 119 - 6
src/components/navbar/index.vue

@@ -5,12 +5,44 @@
                 <img alt="logo"
                     src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/dfdba5317c0c20ce20e64fac803d52bc.svg~tplv-49unhts6dw-image.image" />
                 <a-typography-title :style="{ margin: 0, fontSize: '18px' }" :heading="5">
-                    Molilian
+                    魔力链
+                    <a-tag v-if="false && currentPlatform == 'parse'" color="arcoblue"
+                        @click="clickChangePlatform">口令</a-tag>
+                    <a-tag v-if="false && currentPlatform == 'coupon'" color="red"
+                        @click="clickChangePlatform">优惠券</a-tag>
                 </a-typography-title>
                 <icon-menu-fold v-if="!topMenu && appStore.device === 'mobile'" style="font-size: 22px; cursor: pointer"
                     @click="toggleDrawerMenu" />
             </a-space>
         </div>
+
+
+        <a-modal v-model:visible="visibleChangePlatform" title="切换平台" @before-ok="changePlatform">
+            <a-radio-group v-model="currentPlatform">
+                <template v-for="item in platformList" :key="item">
+                    <a-radio :value="item.value">
+                        <template #radio="{ checked }">
+                            <a-space align="start" class="custom-radio-card"
+                                :class="{ 'custom-radio-card-checked': checked }">
+                                <div className="custom-radio-card-mask">
+                                    <div className="custom-radio-card-mask-dot" />
+                                </div>
+                                <div>
+                                    <div className="custom-radio-card-title">
+                                        {{ item.name }}
+                                    </div>
+                                    <a-typography-text type="secondary"> {{ item.desc }}
+                                    </a-typography-text>
+                                </div>
+                            </a-space>
+                        </template>
+                    </a-radio>
+                </template>
+            </a-radio-group>
+
+        </a-modal>
+
+
         <div class="center-side">
             <Menu v-if="topMenu" />
         </div>
@@ -46,8 +78,8 @@
             </li>
             <li>
                 <a-tooltip :content="theme === 'light'
-                        ? $t('settings.navbar.theme.toDark')
-                        : $t('settings.navbar.theme.toLight')
+                    ? $t('settings.navbar.theme.toDark')
+                    : $t('settings.navbar.theme.toLight')
                     ">
                     <a-button class="nav-btn" type="outline" :shape="'circle'" @click="handleToggleTheme">
                         <template #icon>
@@ -77,8 +109,8 @@
             </li>
             <li>
                 <a-tooltip :content="isFullscreen
-                        ? $t('settings.navbar.screen.toExit')
-                        : $t('settings.navbar.screen.toFull')
+                    ? $t('settings.navbar.screen.toExit')
+                    : $t('settings.navbar.screen.toFull')
                     ">
                     <a-button class="nav-btn" type="outline" :shape="'circle'" @click="toggleFullScreen">
                         <template #icon>
@@ -136,7 +168,7 @@
 
 <script lang="ts" setup>
 import { computed, ref, inject } from 'vue';
-import { useDark, useToggle, useFullscreen } from '@vueuse/core';
+import { useDark, useToggle, useFullscreen, } from '@vueuse/core';
 import { useAppStore, useUserStore } from '@/store';
 import { LOCALE_OPTIONS } from '@/locale';
 import useLocale from '@/hooks/locale';
@@ -169,6 +201,7 @@ const isDark = useDark({
     },
 });
 const toggleTheme = useToggle(isDark);
+const visibleChangePlatform = ref(false);
 const handleToggleTheme = () => {
     toggleTheme();
 };
@@ -185,6 +218,32 @@ const setPopoverVisible = () => {
     });
     refBtn.value.dispatchEvent(event);
 };
+
+const currentPlatform = ref('parse')
+currentPlatform.value = appStore.currentPlatform
+
+
+const platformList = computed(() => [
+    {
+        value: 'parse',
+        name: "口令",
+        desc: "口令平台",
+    },
+    {
+        value: 'coupon',
+        name: "优惠券",
+        desc: "优惠券平台",
+    },
+]);
+const clickChangePlatform = (val: string) => {
+    visibleChangePlatform.value = true;
+};
+const changePlatform = () => {
+    console.log(currentPlatform.value);
+    appStore.togglePlatform(currentPlatform.value);
+    return true;
+};
+
 const handleLogout = () => {
     logout();
 };
@@ -263,3 +322,57 @@ const toggleDrawerMenu = inject('toggleDrawerMenu') as () => void;
     }
 }
 </style>
+
+<style scoped>
+.custom-radio-card {
+    padding: 10px 16px;
+    border: 1px solid var(--color-border-2);
+    border-radius: 4px;
+    width: 200px;
+    box-sizing: border-box;
+}
+
+.custom-radio-card-mask {
+    height: 14px;
+    width: 14px;
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    border-radius: 100%;
+    border: 1px solid var(--color-border-2);
+    box-sizing: border-box;
+}
+
+.custom-radio-card-mask-dot {
+    width: 8px;
+    height: 8px;
+    border-radius: 100%;
+}
+
+.custom-radio-card-title {
+    color: var(--color-text-1);
+    font-size: 14px;
+    font-weight: bold;
+    margin-bottom: 8px;
+}
+
+.custom-radio-card:hover,
+.custom-radio-card-checked,
+.custom-radio-card:hover .custom-radio-card-mask,
+.custom-radio-card-checked .custom-radio-card-mask {
+    border-color: rgb(var(--primary-6));
+}
+
+.custom-radio-card-checked {
+    background-color: var(--color-primary-light-1);
+}
+
+.custom-radio-card:hover .custom-radio-card-title,
+.custom-radio-card-checked .custom-radio-card-title {
+    color: rgb(var(--primary-6));
+}
+
+.custom-radio-card-checked .custom-radio-card-mask-dot {
+    background-color: rgb(var(--primary-6));
+}
+</style>

+ 16 - 15
src/config/settings.json

@@ -1,17 +1,18 @@
 {
-  "theme": "light",
-  "colorWeak": false,
-  "navbar": true,
-  "menu": true,
-  "topMenu": false,
-  "hideMenu": false,
-  "menuCollapse": false,
-  "footer": true,
-  "themeColor": "#165DFF",
-  "menuWidth": 220,
-  "globalSettings": false,
-  "device": "desktop",
-  "tabBar": false,
-  "menuFromServer": false,
-  "serverMenu": []
+    "theme": "light",
+    "colorWeak": false,
+    "navbar": true,
+    "menu": true,
+    "topMenu": false,
+    "hideMenu": false,
+    "platform": "",
+    "menuCollapse": false,
+    "footer": true,
+    "themeColor": "#165DFF",
+    "menuWidth": 220,
+    "globalSettings": false,
+    "device": "desktop",
+    "tabBar": false,
+    "menuFromServer": false,
+    "serverMenu": []
 }

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

@@ -2,7 +2,10 @@ export default {
   'menu.settings': 'Settings',
   'menu.settings.config': 'System Config',
   'menu.jd': 'JD Union',
+  'menu.jd.updateCookies': 'Update JD Cookies',
+
   'menu.taobao': 'Taobao Union',
+  'menu.taobaoCoupon': 'Taobao Coupon',
   'menu.taobao.updateCookies': 'Update Cookies',
   'menu.taobao.list': 'Union Account',
 

+ 5 - 1
src/locale/zh-CN/taoke.ts

@@ -2,7 +2,11 @@ export default {
   'menu.settings': '系统设置',
   'menu.settings.config': '全局配置',
   'menu.jd': '京东联盟',
-  'menu.taobao': '淘宝联盟',
+  'menu.jd.updateCookies': '更新 JD Cookies',
+
+
+  'menu.taobao': '口令',
+  'menu.taobaoCoupon': '优惠券',
   'menu.taobao.updateCookies': '更新Cookies',
   'menu.taobao.list': '联盟账号管理',
 

+ 12 - 12
src/router/routes/index.ts

@@ -2,24 +2,24 @@ import type { RouteRecordNormalized } from 'vue-router';
 
 const modules = import.meta.glob('./modules/*.ts', { eager: true });
 const externalModules = import.meta.glob('./externalModules/*.ts', {
-  eager: true,
+    eager: true,
 });
 
 function formatModules(_modules: any, result: RouteRecordNormalized[]) {
-  Object.keys(_modules).forEach((key) => {
-    const defaultModule = _modules[key].default;
-    if (!defaultModule) return;
-    const moduleList = Array.isArray(defaultModule)
-      ? [...defaultModule]
-      : [defaultModule];
-    result.push(...moduleList);
-  });
-  return result;
+    Object.keys(_modules).forEach((key) => {
+        const defaultModule = _modules[key].default;
+        if (!defaultModule) return;
+        const moduleList = Array.isArray(defaultModule)
+            ? [...defaultModule]
+            : [defaultModule];
+        result.push(...moduleList);
+    });
+    return result;
 }
 
 export const appRoutes: RouteRecordNormalized[] = formatModules(modules, []);
 
 export const appExternalRoutes: RouteRecordNormalized[] = formatModules(
-  externalModules,
-  []
+    externalModules,
+    []
 );

+ 21 - 21
src/router/routes/modules/jd.ts

@@ -1,28 +1,28 @@
 import { DEFAULT_LAYOUT } from '../base';
 import { AppRouteRecordRaw } from '../types';
 
-const JD: AppRouteRecordRaw = {
-  path: '/jd',
-  name: 'jd',
-  component: DEFAULT_LAYOUT,
-  meta: {
-    locale: 'menu.jd',
-    requiresAuth: true,
-    icon: 'icon-menu',
-    order: 0,
-  },
-  children: [
-    {
-      path: 'workplace',
-      name: 'workplace',
-      component: () => import('@/views/jd/workplace/index.vue'),
-      meta: {
-        locale: 'menu.jd.workplace',
+const TBCOUPON: AppRouteRecordRaw = {
+    path: '/jd',
+    name: 'jd',
+    component: DEFAULT_LAYOUT,
+    meta: {
+        locale: 'menu.jd',
         requiresAuth: true,
-        roles: ['*'],
-      },
+        icon: 'icon-menu',
+        order: 0,
     },
-  ],
+    children: [
+        {
+            path: 'updateCookies',
+            name: 'jd_UpdateCookies',
+            component: () => import('@/views/jd/updateCookies.vue'),
+            meta: {
+                locale: 'menu.taobao.updateCookies',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        }, 
+    ],
 };
 
-// export default JD;
+export default TBCOUPON;

+ 1 - 1
src/router/routes/modules/taobao.ts

@@ -14,7 +14,7 @@ const TAOBAO: AppRouteRecordRaw = {
     children: [
         {
             path: 'updateCookies',
-            name: 'updateCookies',
+            name: 'tbUpdateCookies',
             component: () => import('@/views/taobao/updateCookies.vue'),
             meta: {
                 locale: 'menu.taobao.updateCookies',

+ 78 - 0
src/router/routes/modules/tbcoupon.ts

@@ -0,0 +1,78 @@
+import { DEFAULT_LAYOUT } from '../base';
+import { AppRouteRecordRaw } from '../types';
+
+const TBCOUPON: AppRouteRecordRaw = {
+    path: '/tbcoupon',
+    name: 'tbcoupon',
+    component: DEFAULT_LAYOUT,
+    meta: {
+        locale: 'menu.taobaoCoupon',
+        requiresAuth: true,
+        icon: 'icon-menu',
+        order: 0,
+    },
+    children: [
+        {
+            path: 'updateCookies',
+            name: 'tbcoupon_UpdateCookies',
+            component: () => import('@/views/taobao/updateCookies.vue'),
+            meta: {
+                locale: 'menu.taobao.updateCookies',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+        {
+            path: 'list',
+            name: 'tbcoupon_list',
+            component: () => import('@/views/taobao/list.vue'),
+            meta: {
+                locale: 'menu.taobao.list',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+        // {
+        //     path: 'income_report',
+        //     name: 'tbcoupon_income_report',
+        //     component: () => import('@/views/taobao/income_report.vue'),
+        //     meta: {
+        //         locale: 'menu.taobao.income_report',
+        //         requiresAuth: true,
+        //         roles: ['*'],
+        //     },
+        // },
+        {
+            path: 'report_daily',
+            name: 'tbcoupon_report_daily',
+            component: () => import('@/views/taobao/report_daily.vue'),
+            meta: {
+                locale: 'menu.taobao.report_daily',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+        {
+            path: 'bill_dailys',
+            name: 'tbcoupon_bill_dailys',
+            component: () => import('@/views/taobao/bill_dailys.vue'),
+            meta: {
+                locale: 'menu.taobao.bill_dailys',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+        {
+            path: 'tbcoupon_orders',
+            name: 'tbcoupon_orders',
+            component: () => import('@/views/taobao/orders.vue'),
+            meta: {
+                locale: 'menu.taobao.orders',
+                requiresAuth: true,
+                roles: ['*'],
+            },
+        },
+    ],
+};
+
+export default TBCOUPON;

+ 13 - 13
src/router/routes/types.ts

@@ -2,19 +2,19 @@ import { defineComponent } from 'vue';
 import type { RouteMeta, NavigationGuard } from 'vue-router';
 
 export type Component<T = any> =
-  | ReturnType<typeof defineComponent>
-  | (() => Promise<typeof import('*.vue')>)
-  | (() => Promise<T>);
+    | ReturnType<typeof defineComponent>
+    | (() => Promise<typeof import('*.vue')>)
+    | (() => Promise<T>);
 
 export interface AppRouteRecordRaw {
-  path: string;
-  name?: string | symbol;
-  meta?: RouteMeta;
-  redirect?: string;
-  component: Component | string;
-  children?: AppRouteRecordRaw[];
-  alias?: string | string[];
-  props?: Record<string, any>;
-  beforeEnter?: NavigationGuard | NavigationGuard[];
-  fullPath?: string;
+    path: string;
+    name?: string | symbol;
+    meta?: RouteMeta;
+    redirect?: string;
+    component: Component | string;
+    children?: AppRouteRecordRaw[];
+    alias?: string | string[];
+    props?: Record<string, any>;
+    beforeEnter?: NavigationGuard | NavigationGuard[];
+    fullPath?: string;
 }

+ 71 - 60
src/store/modules/app/index.ts

@@ -4,74 +4,85 @@ import type { NotificationReturn } from '@arco-design/web-vue/es/notification/in
 import type { RouteRecordNormalized } from 'vue-router';
 import defaultSettings from '@/config/settings.json';
 import { getMenuList } from '@/api/user';
+import { setStorage, getStorage } from '@/utils/util';
 import { AppState } from './types';
 
 const useAppStore = defineStore('app', {
-  state: (): AppState => ({ ...defaultSettings }),
+    state: (): AppState => ({
+        ...defaultSettings,
+        platform: getStorage('platform'),
+    }),
 
-  getters: {
-    appCurrentSetting(state: AppState): AppState {
-      return { ...state };
+    getters: {
+        appCurrentSetting(state: AppState): AppState {
+            return { ...state };
+        },
+        appDevice(state: AppState) {
+            return state.device;
+        },
+        appAsyncMenus(state: AppState): RouteRecordNormalized[] {
+            return state.serverMenu as unknown as RouteRecordNormalized[];
+        },
+        currentPlatform(state: AppState) {
+            return state.platform;
+        },
     },
-    appDevice(state: AppState) {
-      return state.device;
-    },
-    appAsyncMenus(state: AppState): RouteRecordNormalized[] {
-      return state.serverMenu as unknown as RouteRecordNormalized[];
-    },
-  },
 
-  actions: {
-    // Update app settings
-    updateSettings(partial: Partial<AppState>) {
-      // @ts-ignore-next-line
-      this.$patch(partial);
-    },
+    actions: {
+        // Update app settings
+        updateSettings(partial: Partial<AppState>) {
+            // @ts-ignore-next-line
+            this.$patch(partial);
+        },
 
-    // Change theme color
-    toggleTheme(dark: boolean) {
-      if (dark) {
-        this.theme = 'dark';
-        document.body.setAttribute('arco-theme', 'dark');
-      } else {
-        this.theme = 'light';
-        document.body.removeAttribute('arco-theme');
-      }
-    },
-    toggleDevice(device: string) {
-      this.device = device;
-    },
-    toggleMenu(value: boolean) {
-      this.hideMenu = value;
-    },
-    async fetchServerMenuConfig() {
-      let notifyInstance: NotificationReturn | null = null;
-      try {
-        notifyInstance = Notification.info({
-          id: 'menuNotice', // Keep the instance id the same
-          content: 'loading',
-          closable: true,
-        });
-        const { data } = await getMenuList();
-        this.serverMenu = data;
-        notifyInstance = Notification.success({
-          id: 'menuNotice',
-          content: 'success',
-          closable: true,
-        });
-      } catch (error) {
-        // eslint-disable-next-line @typescript-eslint/no-unused-vars
-        notifyInstance = Notification.error({
-          id: 'menuNotice',
-          content: 'error',
-          closable: true,
-        });
-      }
-    },
-    clearServerMenu() {
-      this.serverMenu = [];
+        // Change theme color
+        toggleTheme(dark: boolean) {
+            if (dark) {
+                this.theme = 'dark';
+                document.body.setAttribute('arco-theme', 'dark');
+            } else {
+                this.theme = 'light';
+                document.body.removeAttribute('arco-theme');
+            }
+        },
+        toggleDevice(device: string) {
+            this.device = device;
+        },
+        toggleMenu(value: boolean) {
+            this.hideMenu = value;
+        },
+        togglePlatform(value: string) {
+            setStorage('platform', value);
+            this.platform = value;
+        },
+        async fetchServerMenuConfig() {
+            let notifyInstance: NotificationReturn | null = null;
+            try {
+                notifyInstance = Notification.info({
+                    id: 'menuNotice', // Keep the instance id the same
+                    content: 'loading',
+                    closable: true,
+                });
+                const { data } = await getMenuList();
+                this.serverMenu = data;
+                notifyInstance = Notification.success({
+                    id: 'menuNotice',
+                    content: 'success',
+                    closable: true,
+                });
+            } catch (error) {
+                // eslint-disable-next-line @typescript-eslint/no-unused-vars
+                notifyInstance = Notification.error({
+                    id: 'menuNotice',
+                    content: 'error',
+                    closable: true,
+                });
+            }
+        },
+        clearServerMenu() {
+            this.serverMenu = [];
+        },
     },
-  },
 });
 
 export default useAppStore;

+ 17 - 16
src/store/modules/app/types.ts

@@ -1,20 +1,21 @@
 import type { RouteRecordNormalized } from 'vue-router';
 
 export interface AppState {
-  theme: string;
-  colorWeak: boolean;
-  navbar: boolean;
-  menu: boolean;
-  topMenu: boolean;
-  hideMenu: boolean;
-  menuCollapse: boolean;
-  footer: boolean;
-  themeColor: string;
-  menuWidth: number;
-  globalSettings: boolean;
-  device: string;
-  tabBar: boolean;
-  menuFromServer: boolean;
-  serverMenu: RouteRecordNormalized[];
-  [key: string]: unknown;
+    theme: string;
+    colorWeak: boolean;
+    navbar: boolean;
+    menu: boolean;
+    topMenu: boolean;
+    hideMenu: boolean;
+    platform: string;
+    menuCollapse: boolean;
+    footer: boolean;
+    themeColor: string;
+    menuWidth: number;
+    globalSettings: boolean;
+    device: string;
+    tabBar: boolean;
+    menuFromServer: boolean;
+    serverMenu: RouteRecordNormalized[];
+    [key: string]: unknown;
 }

+ 18 - 2
src/utils/util.ts

@@ -1,9 +1,25 @@
-export function numberFormat(value: number): string {
+function numberFormat(value: number): string {
     return new Intl.NumberFormat('en-US').format(value);
 }
-export function amountFormat(value: number): string {
+function amountFormat(value: number): string {
     return `¥${new Intl.NumberFormat('en-US', {
         minimumFractionDigits: 2,
         maximumFractionDigits: 2,
     }).format(value)}`;
 }
+
+const getStorage = (key: string) => {
+    const value = localStorage.getItem(key);
+    console.log(key,value)
+    return value !== null ? value : '';
+};
+
+const setStorage = (key: string, value: string) => {
+    localStorage.setItem(key, value);
+};
+
+const clearStorage = (key: string) => {
+    localStorage.removeItem(key);
+};
+
+export { amountFormat, numberFormat, getStorage, setStorage, clearStorage };

+ 134 - 0
src/views/dashboard/dailyLog/components/categories-percent.vue

@@ -0,0 +1,134 @@
+<template>
+    <a-spin :loading="loading" style="width: 400px">
+        <a-card class="general-card" :header-style="{ paddingBottom: '0' }">
+
+            <div>
+                <template v-if="record.accountName !== ''">
+                    {{ record.accountName }}
+                </template>
+                API调用记录 -
+                {{
+                    dayjs(record.report_date).format(
+                        record.isLeaf ? 'YYYY-MM-DD HH:mm' : 'YYYY-MM-DD'
+                    )
+                }}
+            </div>
+            <a-radio-group v-model:model-value="showTable" type="button" @change="showTableChange as any"
+                style="margin-bottom:5px">
+                <a-radio value="message"> 响应类型 </a-radio>
+                <a-radio value="reason"> 放弃明细 </a-radio>
+            </a-radio-group>
+            <a-table v-if="showTable === 'message'" size="mini" :data="renderList" :scrollbar="scrollbar"
+                :scroll="scroll" :pagination="false" :bordered="false">
+                <template #columns>
+                    <a-table-column title="内容标题" data-index="title">
+                        <template #cell="{ record }">
+                            <a-typography-paragraph :ellipsis="{ rows: 1 }">
+                                {{ record.name }}
+                            </a-typography-paragraph>
+                        </template>
+                    </a-table-column>
+                    <a-table-column title="次数" data-index="value">
+                    </a-table-column>
+                    <a-table-column title="百分比" data-index="increases">
+                        <template #cell="{ record }">
+                            <div class="increases-cell">
+                                <span>{{ record.increases }}%</span>
+                            </div>
+                        </template>
+                    </a-table-column>
+                </template>
+            </a-table>
+
+            <a-table v-if="showTable === 'reason'" size="mini" :data="renderList2" :scrollbar="scrollbar"
+                :scroll="scroll" :pagination="false" :bordered="false">
+                <template #columns>
+                    <a-table-column title="错误原因" data-index="title">
+                        <template #cell="{ record }">
+                            <a-typography-paragraph :ellipsis="{
+                                rows: 1,
+                            }">
+                                {{ record.name }}
+                            </a-typography-paragraph>
+                        </template>
+                    </a-table-column>
+                    <a-table-column title="次数" data-index="value">
+                    </a-table-column>
+                    <a-table-column title="百分比" data-index="increases">
+                        <template #cell="{ record }">
+                            <div class="increases-cell">
+                                <span>{{ record.increases }}%</span>
+                            </div>
+                        </template>
+                    </a-table-column>
+                </template>
+            </a-table>
+        </a-card>
+    </a-spin>
+</template>
+
+<script lang="ts" setup>
+import dayjs from 'dayjs';
+import useLoading from '@/hooks/loading';
+import { defineProps, ref } from 'vue';
+import { DailyLogRecord, ChartDataResponse, ReportParams, queryReportChartData } from '@/api/app';
+
+const props = defineProps<{
+    record: DailyLogRecord;
+    total_key: string;
+
+}>();
+
+const scrollbar = ref(true);
+const scroll = {
+    x: '100%',
+    y: '100%',
+    maxHeight: '300px',
+};
+const showTable = ref('message');
+
+const { loading, setLoading } = useLoading(true);
+const renderList = ref<ChartDataResponse[]>();
+const renderList2 = ref<ChartDataResponse[]>();
+
+const fetchData = async (
+    params: ReportParams = {
+        current: 1,
+        pageSize: 0,
+        total_key: props.total_key,
+    }
+) => {
+    setLoading(true);
+    try {
+        const res = await queryReportChartData(params);
+        renderList.value = res.data;
+        renderList2.value = res.data2;
+    } catch (err) {
+        console.log(err);
+    } finally {
+        setLoading(false);
+    }
+};
+
+const search = () => {
+    fetchData({
+        accountName: props.record.accountName,
+        isLeaf: props.record.isLeaf,
+        query_date: [props.record.log_date],
+        total_key: props.total_key,
+    } as unknown as ReportParams);
+};
+
+const showTableChange = (contentType: string) => {
+    showTable.value = contentType;
+};
+
+console.log(props.record)
+search();
+</script>
+
+<style scoped lang="less">
+.popover-content {
+    width: 600px;
+}
+</style>

+ 351 - 0
src/views/dashboard/dailyLog/index copy 2.vue

@@ -0,0 +1,351 @@
+<template>
+    <div class="container">
+      <Breadcrumb :items="['menu.taobao', 'menu.taobao.list']" />
+      <a-card class="general-card" :title="$t('menu.taobao.list')">
+        <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" :columns="(cloneColumns as TableColumnData[])"
+          :data="renderData" :bordered="false" :size="size" @page-change="onPageChange" :load-more="loadMore">
+          <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>
+  
+        </a-table>
+      </a-card>
+    </div>
+  </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/taobao';
+  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';
+  
+  type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+  type Column = TableColumnData & { checked?: true };
+  
+  const generateFormModel = () => {
+    return {
+      accountName: 'all',
+      current: 1, pageSize: 20, 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 basePagination: Pagination = {
+    current: 1,
+    pageSize: 20,
+  };
+  const pagination = reactive({
+    ...basePagination,
+  });
+  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: '日期',
+      slotName: 'xAxis',
+    },
+    {
+      title: 'API调用数',
+      dataIndex: 'total_count',
+    },
+    {
+      title: '转链成功数',
+      dataIndex: 'success_count',
+    },
+    {
+      title: '转链成功率 %',
+      dataIndex: 'success_percentage',
+      slotName: 'success_percentage',
+    },
+    {
+      title: '放弃转链数',
+      dataIndex: 'abandon_count',
+      slotName: 'abandon_count',
+    },
+    {
+      title: '放弃转链 %',
+      dataIndex: 'abandon_percentage',
+      slotName: 'abandon_percentage',
+    },
+    {
+      title: '最后更新',
+      dataIndex: 'last_time',
+    },
+  ]);
+  
+  const fetchData = async (
+    params: DailyLogParams = {
+      // query_date: [row.report_date, row.report_date],
+      accountName: 'all',
+      current: 1, pageSize: 20, 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>
+  

+ 1022 - 0
src/views/dashboard/dailyLog/index copy.vue

@@ -0,0 +1,1022 @@
+<template>
+  <div class="container">
+      <Breadcrumb :items="['menu.dashboard', 'menu.taobao.report_daily']" />
+      <a-card class="general-card" :title="$t('menu.taobao.report_daily')">
+          <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 #xAxis="{ record }">
+                  <template v-if="record.accountName !== '' && !record.isLeaf">
+                      {{ record.accountName }}
+                  </template>
+                  <template v-else>
+                      {{ dayjs(record.report_date).format(record.isLeaf ? 'HH:mm' : 'YYYY-MM-DD') }}
+                  </template>
+              </template>
+
+              <template #accountName="{ record }">
+                  {{ record.isLeaf ? '' : record.accountName }}
+              </template>
+
+
+
+              <template #pay_ord_amt_56="{ record }">
+                  <viewOrdersModal filter-type='pay_ord_amt_56' :data="record">
+                      {{ amountFormat(record.pay_ord_amt_56) }}
+                  </viewOrdersModal>
+              </template>
+              <template #eff_ord_amt="{ record }">
+                  <viewOrdersModal filter-type='eff_ord_amt' :data="record">
+                      {{ amountFormat(record.eff_ord_amt) }}
+                  </viewOrdersModal>
+              </template>
+              <template #sett_ord_amt_56="{ record }">
+
+                  <viewOrdersModal filter-type='sett_ord_amt_56' :data="record">
+                      {{ amountFormat(record.sett_ord_amt_56) }}
+                  </viewOrdersModal>
+              </template>
+              <template #order_ord_amt="{ record }">
+                  <viewOrdersModal filter-type='order_ord_amt' :data="record">
+                      {{ amountFormat(record.order_ord_amt) }}
+                  </viewOrdersModal>
+              </template>
+
+              <template #order_ord_amt_12_14="{ record }">
+                  <a-popover popup-container="body">
+                      <viewOrdersModal filter-type='order_ord_amt_12_14' :data="record">
+                          {{ amountFormat(record.order_ord_amt_12_14) }}
+                      </viewOrdersModal>
+                      <template #content>
+
+                          <div style="min-width:400px;">
+                              <a-row>
+                                  <a-col :span="8">已付款金额/收入: </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_amt_12) }} </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_12) }} </a-col>
+                              </a-row>
+                              <a-row>
+                                  <a-col :span="8">已收货金额/收入: </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_amt_14) }} </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_14) }} </a-col>
+                              </a-row>
+                              <a-row>
+                                  <a-col :span="8">已失效金额/收入: </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_amt_13) }} </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_13) }} </a-col>
+                              </a-row>
+                          </div>
+                      </template>
+                  </a-popover>
+
+              </template>
+              <template #order_ord_tfee_12_14="{ record }">
+                  <a-popover popup-container="body">
+                      <div>{{ amountFormat(record.order_ord_tfee_12_14) }}</div>
+                      <template #content>
+                          <div style="min-width:400px;">
+                              <a-row>
+                                  <a-col :span="8">已付款金额/收入: </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_amt_12) }} </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_12) }} </a-col>
+                              </a-row>
+                              <a-row>
+                                  <a-col :span="8">已收货金额/收入: </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_amt_14) }} </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_14) }} </a-col>
+                              </a-row>
+                              <a-row>
+                                  <a-col :span="8">已失效金额/收入: </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_amt_13) }} </a-col>
+                                  <a-col :span="8"> {{ amountFormat(record.order_ord_tfee_13) }} </a-col>
+                              </a-row>
+                          </div>
+                      </template>
+                  </a-popover>
+              </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>
+              <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 #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 }">
+                  <!-- 
+                  { "title": "点击人数", "dataIndex": "uclk_uv_56", "width": 100, "align": "right", "parent": { "title": "点击", "children": [ { "title": "点击人数", "dataIndex": "uclk_uv_56", "width": 100, "align": "right" }, { "title": "点击次数", "dataIndex": "uclk_pv_56", "width": 100, "align": "right" } ], "checked": true, "colSpan": 2 } }
+                  { "title": "付款金额", "slotName": "pay_ord_amt_56", "dataIndex": "pay_ord_amt_56", "width": 150, "align": "right", "parent": { "title": "付款", "children": [ { "title": "付款笔数", "dataIndex": "pay_ord_num_56", "width": 100, "align": "right" }, { "title": "付款金额", "slotName": "pay_ord_amt_56", "dataIndex": "pay_ord_amt_56", "width": 150, "align": "right" }, { "title": "付款预估收入", "dataIndex": "pay_tk_disp_tfee_56", "width": 150, "align": "right" }, { "title": "付款人数", "dataIndex": "pay_ord_uv_56", "width": 120, "align": "right" } ], "checked": true, "colSpan": 4 } } -->
+
+
+                  <template v-if="column.slotName == 'pay_ord_amt_56' ||
+                      column.slotName == 'eff_ord_amt' ||
+                      column.slotName == 'sett_ord_amt_56' ||
+                      column.slotName == 'order_ord_amt' ||
+                      column.slotName == 'order_ord_tfee' ||
+                      column.slotName == 'pay_tk_disp_tfee_56' ||
+                      column.slotName == 'eff_tk_disp_tfee' ||
+                      column.slotName == 'sett_tk_disp_tfee_56' ||
+                      column.slotName == 'order_ord_tfee_12_14' ||
+                      column.slotName == 'order_ord_amt_12_14' ||
+                      column.slotName == 'refund_order_ord_amt' ||
+                      column.slotName == 'refund_order_ord_tfee' ||
+                      column.slotName == 'refund_order_ord_amt_4' ||
+                      column.slotName == 'refund_order_ord_tfee_4' ||
+                      column.slotName == 'refund_order_ord_deduct_tfee' ||
+                      column.slotName == 'refund_order_ord_freeze_tfee' ||
+                      column.slotName == 'refund_order_ord_unfreeze_tfee'">
+
+                      <div>{{ amountFormat(record[column.dataIndex]) }}</div>
+                  </template>
+
+                  <template v-else-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>
+                      <div>{{ toAmount(record[column.dataIndex]) }}</div>
+                  </template>
+
+              </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 { numberFormat, amountFormat } from '@/utils/util';
+
+import {
+  queryTkReport,
+  queryTkReportDailys,
+  queryTkReportHourtrend,
+  TkReportRecord,
+  TkReportParams,
+} from '@/api/taobao';
+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 CategoriesPercent from './components/categories-percent.vue';
+import viewOrdersModal from './components/viewOrdersModal.vue';
+
+type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+type Column = TableColumnData & { checked?: true };
+
+const generateFormModel = () => {
+  return {
+      accountName: '',
+      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<TkReportRecord[]>([]);
+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: '点击',
+      children: [
+          {
+              title: '点击人数',
+              dataIndex: 'uclk_uv_56',
+              width: 100,
+              align: 'right'
+          },
+          {
+              title: '点击次数',
+              dataIndex: 'uclk_pv_56',
+              width: 100,
+              align: 'right'
+          },
+      ]
+  },
+  {
+      title: '付款',
+      children: [
+          {
+              title: '付款笔数',
+              dataIndex: 'pay_ord_num_56',
+              width: 100,
+              align: 'right',
+          },
+          {
+              title: '订单付款数',
+              dataIndex: 'order_ord_num',
+              width: 110,
+          },
+          {
+              title: '付款金额',
+              slotName: 'pay_ord_amt_56',
+              dataIndex: 'pay_ord_amt_56',
+              width: 150,
+              align: 'right',
+              // render: (e: any) => amountFormat(e.record.pay_ord_amt_56)
+          },
+          {
+              title: '付款预估收入',
+              dataIndex: 'pay_tk_disp_tfee_56',
+              slotName: 'pay_tk_disp_tfee_56',
+              width: 150,
+              align: 'right',
+              render: (e: any) => amountFormat(e.record.pay_tk_disp_tfee_56)
+          },
+          {
+              title: '付款人数',
+              dataIndex: 'pay_ord_uv_56',
+              width: 120,
+              align: 'right',
+          },
+      ]
+  },
+  {
+      title: '有效付款',
+      children: [
+          {
+              title: '有效付款笔数',
+              dataIndex: 'eff_ord_num',
+              width: 150,
+              align: 'right',
+          },
+          {
+              title: '有效付款金额',
+              slotName: 'eff_ord_amt',
+              dataIndex: 'eff_ord_amt',
+              width: 150,
+              align: 'right',
+              // render: (e: any) => amountFormat(e.record.eff_ord_amt)
+          },
+          {
+              title: '有效付款预估收入',
+              dataIndex: 'eff_tk_disp_tfee',
+              slotName: 'eff_tk_disp_tfee',
+              width: 150,
+              align: 'right',
+              render: (e: any) => amountFormat(e.record.eff_tk_disp_tfee)
+          },
+      ]
+  },
+  {
+      title: '结算',
+      children: [
+          {
+              title: '结算笔数',
+              dataIndex: 'sett_ord_num_56',
+              width: 100,
+              align: 'right',
+          },
+          {
+              title: '结算金额',
+              slotName: 'sett_ord_amt_56',
+              dataIndex: 'sett_ord_amt_56',
+              width: 150,
+              align: 'right',
+              // render: (e: any) => amountFormat(e.record.sett_ord_amt_56)
+          },
+          {
+              title: '结算预估收入',
+              dataIndex: 'sett_tk_disp_tfee_56',
+              slotName: 'sett_tk_disp_tfee_56',
+              width: 150,
+              align: 'right',
+              render: (e: any) => amountFormat(e.record.sett_tk_disp_tfee_56)
+          },
+      ]
+  },
+  {
+      title: '所属订单结算金额',
+      children: [
+          {
+              title: '结算金额',
+              slotName: 'order_ord_amt',
+              dataIndex: 'order_ord_amt',
+              width: 150,
+              align: 'right',
+              // render: (e: any) => amountFormat(e.record.order_ord_amt)
+          },
+          {
+              title: '结算收入',
+              width: 150,
+              align: 'right',
+              dataIndex: 'order_ord_tfee',
+              slotName: 'order_ord_tfee',
+              render: (e: any) => amountFormat(e.record.order_ord_tfee)
+          },
+          {
+              title: '待结算金额',
+              slotName: 'order_ord_amt_12_14',
+              dataIndex: 'order_ord_amt_12_14',
+              width: 150,
+              align: 'right',
+          },
+          {
+              title: '待结算收入',
+              slotName: 'order_ord_tfee_12_14',
+              dataIndex: 'order_ord_tfee_12_14',
+              width: 120,
+              align: 'right',
+          },
+      ]
+  },
+  {
+      title: '订单维权',
+      children: [
+          {
+              title: '扣款收入',
+              width: 120,
+              align: 'right',
+              dataIndex: 'refund_order_ord_deduct_tfee',
+              slotName: 'refund_order_ord_deduct_tfee',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_deduct_tfee)
+          },
+          {
+              title: '冻结金额',
+              slotName: 'refund_order_ord_freeze_tfee',
+              dataIndex: 'refund_order_ord_freeze_tfee',
+              width: 150,
+              align: 'right',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_freeze_tfee)
+          },
+          {
+              title: '解冻金额',
+              width: 120,
+              align: 'right',
+              dataIndex: 'refund_order_ord_unfreeze_tfee',
+              slotName: 'refund_order_ord_unfreeze_tfee',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_unfreeze_tfee)
+          },
+      ]
+  },
+
+
+  {
+      title: '所属订单维权金额',
+      children: [
+          {
+              title: '维权金额(扣款)',
+              slotName: 'refund_order_ord_amt',
+              dataIndex: 'refund_order_ord_amt',
+              width: 150,
+              align: 'right',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_amt)
+          },
+          {
+              title: '扣款收入',
+              width: 120,
+              align: 'right',
+              dataIndex: 'refund_order_ord_tfee',
+              slotName: 'refund_order_ord_tfee',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_tfee)
+          },
+          {
+              title: '维权金额(冻结)',
+              slotName: 'refund_order_ord_amt_4',
+              dataIndex: 'refund_order_ord_amt_4',
+              width: 150,
+              align: 'right',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_amt_4)
+          },
+          {
+              title: '冻结收入',
+              width: 120,
+              align: 'right',
+              dataIndex: 'refund_order_ord_tfee_4',
+              slotName: 'refund_order_ord_tfee_4',
+              render: (e: any) => amountFormat(e.record.refund_order_ord_tfee_4)
+          },
+      ]
+  },
+
+
+  {
+      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: '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: '调用',
+              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'
+          },
+      ]
+  },
+  {
+      title: '最后更新时间',
+      dataIndex: 'last_time',
+      width: 200,
+      align: 'center'
+  },
+
+  {
+      title: '收藏人数',
+      dataIndex: 'uclt_uv_56',
+      width: 100,
+  },
+  {
+      title: '加购人数',
+      dataIndex: 'ucart_uv_56',
+      width: 100,
+  },
+  {
+      title: '定金笔数',
+      dataIndex: 'dep_ord_num_56',
+      width: 100,
+  },
+  {
+      title: '定金金额',
+      dataIndex: 'dep_ord_dep_amt_56',
+      width: 120,
+  },
+]);
+
+const fetchData = async (
+  params: TkReportParams = {
+      current: 1,
+      pageSize: basePagination.pageSize,
+      sort: 'report_date',
+      order: 'descending',
+  }
+) => {
+  setLoading(true);
+  try {
+      const { data } = await queryTkReportDailys(params);
+      console.log(data);
+      if (!data) return;
+      let list: TableData[] = [];
+
+      list = data.list.map((item: TkReportRecord) => ({
+          ...item,
+          order_ord_amt_12_14: item.order_ord_amt_12 + item.order_ord_amt_14,
+          order_ord_tfee_12_14: item.order_ord_tfee_12 + item.order_ord_tfee_14,
+      }));
+
+      renderData.value = 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 {
+      let list: TableData[] = [];
+
+      if (row.accountName === '') {
+          const params: TkReportParams = {
+              query_date: [row.report_date, row.report_date],
+              current: 1,
+              pageSize: 999,
+              sort: 'report_date',
+              order: 'descending',
+          };
+
+          const { data } = await queryTkReport(params);
+          console.log(data);
+          if (!data) return;
+          list = data.list.map((item: TkReportRecord) => ({
+              ...item,
+              order_ord_amt_12_14: item.order_ord_amt_12 + item.order_ord_amt_14,
+              order_ord_tfee_12_14: item.order_ord_tfee_12 + item.order_ord_tfee_14,
+              isLeaf: false,
+          }));
+      } else {
+          const params: TkReportParams = {
+              query_date: [row.report_date, row.report_date],
+              accountId: row.accountId,
+              current: 1,
+              pageSize: 24,
+              sort: 'report_date',
+              order: 'descending',
+          };
+
+          const { data } = await queryTkReportHourtrend(params);
+          console.log(data);
+          if (!data) return;
+          list = data.list.map((item: TkReportRecord) => ({
+              ...item,
+              order_ord_amt_12_14: item.order_ord_amt_12 + item.order_ord_amt_14,
+              order_ord_tfee_12_14: item.order_ord_tfee_12 + item.order_ord_tfee_14,
+              isLeaf: true,
+          }));
+      }
+      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 TkReportParams);
+};
+const onPageChange = (current: number) => {
+  fetchData({
+      ...basePagination,
+      ...formModel.value,
+      current
+  });
+};
+
+const onPageSizeChange = (current: number) => {
+  basePagination.pageSize = current;
+  pagination.pageSize = current;
+  fetchData({
+      ...basePagination,
+      ...formModel.value,
+      current: 1,
+  });
+};
+
+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>

+ 549 - 241
src/views/dashboard/dailyLog/index.vue

@@ -1,68 +1,180 @@
 <template>
-  <div class="container">
-    <Breadcrumb :items="['menu.taobao', 'menu.taobao.list']" />
-    <a-card class="general-card" :title="$t('menu.taobao.list')">
-      <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" :columns="(cloneColumns as TableColumnData[])"
-        :data="renderData" :bordered="false" :size="size" @page-change="onPageChange" :load-more="loadMore">
-        <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>
-
-      </a-table>
-    </a-card>
-  </div>
+    <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>
+    </div>
 </template>
 
 <script lang="ts" setup>
@@ -71,22 +183,26 @@ 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/taobao';
+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: 20, sort: 'log_date', order: 'descending'
+    return {
+        accountName: 'all',
+        current: 1,
+        pageSize: 31,
+        sort: 'log_date',
+        order: 'descending'
 
-  };
+    };
 };
 const router = useRouter();
 
@@ -99,252 +215,444 @@ 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: 20,
+    current: 1,
+    pageSize: 31,
 };
 const pagination = reactive({
-  ...basePagination,
+    ...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',
-  },
+    {
+        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: '日期',
-    slotName: 'xAxis',
-  },
-  {
-    title: 'API调用数',
-    dataIndex: 'total_count',
-  },
-  {
-    title: '转链成功数',
-    dataIndex: 'success_count',
-  },
-  {
-    title: '转链成功率 %',
-    dataIndex: 'success_percentage',
-    slotName: 'success_percentage',
-  },
-  {
-    title: '放弃转链数',
-    dataIndex: 'abandon_count',
-    slotName: 'abandon_count',
-  },
-  {
-    title: '放弃转链 %',
-    dataIndex: 'abandon_percentage',
-    slotName: 'abandon_percentage',
-  },
-  {
-    title: '最后更新',
-    dataIndex: 'last_time',
-  },
+    {
+        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 = {
-    // query_date: [row.report_date, row.report_date],
-    accountName: 'all',
-    current: 1, pageSize: 20, sort: 'log_date', order: 'descending'
-  }
+    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);
-  }
+    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);
-  }
+    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
+    data: DailyLogRecord
 ) => {
-  router.push({ name: 'updateCookies' });
+    router.push({ name: 'updateCookies' });
 };
 
 
 
 const search = () => {
-  fetchData({
-    ...basePagination,
-    ...formModel.value,
-  } as unknown as DailyLogParams);
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+    } as unknown as DailyLogParams);
 };
 const onPageChange = (current: number) => {
-  fetchData({
-    ...basePagination,
-    ...formModel.value,
-    current
-  });
+    fetchData({
+        ...basePagination,
+        ...formModel.value,
+        current
+    });
 };
 
 fetchData();
 const reset = () => {
-  formModel.value = generateFormModel();
+    formModel.value = generateFormModel();
 };
 
 const handleSelectDensity = (
-  val: string | number | Record<string, any> | undefined,
-  e: Event
+    val: string | number | Record<string, any> | undefined,
+    e: Event
 ) => {
-  size.value = val as SizeProps;
+    size.value = val as SizeProps;
 };
 
 const handleChange = (
-  checked: boolean | (string | boolean | number)[],
-  column: Column,
-  index: number
+    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);
-  }
+    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
+    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 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);
-        },
-      });
-    });
-  }
+    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 }
+    () => 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',
+    name: 'SearchTable',
 };
 </script>
 
 <style scoped lang="less">
 .container {
-  padding: 0 20px 20px 20px;
+    padding: 0 20px 20px 20px;
 }
 
 :deep(.arco-table-th) {
-  &:last-child {
-    .arco-table-th-item-title {
-      margin-left: 16px;
+    &:last-child {
+        .arco-table-th-item-title {
+            margin-left: 16px;
+        }
     }
-  }
 }
 
 .action-icon {
-  margin-left: 12px;
-  cursor: pointer;
+    margin-left: 12px;
+    cursor: pointer;
 }
 
 .active {
-  color: #0960bd;
-  background-color: #e3f4fc;
+    color: #0960bd;
+    background-color: #e3f4fc;
 }
 
 .setting {
-  display: flex;
-  align-items: center;
-  width: 200px;
+    display: flex;
+    align-items: center;
+    width: 200px;
 
-  .title {
-    margin-left: 12px;
-    cursor: pointer;
-  }
+    .title {
+        margin-left: 12px;
+        cursor: pointer;
+    }
 }
 </style>

+ 94 - 0
src/views/jd/updateCookies.vue

@@ -0,0 +1,94 @@
+<template>
+    <div class="container">
+        <Breadcrumb :items="['menu.jd', 'menu.jd.updateCookies']" />
+        <a-card class="general-card" :title="$t('menu.jd.updateCookies')">
+            <a-row class="wrapper">
+                <a-col :span="24">
+                    <a-form ref="formRef" :model="formData" class="form" :label-col-props="{ span: 4 }"
+                        :wrapper-col-props="{ span: 19 }">
+                        <a-form-item field="cookie" :label="$t('taobao.cookies.label')" :rules="[{ required: true }]"
+                            row-class="keep-margin">
+                            <a-textarea v-model="formData.cookie" auto-size class="cookie"
+                                :placeholder="$t('taobao.cookies.placeholder')" />
+                        </a-form-item>
+                        <a-form-item>
+                            <a-space>
+                                <a-button type="primary" @click="validate">
+                                    {{ $t('form.save') }}
+                                </a-button>
+                                <a-button type="secondary" @click="reset">
+                                    {{ $t('form.reset') }}
+                                </a-button>
+                            </a-space>
+                        </a-form-item>
+                    </a-form>
+                </a-col>
+            </a-row>
+        </a-card>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { ref } from 'vue';
+import { useRouter } from 'vue-router';
+import { Message } from '@arco-design/web-vue';
+import { FormInstance } from '@arco-design/web-vue/es/form';
+import { UpdateCookieModel, updateCookies } from '@/api/jd';
+
+
+const router = useRouter();
+
+const formRef = ref<FormInstance>();
+const formData = ref<UpdateCookieModel>({
+    cookie: '',
+});
+const validate = async () => {
+    const res = await formRef.value?.validate();
+    if (!res) {
+        try {
+            const { data } = await updateCookies(formData.value);
+            console.log(data, data.msg);
+            const msg = data.msg || '更新成功!';
+            if (data.success) {
+                Message.success(msg);
+                // router.push('./list');
+            } else {
+                Message.error(data.msg);
+            }
+        } catch (err) {
+            console.error(err)
+        }
+    }
+};
+const reset = async () => {
+    await formRef.value?.resetFields();
+};
+</script>
+
+<style scoped lang="less">
+.container {
+    padding: 0 20px 20px 20px;
+}
+
+.wrapper {
+    padding: 20px 0 0 20px;
+    min-height: 580px;
+    background-color: var(--color-bg-2);
+    border-radius: 4px;
+}
+
+:deep(.section-title) {
+    margin-top: 0;
+    margin-bottom: 16px;
+    font-size: 14px;
+}
+
+.form {
+    margin: 0 auto;
+}
+
+.form .cookie {
+    height: 100%;
+    min-height: 500px;
+}
+</style>

+ 0 - 71
src/views/jd/workplace/components/announcement.vue

@@ -1,71 +0,0 @@
-<template>
-  <a-card
-    class="general-card"
-    :title="$t('workplace.announcement')"
-    :header-style="{ paddingBottom: '0' }"
-    :body-style="{ padding: '15px 20px 13px 20px' }"
-  >
-    <template #extra>
-      <a-link>{{ $t('workplace.viewMore') }}</a-link>
-    </template>
-    <div>
-      <div v-for="(item, idx) in list" :key="idx" class="item">
-        <a-tag :color="item.type" size="small">{{ item.label }}</a-tag>
-        <span class="item-content">
-          {{ item.content }}
-        </span>
-      </div>
-    </div>
-  </a-card>
-</template>
-
-<script lang="ts" setup>
-  const list = [
-    {
-      type: 'orangered',
-      label: '活动',
-      content: '内容最新优惠活动',
-    },
-    {
-      type: 'cyan',
-      label: '消息',
-      content: '新增内容尚未通过审核,详情请点击查看。',
-    },
-    {
-      type: 'blue',
-      label: '通知',
-      content: '当前产品试用期即将结束,如需续费请点击查看。',
-    },
-    {
-      type: 'blue',
-      label: '通知',
-      content: '1月新系统升级计划通知',
-    },
-    {
-      type: 'cyan',
-      label: '消息',
-      content: '新增内容已经通过审核,详情请点击查看。',
-    },
-  ];
-</script>
-
-<style scoped lang="less">
-  .item {
-    display: flex;
-    align-items: center;
-    width: 100%;
-    height: 24px;
-    margin-bottom: 4px;
-    .item-content {
-      flex: 1;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      margin-left: 4px;
-      color: var(--color-text-2);
-      text-decoration: none;
-      font-size: 13px;
-      cursor: pointer;
-    }
-  }
-</style>

+ 0 - 35
src/views/jd/workplace/components/banner.vue

@@ -1,35 +0,0 @@
-<template>
-  <a-col class="banner">
-    <a-col :span="8">
-      <a-typography-title :heading="5" style="margin-top: 0">
-        {{ $t('workplace.welcome') }} {{ userInfo.name }}
-      </a-typography-title>
-    </a-col>
-    <a-divider class="panel-border" />
-  </a-col>
-</template>
-
-<script lang="ts" setup>
-  import { computed } from 'vue';
-  import { useUserStore } from '@/store';
-
-  const userStore = useUserStore();
-  const userInfo = computed(() => {
-    return {
-      name: userStore.name,
-    };
-  });
-</script>
-
-<style scoped lang="less">
-  .banner {
-    width: 100%;
-    padding: 20px 20px 0 20px;
-    background-color: var(--color-bg-2);
-    border-radius: 4px 4px 0 0;
-  }
-
-  :deep(.arco-icon-home) {
-    margin-right: 6px;
-  }
-</style>

+ 0 - 24
src/views/jd/workplace/components/carousel.vue

@@ -1,24 +0,0 @@
-<template>
-  <a-carousel
-    indicator-type="slider"
-    show-arrow="hover"
-    auto-play
-    style="width: 100%; height: 170px; border-radius: 4px; overflow: hidden"
-  >
-    <a-carousel-item v-for="(src, idx) in imageSrc" :key="idx">
-      <div>
-        <img :src="src" style="width: 100%" />
-      </div>
-    </a-carousel-item>
-  </a-carousel>
-</template>
-
-<script lang="ts" setup>
-  const imageSrc = [
-    '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/5cc3cd1d994b7ef9db6a1f619a22addd.jpg~tplv-49unhts6dw-image.image',
-    '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/f256cbcc287139e191fecea9d255a1f0.jpg~tplv-49unhts6dw-image.image',
-    '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/b557ff0cd44146a2e471b477af2f30d0.jpg~tplv-49unhts6dw-image.image',
-    '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/665106f4bbd2a2df96eaf7aec52f7bc3.jpg~tplv-49unhts6dw-image.image',
-    '//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/ea095a2c9c72b5d8f2f2818040db736d.jpg~tplv-49unhts6dw-image.image',
-  ];
-</script>

+ 0 - 114
src/views/jd/workplace/components/categories-percent.vue

@@ -1,114 +0,0 @@
-<template>
-  <a-spin :loading="loading" style="width: 100%">
-    <a-card
-      class="general-card"
-      :header-style="{ paddingBottom: '0' }"
-      :body-style="{
-        padding: '20px',
-      }"
-    >
-      <template #title>
-        {{ $t('workplace.categoriesPercent') }}
-      </template>
-      <Chart height="310px" :option="chartOption" />
-    </a-card>
-  </a-spin>
-</template>
-
-<script lang="ts" setup>
-  import useLoading from '@/hooks/loading';
-  import useChartOption from '@/hooks/chart-option';
-
-  const { loading } = useLoading();
-  const { chartOption } = useChartOption((isDark) => {
-    // echarts support https://echarts.apache.org/zh/theme-builder.html
-    // It's not used here
-    return {
-      legend: {
-        left: 'center',
-        data: ['纯文本', '图文类', '视频类'],
-        bottom: 0,
-        icon: 'circle',
-        itemWidth: 8,
-        textStyle: {
-          color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
-        },
-        itemStyle: {
-          borderWidth: 0,
-        },
-      },
-      tooltip: {
-        show: true,
-        trigger: 'item',
-      },
-      graphic: {
-        elements: [
-          {
-            type: 'text',
-            left: 'center',
-            top: '40%',
-            style: {
-              text: '内容量',
-              textAlign: 'center',
-              fill: isDark ? '#ffffffb3' : '#4E5969',
-              fontSize: 14,
-            },
-          },
-          {
-            type: 'text',
-            left: 'center',
-            top: '50%',
-            style: {
-              text: '928,531',
-              textAlign: 'center',
-              fill: isDark ? '#ffffffb3' : '#1D2129',
-              fontSize: 16,
-              fontWeight: 500,
-            },
-          },
-        ],
-      },
-      series: [
-        {
-          type: 'pie',
-          radius: ['50%', '70%'],
-          center: ['50%', '50%'],
-          label: {
-            formatter: '{d}%',
-            fontSize: 14,
-            color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
-          },
-          itemStyle: {
-            borderColor: isDark ? '#232324' : '#fff',
-            borderWidth: 1,
-          },
-          data: [
-            {
-              value: [148564],
-              name: '纯文本',
-              itemStyle: {
-                color: isDark ? '#3D72F6' : '#249EFF',
-              },
-            },
-            {
-              value: [334271],
-              name: '图文类',
-              itemStyle: {
-                color: isDark ? '#A079DC' : '#313CA9',
-              },
-            },
-            {
-              value: [445694],
-              name: '视频类',
-              itemStyle: {
-                color: isDark ? '#6CAAF5' : '#21CCFF',
-              },
-            },
-          ],
-        },
-      ],
-    };
-  });
-</script>
-
-<style scoped lang="less"></style>

+ 0 - 200
src/views/jd/workplace/components/content-chart.vue

@@ -1,200 +0,0 @@
-<template>
-  <a-spin :loading="loading" style="width: 100%">
-    <a-card
-      class="general-card"
-      :header-style="{ paddingBottom: 0 }"
-      :body-style="{
-        paddingTop: '20px',
-      }"
-      :title="$t('workplace.contentData')"
-    >
-      <template #extra>
-        <a-link>{{ $t('workplace.viewMore') }}</a-link>
-      </template>
-      <Chart height="289px" :option="chartOption" />
-    </a-card>
-  </a-spin>
-</template>
-
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import { graphic } from 'echarts';
-  import useLoading from '@/hooks/loading';
-  import { queryContentData, ContentDataRecord } from '@/api/dashboard';
-  import useChartOption from '@/hooks/chart-option';
-  import { ToolTipFormatterParams } from '@/types/echarts';
-  import { AnyObject } from '@/types/global';
-
-  function graphicFactory(side: AnyObject) {
-    return {
-      type: 'text',
-      bottom: '8',
-      ...side,
-      style: {
-        text: '',
-        textAlign: 'center',
-        fill: '#4E5969',
-        fontSize: 12,
-      },
-    };
-  }
-  const { loading, setLoading } = useLoading(true);
-  const xAxis = ref<string[]>([]);
-  const chartsData = ref<number[]>([]);
-  const graphicElements = ref([
-    graphicFactory({ left: '2.6%' }),
-    graphicFactory({ right: 0 }),
-  ]);
-  const { chartOption } = useChartOption(() => {
-    return {
-      grid: {
-        left: '2.6%',
-        right: '0',
-        top: '10',
-        bottom: '30',
-      },
-      xAxis: {
-        type: 'category',
-        offset: 2,
-        data: xAxis.value,
-        boundaryGap: false,
-        axisLabel: {
-          color: '#4E5969',
-          formatter(value: number, idx: number) {
-            if (idx === 0) return '';
-            if (idx === xAxis.value.length - 1) return '';
-            return `${value}`;
-          },
-        },
-        axisLine: {
-          show: false,
-        },
-        axisTick: {
-          show: false,
-        },
-        splitLine: {
-          show: true,
-          interval: (idx: number) => {
-            if (idx === 0) return false;
-            if (idx === xAxis.value.length - 1) return false;
-            return true;
-          },
-          lineStyle: {
-            color: '#E5E8EF',
-          },
-        },
-        axisPointer: {
-          show: true,
-          lineStyle: {
-            color: '#23ADFF',
-            width: 2,
-          },
-        },
-      },
-      yAxis: {
-        type: 'value',
-        axisLine: {
-          show: false,
-        },
-        axisLabel: {
-          formatter(value: any, idx: number) {
-            if (idx === 0) return value;
-            return `${value}k`;
-          },
-        },
-        splitLine: {
-          show: true,
-          lineStyle: {
-            type: 'dashed',
-            color: '#E5E8EF',
-          },
-        },
-      },
-      tooltip: {
-        trigger: 'axis',
-        formatter(params) {
-          const [firstElement] = params as ToolTipFormatterParams[];
-          return `<div>
-            <p class="tooltip-title">${firstElement.axisValueLabel}</p>
-            <div class="content-panel"><span>总内容量</span><span class="tooltip-value">${(
-              Number(firstElement.value) * 10000
-            ).toLocaleString()}</span></div>
-          </div>`;
-        },
-        className: 'echarts-tooltip-diy',
-      },
-      graphic: {
-        elements: graphicElements.value,
-      },
-      series: [
-        {
-          data: chartsData.value,
-          type: 'line',
-          smooth: true,
-          // symbol: 'circle',
-          symbolSize: 12,
-          emphasis: {
-            focus: 'series',
-            itemStyle: {
-              borderWidth: 2,
-            },
-          },
-          lineStyle: {
-            width: 3,
-            color: new graphic.LinearGradient(0, 0, 1, 0, [
-              {
-                offset: 0,
-                color: 'rgba(30, 231, 255, 1)',
-              },
-              {
-                offset: 0.5,
-                color: 'rgba(36, 154, 255, 1)',
-              },
-              {
-                offset: 1,
-                color: 'rgba(111, 66, 251, 1)',
-              },
-            ]),
-          },
-          showSymbol: false,
-          areaStyle: {
-            opacity: 0.8,
-            color: new graphic.LinearGradient(0, 0, 0, 1, [
-              {
-                offset: 0,
-                color: 'rgba(17, 126, 255, 0.16)',
-              },
-              {
-                offset: 1,
-                color: 'rgba(17, 128, 255, 0)',
-              },
-            ]),
-          },
-        },
-      ],
-    };
-  });
-  const fetchData = async () => {
-    setLoading(true);
-    try {
-      const { data: chartData } = await queryContentData();
-      chartData.forEach((el: ContentDataRecord, idx: number) => {
-        xAxis.value.push(el.x);
-        chartsData.value.push(el.y);
-        if (idx === 0) {
-          graphicElements.value[0].style.text = el.x;
-        }
-        if (idx === chartData.length - 1) {
-          graphicElements.value[1].style.text = el.x;
-        }
-      });
-    } catch (err) {
-      // you can report use errorHandler or other
-    } finally {
-      setLoading(false);
-    }
-  };
-  fetchData();
-</script>
-
-<style scoped lang="less"></style>

+ 0 - 131
src/views/jd/workplace/components/data-panel.vue

@@ -1,131 +0,0 @@
-<template>
-  <a-grid :cols="24" :row-gap="16" class="panel">
-    <a-grid-item
-      class="panel-col"
-      :span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
-    >
-      <a-space>
-        <a-avatar :size="54" class="col-avatar">
-          <img
-            alt="avatar"
-            src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/288b89194e657603ff40db39e8072640.svg~tplv-49unhts6dw-image.image"
-          />
-        </a-avatar>
-        <a-statistic
-          :title="$t('workplace.onlineContent')"
-          :value="373.5"
-          :precision="1"
-          :value-from="0"
-          animation
-          show-group-separator
-        >
-          <template #suffix>
-            W+ <span class="unit">{{ $t('workplace.pecs') }}</span>
-          </template>
-        </a-statistic>
-      </a-space>
-    </a-grid-item>
-    <a-grid-item
-      class="panel-col"
-      :span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
-    >
-      <a-space>
-        <a-avatar :size="54" class="col-avatar">
-          <img
-            alt="avatar"
-            src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/fdc66b07224cdf18843c6076c2587eb5.svg~tplv-49unhts6dw-image.image"
-          />
-        </a-avatar>
-        <a-statistic
-          :title="$t('workplace.putIn')"
-          :value="368"
-          :value-from="0"
-          animation
-          show-group-separator
-        >
-          <template #suffix>
-            <span class="unit">{{ $t('workplace.pecs') }}</span>
-          </template>
-        </a-statistic>
-      </a-space>
-    </a-grid-item>
-    <a-grid-item
-      class="panel-col"
-      :span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
-    >
-      <a-space>
-        <a-avatar :size="54" class="col-avatar">
-          <img
-            alt="avatar"
-            src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/77d74c9a245adeae1ec7fb5d4539738d.svg~tplv-49unhts6dw-image.image"
-          />
-        </a-avatar>
-        <a-statistic
-          :title="$t('workplace.newDay')"
-          :value="8874"
-          :value-from="0"
-          animation
-          show-group-separator
-        >
-          <template #suffix>
-            <span class="unit">{{ $t('workplace.pecs') }}</span>
-          </template>
-        </a-statistic>
-      </a-space>
-    </a-grid-item>
-    <a-grid-item
-      class="panel-col"
-      :span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }"
-      style="border-right: none"
-    >
-      <a-space>
-        <a-avatar :size="54" class="col-avatar">
-          <img
-            alt="avatar"
-            src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/c8b36e26d2b9bb5dbf9b74dd6d7345af.svg~tplv-49unhts6dw-image.image"
-          />
-        </a-avatar>
-        <a-statistic
-          :title="$t('workplace.newFromYesterday')"
-          :value="2.8"
-          :precision="1"
-          :value-from="0"
-          animation
-        >
-          <template #suffix> % <icon-caret-up class="up-icon" /> </template>
-        </a-statistic>
-      </a-space>
-    </a-grid-item>
-    <a-grid-item :span="24">
-      <a-divider class="panel-border" />
-    </a-grid-item>
-  </a-grid>
-</template>
-
-<script lang="ts" setup></script>
-
-<style lang="less" scoped>
-  .arco-grid.panel {
-    margin-bottom: 0;
-    padding: 16px 20px 0 20px;
-  }
-  .panel-col {
-    padding-left: 43px;
-    border-right: 1px solid rgb(var(--gray-2));
-  }
-  .col-avatar {
-    margin-right: 12px;
-    background-color: var(--color-fill-2);
-  }
-  .up-icon {
-    color: rgb(var(--red-6));
-  }
-  .unit {
-    margin-left: 8px;
-    color: rgb(var(--gray-8));
-    font-size: 12px;
-  }
-  :deep(.panel-border) {
-    margin: 4px 0 0 0;
-  }
-</style>

+ 0 - 42
src/views/jd/workplace/components/docs.vue

@@ -1,42 +0,0 @@
-<template>
-  <a-card
-    class="general-card"
-    :title="$t('workplace.docs')"
-    :header-style="{ paddingBottom: 0 }"
-    :body-style="{ paddingTop: 0 }"
-    style="height: 166px"
-  >
-    <template #extra>
-      <a-link>{{ $t('workplace.viewMore') }}</a-link>
-    </template>
-    <a-row>
-      <a-col :span="12">
-        <a-link>
-          {{ $t('workplace.docs.productOverview') }}
-        </a-link>
-      </a-col>
-      <a-col :span="12">
-        <a-link>
-          {{ $t('workplace.docs.userGuide') }}
-        </a-link>
-      </a-col>
-      <a-col :span="12">
-        <a-link>
-          {{ $t('workplace.docs.workflow') }}
-        </a-link>
-      </a-col>
-      <a-col :span="12">
-        <a-link>
-          {{ $t('workplace.docs.interfaceDocs') }}
-        </a-link>
-      </a-col>
-    </a-row>
-  </a-card>
-</template>
-
-<style lang="less" scoped>
-  .arco-card-body .arco-link {
-    margin: 10px 0;
-    color: rgb(var(--gray-8));
-  }
-</style>

+ 0 - 118
src/views/jd/workplace/components/popular-content.vue

@@ -1,118 +0,0 @@
-<template>
-  <a-spin :loading="loading" style="width: 100%">
-    <a-card
-      class="general-card"
-      :header-style="{ paddingBottom: '0' }"
-      :body-style="{ padding: '17px 20px 21px 20px' }"
-    >
-      <template #title>
-        {{ $t('workplace.popularContent') }}
-      </template>
-      <template #extra>
-        <a-link>{{ $t('workplace.viewMore') }}</a-link>
-      </template>
-      <a-space direction="vertical" :size="10" fill>
-        <a-radio-group
-          v-model:model-value="type"
-          type="button"
-          @change="typeChange as any"
-        >
-          <a-radio value="text">
-            {{ $t('workplace.popularContent.text') }}
-          </a-radio>
-          <a-radio value="image">
-            {{ $t('workplace.popularContent.image') }}
-          </a-radio>
-          <a-radio value="video">
-            {{ $t('workplace.popularContent.video') }}
-          </a-radio>
-        </a-radio-group>
-        <a-table
-          :data="renderList"
-          :pagination="false"
-          :bordered="false"
-          :scroll="{ x: '100%', y: '264px' }"
-        >
-          <template #columns>
-            <a-table-column title="排名" data-index="key"></a-table-column>
-            <a-table-column title="内容标题" data-index="title">
-              <template #cell="{ record }">
-                <a-typography-paragraph
-                  :ellipsis="{
-                    rows: 1,
-                  }"
-                >
-                  {{ record.title }}
-                </a-typography-paragraph>
-              </template>
-            </a-table-column>
-            <a-table-column title="点击量" data-index="clickNumber">
-            </a-table-column>
-            <a-table-column
-              title="日涨幅"
-              data-index="increases"
-              :sortable="{
-                sortDirections: ['ascend', 'descend'],
-              }"
-            >
-              <template #cell="{ record }">
-                <div class="increases-cell">
-                  <span>{{ record.increases }}%</span>
-                  <icon-caret-up
-                    v-if="record.increases !== 0"
-                    style="color: #f53f3f; font-size: 8px"
-                  />
-                </div>
-              </template>
-            </a-table-column>
-          </template>
-        </a-table>
-      </a-space>
-    </a-card>
-  </a-spin>
-</template>
-
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import useLoading from '@/hooks/loading';
-  import { queryPopularList } from '@/api/dashboard';
-  import type { TableData } from '@arco-design/web-vue/es/table/interface';
-
-  const type = ref('text');
-  const { loading, setLoading } = useLoading();
-  const renderList = ref<TableData[]>();
-  const fetchData = async (contentType: string) => {
-    try {
-      setLoading(true);
-      const { data } = await queryPopularList({ type: contentType });
-      renderList.value = data;
-    } catch (err) {
-      // you can report use errorHandler or other
-    } finally {
-      setLoading(false);
-    }
-  };
-  const typeChange = (contentType: string) => {
-    fetchData(contentType);
-  };
-  fetchData('text');
-</script>
-
-<style scoped lang="less">
-  .general-card {
-    min-height: 395px;
-  }
-  :deep(.arco-table-tr) {
-    height: 44px;
-    .arco-typography {
-      margin-bottom: 0;
-    }
-  }
-  .increases-cell {
-    display: flex;
-    align-items: center;
-    span {
-      margin-right: 4px;
-    }
-  }
-</style>

+ 0 - 35
src/views/jd/workplace/components/quick-operation.vue

@@ -1,35 +0,0 @@
-<template>
-  <a-card
-    class="general-card"
-    :title="$t('workplace.quick.operation')"
-    :header-style="{ paddingBottom: '0' }"
-    :body-style="{ padding: '24px 20px 0 20px' }"
-  >
-    <template #extra>
-      <a-link>{{ $t('workplace.quickOperation.setup') }}</a-link>
-    </template>
-    <a-row :gutter="8">
-      <a-col v-for="link in links" :key="link.text" :span="8" class="wrapper">
-        <div class="icon">
-          <component :is="link.icon" />
-        </div>
-        <a-typography-paragraph class="text">
-          {{ $t(link.text) }}
-        </a-typography-paragraph>
-      </a-col>
-    </a-row>
-    <a-divider class="split-line" style="margin: 0" />
-  </a-card>
-</template>
-
-<script lang="ts" setup>
-  const links = [
-    { text: 'workplace.contentManagement', icon: 'icon-file' },
-    { text: 'workplace.contentStatistical', icon: 'icon-storage' },
-    { text: 'workplace.advanced', icon: 'icon-settings' },
-    { text: 'workplace.onlinePromotion', icon: 'icon-mobile' },
-    { text: 'workplace.contentPutIn', icon: 'icon-fire' },
-  ];
-</script>
-
-<style scoped lang="less"></style>

+ 0 - 44
src/views/jd/workplace/components/recently-visited.vue

@@ -1,44 +0,0 @@
-<template>
-  <a-card
-    class="general-card"
-    :title="$t('workplace.recently.visited')"
-    :header-style="{ paddingBottom: '0' }"
-    :body-style="{ paddingTop: '26px' }"
-  >
-    <div style="margin-bottom: -1rem">
-      <a-row :gutter="8">
-        <a-col v-for="link in links" :key="link.text" :span="8" class="wrapper">
-          <div class="icon">
-            <component :is="link.icon" />
-          </div>
-          <a-typography-paragraph class="text">
-            {{ $t(link.text) }}
-          </a-typography-paragraph>
-        </a-col>
-      </a-row>
-    </div>
-  </a-card>
-</template>
-
-<script lang="ts" setup>
-  const links = [
-    {
-      text: 'workplace.contentManagement',
-      icon: 'icon-storage',
-    },
-    {
-      text: 'workplace.contentStatistical',
-      icon: 'icon-file',
-    },
-    {
-      text: 'workplace.advanced',
-      icon: 'icon-settings',
-    },
-  ];
-</script>
-
-<style lang="less" scoped>
-  :deep(.arco-card-header-title) {
-    line-height: inherit;
-  }
-</style>

+ 0 - 148
src/views/jd/workplace/index.vue

@@ -1,148 +0,0 @@
-<template>
-  <div class="container">
-    <div class="left-side">
-      <div class="panel">
-        <Banner />
-        <DataPanel />
-        <ContentChart />
-      </div>
-      <a-grid :cols="24" :col-gap="16" :row-gap="16" style="margin-top: 16px">
-        <a-grid-item
-          :span="{ xs: 24, sm: 24, md: 24, lg: 12, xl: 12, xxl: 12 }"
-        >
-          <PopularContent />
-        </a-grid-item>
-        <a-grid-item
-          :span="{ xs: 24, sm: 24, md: 24, lg: 12, xl: 12, xxl: 12 }"
-        >
-          <CategoriesPercent />
-        </a-grid-item>
-      </a-grid>
-    </div>
-    <div class="right-side">
-      <a-grid :cols="24" :row-gap="16">
-        <a-grid-item :span="24">
-          <div class="panel moduler-wrap">
-            <QuickOperation />
-            <RecentlyVisited />
-          </div>
-        </a-grid-item>
-        <a-grid-item class="panel" :span="24">
-          <Carousel />
-        </a-grid-item>
-        <a-grid-item class="panel" :span="24">
-          <Announcement />
-        </a-grid-item>
-        <a-grid-item class="panel" :span="24">
-          <Docs />
-        </a-grid-item>
-      </a-grid>
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import Banner from './components/banner.vue';
-  import DataPanel from './components/data-panel.vue';
-  import ContentChart from './components/content-chart.vue';
-  import PopularContent from './components/popular-content.vue';
-  import CategoriesPercent from './components/categories-percent.vue';
-  import RecentlyVisited from './components/recently-visited.vue';
-  import QuickOperation from './components/quick-operation.vue';
-  import Announcement from './components/announcement.vue';
-  import Carousel from './components/carousel.vue';
-  import Docs from './components/docs.vue';
-</script>
-
-<script lang="ts">
-  export default {
-    name: 'Dashboard', // If you want the include property of keep-alive to take effect, you must name the component
-  };
-</script>
-
-<style lang="less" scoped>
-  .container {
-    background-color: var(--color-fill-2);
-    padding: 16px 20px;
-    padding-bottom: 0;
-    display: flex;
-  }
-
-  .left-side {
-    flex: 1;
-    overflow: auto;
-  }
-
-  .right-side {
-    width: 280px;
-    margin-left: 16px;
-  }
-
-  .panel {
-    background-color: var(--color-bg-2);
-    border-radius: 4px;
-    overflow: auto;
-  }
-  :deep(.panel-border) {
-    margin-bottom: 0;
-    border-bottom: 1px solid rgb(var(--gray-2));
-  }
-  .moduler-wrap {
-    border-radius: 4px;
-    background-color: var(--color-bg-2);
-    :deep(.text) {
-      font-size: 12px;
-      text-align: center;
-      color: rgb(var(--gray-8));
-    }
-
-    :deep(.wrapper) {
-      margin-bottom: 8px;
-      text-align: center;
-      cursor: pointer;
-
-      &:last-child {
-        .text {
-          margin-bottom: 0;
-        }
-      }
-      &:hover {
-        .icon {
-          color: rgb(var(--arcoblue-6));
-          background-color: #e8f3ff;
-        }
-        .text {
-          color: rgb(var(--arcoblue-6));
-        }
-      }
-    }
-
-    :deep(.icon) {
-      display: inline-block;
-      width: 32px;
-      height: 32px;
-      margin-bottom: 4px;
-      color: rgb(var(--dark-gray-1));
-      line-height: 32px;
-      font-size: 16px;
-      text-align: center;
-      background-color: rgb(var(--gray-1));
-      border-radius: 4px;
-    }
-  }
-</style>
-
-<style lang="less" scoped>
-  // responsive
-  .mobile {
-    .container {
-      display: block;
-    }
-    .right-side {
-      // display: none;
-      width: 100%;
-      margin-left: 0;
-      margin-top: 16px;
-    }
-  }
-</style>

+ 0 - 38
src/views/jd/workplace/locale/en-US.ts

@@ -1,38 +0,0 @@
-export default {
-  'menu.settings.updateCookies': 'Update Cookie',
-  'workplace.welcome': 'Welcome!',
-  'workplace.balance': 'Balance (CNY)',
-  'workplace.order.pending': 'Pending',
-  'workplace.order.pendingRenewal': 'Renewal Order',
-  'workplace.onlineContent': 'Online Content',
-  'workplace.putIn': 'Put In',
-  'workplace.newDay': 'Daily Additional Comments',
-  'workplace.newFromYesterday': 'New From Yesterday',
-  'workplace.minute': 'Min',
-  'workplace.docs': 'Documents',
-  'workplace.docs.productOverview': 'Product Overview',
-  'workplace.docs.userGuide': 'User Guide',
-  'workplace.docs.workflow': 'Workflow',
-  'workplace.docs.interfaceDocs': 'Interface Docs',
-  //
-  'workplace.contentManagement': 'Content Management',
-  'workplace.contentStatistical': 'Content Statistical',
-  'workplace.advanced': 'Advanced',
-  'workplace.onlinePromotion': 'Online Promotion',
-  'workplace.contentPutIn': 'Put In',
-  'workplace.announcement': 'Announcement',
-  'workplace.recently.visited': 'Recently Visited',
-  'workplace.record.nodata': 'No data',
-  'workplace.quick.operation': 'Quick Operation',
-  'workplace.quickOperation.setup': 'Setup',
-  'workplace.allProject': 'All',
-  'workplace.loadMore': 'More',
-  'workplace.viewMore': 'More',
-  'workplace.contentData': 'Content Data',
-  'workplace.popularContent': 'Popular Content',
-  'workplace.popularContent.text': 'text',
-  'workplace.popularContent.image': 'image',
-  'workplace.popularContent.video': 'video',
-  'workplace.categoriesPercent': 'Categories Percent',
-  'workplace.pecs': 'pecs',
-};

+ 0 - 37
src/views/jd/workplace/locale/zh-CN.ts

@@ -1,37 +0,0 @@
-export default {
-  'menu.settings.updateCookies': '更新Cookie',
-  'workplace.welcome': '欢迎回来!',
-  'workplace.balance': '余额(元)',
-  'workplace.order.pending': '待支付',
-  'workplace.order.pendingRenewal': '待续费订单',
-  'workplace.onlineContent': '线上总内容',
-  'workplace.putIn': '投放中内容',
-  'workplace.newDay': '日新增评论',
-  'workplace.newFromYesterday': '较昨日新增',
-  'workplace.minute': '分钟',
-  'workplace.docs': '帮助文档',
-  'workplace.docs.productOverview': '产品概要',
-  'workplace.docs.userGuide': '使用指南',
-  'workplace.docs.workflow': '接入流程',
-  'workplace.docs.interfaceDocs': '接口文档',
-  'workplace.contentManagement': '内容管理',
-  'workplace.contentStatistical': '内容分析',
-  'workplace.advanced': '高级管理',
-  'workplace.onlinePromotion': '线上推广',
-  'workplace.contentPutIn': '内容投放',
-  'workplace.announcement': '公告',
-  'workplace.recently.visited': '最近访问',
-  'workplace.record.nodata': '暂无数据',
-  'workplace.quick.operation': '快捷操作',
-  'workplace.quickOperation.setup': '管理',
-  'workplace.allProject': '所有项目',
-  'workplace.loadMore': '加载更多',
-  'workplace.viewMore': '查看更多',
-  'workplace.contentData': '内容数据',
-  'workplace.popularContent': '线上热门内容',
-  'workplace.popularContent.text': '文本',
-  'workplace.popularContent.image': '图片',
-  'workplace.popularContent.video': '视频',
-  'workplace.categoriesPercent': '内容类型占比',
-  'workplace.pecs': '个',
-};

+ 0 - 129
src/views/jd/workplace/mock.ts

@@ -1,129 +0,0 @@
-import Mock from 'mockjs';
-import qs from 'query-string';
-import dayjs from 'dayjs';
-import { GetParams } from '@/types/global';
-import setupMock, { successResponseWrap } from '@/utils/setup-mock';
-
-const textList = [
-  {
-    key: 1,
-    clickNumber: '346.3w+',
-    title: '经济日报:财政政策要精准提升…',
-    increases: 35,
-  },
-  {
-    key: 2,
-    clickNumber: '324.2w+',
-    title: '双12遇冷,消费者厌倦了电商平…',
-    increases: 22,
-  },
-  {
-    key: 3,
-    clickNumber: '318.9w+',
-    title: '致敬坚守战“疫”一线的社区工作…',
-    increases: 9,
-  },
-  {
-    key: 4,
-    clickNumber: '257.9w+',
-    title: '普高还是职高?家长们陷入选择…',
-    increases: 17,
-  },
-  {
-    key: 5,
-    clickNumber: '124.2w+',
-    title: '人民快评:没想到“浓眉大眼”的…',
-    increases: 37,
-  },
-];
-const imageList = [
-  {
-    key: 1,
-    clickNumber: '15.3w+',
-    title: '杨涛接替陆慷出任外交部美大司…',
-    increases: 15,
-  },
-  {
-    key: 2,
-    clickNumber: '12.2w+',
-    title: '图集:龙卷风袭击美国多州房屋…',
-    increases: 26,
-  },
-  {
-    key: 3,
-    clickNumber: '18.9w+',
-    title: '52岁大姐贴钱照顾自闭症儿童八…',
-    increases: 9,
-  },
-  {
-    key: 4,
-    clickNumber: '7.9w+',
-    title: '杭州一家三口公园宿营取暖中毒',
-    increases: 0,
-  },
-  {
-    key: 5,
-    clickNumber: '5.2w+',
-    title: '派出所副所长威胁市民?警方调…',
-    increases: 4,
-  },
-];
-const videoList = [
-  {
-    key: 1,
-    clickNumber: '367.6w+',
-    title: '这是今日10点的南京',
-    increases: 5,
-  },
-  {
-    key: 2,
-    clickNumber: '352.2w+',
-    title: '立陶宛不断挑衅致经济受损民众…',
-    increases: 17,
-  },
-  {
-    key: 3,
-    clickNumber: '348.9w+',
-    title: '韩国艺人刘在石确诊新冠',
-    increases: 30,
-  },
-  {
-    key: 4,
-    clickNumber: '346.3w+',
-    title: '关于北京冬奥会,文在寅表态',
-    increases: 12,
-  },
-  {
-    key: 5,
-    clickNumber: '271.2w+',
-    title: '95后现役军人荣立一等功',
-    increases: 2,
-  },
-];
-setupMock({
-  setup() {
-    Mock.mock(new RegExp('/api/content-data'), () => {
-      const presetData = [58, 81, 53, 90, 64, 88, 49, 79];
-      const getLineData = () => {
-        const count = 8;
-        return new Array(count).fill(0).map((el, idx) => ({
-          x: dayjs()
-            .day(idx - 2)
-            .format('YYYY-MM-DD'),
-          y: presetData[idx],
-        }));
-      };
-      return successResponseWrap([...getLineData()]);
-    });
-    Mock.mock(new RegExp('/api/popular/list'), (params: GetParams) => {
-      const { type = 'text' } = qs.parseUrl(params.url).query;
-      if (type === 'image') {
-        return successResponseWrap([...videoList]);
-      }
-      if (type === 'video') {
-        return successResponseWrap([...imageList]);
-      }
-      return successResponseWrap([...textList]);
-    });
-  },
-});

+ 15 - 3
src/views/settings/config.vue

@@ -38,12 +38,22 @@
                             </a-form-item>
 
 
-                            <a-form-item field="fake_click_min" label="补点击时长" :rules="[{ required: true }]">
-                                <a-input-number v-model="formData.fake_click_ttl" :min="24"
-                                    placeholder="转链后多少时间内需要补点击,默认24小时" />
+                            
+                            <a-form-item field="fake_click_min" label="补点击次数" :rules="[{ required: true }]">
+                                <a-input-number v-model="formData.fake_click_min" :min="0" /> -
+                                <a-input-number v-model="formData.fake_click_max" :min="0" />
                             </a-form-item>
 
 
+                            <a-form-item field="jd_limit_per_ip_24h" label="24小时转链次数(JD)" :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="tk_limit_per_ip_24h" label="24小时转链次数(TK)" :rules="[{ required: true }]">
+                                <a-input-number v-model="formData.tk_limit_per_ip_24h" :min="0"
+                                    placeholder="同ip在24小时内可转链的次数。" />
+                            </a-form-item>
+
 
                             <a-form-item field="rt_max" label="转链超时" :rules="[{ required: true }]">
                                 <a-input-number v-model="formData.rt_max" :min="500" placeholder="转链API最长超时时间,单位毫秒" />
@@ -140,6 +150,8 @@ const formData = ref<UpdateConfigModel>({
     tk_whitelist_regular: '',
     tk_blacklist_regular: '',
     multi_token_regular: '',
+    jd_limit_per_ip_24h: 0,
+    tk_limit_per_ip_24h: 0,
 });
 
 const showRegularTester = ref<boolean>(false);

+ 1 - 2
src/views/taobao/report_daily.vue

@@ -297,7 +297,7 @@ const generateFormModel = () => {
         accountName: '',
         query_date: [],
         current: 1,
-        pageSize: 30,
+        pageSize: 31,
         sort: 'report_date',
         order: 'descending',
     };
@@ -582,7 +582,6 @@ const columns = computed<TableColumnData[]>(() => [
         ]
     },
 
-
     {
         title: '转链API调用',
         children: [

+ 1 - 3
src/views/taobao/updateCookies.vue

@@ -51,12 +51,10 @@ const validate = async () => {
             const msg = data.msg || '更新成功!';
             if (data.success) {
                 Message.success(msg);
-                router.push('/taobao/list');
+                router.push('./list');
             } else {
                 Message.error(data.msg);
             }
-
-
         } catch (err) {
             console.error(err)
         }