浏览代码

✨ feat: 表格数据对比功能及代码优化

WanGxC 1 年之前
父节点
当前提交
fe9c23b342

+ 1 - 1
src/views/productCenter/productList/api.ts

@@ -95,7 +95,7 @@ export function getTableDataForProductLine(query) {
     params: query,
   })
 }
-export function getTableDataForFaASIN(query) {
+export function getTableDataForParentASIN(query) {
   return request({
     url: '/api/sellers/home/productline/list/',
     method: 'GET',

+ 36 - 0
src/views/productCenter/productList/components/CustomCell/index.vue

@@ -0,0 +1,36 @@
+<template>
+  <div>
+    <!-- 这里可以基于 field 和 row 自定义不同的展示 -->
+    <!-- <div v-if="field === 'TotalSales'">
+      {{ 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) + '%') : '' }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+  value: String,
+  field: String,
+  row: Object,
+  isCompare: Boolean,
+})
+
+// 计算 'gap' 值
+const prevValue = computed(() => {
+  const prevField = `gap${props.field.charAt(0).toUpperCase()}${props.field.slice(1)}` // 构建对应的 prev 前缀字段名称
+  return props.row[prevField] // 返回行数据中对应的 gap 值
+})
+</script>

+ 20 - 22
src/views/productCenter/productList/components/DataTable/index.vue

@@ -7,17 +7,14 @@
           <vxe-switch v-model="isCompare" size="mini" />
         </span>
       </template>
-      <template #name_default="{ row }">
-        <vxe-button type="text" @click="openDetail(row)">点击{{ row.name }}</vxe-button>
+      <!-- <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 #sex_default="{ row }">
-        <span>{{ formatSex(row) }}</span>
-      </template>
-      <vxe-grid v-bind="gridOptions">
-        <template #num_footer="{ items, _columnIndex }">
-          <span>¥{{ items[_columnIndex] }}</span>
-        </template>
-      </vxe-grid>
+
       <template #pager>
         <vxe-pager
           :layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
@@ -32,13 +29,13 @@
 </template>
 
 <script setup lang="ts">
-import { reactive, ref, inject, watch } from 'vue'
+import { inject, reactive, ref, watch } from 'vue'
 import { VXETable } from 'vxe-table'
-import { getTableDataForSKU, getTableDataForProductLine, getTableDataForFaASIN, getTableDataForASIN } from '/@/views/productCenter/productList/api'
-import emitter from '/@/utils/emitter'
-import { skuColumns, productLineColumns } from '/@/views/productCenter/productList/utils/columns'
+import CustomCell from '../CustomCell/index.vue'
+import { getTableDataForASIN, getTableDataForParentASIN, getTableDataForProductLine, getTableDataForSKU } from '/@/views/productCenter/productList/api'
 import useProductlineId from '/@/views/productCenter/productList/hooks/useProductlineId'
-import useTableColumns from '../../hooks/useTableColumns'
+import useTableColumns from '/@/views/productCenter/productList/hooks/useTableColumns'
+import { productLineColumns, skuColumns } from '/@/views/productCenter/productList/utils/columns'
 
 const profile = <any>inject('profile')
 const dateRange = <any>inject('dateRange')
@@ -50,6 +47,8 @@ const tableLoading = ref(false)
 const { productlineId } = useProductlineId()
 const { totalSummary, summaryFormats } = useTableColumns()
 
+const dynamicCols = ref([])
+
 const tablePage = reactive({
   total: 0,
   currentPage: 1,
@@ -77,7 +76,7 @@ const gridOptions = reactive({
     return [
       columns.map((column) => {
         if (column.field === 'productlineName') return '合计'
-        if (summaryFormats[column.field]) return summaryFormats[column.field](totalSummary[column.field])
+        if (summaryFormats[column.field]) return summaryFormats[column.field](totalSummary[column.field]) // 格式化后端返回的值
         return '-'
       }),
     ]
@@ -95,10 +94,11 @@ async function fetchTableData(type) {
     limit: tablePage.pageSize,
   }
 
+  // 要用引号扩住key '产品线'
   const typeToApiAndColumns = {
     '产品线': { api: getTableDataForProductLine, columns: productLineColumns },
     'SKU': { api: getTableDataForSKU, columns: skuColumns },
-    '父ASIN': { api: getTableDataForFaASIN, columns: skuColumns },
+    '父ASIN': { api: getTableDataForParentASIN, columns: skuColumns },
     'ASIN': { api: getTableDataForASIN, columns: skuColumns },
   }
   // 根据类型获取对应的API函数和列配置
@@ -115,6 +115,7 @@ async function fetchTableData(type) {
     tablePage.total = response.total
     gridOptions.data = response.data.list
     gridOptions.columns = columns
+    dynamicCols.value = columns
   } catch (error) {
     console.log('error:', error)
   } finally {
@@ -130,20 +131,17 @@ function handlePageChange({ currentPage, pageSize }) {
 
 watch([activeButton, productlineId, dateRange], () => {
   tablePage.currentPage = 1
+  isCompare.value = false
+  console.log('activeButton.value', activeButton.value)
   fetchTableData(activeButton.value)
 })
 
-function formatSex(row) {
-  return row.sex === '1' ? '男' : '女'
-}
-
 function openDetail(row) {
   VXETable.modal.message({
     status: 'success',
     content: `点击了${row.name}`,
   })
 }
-
 </script>
 
 <style scoped></style>

+ 1 - 1
src/views/productCenter/productList/hooks/useTableColumns.ts

@@ -8,7 +8,7 @@ export default function () {
 
   // 定义合计数据的对象,键是字段名,值是处理逻辑
   const summaryFormats = {
-    TotalSales: (value) => `$${value}`, // 格式化为货币格式
+    TotalSales: value => `$${value}`, // 格式化为货币格式
     TotalOrderItems: (value) => `${value}`,
     TotalUnitOrdered: (value) => `${value}`,
     SAP: (value) => `${value}`,

+ 67 - 64
src/views/productCenter/productList/utils/columns.ts

@@ -1,70 +1,73 @@
-export const productLineColumns = [
-  // { field: 'name', title: 'Name', align: 'center', width: 130, slots: { default: 'name_default' } },
-  //   { field: 'sex', title: 'Sex', align: 'center', width: 80, slots: { default: 'sex_default' } },
-  { field: 'productlineName', title: '产品线', align: 'left', fixed: 'left', width: 180, sortable: true },
-  { field: 'TotalSales', title: '总销售额', align: 'right', width: 130, sortable: true },
-  { field: 'TotalOrderItems', title: '总订单数', align: 'right', width: 130, sortable: true },
-  { field: 'TotalUnitOrdered', title: '总销量', align: 'right', width: 130, sortable: true },
-  { field: 'SAP', title: '单均价', align: 'right', width: 130, sortable: true },
-  { field: 'TotalAdSales', title: '广告销售额', align: 'right', width: 130, sortable: true },
-  { field: 'TotalAdSalesSameSKU', title: '本商品广告销售额', align: 'right', width: 180, sortable: true },
-  { field: 'TotalAdPurchases', title: '广告订单数', align: 'right', width: 130, sortable: true },
-  { field: 'TotalAdPurchasesSameSKU', title: '本商品广告订单数', align: 'right', width: 180, sortable: true },
-  { field: 'TotalAdUnitOrdered', title: '广告销量', align: 'right', width: 130, sortable: true },
-  { field: 'TotalAdUnitOrderedSameSKU', title: '本商品广告销量', align: 'right', width: 180, sortable: true },
-  { field: 'Spend', title: '花费', align: 'right', width: 130, sortable: true, showOverflow: true },
-  { field: 'ACOS', title: 'ACOS', align: 'right', width: 130, sortable: true },
-  { field: 'ROAS', title: 'ROAS', align: 'right', width: 130, sortable: true },
-  { field: 'TACOS', title: 'TACOS', align: 'right', width: 130, sortable: true },
-  { field: 'CR', title: '转化率', align: 'right', width: 130, sortable: true },
-  { field: 'CTR', title: '点击率', align: 'right', width: 130, sortable: true },
-  { field: 'CPC', title: '点击成本', align: 'right', width: 130, sortable: true },
-  { field: 'CPO', title: '总订单成本', align: 'right', width: 130, sortable: true },
-  { field: 'CPA', title: '广告订单成本', align: 'right', width: 180, sortable: true },
-  { field: 'Impression', title: '曝光量', align: 'right', width: 130, sortable: true },
-  { field: 'Click', title: '点击量', align: 'right', width: 130, sortable: true },
-  { field: 'ProductCr', title: '会话次数', align: 'right', width: 150, sortable: true },
-  { field: 'BuyBoxPercentage', title: '商品会话百分比', align: 'right', width: 150, sortable: true },
-  { field: 'Sessions', title: '页面浏览量', align: 'right', width: 130, sortable: true },
-  { field: 'PageViews', title: '推荐报价(购买按钮)百分比', align: 'right', width: 180, sortable: true, showHeaderOverflow: true },
+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 },
 ]
 
+export const productLineColumns = [
+  {
+    field: 'productlineName',
+    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' } }, 
+  ...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
+]
+
+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
+]
+
 export const skuColumns = [
-  { field: 'sku', title: 'SKU', align: 'left', fixed: 'left', width: 130 },
-  { field: 'name', title: '产品线', align: 'left', width: 180 },
-  { field: 'sex', title: '总销售额', align: 'right', width: 130, sortable: true },
-  { field: 'age', title: '总订单数', align: 'right', width: 130, sortable: true },
-  { field: 'status', title: '商品状态', align: 'right', width: 130 },
-  { field: 'time', title: '总销量', align: 'right', width: 130, sortable: true },
-  { field: 'time', title: '排名', align: 'right', width: 130 },
-  { field: 'time', title: '单均价', align: 'right', width: 130, sortable: true },
-  { field: 'time', title: '父ASIN', align: 'right', width: 130 },
-  { field: 'address', title: '广告销售额', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '上架时间', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '本商品广告销售额', align: 'right', width: 180, sortable: true },
-  { field: 'time', title: '异常推广', align: 'right', width: 130 },
-  { field: 'address', title: '广告订单数', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '本商品广告订单数', align: 'right', width: 180, sortable: true },
-  { field: 'address', title: '广告销量', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '本商品广告销量', align: 'right', width: 180, sortable: true },
-  { field: 'address', title: '花费', align: 'right', width: 130, sortable: true, showOverflow: true },
-  { field: 'address', title: 'ACOS', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: 'ROAS', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: 'TACOS', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '转化率', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '点击率', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '点击成本', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '总订单成本', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '广告订单成本', align: 'right', width: 180, sortable: true },
-  { field: 'Impression', title: '曝光量', align: 'right', width: 130, sortable: true },
-  { field: 'Click', title: '点击量', align: 'right', width: 130, sortable: true },
-  { field: 'TACOS', title: '预警TACOS', align: 'right', width: 130 },
-  { field: 'Sessions', title: '会话次数', align: 'right', width: 150, sortable: true },
-  { field: 'address', title: '商品会话百分比', align: 'right', width: 150, sortable: true },
-  { field: 'address', title: '页面浏览量', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: '推荐报价(购买按钮)百分比', align: 'right', width: 180, sortable: true, showHeaderOverflow: true },
-  { field: 'address', title: 'FBA库存', align: 'right', width: 130, sortable: true },
-  { field: 'address', title: 'FBM库存', align: 'right', width: 130, sortable: true, showHeaderOverflow: true },
+  { 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' } },
 ]