Просмотр исходного кода

Merge branch 'master' into xinyan

xinyan 5 месяцев назад
Родитель
Сommit
5fcb24f1a0
22 измененных файлов с 1354 добавлено и 12135 удалено
  1. 2 2
      .env.development
  2. 0 67
      components.d.ts
  3. 344 11754
      package-lock.json
  4. 1 1
      package.json
  5. 1 1
      src/layout/component/main.vue
  6. 38 0
      src/utils/useCustomHeight.ts
  7. 47 0
      src/utils/useTableHeight.ts
  8. 11 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWord/api.ts
  9. 181 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWord/crud.tsx
  10. 68 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWord/index.vue
  11. 11 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWordGroup/api.ts
  12. 181 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWordGroup/crud.tsx
  13. 68 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWordGroup/index.vue
  14. 9 0
      src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/index.vue
  15. 3 3
      src/views/reportManage/dataCenter/utils/enum.ts
  16. 71 63
      src/views/searchTerm/asinView/index.vue
  17. 56 48
      src/views/searchTerm/brandView/index.vue
  18. 23 15
      src/views/searchTerm/importPage/index.vue
  19. 17 7
      src/views/searchTerm/rootWordManage/components/root-word-manage-table.vue
  20. 0 1
      src/views/searchTerm/targetingSearchTerm/index.vue
  21. 82 54
      src/views/searchTerm/topSearchTermRank/index.vue
  22. 140 119
      src/views/searchTerm/topSearchTermTable/index.vue

+ 2 - 2
.env.development

@@ -4,9 +4,9 @@ ENV='development'
 
 # 本地环境接口地址
 # VITE_API_URL = 'http://127.0.0.1:8000'
-VITE_API_URL='http://192.168.1.225/'
+#VITE_API_URL='http://192.168.1.225/'
 # VITE_API_URL='http://192.168.1.25:8080/'
-# VITE_API_URL = 'http://amzads.zositechc.cn'
+ VITE_API_URL = 'http://amzads.zositechc.cn'
 
 # 是否启用按钮权限
 VITE_PM_ENABLED=true

+ 0 - 67
components.d.ts

@@ -23,70 +23,7 @@ declare module 'vue' {
     DynamicCard: typeof import('./src/components/cardComponents/dynamicCard.vue')['default']
     DynamicTime: typeof import('./src/components/DynamicTime/index.vue')['default']
     Editor: typeof import('./src/components/editor/index.vue')['default']
-    ElAlert: typeof import('element-plus/es')['ElAlert']
-    ElAside: typeof import('element-plus/es')['ElAside']
-    ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
-    ElBacktop: typeof import('element-plus/es')['ElBacktop']
-    ElBadge: typeof import('element-plus/es')['ElBadge']
-    ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
-    ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
-    ElButton: typeof import('element-plus/es')['ElButton']
-    ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
-    ElCard: typeof import('element-plus/es')['ElCard']
-    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
-    ElCol: typeof import('element-plus/es')['ElCol']
-    ElCollapse: typeof import('element-plus/es')['ElCollapse']
-    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
-    ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
-    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
-    ElContainer: typeof import('element-plus/es')['ElContainer']
-    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
-    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
-    ElDialog: typeof import('element-plus/es')['ElDialog']
-    ElDivider: typeof import('element-plus/es')['ElDivider']
-    ElDrawer: typeof import('element-plus/es')['ElDrawer']
-    ElDropdown: typeof import('element-plus/es')['ElDropdown']
-    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
-    ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
-    ElEmpty: typeof import('element-plus/es')['ElEmpty']
-    ElForm: typeof import('element-plus/es')['ElForm']
-    ElFormItem: typeof import('element-plus/es')['ElFormItem']
-    ElHeader: typeof import('element-plus/es')['ElHeader']
-    ElIcon: typeof import('element-plus/es')['ElIcon']
-    ElImage: typeof import('element-plus/es')['ElImage']
-    ElInput: typeof import('element-plus/es')['ElInput']
-    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
-    ElLink: typeof import('element-plus/es')['ElLink']
-    ElMain: typeof import('element-plus/es')['ElMain']
-    ElMenu: typeof import('element-plus/es')['ElMenu']
-    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
-    ElOption: typeof import('element-plus/es')['ElOption']
-    ElPagination: typeof import('element-plus/es')['ElPagination']
-    ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
-    ElPopover: typeof import('element-plus/es')['ElPopover']
-    ElProgress: typeof import('element-plus/es')['ElProgress']
-    ElRadio: typeof import('element-plus/es')['ElRadio']
-    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
-    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
-    ElRate: typeof import('element-plus/es')['ElRate']
-    ElRow: typeof import('element-plus/es')['ElRow']
-    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
-    ElSelect: typeof import('element-plus/es')['ElSelect']
-    ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
-    ElSwitch: typeof import('element-plus/es')['ElSwitch']
-    ElTable: typeof import('element-plus/es')['ElTable']
-    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
-    ElTabPane: typeof import('element-plus/es')['ElTabPane']
-    ElTabs: typeof import('element-plus/es')['ElTabs']
-    ElTag: typeof import('element-plus/es')['ElTag']
-    ElTooltip: typeof import('element-plus/es')['ElTooltip']
-    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
-    ElUpload: typeof import('element-plus/es')['ElUpload']
-    FileDload: typeof import('./src/components/FileDload/index.vue')['default']
     FileDowlander: typeof import('./src/components/FileDowlander/index.vue')['default']
-    FileDownload: typeof import('./src/components/FileDownload/index.vue')['default']
-    FileDownloader: typeof import('./src/components/FileDowlander/FileDownloader.vue')['default']
     FileUploader: typeof import('./src/components/FileUploader/index.vue')['default']
     ForeignKey: typeof import('./src/components/foreignKey/index.vue')['default']
     IconSelector: typeof import('./src/components/iconSelector/index.vue')['default']
@@ -117,8 +54,4 @@ declare module 'vue' {
     TimerBudgetTable: typeof import('./src/components/TimerBudgetTable/index.vue')['default']
     WeekRangePicker: typeof import('./src/components/WeekRangePicker/index.vue')['default']
   }
-  export interface ComponentCustomProperties {
-    vInfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll']
-    vLoading: typeof import('element-plus/es')['ElLoadingDirective']
-  }
 }

Разница между файлами не показана из-за своего большого размера
+ 344 - 11754
package-lock.json


+ 1 - 1
package.json

@@ -20,7 +20,7 @@
 		"@wecom/jssdk": "^1.4.5",
 		"autoprefixer": "^10.4.14",
 		"axios": "^1.2.1",
-		"caniuse-lite": "^1.0.30001605",
+		"caniuse-lite": "1.0.30001605",
 		"countup.js": "^2.3.2",
 		"cropperjs": "^2.0.0-beta.4",
 		"dayjs": "^1.11.11",

+ 1 - 1
src/layout/component/main.vue

@@ -6,7 +6,7 @@
 			<LayoutParentView />
 			<!-- <LayoutFooter v-if="isFooter" /> -->
 		</el-scrollbar>
-		<el-backtop :target="setBacktopClass" />
+		<!--<el-backtop :target="setBacktopClass" />-->
 	</el-main>
 </template>
 

+ 38 - 0
src/utils/useCustomHeight.ts

@@ -0,0 +1,38 @@
+export function useCustomHeight(heightObj: Record<string, number | Ref<HTMLElement | null>>) {
+  const tableHeight = ref<number>(0);
+
+  const calculateHeight = () => {
+    let totalHeight = 0;
+    const entries = Object.entries(heightObj);
+
+    entries.forEach(([key, height], index) => {
+      // console.log(`Processing ${key} at index ${index}:`);
+
+      // 判断 height 是否为 ref,如果是则解引用,否则直接使用数值
+      const resolvedHeight = isRef(height) ? unref(height) : height;
+
+      let currentHeight = 0;
+      if (typeof resolvedHeight === 'number') {
+        currentHeight = resolvedHeight;
+      } else if (resolvedHeight instanceof HTMLElement) {
+        currentHeight = resolvedHeight.offsetHeight;
+      }
+
+      totalHeight += currentHeight;
+      // console.log(`Key: ${key}, Current height: ${currentHeight}, Total so far: ${totalHeight}`);
+    });
+
+    tableHeight.value = window.innerHeight - totalHeight;
+  };
+
+  onMounted(() => {
+    calculateHeight();
+    window.addEventListener('resize', calculateHeight);
+  });
+
+  onBeforeUnmount(() => {
+    window.removeEventListener('resize', calculateHeight);
+  });
+
+  return { tableHeight };
+}

+ 47 - 0
src/utils/useTableHeight.ts

@@ -0,0 +1,47 @@
+/**
+ * 计算表格高度
+ * @param titleRef 标题容器
+ * @param queryRef 查询条件的容器
+ */
+export function useTableHeight(titleRef: Ref<HTMLElement | null>, queryRef: Ref<HTMLElement | null>) {
+  const computeTableHeight = ref({
+    titleHeight: 0,
+    queryHeight: 0,
+    // headerHeight: 50,
+    dividerHeight: 48,
+    toolbarHeight: 32 + 13 + 40 + 70,
+    padding: 40,
+  });
+
+  const totalOtherHeight = ref(0);
+  const tableHeight = ref(0);
+
+  const computeHeight = () => {
+    const titleElement = unref(titleRef);
+    const queryElement = unref(queryRef);
+
+    computeTableHeight.value.titleHeight = titleElement ? titleElement.scrollHeight : 0;
+    computeTableHeight.value.queryHeight = queryElement ? queryElement.scrollHeight : 0;
+
+    totalOtherHeight.value =
+        computeTableHeight.value.titleHeight +
+        computeTableHeight.value.queryHeight +
+        // computeTableHeight.value.headerHeight +
+        computeTableHeight.value.dividerHeight +
+        computeTableHeight.value.toolbarHeight +
+        computeTableHeight.value.padding;
+// 1355 960
+    tableHeight.value = window.innerHeight - totalOtherHeight.value;
+  };
+
+  onMounted(() => {
+    computeHeight(); // 组件挂载时计算一次高度
+    window.addEventListener('resize', computeHeight); // 监听窗口大小变化
+  });
+
+  onUnmounted(() => {
+    window.removeEventListener('resize', computeHeight); // 移除事件监听器
+  });
+  console.log('tableHeight=> ', tableHeight);
+  return { tableHeight: tableHeight as Ref<number> }; // 返回类型注释
+}

+ 11 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWord/api.ts

@@ -0,0 +1,11 @@
+import { request } from '/@/utils/service';
+import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
+
+export const apiPrefix = '/api/ad_manage/spcampaigns/asin_word/';
+export function GetList(query: UserPageQuery) {
+	return request({
+		url: apiPrefix + 'split/',
+		method: 'get',
+		params: query,
+	})
+}

+ 181 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWord/crud.tsx

@@ -0,0 +1,181 @@
+import * as api from './api';
+import { CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery } from '@fast-crud/fast-crud';
+import { inject } from 'vue';
+import { parseQueryParams } from '/@/views/adManage/utils/tools.js';
+import XEUtils from 'xe-utils';
+
+
+export const createCrudOptions = function({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
+  const pageRequest = async (query: UserPageQuery) => {
+    const params = parseQueryParams(context.value);
+    XEUtils.assign(query, params);
+    return await api.GetList(query);
+  };
+
+  //权限判定
+  const hasPermissions = inject('$hasPermissions');
+
+  return {
+    crudOptions: {
+      table: {},
+      container: {
+        fixedHeight: false
+      },
+      actionbar: {
+        show: false
+      },
+      search: {
+        show: true,
+        buttons: {
+          search: {
+            show: false
+          },
+          reset: {
+            show: false
+          }
+        }
+      },
+      // toolbar: {
+      //   buttons: {
+      //     search: {
+      //       show: true,
+      //     },
+      //     compact: {
+      //       show: false,
+      //     },
+      //   },
+      // },
+      request: {
+        pageRequest
+      },
+      rowHandle: {
+        show: false
+      },
+      columns: {
+        searchTerm: {
+          title: '搜索词',
+          column: {
+            width: '200px',
+            fixed: 'left'
+          }
+        },
+        Impression: {
+          title: '曝光量',
+          column: {
+            align: 'center'
+          }
+        },
+        Click: {
+          title: '点击量',
+          column: {
+            align: 'center'
+          }
+        },
+        Spend: {
+          title: '花 费',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalPurchases: {
+          title: '订单数',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalSales: {
+          title: '花 费',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalUnitOrdered: {
+          title: '销 量',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalSalesSameSKU: {
+          title: '推广商品销售额',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalSalesOtherSKU: {
+          title: '其他商品销售额',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalPurchasesSameSKU: {
+          title: '推广商品订单数',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalPurchasesOtherSKU: {
+          title: '其他商品订单数',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalUnitOrderedSameSKU: {
+          title: '推广商品销量',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalUnitOrderedOtherSKU: {
+          title: '其它商品销量',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        CPC: {
+          title: '点击成本',
+          column: {
+            width: '130',
+            align: 'center'
+          }
+        },
+        CTR: {
+          title: '点击率',
+          column: {
+            align: 'center'
+          }
+        },
+        PurchasesRate: {
+          title: '转化率',
+          column: {
+            align: 'center'
+          }
+        },
+        ACOS: {
+          title: 'ACOS',
+          column: {
+            align: 'center'
+          }
+        },
+        ROAS: {
+          title: 'ROAS',
+          column: {
+            align: 'center'
+          }
+        },
+        CPA: {
+          title: '订单成本',
+          column: {
+            width: '130',
+            align: 'center'
+          }
+        }
+      }
+    }
+  };
+};

+ 68 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWord/index.vue

@@ -0,0 +1,68 @@
+<script lang="ts" setup>
+/**
+ * @Name: index.vue
+ * @Description:
+ * @Author: Cheney
+ */
+
+import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn';
+import DateRangePicker from '/@/components/DateRangePicker/index.vue';
+import DataCompare from '/@/components/dataCompare/index.vue';
+import { FsPage, useFs } from '@fast-crud/fast-crud';
+import { createCrudOptions } from './crud';
+import { onMounted, ref } from 'vue';
+import { storeToRefs } from 'pinia';
+import { usePublicData } from '/@/stores/publicData';
+import { LocationQueryValue } from 'vue-router';
+
+
+interface Props {
+  adGroupId: LocationQueryValue | LocationQueryValue[];
+}
+
+const props = defineProps<Props>();
+
+const publicData = usePublicData();
+const { dateRange } = storeToRefs(publicData);
+const queryParams = ref({
+  adGroupId: props.adGroupId,
+  dateRange
+});
+
+const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: queryParams });
+
+onMounted(() => {
+  crudExpose.doRefresh();
+});
+</script>
+
+<template>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding">
+      <!--<template #search-left>-->
+      <!--  <DateRangePicker v-model="dateRange"></DateRangePicker>-->
+      <!--</template>-->
+
+      <!--<template v-for="field of Object.keys(BaseColumn)" #[`cell_${field}`]="scope">-->
+      <!--  <DataCompare-->
+      <!--      :field="field"-->
+      <!--      :value="scope.row[field]"-->
+      <!--      :prev-val="scope.row[`prev${field}`]"-->
+      <!--      :gap-val="scope.row[`gap${field}`]"-->
+      <!--      :date-range="dateRange"-->
+      <!--      :show-compare="showCompare"-->
+      <!--  />-->
+      <!--</template>-->
+      <!--<template #toolbar-left>-->
+      <!--  <div class="campare-switch">-->
+      <!--    <span>数据对比 </span>-->
+      <!--    <el-switch v-model="showCompare" size="small" />-->
+      <!--  </div>-->
+      <!--</template>-->
+    </fs-crud>
+  </fs-page>
+</template>
+
+<style scoped>
+
+</style>

+ 11 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWordGroup/api.ts

@@ -0,0 +1,11 @@
+import { request } from '/@/utils/service';
+import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
+
+export const apiPrefix = '/api/ad_manage/spcampaigns/asin_word/';
+export function GetList(query: UserPageQuery) {
+	return request({
+		url: apiPrefix,
+		method: 'get',
+		params: query,
+	})
+}

+ 181 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWordGroup/crud.tsx

@@ -0,0 +1,181 @@
+import * as api from './api';
+import { CreateCrudOptionsProps, CreateCrudOptionsRet, UserPageQuery } from '@fast-crud/fast-crud';
+import { inject } from 'vue';
+import { parseQueryParams } from '/@/views/adManage/utils/tools.js';
+import XEUtils from 'xe-utils';
+
+
+export const createCrudOptions = function({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
+  const pageRequest = async (query: UserPageQuery) => {
+    const params = parseQueryParams(context.value);
+    XEUtils.assign(query, params);
+    return await api.GetList(query);
+  };
+
+  //权限判定
+  const hasPermissions = inject('$hasPermissions');
+
+  return {
+    crudOptions: {
+      table: {},
+      container: {
+        fixedHeight: false
+      },
+      actionbar: {
+        show: false
+      },
+      search: {
+        show: true,
+        buttons: {
+          search: {
+            show: false
+          },
+          reset: {
+            show: false
+          }
+        }
+      },
+      // toolbar: {
+      //   buttons: {
+      //     search: {
+      //       show: true,
+      //     },
+      //     compact: {
+      //       show: false,
+      //     },
+      //   },
+      // },
+      request: {
+        pageRequest
+      },
+      rowHandle: {
+        show: false
+      },
+      columns: {
+        searchTerm: {
+          title: '搜索词',
+          column: {
+            width: '200px',
+            fixed: 'left'
+          }
+        },
+        Impression: {
+          title: '曝光量',
+          column: {
+            align: 'center'
+          }
+        },
+        Click: {
+          title: '点击量',
+          column: {
+            align: 'center'
+          }
+        },
+        Spend: {
+          title: '花 费',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalPurchases: {
+          title: '订单数',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalSales: {
+          title: '花 费',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalUnitOrdered: {
+          title: '销 量',
+          column: {
+            align: 'center'
+          }
+        },
+        TotalSalesSameSKU: {
+          title: '推广商品销售额',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalSalesOtherSKU: {
+          title: '其他商品销售额',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalPurchasesSameSKU: {
+          title: '推广商品订单数',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalPurchasesOtherSKU: {
+          title: '其他商品订单数',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalUnitOrderedSameSKU: {
+          title: '推广商品销量',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        TotalUnitOrderedOtherSKU: {
+          title: '其它商品销量',
+          column: {
+            width: '180',
+            align: 'center'
+          }
+        },
+        CPC: {
+          title: '点击成本',
+          column: {
+            width: '130',
+            align: 'center'
+          }
+        },
+        CTR: {
+          title: '点击率',
+          column: {
+            align: 'center'
+          }
+        },
+        PurchasesRate: {
+          title: '转化率',
+          column: {
+            align: 'center'
+          }
+        },
+        ACOS: {
+          title: 'ACOS',
+          column: {
+            align: 'center'
+          }
+        },
+        ROAS: {
+          title: 'ROAS',
+          column: {
+            align: 'center'
+          }
+        },
+        CPA: {
+          title: '订单成本',
+          column: {
+            width: '130',
+            align: 'center'
+          }
+        }
+      }
+    }
+  };
+};

+ 68 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/asinWordGroup/index.vue

@@ -0,0 +1,68 @@
+<script lang="ts" setup>
+/**
+ * @Name: index.vue
+ * @Description:
+ * @Author: Cheney
+ */
+
+import { BaseColumn } from '/@/views/adManage/utils/commonTabColumn';
+import DateRangePicker from '/@/components/DateRangePicker/index.vue';
+import DataCompare from '/@/components/dataCompare/index.vue';
+import { FsPage, useFs } from '@fast-crud/fast-crud';
+import { createCrudOptions } from './crud';
+import { onMounted, ref } from 'vue';
+import { storeToRefs } from 'pinia';
+import { usePublicData } from '/@/stores/publicData';
+import { LocationQueryValue } from 'vue-router';
+
+
+interface Props {
+  adGroupId: LocationQueryValue | LocationQueryValue[];
+}
+
+const props = defineProps<Props>();
+
+const publicData = usePublicData();
+const { dateRange } = storeToRefs(publicData);
+const queryParams = ref({
+  adGroupId: props.adGroupId,
+  dateRange
+});
+
+const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: queryParams });
+
+onMounted(() => {
+  crudExpose.doRefresh();
+});
+</script>
+
+<template>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding">
+      <!--<template #search-left>-->
+      <!--  <DateRangePicker v-model="dateRange"></DateRangePicker>-->
+      <!--</template>-->
+
+      <!--<template v-for="field of Object.keys(BaseColumn)" #[`cell_${field}`]="scope">-->
+      <!--  <DataCompare-->
+      <!--      :field="field"-->
+      <!--      :value="scope.row[field]"-->
+      <!--      :prev-val="scope.row[`prev${field}`]"-->
+      <!--      :gap-val="scope.row[`gap${field}`]"-->
+      <!--      :date-range="dateRange"-->
+      <!--      :show-compare="showCompare"-->
+      <!--  />-->
+      <!--</template>-->
+      <!--<template #toolbar-left>-->
+      <!--  <div class="campare-switch">-->
+      <!--    <span>数据对比 </span>-->
+      <!--    <el-switch v-model="showCompare" size="small" />-->
+      <!--  </div>-->
+      <!--</template>-->
+    </fs-crud>
+  </fs-page>
+</template>
+
+<style scoped>
+
+</style>

+ 9 - 0
src/views/adManage/sp/campaigns/campaignDetail/adGroups/adGroupDetail/index.vue

@@ -42,6 +42,12 @@
         <el-tab-pane label="否定商品" name="tab3">
           <NegProduct v-if="tabActiveName === 'tab3'" :adGroupId="route.query.adGroupId">否定商品</NegProduct>
         </el-tab-pane>
+        <el-tab-pane label="ASIN跑词" name="asinWord">
+          <AsinWord v-if="tabActiveName === 'asinWord'" :adGroupId="route.query.adGroupId" />
+        </el-tab-pane>
+        <el-tab-pane label="ASIN跑词(词组)" name="asinWordGroup">
+          <AsinWordGroup v-if="tabActiveName === 'asinWordGroup'" :adGroupId="route.query.adGroupId" />
+        </el-tab-pane>
       </template>
       <template v-else>
         <el-tab-pane label="关键词" name="tab2">
@@ -73,6 +79,8 @@ import ManualTarget from './manualTarget/index.vue'
 import NegProduct from './negProduct/index.vue'
 import NegKeyword from './negKeyword/index.vue'
 import NegTarget from './negTarget/index.vue'
+import AsinWord from './asinWord/index.vue'
+import AsinWordGroup from './asinWordGroup/index.vue'
 
 const tabActiveName = ref('adProducts')
 const shopInfo = useShopInfo()
@@ -82,6 +90,7 @@ const adGroupInfo: Ref<SpAdGroup> = ref({})
 
 onMounted(async () => {
   const resp = await GetObj(route.query.adGroupId)
+  console.log("(index.vue: 89)=> resp", resp);
   adGroupInfo.value = resp.data
 })
 

+ 3 - 3
src/views/reportManage/dataCenter/utils/enum.ts

@@ -9,7 +9,7 @@ export const dayMetricsEnum = [
   {value: 'acos', label: '广告ACOS'},
   {value: 'roi', label: '广告ROI'},
   {value: 'roas', label: '广告ROAS'},
-    {value: 'tacos', label: 'TACOS'},
+    {value: 'tacos', label: '广告TACOS'},
 ]
 
 export const weekMetricsEnum = [
@@ -31,7 +31,7 @@ export const weekMetricsEnum = [
   { value: 'ad_click_rate', label: '广告点击率'},
   { value: 'ad_conversion_rate', label: '广告转化率'},
   { value: 'conversion_rate', label: '转化率'},
-  {value: 'tacos', label: 'TACOS'},
+  {value: 'tacos', label: '广告TACOS'},
 ]
 
 export const monthMetricsEnum = [
@@ -48,7 +48,7 @@ export const monthMetricsEnum = [
   { value: 'ad_order', label: '广告订单'},
   { value: 'ad_click_rate', label: '广告点击率'},
   { value: 'ad_conversion_rate', label: '广告转化率'},
-  {value: 'tacos', label: 'TACOS'},
+  {value: 'tacos', label: '广告TACOS'},
 ]
 
 export const monthCompareMetricsEnum = [

+ 71 - 63
src/views/searchTerm/asinView/index.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script lang="ts" setup>
 /**
  * @Name: index.vue
  * @Description: asinView
@@ -13,48 +13,54 @@ import { ElMessage } from 'element-plus';
 import { asinColumns } from './useColumns';
 import WeekRangePicker from '/@/components/WeekRangePicker/index.vue';
 import MonthRangePicker from '/@/components/MonthRangePicker/index.vue';
+import { useCustomHeight } from '/@/utils/useCustomHeight';
+
+
+const topCard = ref();
+const heightObj = { topBar: 50, topCard: topCard, cardMargin: 32 };
+const { tableHeight } = useCustomHeight(heightObj);
 
 const weekDate = ref([
   dayjs().subtract(2, 'week').day(0).format('YYYY-MM-DD'),
-  dayjs().subtract(1, 'week').day(6).format('YYYY-MM-DD'),
+  dayjs().subtract(1, 'week').day(6).format('YYYY-MM-DD')
 ]);
 const monthDate = ref([
   dayjs().subtract(2, 'month').startOf('month').format('YYYY-MM-DD'),
-  dayjs().subtract(0, 'month').startOf('month').format('YYYY-MM-DD'),
+  dayjs().subtract(0, 'month').startOf('month').format('YYYY-MM-DD')
 ]);
 const reportTypeSelect = ref('weekly');
 const searchTermInp = ref('');
 const asinInp = ref('B0');
 const tableLoading = ref(false);
 
+const tablePage = reactive({
+  total: 0,
+  currentPage: 1,
+  pageSize: 20
+});
+
 const gridOptions: any = reactive({
   height: 'auto',
   border: false,
   round: true,
   columnConfig: {
-    resizable: true,
+    resizable: true
   },
   toolbarConfig: {
     custom: true,
     slots: {
-      buttons: 'toolbar_buttons',
-    },
+      buttons: 'toolbar_buttons'
+    }
   },
   columns: asinColumns,
-  data: [],
-});
-
-const tablePage = reactive({
-  total: 0,
-  currentPage: 1,
-  pageSize: 20,
+  data: []
 });
 
 onBeforeMount(() => {
   fetchTableData();
 });
 
-watch([weekDate, monthDate], () => {
+watch([ weekDate, monthDate ], () => {
   fetchTableData();
 });
 
@@ -92,7 +98,7 @@ async function fetchTableData() {
     search_term: searchTermInp.value,
     report_type: reportTypeSelect.value,
     date_start: reportTypeSelect.value == 'weekly' ? weekDate.value[0] : monthDate.value[0],
-    date_end: reportTypeSelect.value == 'weekly' ? weekDate.value[1] : monthDate.value[1],
+    date_end: reportTypeSelect.value == 'weekly' ? weekDate.value[1] : monthDate.value[1]
   };
   try {
     const response = await getTableData(query);
@@ -145,56 +151,58 @@ function validateAsinInput(input: string) {
 
 <template>
   <div class="py-2 px-2.5" style="background-color: #f7f7f7">
-    <el-card shadow="hover" class="mb-2.5" style="border: none; margin-bottom: 10px">
-      <div class="flex justify-between">
-        <div class="flex gap-5 flex-wrap">
-          <div>
-            <span class="font-medium mr-0.5">报告类型 </span>
-            <el-select v-model="reportTypeSelect" @change="handleSelectChange" style="width: 90px">
-              <el-option label="周度" value="weekly" />
-              <el-option label="月度" value="monthly" />
-            </el-select>
-          </div>
-          <div>
-            <span class="font-medium mr-0.5">搜索词 </span>
-            <el-input
-              v-model="searchTermInp"
-              @keyup.enter="handleQueryChange"
-              :prefix-icon="Search"
-              placeholder="输入后回车查询"
-              clearable
-              @clear="handleSelectChange"
-              style="width: 240px" />
-          </div>
-          <div>
-            <span class="font-medium mr-0.5">ASIN </span>
-            <el-input
-              v-model="asinInp"
-              @keyup.enter="handleQueryChange"
-              :prefix-icon="Search"
-              placeholder="输入后回车查询"
-              clearable
-              @clear="handleSelectChange"
-              style="width: 180px" />
+    <div ref="topCard">
+      <el-card class="mb-2.5" shadow="hover" style="border: none; margin-bottom: 10px">
+        <div ref="queryContainer" class="flex justify-between">
+          <div class="flex gap-5 flex-wrap">
+            <div>
+              <span class="font-medium mr-0.5">报告类型 </span>
+              <el-select v-model="reportTypeSelect" style="width: 90px" @change="handleSelectChange">
+                <el-option label="周度" value="weekly"/>
+                <el-option label="月度" value="monthly"/>
+              </el-select>
+            </div>
+            <div>
+              <span class="font-medium mr-0.5">搜索词 </span>
+              <el-input
+                  v-model="searchTermInp"
+                  :prefix-icon="Search"
+                  clearable
+                  placeholder="输入后回车查询"
+                  style="width: 240px"
+                  @clear="handleSelectChange"
+                  @keyup.enter="handleQueryChange"/>
+            </div>
+            <div>
+              <span class="font-medium mr-0.5">ASIN </span>
+              <el-input
+                  v-model="asinInp"
+                  :prefix-icon="Search"
+                  clearable
+                  placeholder="输入后回车查询"
+                  style="width: 180px"
+                  @clear="handleSelectChange"
+                  @keyup.enter="handleQueryChange"/>
+            </div>
+            <div>
+              <span class="font-medium mr-0.5">报告日期 </span>
+              <MonthRangePicker v-if="reportTypeSelect === 'monthly'" v-model="monthDate"/>
+              <WeekRangePicker v-else v-model="weekDate"/>
+            </div>
           </div>
-          <div>
-            <span class="font-medium mr-0.5">报告日期 </span>
-            <MonthRangePicker v-model="monthDate" v-if="reportTypeSelect === 'monthly'" />
-            <WeekRangePicker v-model="weekDate" v-else />
+          <div class="flex">
+            <el-button :icon="Refresh" circle @click="refreshTable"></el-button>
           </div>
         </div>
-        <div class="flex">
-          <el-button @click="refreshTable" :icon="Refresh" circle></el-button>
-        </div>
-      </div>
-    </el-card>
-    <el-card shadow="hover" style="border: none">
-      <div style="overflow: hidden; width: 100%; height: 950px" v-loading="tableLoading">
+      </el-card>
+    </div>
+    <el-card :body-style="{ height: tableHeight + 'px' }" shadow="hover" style="border: none;">
+      <div v-loading="tableLoading" class=" w-full h-full">
         <vxe-grid v-bind="gridOptions">
           <template #toolbar_buttons></template>
           <template v-for="col in asinColumns" #[`${col.field}_default`]="{ row }">
             <div v-if="col.field === 'clickedItemName'">
-              <el-tooltip effect="dark" :content="row.clickedItemName" placement="top" :show-after="300">
+              <el-tooltip :content="row.clickedItemName" :show-after="300" effect="dark" placement="top">
                 <div class="line-text font-medium">
                   {{ row.clickedItemName }}
                 </div>
@@ -206,11 +214,11 @@ function validateAsinInput(input: string) {
           </template>
           <template #pager>
             <vxe-pager
-              :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
-              v-model:current-page="tablePage.currentPage"
-              v-model:page-size="tablePage.pageSize"
-              :total="tablePage.total"
-              @page-change="handlePageChange">
+                v-model:current-page="tablePage.currentPage"
+                v-model:page-size="tablePage.pageSize"
+                :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
+                :total="tablePage.total"
+                @page-change="handlePageChange">
             </vxe-pager>
           </template>
         </vxe-grid>

+ 56 - 48
src/views/searchTerm/brandView/index.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script lang="ts" setup>
 /**
  * @Name: index.vue
  * @Description: brandView
@@ -13,14 +13,20 @@ import { ElMessage } from 'element-plus';
 import { brandColumns } from './useColumns';
 import WeekRangePicker from '/@/components/WeekRangePicker/index.vue';
 import MonthRangePicker from '/@/components/MonthRangePicker/index.vue';
+import { useCustomHeight } from '/@/utils/useCustomHeight';
+
+
+const topCard = ref();
+const heightObj = { topBar: 50, topCard: topCard, cardMargin: 32 };
+const { tableHeight } = useCustomHeight(heightObj);
 
 const weekDate = ref([
   dayjs().subtract(2, 'week').day(0).format('YYYY-MM-DD'),
-  dayjs().subtract(1, 'week').day(6).format('YYYY-MM-DD'),
+  dayjs().subtract(1, 'week').day(6).format('YYYY-MM-DD')
 ]);
 const monthDate = ref([
   dayjs().subtract(2, 'month').startOf('month').format('YYYY-MM-DD'),
-  dayjs().subtract(0, 'month').startOf('month').format('YYYY-MM-DD'),
+  dayjs().subtract(0, 'month').startOf('month').format('YYYY-MM-DD')
 ]);
 const reportTypeSelect = ref('weekly');
 const searchTermInp = ref('zosi');
@@ -31,29 +37,29 @@ const gridOptions: any = reactive({
   border: false,
   round: true,
   columnConfig: {
-    resizable: true,
+    resizable: true
   },
   toolbarConfig: {
     custom: true,
     slots: {
-      buttons: 'toolbar_buttons',
-    },
+      buttons: 'toolbar_buttons'
+    }
   },
   columns: brandColumns,
-  data: [],
+  data: []
 });
 
 const tablePage = reactive({
   total: 0,
   currentPage: 1,
-  pageSize: 20,
+  pageSize: 20
 });
 
 onBeforeMount(() => {
   fetchTableData();
 });
 
-watch([weekDate, monthDate], () => {
+watch([ weekDate, monthDate ], () => {
   fetchTableData();
 });
 
@@ -83,7 +89,7 @@ async function fetchTableData() {
     search_term: searchTermInp.value,
     report_type: reportTypeSelect.value,
     date_start: reportTypeSelect.value == 'weekly' ? weekDate.value[0] : monthDate.value[0],
-    date_end: reportTypeSelect.value == 'weekly' ? weekDate.value[1] : monthDate.value[1],
+    date_end: reportTypeSelect.value == 'weekly' ? weekDate.value[1] : monthDate.value[1]
   };
   try {
     const response = await getTableData(query);
@@ -140,51 +146,53 @@ function calculateLastWeek() {
   const today = dayjs();
   const lastDay = today.subtract(1, 'day'); // 昨天
   const firstDay = lastDay.subtract(6, 'day'); // 一周前
-  return [firstDay.format('YYYY-MM-DD'), lastDay.format('YYYY-MM-DD')];
+  return [ firstDay.format('YYYY-MM-DD'), lastDay.format('YYYY-MM-DD') ];
 }
 </script>
 
 <template>
   <div class="py-2 px-2.5" style="background-color: #f7f7f7">
-    <el-card shadow="hover" class="mb-2.5" style="border: none; margin-bottom: 10px">
-      <div class="flex justify-between">
-        <div class="flex gap-5 flex-wrap">
-          <div>
-            <span class="font-medium mr-0.5">报告类型 </span>
-            <el-select v-model="reportTypeSelect" @change="handleSelectChange" style="width: 90px">
-              <el-option label="周度" value="weekly" />
-              <el-option label="月度" value="monthly" />
-            </el-select>
-          </div>
-          <div>
-            <span class="font-medium mr-0.5">搜索词 </span>
-            <el-input
-              v-model="searchTermInp"
-              @keyup.enter="handleQueryChange"
-              :prefix-icon="Search"
-              placeholder="输入后回车查询"
-              clearable
-              @clear="handleSelectChange"
-              style="width: 240px" />
+    <div ref="topCard">
+      <el-card class="mb-2.5" shadow="hover" style="border: none; margin-bottom: 10px">
+        <div class="flex justify-between">
+          <div class="flex gap-5 flex-wrap">
+            <div>
+              <span class="font-medium mr-0.5">报告类型 </span>
+              <el-select v-model="reportTypeSelect" style="width: 90px" @change="handleSelectChange">
+                <el-option label="周度" value="weekly"/>
+                <el-option label="月度" value="monthly"/>
+              </el-select>
+            </div>
+            <div>
+              <span class="font-medium mr-0.5">搜索词 </span>
+              <el-input
+                  v-model="searchTermInp"
+                  :prefix-icon="Search"
+                  clearable
+                  placeholder="输入后回车查询"
+                  style="width: 240px"
+                  @clear="handleSelectChange"
+                  @keyup.enter="handleQueryChange"/>
+            </div>
+            <div>
+              <span class="font-medium mr-0.5">报告日期 </span>
+              <MonthRangePicker v-if="reportTypeSelect === 'monthly'" v-model="monthDate"/>
+              <WeekRangePicker v-else v-model="weekDate"/>
+            </div>
           </div>
-          <div>
-            <span class="font-medium mr-0.5">报告日期 </span>
-            <MonthRangePicker v-model="monthDate" v-if="reportTypeSelect === 'monthly'" />
-            <WeekRangePicker v-model="weekDate" v-else />
+          <div class="flex">
+            <el-button :icon="Refresh" circle @click="refreshTable"></el-button>
           </div>
         </div>
-        <div class="flex">
-          <el-button @click="refreshTable" :icon="Refresh" circle></el-button>
-        </div>
-      </div>
-    </el-card>
-    <el-card shadow="hover" style="border: none">
-      <div style="overflow: hidden; width: 100%; height: 950px" v-loading="tableLoading">
+      </el-card>
+    </div>
+    <el-card :body-style="{ height: tableHeight + 'px' }" shadow="hover" style="border: none;">
+      <div v-loading="tableLoading" class="w-full h-full">
         <vxe-grid v-bind="gridOptions">
           <template #toolbar_buttons></template>
           <template v-for="col in brandColumns" #[`${col.field}_default`]="{ row }">
             <div v-if="col.field === 'clickedItemName'">
-              <el-tooltip effect="dark" :content="row.clickedItemName" placement="top" :show-after="300">
+              <el-tooltip :content="row.clickedItemName" :show-after="300" effect="dark" placement="top">
                 <div class="line-text">
                   {{ row.clickedItemName }}
                 </div>
@@ -196,11 +204,11 @@ function calculateLastWeek() {
           </template>
           <template #pager>
             <vxe-pager
-              :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
-              v-model:current-page="tablePage.currentPage"
-              v-model:page-size="tablePage.pageSize"
-              :total="tablePage.total"
-              @page-change="handlePageChange">
+                v-model:current-page="tablePage.currentPage"
+                v-model:page-size="tablePage.pageSize"
+                :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
+                :total="tablePage.total"
+                @page-change="handlePageChange">
             </vxe-pager>
           </template>
         </vxe-grid>

+ 23 - 15
src/views/searchTerm/importPage/index.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script lang="ts" setup>
 /**
  * @Name: index.vue
  * @Description: 导入页
@@ -11,6 +11,7 @@ import { SUCCESS_CODE, WARNING_CODE } from '/@/utils/requestCode';
 import * as api from './api';
 import { VxeGridProps } from 'vxe-table';
 
+
 const upload = ref<UploadInstance>();
 const upBtnLoading = ref(false);
 const defaultLabel = ref('ASIN');
@@ -18,7 +19,7 @@ const filter = reactive({
   reportFilter: '',
   reportDateFilter: '',
   typeFilter: '',
-  variableFilter: '',
+  variableFilter: ''
 });
 
 const gridOptions = reactive<VxeGridProps>({
@@ -29,13 +30,13 @@ const gridOptions = reactive<VxeGridProps>({
   resizable: true,
   height: 900,
   toolbarConfig: {
-    custom: true,
+    custom: true
   },
   columns: [
     // { type: 'seq', width: 70 },
     // { field: 'name', title: 'Name' },
   ],
-  data: [],
+  data: []
 });
 
 /**
@@ -113,7 +114,7 @@ function processResponseData(data: any) {
     return {
       field: key,
       title,
-      minWidth,
+      minWidth
     };
   });
 
@@ -173,24 +174,31 @@ async function confirmUpload() {
         <!-- 想要不页面不跳动可以加72的高度 -->
         <div>
           <el-upload
-            ref="upload"
-            action="#"
-            :limit="1"
-            :show-file-list="false"
-            :auto-upload="true"
-            :on-exceed="handleExceed"
-            :http-request="handleCustomUpload">
+              ref="upload"
+              :auto-upload="true"
+              :http-request="handleCustomUpload"
+              :limit="1"
+              :on-exceed="handleExceed"
+              :show-file-list="false"
+              action="#">
             <template #trigger>
-              <el-button :loading="upBtnLoading" plain color="#6366f1" :icon="View">导入预览</el-button>
+              <el-button :icon="View" :loading="upBtnLoading" color="#6366f1" plain>导入预览</el-button>
             </template>
           </el-upload>
         </div>
-        <el-button plain round type="warning" :icon="Upload" @click="confirmUpload"> 确认导入 </el-button>
+        <el-button :icon="Upload" plain round type="warning" @click="confirmUpload"> 确认导入</el-button>
       </div>
     </el-card>
     <el-card shadow="hover" style="border: none">
       <div class="text-xl font-bold text-center font-sans subpixel-antialiased">导入预览</div>
-      <vxe-grid v-bind="gridOptions"></vxe-grid>
+      <vxe-grid v-bind="gridOptions">
+        <template #empty>
+          <p class="text-3xl w-full" style="color: red;">
+            该页面用来导入从后台下载的 Asin view 或 Brand view 数据
+          </p>
+          <p class="text-3xl w-full" style="color: red;">导入格式为csv格式!</p>
+        </template>
+      </vxe-grid>
     </el-card>
   </div>
 </template>

+ 17 - 7
src/views/searchTerm/rootWordManage/components/root-word-manage-table.vue

@@ -53,6 +53,8 @@ const rules = reactive<FormRules<typeof ruleForm>>({
 
 const searchTermTypeFilter = ref('all');
 const searchTermFilter = ref('');
+const sortFields = ref('');
+const isAscending = ref(false);
 const upload = ref<UploadInstance>();
 
 onMounted(() => {
@@ -105,7 +107,9 @@ async function fetchSearchTermList() {
     page: currentPage.value,
     limit: pageSize.value,
     searchTerm: searchTermFilter.value,
-    searchTerm_type: searchTermTypeFilter.value
+    searchTerm_type: searchTermTypeFilter.value,
+    sort_fields: sortFields.value,
+    isAscending: isAscending.value,
   };
   try {
     const response = await api.getSearchTermList(query);
@@ -308,6 +312,12 @@ function handleResponse(response: any) {
     ElMessage.error({ message: response.msg, plain: true });
   }
 }
+
+function handleSort(col: any) {
+  sortFields.value = col.prop;
+  isAscending.value = col.order === 'ascending';
+  fetchSearchTermList();
+}
 </script>
 
 <template>
@@ -360,14 +370,14 @@ function handleResponse(response: any) {
     </el-card>
     <!-- 表格 -->
     <el-card shadow="hover" style="border: none">
-      <div style="height: 800px">
-        <el-table :data="tableData" height="800" stripe style="width: 100%">
+      <div>
+        <el-table :data="tableData" @sort-change="handleSort" height="600" stripe style="width: 100%">
           <el-table-column align="center" type="index" width="60">
             <template #header>
               <span>序号</span>
             </template>
           </el-table-column>
-          <el-table-column align="center" label="添加日期" prop="add_date" sortable>
+          <el-table-column align="center" label="添加日期" prop="add_date" sortable="custom">
             <template #header>
               <el-icon style="top: 2px; margin-right: 3px">
                 <Calendar/>
@@ -378,7 +388,7 @@ function handleResponse(response: any) {
               <span class="font-medium">{{ row.add_date }}</span>
             </template>
           </el-table-column>
-          <el-table-column label="词根" prop="searchTerm" sortable>
+          <el-table-column label="词根" prop="searchTerm" sortable="custom">
             <template #header>
               <el-icon style="top: 2px; right: 2px">
                 <Key/>
@@ -390,7 +400,7 @@ function handleResponse(response: any) {
               <span v-else class="font-semibold">{{ row.searchTerm }}</span>
             </template>
           </el-table-column>
-          <el-table-column label="词根类型" prop="searchTerm_type" sortable>
+          <el-table-column label="词根类型" prop="searchTerm_type" sortable="custom">
             <template #header>
               <el-icon style="top: 2px; right: 2px">
                 <Coin/>
@@ -437,7 +447,7 @@ function handleResponse(response: any) {
             v-model:page-size="pageSize"
             :page-sizes="[20, 40, 50, 100]"
             :total="total"
-            layout="total, sizes, prev, pager, next"
+            layout="prev, pager, next, sizes, total"
             @size-change="handleSizeChange"
             @current-change="handleCurrentChange"/>
       </div>

+ 0 - 1
src/views/searchTerm/targetingSearchTerm/index.vue

@@ -212,7 +212,6 @@ async function fetchSearchTermData() {
             <vxe-pager
                 v-model:current-page="targetingPage.currentPage"
                 v-model:page-size="targetingPage.pageSize"
-                :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
                 :total="targetingPage.total"
                 @page-change="targetingPageChange">
             </vxe-pager>

+ 82 - 54
src/views/searchTerm/topSearchTermRank/index.vue

@@ -1,11 +1,11 @@
-<script setup lang="ts">
+<script lang="ts" setup>
 /**
  * @Name: index.vue
  * @Description: 搜索词-TopSearchTerm Rank
  * @Author: Cheney
  */
 
-import { Key, PictureRounded, Refresh, Search, TopRight } from '@element-plus/icons-vue';
+import { DataLine, Key, PictureRounded, Refresh, Search, TopRight } from '@element-plus/icons-vue';
 import { nextTick, onBeforeMount, ref, watch } from 'vue';
 import { useRouter } from 'vue-router';
 import { marketplaceIdEnum } from '/@/utils/marketplaceIdEnum';
@@ -16,14 +16,23 @@ import ColumnChart from '/src/views/searchTerm/topSearchTermRank/column-chart.vu
 import dayjs from 'dayjs';
 import WeekRangePicker from '/@/components/WeekRangePicker/index.vue';
 import MonthRangePicker from '/@/components/MonthRangePicker/index.vue';
+import { useCustomHeight } from '/@/utils/useCustomHeight';
+
+
+const titleContainer = ref();
+const queryContainer = ref();
+const heightObj = {
+  a: 32 + 13 + 40 + 70 + 40 + 48 + 95
+}
+const { tableHeight } = useCustomHeight(heightObj);
 
 const weekDate = ref([
   dayjs().subtract(2, 'week').day(0).format('YYYY-MM-DD'),
-  dayjs().subtract(1, 'week').day(6).format('YYYY-MM-DD'),
+  dayjs().subtract(1, 'week').day(6).format('YYYY-MM-DD')
 ]);
 const monthDate = ref([
   dayjs().subtract(2, 'month').startOf('month').format('YYYY-MM-DD'),
-  dayjs().subtract(0, 'month').startOf('month').format('YYYY-MM-DD'),
+  dayjs().subtract(0, 'month').startOf('month').format('YYYY-MM-DD')
 ]);
 const router = useRouter();
 const { tableData, total, currentPage, pageSize, handlePageChange } = usePagination(fetchTableData);
@@ -38,7 +47,7 @@ onBeforeMount(() => {
   fetchTableData();
 });
 
-watch([weekDate, monthDate], () => {
+watch([ weekDate, monthDate ], () => {
   fetchTableData();
 });
 
@@ -52,8 +61,27 @@ async function refreshTable() {
   await fetchTableData();
 }
 
-async function fetchTableData() {
+async function fetchTableData(isQuery = false) {
+  if (!validateSearchTermInput(searchTermInp.value)) {
+    if (searchTermInp.value.length == 0) {
+      return;
+    } else {
+      ElMessage.warning({ message: '搜索词只能输入数字和英文字母', plain: true });
+      return;
+    }
+  }
+  if (asinInp.value.length > 0 && !validateAsinInput(asinInp.value)) {
+    ElMessage.warning({ message: '不符合匹配规范', plain: true });
+    return;
+  }
+  // await fetchTableData();
+  
   tableLoading.value = true;
+  
+  if (isQuery) {
+    currentPage.value = 1;
+  }
+  
   const query = {
     page: currentPage.value,
     limit: pageSize.value,
@@ -62,7 +90,7 @@ async function fetchTableData() {
     report_type: reportTypeSelect.value,
     marketplace_Ids: marketplaceSelect.value,
     date_start: reportTypeSelect.value == 'weekly' ? weekDate.value[0] : monthDate.value[0],
-    date_end: reportTypeSelect.value == 'weekly' ? weekDate.value[1] : monthDate.value[1],
+    date_end: reportTypeSelect.value == 'weekly' ? weekDate.value[1] : monthDate.value[1]
   };
   try {
     const response = await getTopSearchTermTable(query);
@@ -122,109 +150,109 @@ function handleJump() {
 </script>
 
 <template>
-  <div class="mx-3">
+  <div ref="titleContainer" class="mx-3">
     <el-divider>
       <div class="font-bold text-xl">
         <el-icon style="top: 3px">
-          <DataLine />
+          <DataLine/>
         </el-icon>
         Top Search Term - Rank
       </div>
     </el-divider>
   </div>
-  <el-card class="mx-3 mb-2.5" v-loading="tableLoading" style="border: none">
+  <el-card v-loading="tableLoading" class="mx-3 mb-2.5" style="border: none">
     <!-- table筛选栏 -->
-    <div class="flex justify-between">
+    <div ref="queryContainer" class="flex justify-between">
       <div class="flex gap-5 flex-wrap">
         <div>
-          <span class="font-medium mr-0.5">市场 </span>
-          <el-select v-model="marketplaceSelect" @change="handleSelectChange" style="width: 90px">
+          <span class="font-medium mr-0.5">市 场 </span>
+          <el-select v-model="marketplaceSelect" style="width: 90px" @change="fetchTableData">
             <el-option
-              v-for="item in marketplaceOptions"
-              :disabled="item.disabled"
-              :key="item.value"
-              :value="item.value"
-              :label="item.label" />
+                v-for="item in marketplaceOptions"
+                :key="item.value"
+                :disabled="item.disabled"
+                :label="item.label"
+                :value="item.value"/>
           </el-select>
         </div>
         <div>
           <span class="font-medium mr-0.5">报告类型 </span>
-          <el-select v-model="reportTypeSelect" @change="handleSelectChange" style="width: 90px">
-            <el-option label="周度" value="weekly" />
-            <el-option label="月度" value="monthly" />
+          <el-select v-model="reportTypeSelect" style="width: 90px" @change="fetchTableData">
+            <el-option label="周度" value="weekly"/>
+            <el-option label="月度" value="monthly"/>
           </el-select>
         </div>
         <div>
           <span class="font-medium mr-0.5">搜索词 </span>
           <el-input
-            v-model="searchTermInp"
-            @keyup.enter="handleQueryChange"
-            :prefix-icon="Search"
-            placeholder="输入后回车查询"
-            clearable
-            @clear="handleSelectChange"
-            style="width: 240px" />
+              v-model="searchTermInp"
+              :prefix-icon="Search"
+              clearable
+              placeholder="请输入"
+              style="width: 240px" />
         </div>
         <div>
           <span class="font-medium mr-0.5">ASIN </span>
           <el-input
-            v-model="asinInp"
-            @keyup.enter="handleQueryChange"
-            :prefix-icon="Search"
-            placeholder="输入后回车查询"
-            clearable
-            @clear="handleSelectChange"
-            style="width: 180px" />
+              v-model="asinInp"
+              :prefix-icon="Search"
+              clearable
+              placeholder="请输入"
+              style="width: 180px" />
         </div>
         <div>
           <span class="font-medium mr-0.5">报告日期 </span>
-          <MonthRangePicker v-model="monthDate" v-if="reportTypeSelect === 'monthly'" />
-          <WeekRangePicker v-model="weekDate" v-else />
+          <MonthRangePicker v-if="reportTypeSelect === 'monthly'" v-model="monthDate"/>
+          <WeekRangePicker v-else v-model="weekDate"/>
         </div>
       </div>
       <div class="flex">
-        <el-button type="primary" plain @click="handleJump" :icon="TopRight">搜索词管理</el-button>
-        <el-button @click="refreshTable" :icon="Refresh" circle></el-button>
+        <el-button :icon="Search" type="primary" @click="fetchTableData(true)">查 询</el-button>
+        <el-button :icon="Refresh" @click="refreshTable">刷 新</el-button>
       </div>
+      
+    </div>
+    <div class="mt-6">
+      <el-button :icon="TopRight" plain type="primary" @click="handleJump">搜索词管理</el-button>
     </div>
     <!-- table -->
-    <el-card shadow="never" class="mt-5">
-      <div style="height: 100%; overflow: auto">
-        <el-table :data="tableData" height="920" stripe style="width: 100%">
-          <el-table-column fixed prop="searchTerm" label="搜索词" width="260">
+    <el-card class="mt-5" shadow="never">
+      <div>
+        <el-table :data="tableData" :height="tableHeight" stripe style="width: 100%">
+          <el-table-column fixed label="搜索词" prop="searchTerm" width="260">
             <template #header>
               <el-icon style="top: 2px; margin-right: 3px">
-                <Key />
+                <Key/>
               </el-icon>
               <span>搜索词</span>
             </template>
             <template #default="{ row }">
-              <el-link :underline="false" target="_blank" style="color: #5a6fc0">
+              <el-link :underline="false" style="color: #5a6fc0" target="_blank">
                 {{ row.searchTerm }}
               </el-link>
             </template>
           </el-table-column>
-          <el-table-column prop="rank" label="搜索词搜索排名" align="center">
+          <el-table-column align="center" label="搜索词搜索排名" prop="rank">
             <template #header>
               <el-icon style="top: 2px; margin-right: 4px">
-                <PictureRounded />
+                <PictureRounded/>
               </el-icon>
               <span>Tendency</span>
             </template>
             <template #default="{ row }">
-              <ColumnChart :rowData="row" />
+              <ColumnChart :rowData="row"/>
             </template>
           </el-table-column>
         </el-table>
       </div>
       <div class="mt-3.5 flex justify-end">
         <el-pagination
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[10, 20, 30, 50, 100, 200]"
-          layout="sizes, prev, pager, next, total"
-          :total="total"
-          @change="handlePageChange" />
+            v-model:current-page="currentPage"
+            v-model:page-size="pageSize"
+            :page-sizes="[10, 20, 30, 50, 100, 200]"
+            :total="total"
+            layout="prev, pager, next, sizes, total"
+            @change="handlePageChange"/>
       </div>
     </el-card>
   </el-card>

+ 140 - 119
src/views/searchTerm/topSearchTermTable/index.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script lang="ts" setup>
 /**
  * @Name: index.vue
  * @Description: 搜索词-TopSearchTerm Table
@@ -14,9 +14,12 @@ import { useRouter } from 'vue-router';
 import { ElMessage } from 'element-plus';
 import dayjs from 'dayjs';
 import enLocale from 'element-plus/es/locale/lang/en';
+import { useTableHeight } from '/@/utils/useTableHeight';
+import { useCustomHeight } from '/@/utils/useCustomHeight';
+
 
 const router = useRouter();
-const { tableData, total, currentPage, pageSize, handlePageChange } = usePagination(fetchTableData);
+const { tableData, total, currentPage, pageSize } = usePagination(fetchTableData);
 const marketplaceSelect = ref(marketplaceIdEnum[0].value); // 当前只有美国区 默认第一个为美国
 const marketplaceOptions = marketplaceIdEnum;
 const reportTypeSelect = ref('weekly');
@@ -27,8 +30,15 @@ const downloadLoading = ref(false);
 const date = ref(calculateLastWeek()); // 设置默认日期为上周的周日到周六
 const dateDimension = ref(date.value[0]);
 
+const titleContainer = ref();
+const queryContainer = ref();
+const heightObj = {
+  a: 32 + 13 + 40 + 70 + 40 + 48 + 95
+}
+const { tableHeight } = useCustomHeight(heightObj);
+
 onBeforeMount(() => {
-  pageSize.value = 21; // 将usePagination中的pageSize默认修改每页显示21条
+  pageSize.value = 7; // 将usePagination中的pageSize默认修改每页显示21条
   fetchTableData();
 });
 
@@ -59,7 +69,7 @@ function calculateLastWeek() {
   const today = dayjs();
   const lastSaturday = today.subtract(today.day() + 1, 'day'); // 上周六
   const lastSunday = lastSaturday.subtract(6, 'day'); // 上周日
-  return [lastSunday.format('YYYY-MM-DD'), lastSaturday.format('YYYY-MM-DD')];
+  return [ lastSunday.format('YYYY-MM-DD'), lastSaturday.format('YYYY-MM-DD') ];
 }
 
 /**
@@ -72,7 +82,7 @@ function calculateEndDate(startDate: string) {
 
 async function refreshTable() {
   currentPage.value = 1;
-  pageSize.value = 21;
+  pageSize.value = 7;
   asinInp.value = '';
   searchTermInp.value = '';
   reportTypeSelect.value = 'weekly';
@@ -80,17 +90,22 @@ async function refreshTable() {
   await fetchTableData();
 }
 
-async function fetchTableData() {
+async function fetchTableData(isQuery = false) {
   tableLoading.value = true;
+
+  if (isQuery) {
+    currentPage.value = 1;
+  }
+
   const query = {
     page: currentPage.value,
-    limit: pageSize.value,
+    limit: pageSize.value * 3,
     asin: asinInp.value,
     search_term: searchTermInp.value,
     report_type: reportTypeSelect.value,
     marketplace_Ids: marketplaceSelect.value,
     date_start: date.value[0],
-    date_end: date.value[1],
+    date_end: date.value[1]
   };
   try {
     const response = await getTopSearchTermTable(query);
@@ -109,9 +124,9 @@ async function fetchTableData() {
 /**
  * 下拉框值改变和input清空事件触发
  */
-async function handleSelectChange() {
+function handleSelectChange() {
   calculateDate();
-  await fetchTableData();
+  // await fetchTableData();
 }
 
 /**
@@ -165,12 +180,12 @@ async function handleDownload() {
       date_end: date.value[1],
       search_term: searchTermInp.value,
       marketplace_Ids: marketplaceSelect.value,
-      report_type: reportTypeSelect.value,
+      report_type: reportTypeSelect.value
     };
 
     const response = await postDownload(body);
 
-    const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+    const blob = new Blob([ response.data ], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
 
     // 创建一个临时 URL
     const url = window.URL.createObjectURL(blob);
@@ -181,7 +196,7 @@ async function handleDownload() {
 
     // 设置文件名
     const currentTime = dayjs().format('YYYY-MM-DD_HH_mm_ss');
-    const filename = `TopSearchTerm_${currentTime}.xlsx`;
+    const filename = `TopSearchTerm_${ currentTime }.xlsx`;
 
     link.setAttribute('download', filename);
 
@@ -202,151 +217,156 @@ async function handleDownload() {
   }
 }
 
-function getTagStyle(clickShareRank: number): Record<string, string> {
-  switch (clickShareRank) {
-    case 1:
-      return { backgroundColor: '#fbbf24', color: '#fff', border: '1px solid #fbbf24' }; // 金色
-    case 2:
-      return { backgroundColor: '#C0C0C0', color: '#fff', border: '1px solid #C0C0C0' }; // 银色
-    case 3:
-      return { backgroundColor: '#CD7F32', color: '#fff', border: '1px solid #CD7F32' }; // 铜色
-    default:
-      return { backgroundColor: '#f0f0f0', color: '#000', border: '1px solid #e0e0e0' };
-  }
-}
+// function getTagStyle(clickShareRank: number): Record<string, string> {
+//   switch (clickShareRank) {
+//     case 1:
+//       return { backgroundColor: '#fbbf24', color: '#fff', border: '1px solid #fbbf24' }; // 金色
+//     case 2:
+//       return { backgroundColor: '#C0C0C0', color: '#fff', border: '1px solid #C0C0C0' }; // 银色
+//     case 3:
+//       return { backgroundColor: '#CD7F32', color: '#fff', border: '1px solid #CD7F32' }; // 铜色
+//     default:
+//       return { backgroundColor: '#f0f0f0', color: '#000', border: '1px solid #e0e0e0' };
+//   }
+// }
 
 function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
   // 每三个合并为一个单元格
   if (columnIndex >= 0 && columnIndex <= 4) {
     if (rowIndex % 3 === 0) {
-      return [3, 1]; // 跨越三行
+      return [ 3, 1 ]; // 跨越三行
     } else {
-      return [0, 0]; // 被合并的单元格
+      return [ 0, 0 ]; // 被合并的单元格
     }
   }
-  return [1, 1];
+  return [ 1, 1 ];
+}
+
+async function handlePageChange(newPage: number, newSize: number) {
+  currentPage.value = newPage;
+  pageSize.value = newSize;
+  await fetchTableData();
 }
 </script>
 
 <template>
-  <div class="mx-3">
+  <div ref="titleContainer" class="mx-3">
     <el-divider>
       <div class="font-bold text-xl">
         <el-icon style="top: 3px">
-          <DataAnalysis />
+          <DataAnalysis/>
         </el-icon>
         Top Search Term - Table
       </div>
     </el-divider>
   </div>
-  <el-card class="mx-3 mb-2.5" v-loading="tableLoading" style="border: none;">
+  <el-card v-loading="tableLoading" class="mx-3 mb-2.5" style="border: none;">
     <!-- table筛选栏 -->
-    <div class="flex justify-between">
+    <div ref="queryContainer" class="flex justify-between">
       <div class="flex gap-5 flex-wrap">
         <div>
-          <span class="font-medium mr-0.5">市场 </span>
-          <el-select v-model="marketplaceSelect" @change="handleSelectChange" style="width: 90px">
+          <span class="font-medium mr-0.5">市 场 </span>
+          <el-select v-model="marketplaceSelect" style="width: 90px" @change="handleSelectChange">
             <el-option
-              v-for="item in marketplaceOptions"
-              :disabled="item.disabled"
-              :key="item.value"
-              :value="item.value"
-              :label="item.label" />
+                v-for="item in marketplaceOptions"
+                :key="item.value"
+                :disabled="item.disabled"
+                :label="item.label"
+                :value="item.value"/>
           </el-select>
         </div>
         <div>
           <span class="font-medium mr-0.5">报告类型 </span>
-          <el-select v-model="reportTypeSelect" @change="handleSelectChange" style="width: 90px">
-            <el-option label="周度" value="weekly" />
-            <el-option label="月度" value="monthly" />
+          <el-select v-model="reportTypeSelect" style="width: 90px" @change="handleSelectChange">
+            <el-option label="周度" value="weekly"/>
+            <el-option label="月度" value="monthly"/>
           </el-select>
         </div>
         <div>
           <span class="font-medium mr-0.5">搜索词 </span>
           <el-input
-            v-model="searchTermInp"
-            @keyup.enter="handleQueryChange"
-            :prefix-icon="Search"
-            placeholder="输入后回车查询"
-            clearable
-            @clear="handleSelectChange"
-            style="width: 240px" />
+              v-model="searchTermInp"
+              :prefix-icon="Search"
+              clearable
+              placeholder="请输入"
+              style="width: 240px" />
         </div>
         <div>
           <span class="font-medium mr-0.5">ASIN </span>
           <el-input
-            v-model="asinInp"
-            @keyup.enter="handleQueryChange"
-            :prefix-icon="Search"
-            placeholder="输入后回车查询"
-            clearable
-            @clear="handleSelectChange"
-            style="width: 180px" />
+              v-model="asinInp"
+              :prefix-icon="Search"
+              clearable
+              placeholder="请输入"
+              style="width: 180px" />
         </div>
         <div>
           <span class="font-medium mr-0.5">报告日期 </span>
-          <el-config-provider :locale="enLocale">
-            <el-date-picker
-              v-if="reportTypeSelect === 'weekly'"
-              v-model="dateDimension"
-              type="week"
-              value-format="YYYY-MM-DD"
-              :format="`${date[0]} To ${date[1]}`"
-              :popper-options="{ placement: 'bottom-end' }"
-              :disabled-date="(time: Date) => time > new Date()"
-              :clearable="false" />
+          <el-config-provider v-if="reportTypeSelect === 'weekly'" :locale="enLocale">
             <el-date-picker
+                v-model="dateDimension"
+                :clearable="false"
+                :disabled-date="(time: Date) => time > new Date()"
+                :format="`${date[0]} To ${date[1]}`"
+                :popper-options="{ placement: 'bottom-end' }"
+                type="week"
+                value-format="YYYY-MM-DD"/>
+          </el-config-provider>
+          <el-date-picker
               v-else
               v-model="dateDimension"
-              type="month"
-              value-format="YYYY-MM"
+              :clearable="false"
+              :disabled-date="(time: Date) => time > new Date()"
               :format="`${date[0]} To ${date[1]}`"
               :popper-options="{ placement: 'bottom-end' }"
-              :disabled-date="(time: Date) => time > new Date()"
-              :clearable="false">
-              <template #default> 123</template>
-            </el-date-picker>
-          </el-config-provider>
+              type="month"
+              value-format="YYYY-MM">
+            <!--<template #default> 123</template>-->
+          </el-date-picker>
         </div>
       </div>
       <div class="flex">
-        <el-button type="primary" plain @click="handleJump" :icon="TopRight">搜索词管理</el-button>
-        <el-button
-          type="success"
-          plain
-          @click="handleDownload"
+        <el-button :icon="Search" type="primary" @click="fetchTableData(true)">查 询</el-button>
+        <el-button :icon="Refresh" @click="refreshTable">刷 新</el-button>
+      </div>
+    </div>
+    <div class="mt-6">
+      <el-button :icon="TopRight" plain type="primary" @click="handleJump">搜索词管理</el-button>
+      <el-button
+          :disabled="!tableData.length"
           :icon="Download"
-          round
           :loading="downloadLoading"
-          :disabled="!tableData.length"
-          >下载表格
-        </el-button>
-        <el-button @click="refreshTable" :icon="Refresh" circle></el-button>
-      </div>
+          plain
+          round
+          type="success"
+          @click="handleDownload"
+      >下载表格
+      </el-button>
     </div>
     <!-- table -->
-    <el-card shadow="never" class="mt-5">
-      <div style="height: 100%; overflow: auto">
-        <el-table :data="tableData" :span-method="arraySpanMethod" height="920" stripe style="width: 100%">
+    <el-card class="mt-5" shadow="never">
+      <div>
+        <el-table :data="tableData" :span-method="arraySpanMethod" :height="tableHeight" stripe style="width: 100%">
           <!-- 保持索引是1, 2, 3的顺序 不会收到合并单元格的影响 -->
-          <el-table-column fixed type="index" width="50" :index="(index) => Math.floor(index / 3) + 1" />
-          <el-table-column prop="searchTerm" label="搜索词" width="260">
+          <el-table-column :index="(index) => Math.floor(index / 3) + (currentPage - 1) * pageSize + 1" fixed
+                           label="No." type="index" width="80"/>
+          <el-table-column label="搜索词" prop="searchTerm">
             <template #header>
               <el-icon style="top: 2px; margin-right: 3px">
-                <Key />
+                <Key/>
               </el-icon>
               <span>搜索词</span>
             </template>
             <template #default="{ row }">
-              <el-link :underline="false" target="_blank" style="color: #5a6fc0"
-                >{{ row.searchTerm }}
+              <el-link :underline="false" style="font-size: 18px;" target="_blank" type="primary">
+                {{ row.searchTerm }}
               </el-link>
             </template>
           </el-table-column>
-          <el-table-column prop="searchFrequencyRank" label="搜索词搜索排名" align="center" width="150">
+          <el-table-column align="center" label="搜索词搜索排名" prop="searchFrequencyRank" width="90">
             <template #header>
               <el-icon style="top: 2px; margin-right: 4px">
-                <Rank />
+                <Rank/>
               </el-icon>
               <span>搜索词搜索排名</span>
             </template>
@@ -354,10 +374,10 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
               <span class="font-medium">{{ row.searchFrequencyRank }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="clickShareSummary" label="点击分享率(SUM)" align="center" width="150">
+          <el-table-column align="center" label="点击分享率(SUM)" prop="clickShareSummary" width="90">
             <template #header>
               <el-icon style="top: 2px; margin-right: 4px">
-                <Star />
+                <Star/>
               </el-icon>
               <span>点击分享率汇总</span>
             </template>
@@ -365,10 +385,10 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
               <span class="font-medium">{{ row.clickShareSummary }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="conversionShareSummary" label="转化分享率(SUM)" align="center" width="150">
+          <el-table-column align="center" label="转化分享率(SUM)" prop="conversionShareSummary" width="90">
             <template #header>
               <el-icon style="top: 2px; margin-right: 4px">
-                <Star />
+                <Star/>
               </el-icon>
               <span>转化分享率汇总</span>
             </template>
@@ -376,10 +396,10 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
               <span class="font-medium">{{ row.conversionShareSummary }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="clickedAsin" label="Asin" align="center">
+          <el-table-column align="center" label="Asin" prop="clickedAsin" width="160">
             <template #header>
               <el-icon style="top: 2px; margin-right: 5px">
-                <Goods />
+                <Goods/>
               </el-icon>
               <span>Asin</span>
             </template>
@@ -395,16 +415,17 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
               <!--</div>-->
             </template>
           </el-table-column>
-          <el-table-column prop="clickedItemName" label="标题">
+          <el-table-column label="标 题" prop="clickedItemName">
             <template #header>
               <el-icon style="top: 2px; margin-right: 5px">
-                <Reading />
+                <Reading/>
               </el-icon>
-              <span>标题</span>
+              <span>标 题</span>
             </template>
             <template #default="{ row }">
               <div class="text-sm text-left">
-                <el-tooltip class="box-item" effect="dark" :content="row.clickedItemName" placement="top" :show-after="500">
+                <el-tooltip :content="row.clickedItemName" :show-after="500" class="box-item" effect="dark"
+                            placement="top">
                   <div class="tooltip-text">
                     {{ row.clickedItemName }}
                   </div>
@@ -412,23 +433,23 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
               </div>
             </template>
           </el-table-column>
-          <el-table-column prop="clickShareRank" label="点击分享率排名" align="center" width="150">
+          <el-table-column align="center" label="点击分享率排名" prop="clickShareRank" width="90">
             <template #header>
               <el-icon style="top: 2px; margin-right: 4px">
-                <Medal />
+                <Medal/>
               </el-icon>
               <span>点击分享率排名</span>
             </template>
             <template #default="{ row }">
-              <el-tag :style="getTagStyle(row.clickShareRank)">
-                {{ row.clickShareRank }}
-              </el-tag>
+              <!--<el-tag :style="getTagStyle(row.clickShareRank)">-->
+              {{ row.clickShareRank }}
+              <!--</el-tag>-->
             </template>
           </el-table-column>
-          <el-table-column prop="clickShare" align="center" label="点击分享率">
+          <el-table-column align="center" label="点击分享率" prop="clickShare" width="90">
             <template #header>
               <el-icon style="top: 2px; margin-right: 4px">
-                <Pointer />
+                <Pointer/>
               </el-icon>
               <span>点击分享率</span>
             </template>
@@ -436,10 +457,10 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
               <span class="font-semibold">{{ row.clickShare }}</span>
             </template>
           </el-table-column>
-          <el-table-column prop="conversionShare" align="center" label="转化分享率">
+          <el-table-column align="center" label="转化分享率" prop="conversionShare" width="90">
             <template #header>
               <el-icon style="top: 2px; margin-right: 5px">
-                <Switch />
+                <Switch/>
               </el-icon>
               <span>转化分享率</span>
             </template>
@@ -451,12 +472,12 @@ function arraySpanMethod({ row, column, rowIndex, columnIndex }) {
       </div>
       <div class="mt-3.5 flex justify-end">
         <el-pagination
-          v-model:current-page="currentPage"
-          v-model:page-size="pageSize"
-          :page-sizes="[21, 42, 72, 102, 132, 162]"
-          layout="sizes, prev, pager, next, total"
-          :total="total"
-          @change="handlePageChange" />
+            v-model:current-page="currentPage"
+            v-model:page-size="pageSize"
+            :page-sizes="[7, 14, 21, 28, 35]"
+            :total="Math.floor(total / 3)"
+            layout="prev, pager, next, sizes, total"
+            @change="handlePageChange"/>
       </div>
     </el-card>
   </el-card>

Некоторые файлы не были показаны из-за большого количества измененных файлов