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

+ 1 - 1
.prettierrc.js

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

+ 0 - 14
src/views/productCenter/productAnalysis/api.ts

@@ -37,20 +37,6 @@ export function getLineMonthData(query: UserPageQuery) {
   })
 }
 
-// export function getProductLineSelect(query) {
-//   return request({
-//     url: '/api/sellers/productline/',
-//     method: 'GET',
-//     params: query,
-//   })
-// }
-// export function postCreateProductLine(body) {
-//   return request({
-//     url: '/api/sellers/productline/create/',
-//     method: 'POST',
-//     data: body,
-//   })
-// }
 export function getProductLineSelect(query) {
   return request({
     url: '/api/sellers/productline/',

+ 4 - 4
src/views/productCenter/productAnalysis/components/CpRecommendations/index.vue

@@ -1,12 +1,12 @@
+<script setup>
+
+</script>
+
 <template>
   <div>
     <div></div>  
   </div>
 </template>
   
-<script setup>
-
-</script>
-  
 <style scoped>
 </style>

+ 21 - 39
src/views/productCenter/productAnalysis/components/DataTable/index.vue

@@ -1,32 +1,5 @@
-<template>
-  <el-card body-style="padding-top: 0;" style="margin-top: 10px;">
-    <div style="overflow: hidden; width: 100%; height: 800px" v-loading="tableLoading">
-      <vxe-grid v-bind="gridOptions">
-        <template v-for="col in universalColumns" #[`${col.field}_default`]="{ row }">
-          <div>
-            {{ row[col.field] ? row[col.field] : '-' }}
-          </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']"
-          v-model:current-page="tablePage.currentPage"
-          v-model:page-size="tablePage.pageSize"
-          :total="tablePage.total"
-          @page-change="handlePageChange">
-        </vxe-pager>
-      </template> -->
-      </vxe-grid>
-    </div>
-  </el-card>
-</template>
-
 <script setup lang="ts">
 import { inject, onMounted, reactive, ref, watch } from 'vue'
-// import { VXETable } from 'vxe-table'
 import { getListData } from '../../api'
 import { universalColumns } from '../../utils/columns'
 
@@ -36,12 +9,6 @@ const tableData = <any>inject('tableData')
 
 const tableLoading = ref(false)
 
-// const tablePage = reactive({
-//   total: 0,
-//   currentPage: 1,
-//   pageSize: 15,
-// })
-
 const gridOptions = reactive({
   height: 'auto',
   border: false,
@@ -53,9 +20,6 @@ const gridOptions = reactive({
   },
   toolbarConfig: {
     custom: true,
-    // slots: {
-    //   buttons: 'toolbar_buttons',
-    // },
   },
   columns: [],
   data: [],
@@ -67,7 +31,6 @@ async function fetchListData() {
     profileId: profile.value.profile_id,
     startDate: dateRange.value[0],
     endDate: dateRange.value[1],
-    // dateRangeType: 'D'
   }
   try {
     const res = await getListData(query)
@@ -81,7 +44,6 @@ async function fetchListData() {
 }
 
 watch(tableData, () => {
-  // console.log('tableData.value', tableData.value)
   gridOptions.data = tableData.value
 })
 
@@ -90,4 +52,24 @@ onMounted(() => {
 })
 </script>
 
-<style scoped></style>
+<template>
+  <el-card body-style="padding-top: 0;" style="margin-top: 10px">
+    <div class="outer-container" v-loading="tableLoading">
+      <vxe-grid v-bind="gridOptions">
+        <template v-for="col in universalColumns" #[`${col.field}_default`]="{ row }">
+          <div>
+            {{ row[col.field] ? row[col.field] : '-' }}
+          </div>
+        </template>
+      </vxe-grid>
+    </div>
+  </el-card>
+</template>
+
+<style scoped>
+.outer-container {
+  overflow: hidden;
+  width: 100%;
+  height: 800px;
+}
+</style>

+ 73 - 58
src/views/productCenter/productAnalysis/components/SalesOverview/index.vue

@@ -1,63 +1,9 @@
-<template>
-  <div style="overflow: hidden; width: 100%; height: 800px" v-loading="tableLoading">
-    <vxe-grid v-bind="gridOptions">
-      <template #toolbar_buttons>
-        <vxe-input v-model="searchInp" @search-click="handleSearch" @keydown="handleKeydown" placeholder="快速查询ASIN、SKU或商品标题" type="search" style="width: 300px;"></vxe-input>
-        <vxe-select v-model="selectVal" @change="handleSelect" style="margin-left: 10px">
-          <vxe-option v-for="num in 15" :key="num" :value="num" :label="`选项${num}`"></vxe-option>
-        </vxe-select>
-      </template>
-
-      <template v-for="col in salesColumns" #[`${col.field}_default`]="{ row }">
-        <div>
-          <template v-if="col.field == 'sku'">
-            <div class="list-content">
-              <div class="image-item">
-                <img v-if="row.Image" :src="row.Image" />
-                <div v-else>
-                  <el-image>
-                    <template #error>
-                      <div class="image-slot">
-                        <el-icon><icon-picture /></el-icon>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-              </div>
-              <div>
-                <el-tooltip effect="dark" :content="row.Title" placement="top-start">
-                  <span class="item-title">{{ row.Title ? row.Title : '--' }}</span>
-                </el-tooltip>
-                <div>
-                  <span class="item-font">{{ row.quantity ? '有库存' : '缺货' }}</span>
-                </div>
-                <span class="item-font">
-                  ASIN: <span class="black-color">{{ row.Asin }}</span>
-                  </span>
-                <el-tooltip effect="dark" :content="row.sku" placement="top-start">
-                  <span class="item-font display-line">
-                    SKU: <span class="black-color">{{ row.sku }}</span>
-                  </span>
-                </el-tooltip>
-              </div>
-            </div>
-          </template>
-          <template v-else>
-            {{ row[col.field] ? row[col.field] : '-' }}
-          </template>
-        </div>
-      </template>
-    </vxe-grid>
-  </div>
-</template>
-
 <script setup lang="ts">
-import { inject, onMounted, reactive, ref, watch } from 'vue'
-// import { VXETable } from 'vxe-table'
+import { Picture as IconPicture } from '@element-plus/icons-vue'
+import { inject, onMounted, reactive, ref } from 'vue'
 import { getSalesListData } from '../../api'
 import { salesColumns } from '../../utils/columns'
 import emitter from '/@/utils/emitter'
-import { Picture as IconPicture } from '@element-plus/icons-vue'
 
 const profile = <any>inject('profile')
 const dateRange = <any>inject('dateRange')
@@ -144,7 +90,7 @@ function handleSearch() {
   } catch (error) {
     console.log('error:', error)
   } finally {
-  tableLoading.value = true
+    tableLoading.value = true
   }
 }
 
@@ -163,7 +109,77 @@ onMounted(() => {
 })
 </script>
 
+<template>
+  <div class="outer-container" v-loading="tableLoading">
+    <vxe-grid v-bind="gridOptions">
+      <template #toolbar_buttons>
+        <vxe-input
+          v-model="searchInp"
+          @search-click="handleSearch"
+          @keydown="handleKeydown"
+          placeholder="快速查询ASIN、SKU或商品标题"
+          type="search"
+          class="custom-vxe-input"></vxe-input>
+        <vxe-select v-model="selectVal" @change="handleSelect" class="custom-vxe-select">
+          <vxe-option v-for="num in 15" :key="num" :value="num" :label="`选项${num}`"></vxe-option>
+        </vxe-select>
+      </template>
+
+      <template v-for="col in salesColumns" #[`${col.field}_default`]="{ row }">
+        <div>
+          <template v-if="col.field == 'sku'">
+            <div class="list-content">
+              <div class="image-item">
+                <img v-if="row.Image" :src="row.Image" />
+                <div v-else>
+                  <el-image>
+                    <template #error>
+                      <div class="image-slot">
+                        <el-icon><icon-picture /></el-icon>
+                      </div>
+                    </template>
+                  </el-image>
+                </div>
+              </div>
+              <div>
+                <el-tooltip effect="dark" :content="row.Title" placement="top-start">
+                  <span class="item-title">{{ row.Title ? row.Title : '--' }}</span>
+                </el-tooltip>
+                <div>
+                  <span class="item-font">{{ row.quantity ? '有库存' : '缺货' }}</span>
+                </div>
+                <span class="item-font">
+                  ASIN: <span class="black-color">{{ row.Asin }}</span>
+                </span>
+                <el-tooltip effect="dark" :content="row.sku" placement="top-start">
+                  <span class="item-font display-line">
+                    SKU: <span class="black-color">{{ row.sku }}</span>
+                  </span>
+                </el-tooltip>
+              </div>
+            </div>
+          </template>
+          <template v-else>
+            {{ row[col.field] ? row[col.field] : '-' }}
+          </template>
+        </div>
+      </template>
+    </vxe-grid>
+  </div>
+</template>
+
 <style scoped>
+.outer-container {
+  overflow: hidden;
+  width: 100%;
+  height: 800px;
+}
+.custom-vxe-input {
+  width: 300px;
+}
+.custom-vxe-select {
+  margin-left: 10px;
+}
 .list-content {
   display: flex;
   align-items: center;
@@ -215,5 +231,4 @@ onMounted(() => {
   color: var(--el-text-color-secondary);
   font-size: 30px;
 }
-
 </style>

+ 116 - 88
src/views/productCenter/productAnalysis/components/TopParentAsin/ExchangeProduct.vue

@@ -1,3 +1,96 @@
+<script setup lang="ts">
+import { Search } from '@element-plus/icons-vue'
+import { inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'
+import { getProductLineSelect, getProduct } from '../../api'
+import emitter from '/@/utils/emitter'
+import useSelectItem from '../../hooks/useSelectItem'
+import useInfiniteScroll from '../../hooks/useInfiniteScroll'
+
+const profile = <any>inject('profile')
+const { allData, parentloading, currentPage, load, fetchProduct } = useInfiniteScroll()
+const {
+  visible,
+  skuData,
+  asinData,
+  selectedIndex,
+  selectedAsinIndex,
+  selectedSkuIndex,
+  selectPaAsin,
+  selectAsin,
+  selectSku,
+  clickParentAsinBtn,
+  clickAsinBtn,
+} = useSelectItem()
+
+const searchInp = ref('')
+const filterSelect = ref('vague')
+
+const productSelect = ref('ALL')
+const options = ref([])
+
+async function fetchProductLine() {
+  try {
+    const resp = await getProductLineSelect({ profileId: profile.value.profile_id })
+    options.value = resp.data
+    productSelect.value = options.value[0].productlineId
+  } catch (error) {
+    console.log('error:', error)
+  }
+}
+
+async function handleChange() {
+  parentloading.value = true
+  const query = {
+    profileId: profile.value.profile_id,
+    productlineId: productSelect.value,
+    searchItem: searchInp.value,
+  }
+  if (searchInp.value) {
+    const res = await getProduct(query)
+    allData.value = res.data
+    emitter.emit('ExchangeProduct-allData', allData) // 让useSelectItem()中的allData得到正确更新, 否则无法正确选择parentAsin
+  }
+  parentloading.value = false
+}
+
+function searchClick() {
+  console.log(123)
+}
+
+function resetProductList() {
+  currentPage.value = 1
+  fetchProduct()
+  asinData.value = []
+  skuData.value = []
+  selectedIndex.value = -1
+}
+
+watch(searchInp, () => {
+  emitter.emit('ExchangeProduct-searchInp', searchInp)
+  if (searchInp.value === '') {
+    resetProductList()
+  }
+})
+
+// 若产品选择改变则 重置分页并清空其他的数据
+watch(
+  productSelect,
+  (value) => {
+    emitter.emit('ExchangeProduct-productSelect', value)
+    resetProductList()
+  },
+  { immediate: true }
+)
+
+onMounted(() => {
+  fetchProductLine()
+})
+
+onBeforeUnmount(() => {
+  emitter.all.clear()
+})
+</script>
+
 <template>
   <el-popover placement="bottom-start" :width="1000" :visible="visible">
     <template #reference>
@@ -11,9 +104,9 @@
       <el-icon @click="visible = false" style="cursor: pointer"><CloseBold /></el-icon>
     </div>
     <div class="filter-bar">
-      <el-input v-model="searchInp" style="max-width: 600px" @change="handleChange"  placeholder="请输入标题/父ASIN/ASIN/SKU查询商品">
+      <el-input v-model="searchInp" style="max-width: 600px" @change="handleChange" placeholder="请输入标题/父ASIN/ASIN/SKU查询商品">
         <template #prepend>
-          <el-select v-model="filterSelect" style="width: 80px">
+          <el-select v-model="filterSelect" class="filter-bar-select">
             <el-option label="模糊" value="vague" />
             <el-option label="精确" value="accurate" />
           </el-select>
@@ -30,7 +123,12 @@
       <div class="asin-selector__part" v-loading="parentloading">
         <div class="part-title">父ASIN</div>
         <ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto">
-          <li v-for="(item, index) in allData" :key="index" class="infinite-list-item" @click="selectPaAsin(index)" :class="{ selectedItem: index === selectedIndex }">
+          <li
+            v-for="(item, index) in allData"
+            :key="index"
+            class="infinite-list-item"
+            @click="selectPaAsin(index)"
+            :class="{ selectedItem: index === selectedIndex }">
             <el-button color="#3c58af" size="small" class="view-btn" @click.stop="clickParentAsinBtn(index)">查看</el-button>
             <div class="list-content">
               <img :src="item.Image" class="list-item-image" />
@@ -64,7 +162,12 @@
       <div class="asin-selector__part">
         <div class="part-title">ASIN</div>
         <el-scrollbar height="450px">
-          <li v-for="(item, index) in asinData" :key="index" class="infinite-list-item" @click="selectAsin(index)" :class="{ selectedItem: index === selectedAsinIndex }">
+          <li
+            v-for="(item, index) in asinData"
+            :key="index"
+            class="infinite-list-item"
+            @click="selectAsin(index)"
+            :class="{ selectedItem: index === selectedAsinIndex }">
             <div class="list-content">
               <img :src="item.Image" class="asin-list-item-image" />
               <div>
@@ -97,7 +200,12 @@
       <div class="asin-selector__part sku">
         <div class="part-title">SKU</div>
         <el-scrollbar height="450px">
-          <li v-for="(item, index) in skuData" :key="index" class="sku-list-item" @click="selectSku(index)" :class="{ selectedItem: index === selectedSkuIndex }">
+          <li
+            v-for="(item, index) in skuData"
+            :key="index"
+            class="sku-list-item"
+            @click="selectSku(index)"
+            :class="{ selectedItem: index === selectedSkuIndex }">
             <div>{{ item.sku ? item.sku : '--' }}</div>
           </li>
         </el-scrollbar>
@@ -106,89 +214,6 @@
   </el-popover>
 </template>
 
-<script setup lang="ts">
-import { Search } from '@element-plus/icons-vue'
-import { inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'
-import { getProductLineSelect, getProduct } from '../../api'
-import emitter from '/@/utils/emitter'
-import useSelectItem from '../../hooks/useSelectItem'
-import useInfiniteScroll from '../../hooks/useInfiniteScroll'
-
-const profile = <any>inject('profile')
-const { allData, parentloading, currentPage, load, fetchProduct } = useInfiniteScroll()
-const { visible, skuData, asinData, selectedIndex, selectedAsinIndex, selectedSkuIndex, selectPaAsin, selectAsin, selectSku, clickParentAsinBtn, clickAsinBtn } = useSelectItem()
-
-// const visible = ref(false)
-
-const searchInp = ref('')
-const filterSelect = ref('vague')
-
-const productSelect = ref('ALL')
-const options = ref([])
-
-async function fetchProductLine() {
-  try {
-    const resp = await getProductLineSelect({ profileId: profile.value.profile_id })
-    options.value = resp.data
-    productSelect.value = options.value[0].productlineId
-  } catch (error) {
-    console.log('error:', error)
-  }
-}
-
-async function handleChange() {
-  parentloading.value = true
-  const query = {
-    profileId: profile.value.profile_id,
-    productlineId: productSelect.value,
-    searchItem: searchInp.value
-  }
-  if (searchInp.value) {
-    const res = await getProduct(query)
-    allData.value = res.data
-    emitter.emit('ExchangeProduct-allData', allData)  // 让useSelectItem()中的allData得到正确更新, 否则无法正确选择parentAsin
-  }
-  parentloading.value = false
-}
-
-function searchClick() {
-  console.log(123)
-}
-
-function resetProductList() {
-  currentPage.value = 1
-    fetchProduct()
-    asinData.value = []
-    skuData.value = []
-    selectedIndex.value = -1
-}
-
-watch (searchInp, () => {
-  emitter.emit('ExchangeProduct-searchInp', searchInp)
-  if (searchInp.value === '') {
-    resetProductList()
-  }
-})
-
-// 若产品选择改变则 重置分页并清空其他的数据
-watch(
-  productSelect,
-  (value) => {
-    emitter.emit('ExchangeProduct-productSelect', value)
-    resetProductList()
-  },
-  { immediate: true }
-)
-
-onMounted(() => {
-  fetchProductLine()
-})
-
-onBeforeUnmount(() => {
-  emitter.all.clear()
-})
-</script>
-
 <style scoped>
 .custom-top {
   display: flex;
@@ -210,6 +235,9 @@ onBeforeUnmount(() => {
   display: flex;
   gap: 8px;
 }
+.filter-bar-select {
+  width: 80px;
+}
 .asin-selector {
   display: flex;
   align-items: stretch;

+ 49 - 46
src/views/productCenter/productAnalysis/components/TopParentAsin/index.vue

@@ -1,48 +1,3 @@
-<template>
-  <div class="top-parent-asin" v-loading="topCardloading">
-    <el-card body-style="padding: 8px;">
-      <div class="product-card">
-        <div class="product-image">
-          <img :src="dataSet.Image" class="img" />
-        </div>
-        <div class="product-info">
-          <div>
-            <ExchangeProduct />
-            <div style="position: relative">
-              <div class="classification-title" :style="classificationStyle">{{ classification }}</div>
-            </div>
-          </div>
-          <div class="product-title">
-            {{ dataSet.Title }}
-          </div>
-          <div class="product-detail">
-            <span class="product-detail__label"> 父ASIN: </span>
-            <span>{{ dataSet.parentAsin ? dataSet.parentAsin : '--' }}</span>
-            <span class="product-detail__label ml-6"> SKU: </span>
-            <span>{{ dataSet.skuNumbers ? dataSet.skuNumbers : '--' }}</span>
-            <span class="product-detail__label ml-6"> FBA库存: </span>
-            <span>{{ dataSet.FBAQuantity ? dataSet.FBAQuantity : '--' }}</span>
-          </div>
-          <div class="product-brand">
-            <span>ZOSI</span>
-          </div>
-        </div>
-        <div class="product-price">
-          <div class="product-price__label">价格:</div>
-          <div style="position: relative; top: 1px">
-            <div>${{ dataSet.priceMin ? dataSet.priceMin : '--' }} ~ ${{ dataSet.priceMax ? dataSet.priceMax : '--' }}</div>
-          </div>
-        </div>
-        <!-- TODO: 星级评分未完成 -->
-        <div class="product-stars">
-          <div>星级评分:</div>
-          <div>1231341231223213(2131)</div>
-        </div>
-      </div>
-    </el-card>
-  </div>
-</template>
-
 <script setup lang="ts">
 import ExchangeProduct from './ExchangeProduct.vue'
 import { getDetail } from '../../api'
@@ -52,7 +7,6 @@ import emitter from '/@/utils/emitter'
 const profile = <any>inject('profile')
 const topCardloading = ref(false)
 const dataSet = <any>ref({})
-// const classification = ref('')
 
 const parentAsin = ref('')
 const childAsin = ref('')
@@ -121,6 +75,51 @@ onMounted(() => {
 })
 </script>
 
+<template>
+  <div class="top-parent-asin" v-loading="topCardloading">
+    <el-card body-style="padding: 8px;">
+      <div class="product-card">
+        <div class="product-image">
+          <img :src="dataSet.Image" class="img" />
+        </div>
+        <div class="product-info">
+          <div>
+            <ExchangeProduct />
+            <div style="position: relative">
+              <div class="classification-title" :style="classificationStyle">{{ classification }}</div>
+            </div>
+          </div>
+          <div class="product-title">
+            {{ dataSet.Title }}
+          </div>
+          <div class="product-detail">
+            <span class="product-detail__label"> 父ASIN: </span>
+            <span>{{ dataSet.parentAsin ? dataSet.parentAsin : '--' }}</span>
+            <span class="product-detail__label ml-6"> SKU: </span>
+            <span>{{ dataSet.skuNumbers ? dataSet.skuNumbers : '--' }}</span>
+            <span class="product-detail__label ml-6"> FBA库存: </span>
+            <span>{{ dataSet.FBAQuantity ? dataSet.FBAQuantity : '--' }}</span>
+          </div>
+          <div class="product-brand">
+            <span>ZOSI</span>
+          </div>
+        </div>
+        <div class="product-price">
+          <div class="product-price__label">价格:</div>
+          <div class="product-price__content">
+            <div>${{ dataSet.priceMin ? dataSet.priceMin : '--' }} ~ ${{ dataSet.priceMax ? dataSet.priceMax : '--' }}</div>
+          </div>
+        </div>
+        <!-- TODO: 星级评分未完成 -->
+        <div class="product-stars">
+          <div>星级评分:</div>
+          <div>1231341231223213(2131)</div>
+        </div>
+      </div>
+    </el-card>
+  </div>
+</template>
+
 <style scoped>
 .product-card {
   display: flex;
@@ -172,6 +171,10 @@ onMounted(() => {
   color: #6b7785;
   font-size: 12px;
 }
+.product-price__content {
+  position: relative;
+  top: 1px;
+}
 .product-stars {
   flex-shrink: 0;
   min-width: 180px;

+ 15 - 17
src/views/productCenter/productAnalysis/components/TrendOverview/index.vue

@@ -1,18 +1,3 @@
-<template>
-  <el-card>
-    <!-- <p>{{ queryParams }}</p> -->
-    <DataTendencyChart
-      :metricEnum="productListMetricsEnum"
-      :query="queryParams"
-      :fetchCard="getCardData"
-      :fetchLine="getLineData"
-      :fetch-line-month="getLineMonthData"
-      :fetch-line-week="getLineWeekData"
-      @changeStatDim="update">
-    </DataTendencyChart>
-  </el-card>
-</template>
-
 <script setup lang="ts">
 import { storeToRefs } from 'pinia'
 import { onBeforeUnmount, provide, ref, inject } from 'vue'
@@ -64,11 +49,24 @@ function update(value) {
   emit('updateList', value)
 }
 
-
-
 onBeforeUnmount(() => {
   emitter.all.clear()
 })
 </script>
 
+<template>
+  <el-card>
+    <!-- <p>{{ queryParams }}</p> -->
+    <DataTendencyChart
+      :metricEnum="productListMetricsEnum"
+      :query="queryParams"
+      :fetchCard="getCardData"
+      :fetchLine="getLineData"
+      :fetch-line-month="getLineMonthData"
+      :fetch-line-week="getLineWeekData"
+      @changeStatDim="update">
+    </DataTendencyChart>
+  </el-card>
+</template>
+
 <style scoped></style>

+ 33 - 38
src/views/productCenter/productAnalysis/index.vue

@@ -1,41 +1,7 @@
-<template>
-  <div class="outer-container">
-    <TopParentAsin></TopParentAsin>
-    <div class="filters">
-      <DateRangePicker v-model="dateRange"></DateRangePicker>
-      <div v-show="activeName == 'trendOverview'">
-        <el-select v-model="filter1" placeholder="Select" style="width: 240px; margin-right: 8px">
-          <el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-        <el-select v-model="filter2" placeholder="Select" style="width: 240px">
-          <el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-      </div>
-    </div>
-    <div>
-      <el-tabs v-model="activeName" type="border-card" class="chart-tabs">
-      <!-- <DateRangePicker v-model="dateRange" style="position: absolute; right: 0px; top: -10px;"></DateRangePicker> -->
-
-        <el-tab-pane label="趋势总览" name="trendOverview">
-          <TrendOverview @updateList="handleUpdate"></TrendOverview>
-          <DataTable></DataTable>
-        </el-tab-pane>
-        <el-tab-pane label="广告优化" name="adOptimization">广告优化</el-tab-pane>
-        <el-tab-pane label="销售概览" name="salesOverview" lazy>
-          <SalesOverview></SalesOverview>
-        </el-tab-pane>
-        <el-tab-pane label="竞品推荐" name="cpRecommendations">
-          <CpRecommendations></CpRecommendations>
-        </el-tab-pane>
-      </el-tabs>
-    </div>
-  </div>
-</template>
-
 <script setup lang="ts">
 import { storeToRefs } from 'pinia'
 import { provide, ref } from 'vue'
-import DataTable from './components/DataTable/index.vue'
+import DataTable from '/@/views/productCenter/productAnalysis/components/DataTable/index.vue'
 import TopParentAsin from './components/TopParentAsin/index.vue'
 import TrendOverview from './components/TrendOverview/index.vue'
 import SalesOverview from './components/SalesOverview/index.vue'
@@ -85,11 +51,40 @@ provide('tableData', updatedData)
 function handleUpdate(value) {
   updatedData.value = value
 }
-
-
-
 </script>
 
+<template>
+  <div class="outer-container">
+    <TopParentAsin></TopParentAsin>
+    <div class="filters">
+      <DateRangePicker v-model="dateRange"></DateRangePicker>
+      <div v-show="activeName == 'trendOverview'">
+        <el-select v-model="filter1" placeholder="Select" style="width: 240px; margin-right: 8px">
+          <el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
+        <el-select v-model="filter2" placeholder="Select" style="width: 240px">
+          <el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
+      </div>
+    </div>
+    <div>
+      <el-tabs v-model="activeName" type="border-card" class="chart-tabs">
+        <el-tab-pane label="趋势总览" name="trendOverview">
+          <TrendOverview @updateList="handleUpdate"></TrendOverview>
+          <DataTable></DataTable>
+        </el-tab-pane>
+        <el-tab-pane label="广告优化" name="adOptimization">广告优化</el-tab-pane>
+        <el-tab-pane label="销售概览" name="salesOverview" lazy>
+          <SalesOverview></SalesOverview>
+        </el-tab-pane>
+        <el-tab-pane label="竞品推荐" name="cpRecommendations">
+          <CpRecommendations></CpRecommendations>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
 <style scoped>
 .outer-container {
   padding: 5px 10px 0 10px;

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

@@ -1,3 +1,20 @@
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+  value: String,
+  field: String,
+  row: Object,
+  isCompare: Boolean,
+})
+
+// 计算 'gap' 值
+const gapValue = computed(() => {
+  const gapField = `gap${props.field.charAt(0).toUpperCase()}${props.field.slice(1)}` // 构建对应的 gap 前缀字段名称
+  return props.row[gapField] // 返回行数据中对应的 gap 值
+})
+</script>
+
 <template>
   <div>
     <!-- 特定字段的自定义显示,例如 'rank' -->
@@ -51,23 +68,6 @@
   </div>
 </template>
 
-<script setup>
-import { computed } from 'vue'
-
-const props = defineProps({
-  value: String,
-  field: String,
-  row: Object,
-  isCompare: Boolean,
-})
-
-// 计算 'gap' 值
-const gapValue = computed(() => {
-  const gapField = `gap${props.field.charAt(0).toUpperCase()}${props.field.slice(1)}` // 构建对应的 gap 前缀字段名称
-  return props.row[gapField] // 返回行数据中对应的 gap 值
-})
-</script>
-
 <style scoped>
 .img-container {
   width: 72px;

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

@@ -1,3 +1,12 @@
+<script setup>
+defineProps({
+  totalValue: [Number, String],
+  gapValue: Number,
+  isCompare: Boolean,
+  columnIndex: Number,
+})
+</script>
+
 <template>
   <div>
     <!-- 显示合计,这个无条件显示 -->
@@ -14,12 +23,3 @@
     </div>
   </div>
 </template>
-
-<script setup>
-defineProps({
-  totalValue: [Number, String],
-  gapValue: Number,
-  isCompare: Boolean,
-  columnIndex: Number,
-})
-</script>

+ 36 - 37
src/views/productCenter/productList/components/DataTable/index.vue

@@ -1,38 +1,5 @@
-<template>
-  <div style="overflow: hidden; width: 100%; height: 800px" v-loading="tableLoading">
-    <vxe-grid v-bind="gridOptions">
-      <template #toolbar_buttons>
-        <span>
-          数据对比
-          <vxe-switch v-model="isCompare" size="mini" />
-        </span>
-      </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']"
-          v-model:current-page="tablePage.currentPage"
-          v-model:page-size="tablePage.pageSize"
-          :total="tablePage.total"
-          @page-change="handlePageChange">
-        </vxe-pager>
-      </template>
-    </vxe-grid>
-  </div>
-</template>
-
 <script setup lang="ts">
 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'
@@ -119,10 +86,10 @@ async function fetchTableData(type) {
 
   // 要用引号扩住key '产品线'
   const typeToApiAndColumns = {
-    '产品线': { api: getTableDataForProductLine, columns: productLineColumns },
-    '父ASIN': { api: getTableDataForParentASIN, columns: parentAsinColumns },
-    'ASIN': { api: getTableDataForASIN, columns: asinColumns },
-    'SKU': { api: getTableDataForSKU, columns: skuColumns },
+    产品线: { api: getTableDataForProductLine, columns: productLineColumns },
+    父ASIN: { api: getTableDataForParentASIN, columns: parentAsinColumns },
+    ASIN: { api: getTableDataForASIN, columns: asinColumns },
+    SKU: { api: getTableDataForSKU, columns: skuColumns },
   }
   // 根据类型获取对应的API函数和列配置
   const { api: apiFunction, columns } = typeToApiAndColumns[type] || {}
@@ -159,4 +126,36 @@ watch([activeButton, productlineId, dateRange], () => {
 })
 </script>
 
+<template>
+  <div style="overflow: hidden; width: 100%; height: 800px" v-loading="tableLoading">
+    <vxe-grid v-bind="gridOptions">
+      <template #toolbar_buttons>
+        <span>
+          数据对比
+          <vxe-switch v-model="isCompare" size="mini" />
+        </span>
+      </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 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']"
+          v-model:current-page="tablePage.currentPage"
+          v-model:page-size="tablePage.pageSize"
+          :total="tablePage.total"
+          @page-change="handlePageChange">
+        </vxe-pager>
+      </template>
+    </vxe-grid>
+  </div>
+</template>
+
 <style scoped></style>

+ 128 - 122
src/views/productCenter/productList/components/ProductDialog/ProductList.vue

@@ -1,123 +1,3 @@
-<template>
-  <div class="product-select">
-    <div class="left-part" v-loading="infiniteLoad">
-      <el-tabs v-model="activeName">
-        <el-tab-pane label="搜索" name="search">
-          <div class="product-search">
-            <vxe-input v-model="searchInp" @search-click="handleSearch" @keydown="handleKeydown" placeholder="请输入商品名称" type="search" class="search-input" />
-          </div>
-          <div class="padding-0-10">
-            <div class="list-bar">
-              <span class="padding-0-10">商品列表</span>
-              <vxe-button class="custom-vxe-btn" type="text" content="添加" icon="vxe-icon-add" @click="handleSelectedItems" />
-            </div>
-          </div>
-          <ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto;">
-            <div>
-              <el-collapse v-model="activeNames" class="padding-0-10 border-none">
-                <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="" @change="checkAll(item, item.checked)" :disabled="item.allChildrenExist">
-                      {{ item.parentAsin }}
-                    </el-checkbox>
-                    <!-- <p style="margin-left: 10px">111---{{ item.allChildrenExist }}</p> -->
-                    <el-tag style="margin-left: 8px;" effect="plain" size="small" round
-                      >{{ item.num }}
-                      <span v-if="item.num == '1'">ASIN</span>
-                      <span v-else>ASINs</span>
-                    </el-tag>
-                  </template>
-                  <ul class="list-container">
-                    <li v-for="child in item.childAsin" :key="child.asin">
-                      <div class="list-content">
-                        <el-checkbox v-if="child.isExist == false" v-model="child.checked" @change="checkSingle(item)" />
-
-                        <img :src="child.Image" class="image-item" />
-                        <div>
-                          <el-tooltip effect="dark" :content="child.Title" placement="top-start">
-                            <span class="list-item-title">{{ child.Title }}</span>
-                          </el-tooltip>
-                          <div>
-                            <span class="item-font">${{ child.Price ? child.Price : '--' }}</span>
-                            | <span class="item-quantity">{{ child.Quantity ? '有库存' : '缺货' }}</span>
-                          </div>
-                          <div>
-                            <span class="item-asin">ASIN:</span> {{ child.Asin }}
-                            <span v-if="child.isExist" class="exist-item">此商品已存在</span>
-                          </div>
-                        </div>
-                      </div>
-                    </li>
-                  </ul>
-                </el-collapse-item>
-              </el-collapse>
-            </div>
-          </ul>
-        </el-tab-pane>
-        <el-tab-pane label="输入" name="input">
-          <div class="textarea-part">
-            <el-input
-              disabled="true"
-              v-model="textarea"
-              style="width: 100%"
-              :rows="15"
-              type="textarea"
-              placeholder="请输入ASIN, 多个ASIN使用逗号、空格或换行符分隔" />
-            <div class="custom-button">
-              <el-button :disabled="!textarea" type="primary" text bg>添加</el-button>
-            </div>
-          </div>
-        </el-tab-pane>
-      </el-tabs>
-    </div>
-    <div class="right-part">
-      <div>
-        <div class="right-top-part">
-          <span>已添加: {{ addedItem }}</span>
-          <span>
-            <vxe-button
-              v-if="hasSelectedItems"
-              type="text"
-              status="warning"
-              content="删除选中项"
-              icon="vxe-icon-delete"
-              @click="removeSelectedItems"></vxe-button>
-            <vxe-button type="text" status="danger" content="删除所有" icon="vxe-icon-delete" @click="removeAllItems"></vxe-button>
-          </span>
-        </div>
-        <el-scrollbar height="540px">
-          <el-collapse v-model="activeNames" class="padding-0-10 border-none">
-            <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="" @change="checkAll(item, item.checked)">{{ item.parentAsin }}</el-checkbox>
-                <el-tag style="margin-left: 8px" effect="plain" size="small" round>{{ item.childAsin.length }}ASIN</el-tag>
-              </template>
-              <ul class="list-container">
-                <li v-for="child in item.childAsin" :key="child.asin">
-                  <div class="list-content">
-                    <el-checkbox v-model="child.checked" @change="checkSingle(item)"></el-checkbox>
-                    <img :src="child.Image" class="image-item" />
-                    <div>
-                      <el-tooltip effect="dark" :content="child.Title" placement="top-start">
-                        <span class="list-item-title">{{ child.Title }}</span>
-                      </el-tooltip>
-                      <div>
-                        <span class="item-font">${{ child.Price ? child.Price : '--' }}</span>
-                        | <span class="item-quantity">{{ child.Quantity ? '有库存' : '缺货' }}</span>
-                      </div>
-                      <div><span class="item-asin">ASIN:</span> {{ child.Asin }}</div>
-                    </div>
-                  </div>
-                </li>
-              </ul>
-            </el-collapse-item>
-          </el-collapse>
-        </el-scrollbar>
-      </div>
-    </div>
-  </div>
-</template>
-
 <script setup lang="ts">
 import { computed, inject, onBeforeUnmount, onMounted, ref } from 'vue'
 import { getAllProduct } from '/@/views/productCenter/productList/api'
@@ -143,7 +23,7 @@ async function handleSearch() {
     profile_id: profile.value.profile_id,
     asin: searchInp.value,
   }
-  try { 
+  try {
     const response = await getAllProduct(query)
     data.value = response.data
   } catch (error) {
@@ -372,6 +252,132 @@ onBeforeUnmount(() => {
 })
 </script>
 
+<template>
+  <div class="product-select">
+    <div class="left-part" v-loading="infiniteLoad">
+      <el-tabs v-model="activeName">
+        <el-tab-pane label="搜索" name="search">
+          <div class="product-search">
+            <vxe-input
+              v-model="searchInp"
+              @search-click="handleSearch"
+              @keydown="handleKeydown"
+              placeholder="请输入商品名称"
+              type="search"
+              class="search-input" />
+          </div>
+          <div class="padding-0-10">
+            <div class="list-bar">
+              <span class="padding-0-10">商品列表</span>
+              <vxe-button class="custom-vxe-btn" type="text" content="添加" icon="vxe-icon-add" @click="handleSelectedItems" />
+            </div>
+          </div>
+          <ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto">
+            <div>
+              <el-collapse v-model="activeNames" class="padding-0-10 border-none">
+                <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="" @change="checkAll(item, item.checked)" :disabled="item.allChildrenExist">
+                      {{ item.parentAsin }}
+                    </el-checkbox>
+                    <!-- <p style="margin-left: 10px">111---{{ item.allChildrenExist }}</p> -->
+                    <el-tag style="margin-left: 8px" effect="plain" size="small" round
+                      >{{ item.num }}
+                      <span v-if="item.num == '1'">ASIN</span>
+                      <span v-else>ASINs</span>
+                    </el-tag>
+                  </template>
+                  <ul class="list-container">
+                    <li v-for="child in item.childAsin" :key="child.asin">
+                      <div class="list-content">
+                        <el-checkbox v-if="child.isExist == false" v-model="child.checked" @change="checkSingle(item)" />
+
+                        <img :src="child.Image" class="image-item" />
+                        <div>
+                          <el-tooltip effect="dark" :content="child.Title" placement="top-start">
+                            <span class="list-item-title">{{ child.Title }}</span>
+                          </el-tooltip>
+                          <div>
+                            <span class="item-font">${{ child.Price ? child.Price : '--' }}</span>
+                            | <span class="item-quantity">{{ child.Quantity ? '有库存' : '缺货' }}</span>
+                          </div>
+                          <div>
+                            <span class="item-asin">ASIN:</span> {{ child.Asin }}
+                            <span v-if="child.isExist" class="exist-item">此商品已存在</span>
+                          </div>
+                        </div>
+                      </div>
+                    </li>
+                  </ul>
+                </el-collapse-item>
+              </el-collapse>
+            </div>
+          </ul>
+        </el-tab-pane>
+        <el-tab-pane label="输入" name="input">
+          <div class="textarea-part">
+            <el-input
+              disabled="true"
+              v-model="textarea"
+              style="width: 100%"
+              :rows="15"
+              type="textarea"
+              placeholder="请输入ASIN, 多个ASIN使用逗号、空格或换行符分隔" />
+            <div class="custom-button">
+              <el-button :disabled="!textarea" type="primary" text bg>添加</el-button>
+            </div>
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+    <div class="right-part">
+      <div>
+        <div class="right-top-part">
+          <span>已添加: {{ addedItem }}</span>
+          <span>
+            <vxe-button
+              v-if="hasSelectedItems"
+              type="text"
+              status="warning"
+              content="删除选中项"
+              icon="vxe-icon-delete"
+              @click="removeSelectedItems"></vxe-button>
+            <vxe-button type="text" status="danger" content="删除所有" icon="vxe-icon-delete" @click="removeAllItems"></vxe-button>
+          </span>
+        </div>
+        <el-scrollbar height="540px">
+          <el-collapse v-model="activeNames" class="padding-0-10 border-none">
+            <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="" @change="checkAll(item, item.checked)">{{ item.parentAsin }}</el-checkbox>
+                <el-tag style="margin-left: 8px" effect="plain" size="small" round>{{ item.childAsin.length }}ASIN</el-tag>
+              </template>
+              <ul class="list-container">
+                <li v-for="child in item.childAsin" :key="child.asin">
+                  <div class="list-content">
+                    <el-checkbox v-model="child.checked" @change="checkSingle(item)"></el-checkbox>
+                    <img :src="child.Image" class="image-item" />
+                    <div>
+                      <el-tooltip effect="dark" :content="child.Title" placement="top-start">
+                        <span class="list-item-title">{{ child.Title }}</span>
+                      </el-tooltip>
+                      <div>
+                        <span class="item-font">${{ child.Price ? child.Price : '--' }}</span>
+                        | <span class="item-quantity">{{ child.Quantity ? '有库存' : '缺货' }}</span>
+                      </div>
+                      <div><span class="item-asin">ASIN:</span> {{ child.Asin }}</div>
+                    </div>
+                  </div>
+                </li>
+              </ul>
+            </el-collapse-item>
+          </el-collapse>
+        </el-scrollbar>
+      </div>
+    </div>
+  </div>
+</template>
+
 <style scoped>
 .product-select {
   display: flex;
@@ -494,7 +500,7 @@ onBeforeUnmount(() => {
 .border-none {
   border: none;
 }
-:deep(.el-collapse-item:last-child .el-collapse-item__wrap ) {
+:deep(.el-collapse-item:last-child .el-collapse-item__wrap) {
   border-bottom: none;
 }
 </style>

+ 35 - 35
src/views/productCenter/productList/components/ProductDialog/index.vue

@@ -1,38 +1,3 @@
-<template>
-  <el-dialog v-model="createProductDialog" @close="closeDialog" title="新建产品线" width="1300">
-    <el-form
-      v-loading="load"
-      ref="ruleFormRef"
-      class="custom-ruleForm"
-      :model="ruleForm"
-      :rules="rules"
-      label-width="120px"
-      size="default"
-      label-position="top"
-      status-icon>
-      <el-form-item prop="productLineName">
-        <template #label>
-          <span class="form-label"> 产品线名称: </span>
-        </template>
-        <el-input v-model="ruleForm.productLineName" show-word-limit placeholder="请输入产品线名称" maxlength="150" style="width: 500px;" />
-      </el-form-item>
-      <el-form-item required>
-        <template #label>
-          <span class="form-label"> 商品: </span>
-        </template>
-        <ProductList></ProductList>
-      </el-form-item>
-      <el-form-item>
-        <div style="display: flex; flex-direction: row-reverse">
-          <el-button v-if="!isUpdate" style="margin-left: 10px;" color="#3c59b0" @click="submitForm(ruleFormRef)"> 创建 </el-button>
-          <el-button v-if="isUpdate" style="margin-left: 10px;" color="#3c59b0" @click="updateForm(ruleFormRef)"> 确定 </el-button>
-          <el-button plain @click="createProductDialog = false">取消</el-button>
-        </div>
-      </el-form-item>
-    </el-form>
-  </el-dialog>
-</template>
-
 <script setup lang="ts">
 import { onBeforeUnmount, reactive, ref, inject } from 'vue'
 import emitter from '/@/utils/emitter'
@@ -177,6 +142,41 @@ onBeforeUnmount(() => {
 })
 </script>
 
+<template>
+  <el-dialog v-model="createProductDialog" @close="closeDialog" title="新建产品线" width="1300">
+    <el-form
+      v-loading="load"
+      ref="ruleFormRef"
+      class="custom-ruleForm"
+      :model="ruleForm"
+      :rules="rules"
+      label-width="120px"
+      size="default"
+      label-position="top"
+      status-icon>
+      <el-form-item prop="productLineName">
+        <template #label>
+          <span class="form-label"> 产品线名称: </span>
+        </template>
+        <el-input v-model="ruleForm.productLineName" show-word-limit placeholder="请输入产品线名称" maxlength="150" style="width: 500px;" />
+      </el-form-item>
+      <el-form-item required>
+        <template #label>
+          <span class="form-label"> 商品: </span>
+        </template>
+        <ProductList></ProductList>
+      </el-form-item>
+      <el-form-item>
+        <div style="display: flex; flex-direction: row-reverse">
+          <el-button v-if="!isUpdate" style="margin-left: 10px;" color="#3c59b0" @click="submitForm(ruleFormRef)"> 创建 </el-button>
+          <el-button v-if="isUpdate" style="margin-left: 10px;" color="#3c59b0" @click="updateForm(ruleFormRef)"> 确定 </el-button>
+          <el-button plain @click="createProductDialog = false">取消</el-button>
+        </div>
+      </el-form-item>
+    </el-form>
+  </el-dialog>
+</template>
+
 <style scoped>
 /* 不要删除, 否则ProductList组件的样式会错乱 */
 ::v-deep(.el-form-item__content) {

+ 35 - 35
src/views/productCenter/productList/components/ProductSelectCard/index.vue

@@ -1,38 +1,3 @@
-<template>
-  <div class="out-container">
-    <el-scrollbar>
-      <div class="scrollbar-flex-content">
-        <el-card
-          v-for="(item, index) in cardData"
-          :key="item.productlineId"
-          body-style="padding: 0;box-sizing: border-box; position: relative; width: 100%;"
-          class="scrollbar-demo-item"
-          :class="{ selected: selectedCardIndex === index }"
-          @click="selectCard(index, item)">
-          <div class="pct-chart" :id="`chart${index}-${item.productlineId}`"></div>
-          <el-popover v-if="index !== 0" placement="bottom" :width="150" trigger="click">
-            <template #reference>
-              <el-icon class="custom-icon" @click.stop=""><MoreFilled /></el-icon>
-            </template>
-            <div class="custom-popoer">
-              <el-button :icon="Edit" text size="small" @click="editCard(item)">编辑</el-button>
-              <el-button :icon="Delete" text size="small" style="margin-left: 0;">删除</el-button>
-            </div>
-          </el-popover>
-          <div class="left-part-container">
-            <div class="product-line-name">{{ item.productlineName }}</div>
-
-            <div class="custom-part">
-              <div class="total-sales">${{ item.totalSales }}</div>
-              <span class="label">总销售额</span>
-            </div>
-          </div>
-        </el-card>
-      </div>
-    </el-scrollbar>
-  </div>
-</template>
-
 <script setup lang="ts">
 import { onMounted, inject, ref, onBeforeUnmount } from 'vue'
 import { getProductCardData } from '/@/views/productCenter/productList/api'
@@ -147,6 +112,41 @@ onBeforeUnmount(() => {
 })
 </script>
 
+<template>
+  <div class="out-container">
+    <el-scrollbar>
+      <div class="scrollbar-flex-content">
+        <el-card
+          v-for="(item, index) in cardData"
+          :key="item.productlineId"
+          body-style="padding: 0;box-sizing: border-box; position: relative; width: 100%;"
+          class="scrollbar-demo-item"
+          :class="{ selected: selectedCardIndex === index }"
+          @click="selectCard(index, item)">
+          <div class="pct-chart" :id="`chart${index}-${item.productlineId}`"></div>
+          <el-popover v-if="index !== 0" placement="bottom" :width="150" trigger="click">
+            <template #reference>
+              <el-icon class="custom-icon" @click.stop=""><MoreFilled /></el-icon>
+            </template>
+            <div class="custom-popoer">
+              <el-button :icon="Edit" text size="small" @click="editCard(item)">编辑</el-button>
+              <el-button :icon="Delete" text size="small" style="margin-left: 0;">删除</el-button>
+            </div>
+          </el-popover>
+          <div class="left-part-container">
+            <div class="product-line-name">{{ item.productlineName }}</div>
+
+            <div class="custom-part">
+              <div class="total-sales">${{ item.totalSales }}</div>
+              <span class="label">总销售额</span>
+            </div>
+          </div>
+        </el-card>
+      </div>
+    </el-scrollbar>
+  </div>
+</template>
+
 <style scoped>
 .out-container {
   width: 100%;

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

@@ -1,13 +1,3 @@
-<template>
-  <div class="filters">
-    <el-input placeholder="ASIN/父ASIN/标题/SKU"></el-input>
-    <el-select v-model="selectValue" class="filter-select">
-      <el-option v-for="item in options" :key="item.productlineId" :label="item.productlineName" :value="item.productlineId" />
-    </el-select>
-    <DateRangePicker v-model="dateRange"></DateRangePicker>
-  </div>
-</template>
-
 <script setup lang="ts">
 import DateRangePicker from '/@/components/DateRangePicker/index.vue'
 import { usePublicData } from '/@/stores/publicData'
@@ -57,6 +47,16 @@ onBeforeUnmount(() => {
 })
 </script>
 
+<template>
+  <div class="filters">
+    <el-input placeholder="ASIN/父ASIN/标题/SKU"></el-input>
+    <el-select v-model="selectValue" class="filter-select">
+      <el-option v-for="item in options" :key="item.productlineId" :label="item.productlineName" :value="item.productlineId" />
+    </el-select>
+    <DateRangePicker v-model="dateRange"></DateRangePicker>
+  </div>
+</template>
+
 <style scoped>
 .filters {
   display: flex;

+ 41 - 41
src/views/productCenter/productList/index.vue

@@ -1,44 +1,3 @@
-<template>
-  <div class="outer-container">
-    <TopFilters></TopFilters>
-    <div class="table-tips">
-      <el-icon><Warning /></el-icon>
-      <p class="prompt-words">商品中心广告数据统计不包含SB广告</p>
-    </div>
-    <el-card>
-      <DataTendencyChart
-        :metricEnum="productListMetricsEnum"
-        :query="queryParams"
-        :fetchCard="getCardData"
-        :fetchLine="getLineData"
-        :fetch-line-month="getLineMonthData"
-        :fetch-line-week="getLineWeekData">
-      </DataTendencyChart>
-    </el-card>
-  </div>
-  <ProductSelectCard></ProductSelectCard>
-  <div class="pl-and-asin-tables">
-    <div class="asin-table-container">
-      <vxe-button class="custom-button" type="text" status="primary" content="创建产品线" icon="vxe-icon-add" @click="handleProductlog"></vxe-button>
-      <div class="xp-radio-group-wrapper">
-        <el-button-group>
-          <el-button
-            bg
-            text
-            v-for="button in buttons"
-            :key="button"
-            :style="activeButton === button ? activeStyle : {}"
-            @click="() => handleClickBtn(button)">
-            {{ button }}
-          </el-button>
-        </el-button-group>
-      </div>
-      <DataTable></DataTable>
-    </div>
-  </div>
-  <ProductLineDialog></ProductLineDialog>
-</template>
-
 <script setup lang="ts">
 import { storeToRefs } from 'pinia'
 import { onBeforeUnmount, provide, ref } from 'vue'
@@ -90,6 +49,47 @@ onBeforeUnmount(() => {
 })
 </script>
 
+<template>
+  <div class="outer-container">
+    <TopFilters></TopFilters>
+    <div class="table-tips">
+      <el-icon><Warning /></el-icon>
+      <p class="prompt-words">商品中心广告数据统计不包含SB广告</p>
+    </div>
+    <el-card>
+      <DataTendencyChart
+        :metricEnum="productListMetricsEnum"
+        :query="queryParams"
+        :fetchCard="getCardData"
+        :fetchLine="getLineData"
+        :fetch-line-month="getLineMonthData"
+        :fetch-line-week="getLineWeekData">
+      </DataTendencyChart>
+    </el-card>
+  </div>
+  <ProductSelectCard></ProductSelectCard>
+  <div class="pl-and-asin-tables">
+    <div class="asin-table-container">
+      <vxe-button class="custom-button" type="text" status="primary" content="创建产品线" icon="vxe-icon-add" @click="handleProductlog"></vxe-button>
+      <div class="xp-radio-group-wrapper">
+        <el-button-group>
+          <el-button
+            bg
+            text
+            v-for="button in buttons"
+            :key="button"
+            :style="activeButton === button ? activeStyle : {}"
+            @click="() => handleClickBtn(button)">
+            {{ button }}
+          </el-button>
+        </el-button-group>
+      </div>
+      <DataTable></DataTable>
+    </div>
+  </div>
+  <ProductLineDialog></ProductLineDialog>
+</template>
+
 <style scoped>
 .outer-container {
   padding: 5px 10px 0 10px;