Эх сурвалжийг харах

✨ feat: 合计行数据对比功能

WanGxC 1 жил өмнө
parent
commit
cf7c5258df

+ 1 - 1
.prettierrc.js

@@ -2,7 +2,7 @@ module.exports = {
 	singleAttributePerLine: false,
 	htmlWhitespaceSensitivity: 'ignore',
 	// 一行最多多少个字符
-	printWidth: 150,
+	printWidth: 180,
 	// 指定每个缩进级别的空格数
 	tabWidth: 2,
 	// 使用制表符而不是空格缩进行

+ 36 - 235
src/views/demo/index.vue

@@ -1,247 +1,48 @@
 <template>
-  <!-- <fs-page>
-    <fs-crud ref="crudRef" v-bind="crudBinding" />
-  </fs-page> -->
-  <el-upload
-    v-model:file-list="fileList"
-    action="#"
-    method="post"
-    :data="{ profileId: 'xxxx' }"
-    multiple
-    :on-progress="onProgress"
-    :auto-upload="true"
-    :on-success="onSuccess"
-    :http-request="submit">
-    <el-button type="primary">Click to upload</el-button>
-  </el-upload>
-  <el-button @click="submit">上传</el-button>
 
-  <el-card>
-    <div style="display: flex">
-      <div style="width: 50%">
-        <button @click="handleSelectedItems">获取选中项</button>
-        <div class="demo-collapse">
-          <el-collapse v-model="activeNames">
-            <el-collapse-item v-for="(item, index) in data" :key="item.parentAsin" :name="String(index)">
-              <template #title>
-                <el-checkbox v-model="item.checked" @click.stop="stopOpen" @change="checkAll(item, item.checked)">{{ item.parentAsin }}</el-checkbox>
-                <el-tag style="margin-left: 8px" effect="plain" size="small" round>{{ item.num }}ASIN</el-tag>
-              </template>
-              <ul style="padding-left: 20px">
-                <li v-for="child in item.childAsin" :key="child.asin">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px">
-                    <el-checkbox v-model="child.checked" @change="checkSingle(item)"></el-checkbox>
-                    <!-- <img :src="child.image" style="width: 50px; height: 50px; margin-right: 10px" /> -->
-                    <div>
-                      <span>{{ child.Title }}</span>
-                      <span>{{ child.asin }}</span>
-                    </div>
-                  </div>
-                </li>
-              </ul>
-            </el-collapse-item>
-          </el-collapse>
-        </div>
-      </div>
-
-      <div style="width: 50%">
-        <!-- 在右侧面板的上方或下方添加这个按钮 -->
-        <button @click="removeSelectedItems">删除选中项</button>
-        <button @click="removeAllItems">删除所有</button>
-
-        <div class="demo-collapse">
-          <el-collapse v-model="activeNames">
-            <el-collapse-item v-for="(item, index) in selectedData" :key="item.parentAsin" :name="String(index)">
-              <template #title>
-                <el-checkbox v-model="item.checked" @click.stop="stopOpen" @change="checkAll(item, item.checked)">{{ item.parentAsin }}</el-checkbox>
-                <el-tag style="margin-left: 8px" effect="plain" size="small" round>{{ item.num }}ASIN</el-tag>
-              </template>
-              <ul style="padding-left: 20px">
-                <li v-for="child in item.childAsin" :key="child.asin">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px">
-                    <el-checkbox v-model="child.checked" @change="checkSingle(item)"></el-checkbox>
-                    <!-- <img :src="child.image" style="width: 50px; height: 50px; margin-right: 10px" /> -->
-                    <div>
-                      <span>{{ child.Title }}</span>
-                      <span>{{ child.asin }}</span>
-                    </div>
-                  </div>
-                </li>
-              </ul>
-            </el-collapse-item>
-          </el-collapse>
-        </div>
-      </div>
-    </div>
-  </el-card>
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted, computed } from 'vue'
-import { useFs } from '@fast-crud/fast-crud'
-import { createCrudOptions } from './crud'
-import { request } from '/@/utils/service'
-import type { UploadProps, UploadUserFile, UploadFile, UploadFiles, UploadProgressEvent } from 'element-plus'
-
-const data = ref([
-  {
-    parentAsin: '1ParentASIN',
-    checked: false,
-    childAsin: [
-      { asin: '1childASIN-1', image: 'http://xxxxxx.jpg', Title: '这是1childASIN-1', checked: false },
-      { asin: '1childASIN-2', image: 'http://xxxx.jpg', Title: '这是1childASIN-2', checked: false },
-    ],
-    num: 2,
-  },
-  {
-    parentAsin: '2ParentASIN',
-    checked: false,
-    childAsin: [
-      { asin: '2childASIN-1', image: 'http://xxxxx.jpg', Title: '这是2childASIN-1', checked: false },
-      { asin: '2childASIN-2', image: 'http://xxx.jpg', Title: '这是2childASIN-2', checked: false },
-    ],
-    num: 2,
-  },
-])
-
-const activeNames = ref(data.value.map((_, index) => String(index)))
-
-function stopOpen() {
-  console.log(1213)
-}
-
-const checkAll = (parent, checked) => {
-  // 当选中或取消选中父级复选框时
-  parent.childAsin.forEach((child) => {
-    child.checked = checked
-  })
-}
-
-function checkSingle(parent) {
-  // 当选中或取消选中单个子项复选框时
-  const allChecked = parent.childAsin.every((child) => child.checked)
-  parent.checked = allChecked
-}
-
-function getSelectedItems() {
-  // 添加用于获取所有选中项的方法
-  const selectedItems = []
-  data.value.forEach((parentItem) => {
-    if (parentItem.checked) {
-      // 如果父项被选中,添加父项的值,并包含所有子项的完整数据
-      const children = parentItem.childAsin.map((childItem) => {
-        return { ...childItem } // 复制整个childItem对象
-      })
-      selectedItems.push({ parentAsin: parentItem.parentAsin, childAsin: children })
-    } else {
-      // 如果父项未被选中,仅添加被选中的子项的完整数据
-      const selectedChildren = parentItem.childAsin
-        .filter((childItem) => childItem.checked)
-        .map((childItem) => {
-          return { ...childItem } // 复制整个childItem对象
-        })
-      if (selectedChildren.length > 0) {
-        selectedItems.push({ parentAsin: parentItem.parentAsin, childAsin: selectedChildren })
-      }
-    }
-  })
-  return selectedItems
-}
-
-const selectedData = ref([])
-
-function handleSelectedItems() {
-  // 获取所有选中项的深拷贝并取消勾选状态
-  const newSelectedItems = getSelectedItems().map(item => ({
-    ...item,
-    checked: false, // 取消父项勾选状态
-    num: item.childAsin.length, // 更新子项数量
-    childAsin: item.childAsin.map(child => ({ ...child, checked: false })), // 取消子项勾选状态
-  }));
-
-  // 更新selectedData以包含新选中的项,如果项已存在,则合并子项,并确保不重复
-  newSelectedItems.forEach(newItem => {
-    const existingItemIndex = selectedData.value.findIndex(item => item.parentAsin === newItem.parentAsin);
-    if (existingItemIndex !== -1) {
-      // 合并子项,并确保不重复添加相同的子项
-      const existingChildren = selectedData.value[existingItemIndex].childAsin;
-      const newChildren = newItem.childAsin;
-      const mergedChildren = [...existingChildren];
-      newChildren.forEach(newChild => {
-        if (!mergedChildren.some(child => child.asin === newChild.asin)) {
-          mergedChildren.push(newChild);
+import { ref, onMounted, reactive } from 'vue'
+import { VXETable } from 'vxe-table'
+
+const gridOptions = reactive({
+  border: true,
+  showFooter: true,
+  columns: [
+    { type: 'seq', width: 60 },
+    { field: 'name', title: 'Name' },
+    { field: 'sex', title: 'Sex' },
+    { field: 'num', title: 'Number', slots: { footer: 'num_footer' } },
+    { field: 'age', title: 'Age' },
+    { field: 'address', title: 'Address' },
+  ],
+  data: [
+    { id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, num: 234, address: 'test abc' },
+    { id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, num: 34, address: 'Guangzhou' },
+    { id: 10003, name: 'Test3', role: 'PM', sex: '0', age: 32, num: 12, address: 'Shanghai' },
+  ],
+  footerMethod({ columns, data }) {
+    return [
+      columns.map(column => {
+        if (column.type === 'seq') {
+          return '合计'
+        } else if (['num'].includes(column.field)) {
+          return sumNum(data, column.field)
         }
-      });
-
-      // 更新现有项的子项和子项数量
-      selectedData.value[existingItemIndex].childAsin = mergedChildren;
-      selectedData.value[existingItemIndex].num = mergedChildren.length; // 更新子项数量
-    } else {
-      // 如果不存在相同的父Asin,则添加新项
-      selectedData.value.push(newItem);
-    }
-  });
-
-  // 清除原始数据的选中状态
-  clearSelections();
-}
-
-
-// 清除所有选中状态的辅助函数
-function clearSelections() {
-  data.value.forEach((parentItem) => {
-    parentItem.checked = false // 取消父项的选中状态
-    parentItem.childAsin.forEach((childItem) => {
-      childItem.checked = false // 取消子项的选中状态
-    })
-  })
-}
-
-function removeSelectedItems() {
-  // 过滤掉所有被选中的项
-  selectedData.value = selectedData.value.filter((parentItem) => {
-    // 过滤掉父项下所有被选中的子项
-    parentItem.childAsin = parentItem.childAsin.filter((childItem) => !childItem.checked)
-    // 仅保留未被完全移除的父项(即至少有一个子项未被选中)
-    return parentItem.childAsin.length > 0
-  })
-}
-
-// 删除所有selectData的数据
-function removeAllItems() {
-  selectedData.value.splice(0)
-}
-
-const fileList = ref<UploadUserFile[]>([])
-const onProgress = (evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
-  console.log(evt)
-  console.log(uploadFile)
-}
-const onSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
-  console.log(response)
-  console.log(uploadFile)
-  console.log(uploadFiles)
-}
+        return '-'
+      })
+    ]
+  },
+})
 
-const submit = () => {
-  const formData = new FormData()
-  formData.append('file', fileList.value[0].raw)
-  formData.append('profileId', 'xxxx')
-  return request({
-    url: 'http://127.0.0.1:8003/api/amazon/assets/upload/',
-    headers: {
-      'Content-Type': 'multipart/form-data',
-    },
-    method: 'post',
-    data: formData,
+const sumNum = (list, field) => {
+  let count = 0
+  list.forEach(item => {
+    count += Number(item[field])
   })
+  return count
 }
-
-const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions })
-
-onMounted(async () => {
-  crudExpose.doRefresh()
-})
 </script>
 
 <style scoped></style>

+ 9 - 10
src/views/productCenter/productList/components/CustomCell/index.vue

@@ -5,14 +5,13 @@
       {{ formatTotalSales(value) }}
     </div> -->
     <div>
-      <!-- 默认处理 -->
       {{ value }}
-      <!-- 根据 prevValue 的值和 isCompare 调整显示内容 -->
-      <div v-if="isCompare" class="prev-value" :style="{ color: prevValue > 0 ? 'green' : prevValue < 0 ? 'red' : 'black' }">
-        <el-icon v-if="prevValue > 0"><Top /></el-icon>
-        <el-icon v-else-if="prevValue < 0"><Bottom /></el-icon>
-        <!-- 显示 prevValue 值,根据情况加上百分号 -->
-        {{ prevValue !== undefined ? (prevValue === null || prevValue === 0 ? '0%' : (prevValue < 0 ? '-' : '') + Math.abs(prevValue) + '%') : '' }}
+      <!-- 根据 gapValue 的值和 isCompare 调整显示内容 -->
+      <div v-if="isCompare" :style="{ color: gapValue > 0 ? '#59b939' : gapValue < 0 ? '#ee7973' : 'black' }">
+        <el-icon v-if="gapValue > 0"><Top /></el-icon>
+        <el-icon v-else-if="gapValue < 0"><Bottom /></el-icon>
+        <!-- 显示 gapValue 值,根据情况加上百分号 -->
+        {{ gapValue !== undefined ? (gapValue === null || gapValue === 0 ? '0%' : (gapValue < 0 ? '-' : '') + Math.abs(gapValue) + '%') : '' }}
       </div>
     </div>
   </div>
@@ -29,8 +28,8 @@ const props = defineProps({
 })
 
 // 计算 'gap' 值
-const prevValue = computed(() => {
-  const prevField = `gap${props.field.charAt(0).toUpperCase()}${props.field.slice(1)}` // 构建对应的 prev 前缀字段名称
-  return props.row[prevField] // 返回行数据中对应的 gap 值
+const gapValue = computed(() => {
+  const gapField = `gap${props.field.charAt(0).toUpperCase()}${props.field.slice(1)}` // 构建对应的 gap 前缀字段名称
+  return props.row[gapField] // 返回行数据中对应的 gap 值
 })
 </script>

+ 26 - 0
src/views/productCenter/productList/components/CustomFooterCell/index.vue

@@ -0,0 +1,26 @@
+<template>
+  <div>
+    <!-- 显示合计,这个无条件显示 -->
+    <div v-if="columnIndex === 0">
+      <span>合计</span>
+    </div>
+    <!-- 显示总值,当 totalValue 为 null 或 0 时显示 '0', 如果是 undefined 则不显示 -->
+    <div>{{ totalValue === 0 || totalValue === null ? '0' : totalValue }}</div>
+    <!-- 当 isCompare 为 true 时,根据条件显示 gapValue 或 '0',如果是 undefined 则不显示 -->
+    <div v-if="isCompare" :style="{ color: gapValue > 0 ? '#59b939' : gapValue < 0 ? '#ee7973' : 'black' }">
+      <el-icon v-if="gapValue > 0"><Top /></el-icon>
+        <el-icon v-else-if="gapValue < 0"><Bottom /></el-icon>
+      <span>{{ gapValue === 0 || gapValue === null ? '0%' : gapValue !== undefined ? gapValue + '%' : '' }}</span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+
+defineProps({
+  totalValue: [Number, String],
+  gapValue: Number,
+  isCompare: Boolean,
+  columnIndex: Number,
+})
+</script>

+ 38 - 23
src/views/productCenter/productList/components/DataTable/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div style="overflow: hidden; width: 100%; height: 600px" v-loading="tableLoading">
+  <div style="overflow: hidden; width: 100%; height: 800px" v-loading="tableLoading">
     <vxe-grid v-bind="gridOptions">
       <template #toolbar_buttons>
         <span>
@@ -7,14 +7,16 @@
           <vxe-switch v-model="isCompare" size="mini" />
         </span>
       </template>
-      <!-- <template #TotalSales_default="{ row }">
-        <div>{{ row.TotalSales }}</div>
-        <div>123</div>
-      </template> -->
       <template v-for="col in dynamicCols" #[`${col.field}_default`]="{ row }">
         <CustomCell :value="row[col.field]" :field="col.field" :row="row" :isCompare="isCompare" />
       </template>
-
+      <!-- <template #SAP_footer="{ items, _columnIndex }">
+        <div>{{ items[_columnIndex].totalValue }}</div>
+        <div>{{ items[_columnIndex].gapValue }}%</div>
+      </template> -->
+      <template v-for="col in dynamicCols" #[`${col.field}_footer`]="{ items, _columnIndex }">
+        <CustomFooterCell :totalValue="items[_columnIndex].totalValue" :gapValue="items[_columnIndex].gapValue" :isCompare="isCompare" :columnIndex="_columnIndex" />
+      </template>
       <template #pager>
         <vxe-pager
           :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
@@ -32,6 +34,7 @@
 import { inject, reactive, ref, watch } from 'vue'
 import { VXETable } from 'vxe-table'
 import CustomCell from '../CustomCell/index.vue'
+import CustomFooterCell from '../CustomFooterCell/index.vue'
 import { getTableDataForASIN, getTableDataForParentASIN, getTableDataForProductLine, getTableDataForSKU } from '/@/views/productCenter/productList/api'
 import useProductlineId from '/@/views/productCenter/productList/hooks/useProductlineId'
 import useTableColumns from '/@/views/productCenter/productList/hooks/useTableColumns'
@@ -52,7 +55,7 @@ const dynamicCols = ref([])
 const tablePage = reactive({
   total: 0,
   currentPage: 1,
-  pageSize: 10,
+  pageSize: 15,
 })
 
 const gridOptions = reactive({
@@ -73,11 +76,31 @@ const gridOptions = reactive({
   columns: [],
   data: [],
   footerMethod({ columns }) {
+    // return [
+    //   columns.map((column, columnIndex) => {
+    //     if (columnIndex === 0) return '合计'
+    //     if (summaryFormats[column.field]) return summaryFormats[column.field](totalSummary[column.field]) // 格式化后端返回的值
+    //     return '-'
+    //   }),
+    // ]
     return [
-      columns.map((column) => {
-        if (column.field === 'productlineName') return '合计'
-        if (summaryFormats[column.field]) return summaryFormats[column.field](totalSummary[column.field]) // 格式化后端返回的值
-        return '-'
+      columns.map((column, columnIndex) => {
+        if (columnIndex === 0) {
+          return '合计'
+        } else if (totalSummary[column.field] !== undefined) {
+          // 显示普通合计数据
+          let totalValue = totalSummary[column.field]
+          let gapField = `gap${column.field.charAt(0).toUpperCase()}${column.field.slice(1)}`
+          let gapValue = totalSummary[gapField]
+          // if (isCompare.value) {
+          // return `${totalValue} (${gapValue >= 0 ? '+' : ''}${gapValue}%)`
+          return { totalValue, gapValue }
+          // } else {
+          // return totalValue
+          // }
+        } else {
+          return '-'
+        }
       }),
     ]
   },
@@ -96,10 +119,10 @@ async function fetchTableData(type) {
 
   // 要用引号扩住key '产品线'
   const typeToApiAndColumns = {
-    '产品线': { api: getTableDataForProductLine, columns: productLineColumns },
-    'SKU': { api: getTableDataForSKU, columns: skuColumns },
-    '父ASIN': { api: getTableDataForParentASIN, columns: skuColumns },
-    'ASIN': { api: getTableDataForASIN, columns: skuColumns },
+    产品线: { api: getTableDataForProductLine, columns: productLineColumns },
+    SKU: { api: getTableDataForSKU, columns: skuColumns },
+    父ASIN: { api: getTableDataForParentASIN, columns: skuColumns },
+    ASIN: { api: getTableDataForASIN, columns: skuColumns },
   }
   // 根据类型获取对应的API函数和列配置
   const { api: apiFunction, columns } = typeToApiAndColumns[type] || {}
@@ -132,16 +155,8 @@ function handlePageChange({ currentPage, pageSize }) {
 watch([activeButton, productlineId, dateRange], () => {
   tablePage.currentPage = 1
   isCompare.value = false
-  console.log('activeButton.value', activeButton.value)
   fetchTableData(activeButton.value)
 })
-
-function openDetail(row) {
-  VXETable.modal.message({
-    status: 'success',
-    content: `点击了${row.name}`,
-  })
-}
 </script>
 
 <style scoped></style>

+ 28 - 2
src/views/productCenter/productList/hooks/useTableColumns.ts

@@ -1,12 +1,13 @@
 import { onMounted, reactive } from 'vue'
 
 export default function () {
-  const totalSummary = reactive({
+  const totalSummary = reactive({   // 初始化, 不添加也可以通过后端请求添加进去
     TotalSales: 0,
+    ACOS: 0,
     // 其他需要显示的合计数据
   })
 
-  // 定义合计数据的对象,键是字段名,值是处理逻辑
+  // 定义合计数据的对象, 键是字段名, 值是处理逻辑
   const summaryFormats = {
     TotalSales: value => `$${value}`, // 格式化为货币格式
     TotalOrderItems: (value) => `${value}`,
@@ -35,6 +36,31 @@ export default function () {
     PageViews: (value) => `${value}`,
     // FBAQuantity: (value) => `${value}`,
     // FBMQuantity: (value) => `${value}`,
+    gapTotalUnitOrdered: value => `${value}`,
+    gapTotalSales: value => `$${value}`,
+    gapTotalOrderItems: value => `${value}`,
+    gapSessions: value => `${value}`,
+    gapPageViews: value => `${value}`,
+    gapBuyBoxPercentage: value => `${value}`,
+    gapImpression: value => `${value}`,
+    gapClick: value => `${value}`,
+    gapSpend: value => `${value}`,
+    gapTotalAdPurchases: value => `${value}`,
+    gapTotalAdSales: value => `${value}`,
+    gapTotalAdUnitOrdered: value => `${value}`,
+    gapTotalAdSalesSameSKU: value => `${value}`,
+    gapTotalAdPurchasesSameSKU: value => `${value}`,
+    gapTotalAdUnitOrderedSameSKU: value => `${value}`,
+    gapSAP: value => `${value}`,
+    gapACOS: value => `${value}`,
+    gapROAS: value => `${value}`,
+    gapTACOS: value => `${value}`,
+    gapCR: value => `${value}`,
+    gapCTR: value => `${value}`,
+    gapCPC: value => `$${value}`,
+    gapCPO: value => `${value}`,
+    gapCPA: value => `${value}`,
+    gapProductCr: value => `${value}`,
   }
 
   return { totalSummary, summaryFormats }

+ 204 - 52
src/views/productCenter/productList/utils/columns.ts

@@ -1,30 +1,131 @@
 const universal = [
-  { field: 'TotalSales', title: '总销售额', align: 'right', width: 130, sortable: true, slots: { default: 'TotalSales_default' } },
-  { field: 'TotalOrderItems', title: '总订单数', align: 'right', width: 130, sortable: true, slots: { default: 'TotalOrderItems_default' } },
-  { field: 'TotalUnitOrdered', title: '总销量', align: 'right', width: 130, sortable: true, slots: { default: 'TotalUnitOrdered_default' } },
-  { field: 'TotalAdSales', title: '广告销售额', align: 'right', width: 130, sortable: true, slots: { default: 'TotalAdSales_default' } },
-  { field: 'TotalAdSalesSameSKU',title: '本商品广告销售额',align: 'right',width: 180,sortable: true,slots: { default: 'TotalAdSalesSameSKU_default' } },
-  { field: 'TotalAdPurchases', title: '广告订单数', align: 'right', width: 130, sortable: true, slots: { default: 'TotalAdPurchases_default' } },
-  { field: 'TotalAdPurchasesSameSKU', title: '本商品广告订单数', align: 'right', width: 180, sortable: true,slots: { default: 'TotalAdPurchasesSameSKU_default' } },
-  { field: 'TotalAdUnitOrdered', title: '广告销量', align: 'right', width: 130, sortable: true, slots: { default: 'TotalAdUnitOrdered_default' } },
-  { field: 'TotalAdUnitOrderedSameSKU',  title: '本商品广告销量', align: 'right', width: 180,sortable: true,slots: { default: 'TotalAdUnitOrderedSameSKU_default' } },
-  { field: 'Spend', title: '花费', align: 'right', width: 130, sortable: true, showOverflow: true, slots: { default: 'Spend_default' } },
-  { field: 'ACOS', title: 'ACOS', align: 'right', width: 130, sortable: true, slots: { default: 'ACOS_default' } },
-  { field: 'ROAS', title: 'ROAS', align: 'right', width: 130, sortable: true, slots: { default: 'ROAS_default' } },
-  { field: 'TACOS', title: 'TACOS', align: 'right', width: 130, sortable: true, slots: { default: 'TACOS_default' } },
-  { field: 'CR', title: '转化率', align: 'right', width: 130, sortable: true, slots: { default: 'CR_default' } },
-  { field: 'CTR', title: '点击率', align: 'right', width: 130, sortable: true, slots: { default: 'CTR_default' } },
-  { field: 'CPC', title: '点击成本', align: 'right', width: 130, sortable: true, slots: { default: 'CPC_default' } },
-  { field: 'CPO', title: '总订单成本', align: 'right', width: 130, sortable: true, slots: { default: 'CPO_default' } },
-  { field: 'CPA', title: '广告订单成本', align: 'right', width: 180, sortable: true, slots: { default: 'CPA_default' } },
-  { field: 'Impression', title: '曝光量', align: 'right', width: 130, sortable: true, slots: { default: 'Impression_default' } },
-  { field: 'Click', title: '点击量', align: 'right', width: 130, sortable: true, slots: { default: 'Click_default' } },
-  { field: 'Sessions', title: '会话次数', align: 'right', width: 150, sortable: true, slots: { default: 'Sessions_default' } },
-  { field: 'ProductCr', title: '商品会话百分比', align: 'right', width: 150, sortable: true, slots: { default: 'ProductCr_default' } },
-  { field: 'PageViews', title: '页面浏览量', align: 'right', width: 130, sortable: true, slots: { default: 'PageViews_default' } },
-  { field: 'BuyBoxPercentage',title: '推荐报价(购买按钮)百分比', align: 'right', width: 180, sortable: true,showHeaderOverflow: true, slots: { default: 'BuyBoxPercentage_default' }},
-  { field: 'FBAQuantity', title: 'FBA库存', align: 'right', width: 130, sortable: true },
-  { field: 'FBMQuantity', title: 'FBM库存', align: 'right', width: 130, sortable: true, showHeaderOverflow: true },
+  { field: 'TotalSales', title: '总销售额', align: 'right', width: 130, sortable: true, slots: { default: 'TotalSales_default', footer: 'TotalSales_footer' } },
+  { field: 'TotalOrderItems', title: '总订单数', align: 'right', width: 130, sortable: true, slots: { default: 'TotalOrderItems_default', footer: 'TotalOrderItems_footer' } },
+  {
+    field: 'TotalUnitOrdered',
+    title: '总销量',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'TotalUnitOrdered_default', footer: 'TotalUnitOrdered_footer' },
+  },
+  {
+    field: 'TotalAdSales',
+    title: '广告销售额',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'TotalAdSales_default', footer: 'TotalAdSales_footer' },
+  },
+  {
+    field: 'TotalAdSalesSameSKU',
+    title: '本商品广告销售额',
+    align: 'right',
+    width: 180,
+    sortable: true,
+    slots: { default: 'TotalAdSalesSameSKU_default', footer: 'TotalAdSalesSameSKU_footer' },
+  },
+  {
+    field: 'TotalAdPurchases',
+    title: '广告订单数',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'TotalAdPurchases_default', footer: 'TotalAdPurchases_footer' },
+  },
+  {
+    field: 'TotalAdPurchasesSameSKU',
+    title: '本商品广告订单数',
+    align: 'right',
+    width: 180,
+    sortable: true,
+    slots: { default: 'TotalAdPurchasesSameSKU_default', footer: 'TotalAdPurchasesSameSKU_footer' },
+  },
+  {
+    field: 'TotalAdUnitOrdered',
+    title: '广告销量',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'TotalAdUnitOrdered_default', footer: 'TotalAdUnitOrdered_footer' },
+  },
+  {
+    field: 'TotalAdUnitOrderedSameSKU',
+    title: '本商品广告销量',
+    align: 'right',
+    width: 180,
+    sortable: true,
+    slots: { default: 'TotalAdUnitOrderedSameSKU_default', footer: 'TotalAdUnitOrderedSameSKU_footer' },
+  },
+  {
+    field: 'Spend',
+    title: '花费',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    showOverflow: true,
+    slots: { default: 'Spend_default', footer: 'Spend_footer' },
+  },
+  { field: 'ACOS', title: 'ACOS', align: 'right', width: 130, sortable: true, slots: { default: 'ACOS_default', footer: 'ACOS_footer' } },
+  { field: 'ROAS', title: 'ROAS', align: 'right', width: 130, sortable: true, slots: { default: 'ROAS_default', footer: 'ROAS_footer' } },
+  { field: 'TACOS', title: 'TACOS', align: 'right', width: 130, sortable: true, slots: { default: 'TACOS_default', footer: 'TACOS_footer' } },
+  { field: 'CR', title: '转化率', align: 'right', width: 130, sortable: true, slots: { default: 'CR_default', footer: 'CR_footer' } },
+  { field: 'CTR', title: '点击率', align: 'right', width: 130, sortable: true, slots: { default: 'CTR_default', footer: 'CTR_footer' } },
+  { field: 'CPC', title: '点击成本', align: 'right', width: 130, sortable: true, slots: { default: 'CPC_default', footer: 'CPC_footer' } },
+  { field: 'CPO', title: '总订单成本', align: 'right', width: 130, sortable: true, slots: { default: 'CPO_default', footer: 'CPO_footer' } },
+  { field: 'CPA', title: '广告订单成本', align: 'right', width: 180, sortable: true, slots: { default: 'CPA_default', footer: 'CPA_footer' } },
+  {
+    field: 'Impression',
+    title: '曝光量',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'Impression_default', footer: 'Impression_footer' },
+  },
+  { field: 'Click', title: '点击量', align: 'right', width: 130, sortable: true, slots: { default: 'Click_default', footer: 'Click_footer' } },
+  {
+    field: 'Sessions',
+    title: '会话次数',
+    align: 'right',
+    width: 150,
+    sortable: true,
+    slots: { default: 'Sessions_default', footer: 'Sessions_footer' },
+  },
+  {
+    field: 'ProductCr',
+    title: '商品会话百分比',
+    align: 'right',
+    width: 150,
+    sortable: true,
+    slots: { default: 'ProductCr_default', footer: 'ProductCr_footer' },
+  },
+  {
+    field: 'PageViews',
+    title: '页面浏览量',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'PageViews_default', footer: 'PageViews_footer' },
+  },
+  {
+    field: 'BuyBoxPercentage',
+    title: '推荐报价(购买按钮)百分比',
+    align: 'right',
+    width: 180,
+    sortable: true,
+    showHeaderOverflow: true,
+    slots: { default: 'BuyBoxPercentage_default', footer: 'BuyBoxPercentage_footer' },
+  },
+  { field: 'FBAQuantity', title: 'FBA库存', align: 'right', width: 130, sortable: true, slots: { footer: 'FBAQuantity_footer' } },
+  {
+    field: 'FBMQuantity',
+    title: 'FBM库存',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    showHeaderOverflow: true,
+    slots: { footer: 'FBMQuantity_footer' },
+  },
 ]
 
 export const productLineColumns = [
@@ -35,39 +136,90 @@ export const productLineColumns = [
     fixed: 'left',
     width: 180,
     sortable: true,
-    slots: { default: 'productlineName_default' },
-  },  
-  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default' } }, 
-  ...universal
+    slots: { default: 'productlineName_default', footer: 'productlineName_footer' },
+  },
+  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default', footer: 'SAP_footer' } },
+  ...universal,
 ]
 
 export const parentAsinColumns = [
-  { field: 'parentAsin', title: '父ASIN', align: 'left', fixed: 'left', width: 180, sortable: true, slots: { default: 'productlineName_default' } },
-  { field: 'TotalSales', title: '最佳SKU', align: 'right', width: 130, sortable: true, slots: { default: 'TotalSales_default' } },
-  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default' } },
-  // { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130, slots: { default: 'TACOS_default' } },
-  ...universal
+  {
+    field: 'parentAsin',
+    title: '父ASIN',
+    align: 'left',
+    fixed: 'left',
+    width: 180,
+    sortable: true,
+    slots: { default: 'productlineName_default', footer: 'parentAsin_footer' },
+  },
+  {
+    field: 'TotalSales',
+    title: '最佳SKU',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'TotalSales_default', footer: 'TotalSales_footer' },
+  },
+  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default', footer: 'SAP_footer' } },
+  // { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130, slots: { default: 'TACOS_default', footer: 'TACOS_footer' } },
+  ...universal,
 ]
 
 export const asinColumns = [
-  { field: 'Asin', title: 'ASIN', align: 'left', fixed: 'left', width: 180, sortable: true, slots: { default: 'productlineName_default' } },
-  { field: 'productlineName', title: '产品线', align: 'left', fixed: 'left', width: 180, sortable: true, slots: { default: 'productlineName_default' } },
-  { field: 'rank', title: '排名', align: 'left', fixed: 'left', width: 180, sortable: true, slots: { default: 'productlineName_default' } },
-  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default' } },
-  // { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130, slots: { default: 'TACOS_default' } },
-  ...universal
+  {
+    field: 'Asin',
+    title: 'ASIN',
+    align: 'left',
+    fixed: 'left',
+    width: 180,
+    sortable: true,
+    slots: { default: 'productlineName_default', footer: 'Asin_footer' },
+  },
+  {
+    field: 'productlineName',
+    title: '产品线',
+    align: 'left',
+    fixed: 'left',
+    width: 180,
+    sortable: true,
+    slots: { default: 'productlineName_default', footer: 'productlineName_footer' },
+  },
+  {
+    field: 'rank',
+    title: '排名',
+    align: 'left',
+    fixed: 'left',
+    width: 180,
+    sortable: true,
+    slots: { default: 'productlineName_default', footer: 'rank_footer' },
+  },
+  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default', footer: 'SAP_footer' } },
+  // { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130, slots: { default: 'TACOS_default', footer: 'TACOS_footer' } },
+  ...universal,
 ]
 
 export const skuColumns = [
-  { field: 'sku', title: 'SKU', align: 'left', fixed: 'left', width: 130, slots: { default: 'sku_default' } },
-  { field: 'productlineName', title: '产品线', align: 'left', width: 180, slots: { default: 'productlineName_default' } },
-  { field: 'status', title: '商品状态', align: 'right', width: 130, slots: { default: 'status_default' } },
-  { field: 'time', title: '排名', align: 'right', width: 130, slots: { default: 'time_default' } },
-  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default' } },
-  { field: 'parentAsin', title: '父ASIN', align: 'right', width: 130, slots: { default: 'parentAsin_default' } },
-  { field: 'launchDatetime', title: '上架时间', align: 'right', width: 130, sortable: true, slots: { default: 'launchDatetime_default' } },
-  ...universal
-  // { field: 'ABP', title: '异常推广', align: 'right', width: 130, slots: { default: 'ABP_default' } },
-  
-  // { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130, slots: { default: 'TACOS_default' } },
+  { field: 'sku', title: 'SKU', align: 'left', fixed: 'left', width: 130, slots: { default: 'sku_default', footer: 'sku_footer' } },
+  {
+    field: 'productlineName',
+    title: '产品线',
+    align: 'left',
+    width: 180,
+    slots: { default: 'productlineName_default', footer: 'productlineName_footer' },
+  },
+  { field: 'status', title: '商品状态', align: 'right', width: 130, slots: { default: 'status_default', footer: 'status_footer' } },
+  { field: 'time', title: '排名', align: 'right', width: 130, slots: { default: 'time_default', footer: 'time_footer' } },
+  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true, slots: { default: 'SAP_default', footer: 'SAP_footer' } },
+  { field: 'parentAsin', title: '父ASIN', align: 'right', width: 130, slots: { default: 'parentAsin_default', footer: 'parentAsin_footer' } },
+  {
+    field: 'launchDatetime',
+    title: '上架时间',
+    align: 'right',
+    width: 130,
+    sortable: true,
+    slots: { default: 'launchDatetime_default', footer: 'launchDatetime_footer' },
+  },
+  ...universal,
+  // { field: 'ABP', title: '异常推广', align: 'right', width: 130, slots: { default: 'ABP_default', footer: 'ABP_footer' } },
+  // { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130, slots: { default: 'TACOS_default', footer: 'TACOS_footer' } },
 ]