Răsfoiți Sursa

feat(product-manage): 添加历史详情页面和评论详情组件

- 新增历史详情页面,包含商品价格趋势图表
- 优化商品信息组件 sku 展示效果
- 添加获取图表数据的 API 接口
- 优化评论详情页面布局和样式
WanGxC 6 luni în urmă
părinte
comite
e152383dfd

+ 20 - 7
src/views/product-manage/comment-detail/component/AverageMonthly.vue

@@ -65,9 +65,8 @@ function updateChart() {
         type: 'value',
         name: '总量',
         nameTextStyle: {
-          fontWeight: 'bold',
           fontSize: 14,
-          color: '#333'
+          color: '#3480CE',
         },
         splitLine: {
           show: true
@@ -75,7 +74,7 @@ function updateChart() {
         axisLine: {
           show: true,
           lineStyle: {
-            color: '#333',
+            color: '#3480CE',
             width: 1
           }
         }
@@ -85,9 +84,8 @@ function updateChart() {
         type: 'value',
         name: '平均分',
         nameTextStyle: {
-          fontWeight: 'bold',
           fontSize: 14,
-          color: '#333'
+          color: '#F19A38',
         },
         splitLine: {
           show: false
@@ -95,7 +93,7 @@ function updateChart() {
         axisLine: {
           show: true,
           lineStyle: {
-            color: '#333',
+            color: '#F19A38',
             width: 1
           }
         }
@@ -104,6 +102,7 @@ function updateChart() {
     series: [
       {
         yAxisIndex: 0,
+        color: '#3480CE',
         name: '总量',
         type: 'bar',
         barWidth: '18px',
@@ -113,8 +112,22 @@ function updateChart() {
       },
       {
         yAxisIndex: 1,
+        color: '#F19A38',
         name: '平均分',
-        type: 'line'
+        type: 'line',
+        areaStyle: {
+          // 设置渐变颜色
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            {
+              offset: 0,
+              color: 'rgba(241,154,56, 0.1)'
+            },
+            {
+              offset: 1,
+              color: 'rgba(241,154,56, 0)'
+            }
+          ])
+        }
       }
     ]
   };

+ 59 - 0
src/views/product-manage/comment-detail/component/TitleCard.vue

@@ -0,0 +1,59 @@
+<script lang="ts" setup>
+/**
+ * @Name: TitleCard.vue
+ * @Description: 评论详情-标题卡片
+ * @Author: Cheney
+ */
+
+import { handleCopy } from '/@/utils/useCopyText';
+import VerticalDivider from '/@/components/VerticalDivider/index.vue';
+import { DocumentCopy, Picture as IconPicture } from '@element-plus/icons-vue';
+
+
+const props = defineProps({
+  img: String,
+  url: String,
+  title: String,
+  asin: String
+});
+const { img, url, title, asin } = props;
+</script>
+
+<template>
+  <el-card body-class="flex justify-between items-center gap-5" class="border-none sticky top-5 z-10">
+    <div class="flex">
+      <el-image :src="`https://d1ge0kk1l5kms0.cloudfront.net/images/I/${img}.jpg`" class="mr-3"
+                fit="fill"
+                lazy style="min-width: 78px; height: 78px;">
+        <template #error>
+          <div class="flex justify-center items-center h-full w-full text-2xl"
+               style="background:var(--el-fill-color-light)">
+            <el-icon>
+              <icon-picture />
+            </el-icon>
+          </div>
+        </template>
+      </el-image>
+      <div>
+        <el-link :href="url"
+                 :underline="false"
+                 style="font-size: 18px;"
+                 type="primary">
+          <span class="line-clamp-2 text-ellipsis whitespace-normal">{{ title || '--' }}</span>
+        </el-link>
+        <div class="flex items-center">
+          <div class="font-semibold italic">{{ asin }}</div>
+          <VerticalDivider />
+          <el-icon class="ml-2 cursor-pointer" @click="handleCopy(asin)">
+            <DocumentCopy />
+          </el-icon>
+        </div>
+      </div>
+    </div>
+    <!--<el-button :icon="Back" plain round type="info" @click="handleBack">返 回</el-button>-->
+  </el-card>
+</template>
+
+<style scoped>
+
+</style>

+ 2 - 37
src/views/product-manage/comment-detail/index.vue

@@ -5,12 +5,8 @@
  * @Author: Cheney
  */
 
-import { DocumentCopy, Picture as IconPicture } from '@element-plus/icons-vue';
-import NegativeLabel from '/@/views/product-manage/comment-detail/component/NegativeLabel.vue';
-import NegativeClassification from '/@/views/product-manage/comment-detail/component/NegativeClassification.vue';
 import AverageMonthly from '/@/views/product-manage/comment-detail/component/AverageMonthly.vue';
-import VerticalDivider from '/@/components/VerticalDivider/index.vue';
-import { handleCopy } from '/@/utils/useCopyText';
+import TitleCard from './component/TitleCard.vue';
 
 
 const isShowComment = defineModel({ default: false });
@@ -37,38 +33,7 @@ const { rowData } = props;
       <div class="sticky top-0" style="background-color:#F3F4FB; min-height: 20px; z-index: 2"></div>
       <div class="px-5">
         <!-- Title Card -->
-        <el-card body-class="flex justify-between items-center gap-5" class="border-none sticky top-5 z-10">
-          <div class="flex">
-            <el-image :src="`https://d1ge0kk1l5kms0.cloudfront.net/images/I/${rowData.img}.jpg`" class="mr-3"
-                      fit="fill"
-                      lazy style="min-width: 78px; height: 78px;">
-              <template #error>
-                <div class="flex justify-center items-center h-full w-full text-2xl"
-                     style="background:var(--el-fill-color-light)">
-                  <el-icon>
-                    <icon-picture />
-                  </el-icon>
-                </div>
-              </template>
-            </el-image>
-            <div>
-              <el-link :href="rowData.url"
-                       :underline="false"
-                       style="font-size: 18px;"
-                       type="primary">
-                <span class="line-clamp-2 text-ellipsis whitespace-normal">{{ rowData.title || '--' }}</span>
-              </el-link>
-              <div class="flex items-center">
-                <div class="font-semibold italic">{{ rowData.asin }}</div>
-                <VerticalDivider />
-                <el-icon class="ml-2 cursor-pointer" @click="handleCopy(rowData.asin)">
-                  <DocumentCopy />
-                </el-icon>
-              </div>
-            </div>
-          </div>
-          <!--<el-button :icon="Back" plain round type="info" @click="handleBack">返 回</el-button>-->
-        </el-card>
+        <TitleCard :asin="rowData.asin" :img="rowData.img" :title="rowData.title" :url="rowData.url" />
         <!-- Chart -->
         <!--<el-row :gutter="20" class="mt-5" style="z-index: 1">-->
         <!--  <el-col :span="12">-->

+ 1 - 2
src/views/product-manage/component/ProductInfo.vue

@@ -61,9 +61,8 @@ const props = defineProps({
           <span style="color: #1d2129;">
             {{ item.asin || '--' }}
           </span>
-
         </p>
-        <el-tooltip :content="item.sku" effect="light" show-after="300">
+        <el-tooltip :content="item.sku" effect="light" show-after="300" :disabled="!item.sku">
           <p class="m-0 p-0 line-clamp-1 text-ellipsis">
             SKU:
             <span style="color: #1d2129;">

+ 10 - 0
src/views/product-manage/historical-detail/api.ts

@@ -0,0 +1,10 @@
+import { request } from '/@/utils/service';
+
+
+export function getChartData(query: any) {
+  return request({
+    url: '/api/choice/goods/price-chart/',
+    method: 'GET',
+    params: query
+  });
+}

+ 142 - 0
src/views/product-manage/historical-detail/component/PriceChart.vue

@@ -0,0 +1,142 @@
+<script setup lang="ts">
+/**
+ * @Name: TrendChart.vue
+ * @Description:
+ * @Author: Cheney
+ */
+
+import * as echarts from 'echarts';
+import * as api from '../api';
+import { useResponse } from '/@/utils/useResponse';
+
+
+const props = defineProps({
+  asin: String,
+  country: String
+});
+const { asin, country } = props;
+
+let chartRef: any = useTemplateRef('chartRef');
+let chart: echarts.ECharts | null = null;
+let resizeObserver: ResizeObserver | null = null;
+let chartData: any = [];
+
+onBeforeMount(() => {
+  fetchChartData();
+});
+
+onMounted(() => {
+  initChart();
+});
+
+onUnmounted(() => {
+  resizeObserver?.disconnect();
+  chart?.dispose();
+});
+
+function updateChart() {
+  if (!chart || chartData.length === 0) return;
+
+  const chartOptions = {
+    title: {
+      text: '商品价格趋势'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: [ '价格' ]
+    },
+    grid: {
+      top: '20%',
+      left: '10%',
+      right: '10%',
+      bottom: '10%'
+    },
+    dataset: {
+      dimensions: [ 'create_datetime', 'new_val' ],
+      source: chartData
+    },
+    xAxis: {
+      type: 'category'
+    },
+    yAxis: [
+      {
+        type: 'value',
+        name: '价格',
+        nameTextStyle: {
+          fontWeight: 'bold',
+          fontSize: 14,
+          color: '#333'
+        },
+        splitLine: {
+          show: true
+        },
+        axisLine: {
+          show: true,
+          lineStyle: {
+            color: '#333',
+            width: 1
+          }
+        }
+      }
+    ],
+    series: [
+      {
+        name: '价格',
+        type: 'line',
+        areaStyle: {
+          // 设置渐变颜色
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            {
+              offset: 0,
+              color: 'rgba(84,112,198, 0.4)'
+            },
+            {
+              offset: 1,
+              color: 'rgba(84,112,198, 0.1)'
+            }
+          ])
+        }
+      }
+    ]
+  };
+
+  chart.setOption(chartOptions);
+}
+
+function initChart() {
+  if (!chartRef.value) return;
+
+  chart = echarts.init(chartRef.value);
+  updateChart();
+
+  resizeObserver = new ResizeObserver(() => {
+    chart?.resize();
+  });
+  if (chartRef.value) {
+    resizeObserver.observe(chartRef.value);
+  }
+}
+
+async function fetchChartData() {
+  const res = await useResponse(api.getChartData, { asin, country_code: country });
+  if (res.code === 2000 && res.data) {
+    chartData = res.data;
+    updateChart();
+  }
+}
+</script>
+
+<template>
+  <el-card class="border-none sticky top-5  z-10">
+    <div ref="chartRef" class="chart"></div>
+  </el-card>
+</template>
+
+<style scoped>
+.chart {
+  width: 100%;
+  height: 400px;
+}
+</style>

+ 5 - 18
src/views/product-manage/historical-detail/index.vue

@@ -6,6 +6,7 @@
  */
 
 import { useTableHeight } from '/@/utils/useCustomHeight';
+import PriceChart from '/@/views/product-manage/historical-detail/component/PriceChart.vue';
 
 
 const isShowHistory = defineModel({ default: false });
@@ -15,8 +16,6 @@ const props = defineProps({
   title: String
 });
 const { rowData, title } = props;
-console.log("(index.vue: 15)=> rowData", rowData);
-
 
 const heightObj = { topBar: 50, cardMargin: 8, cardPadding: 20 };
 const { tableHeight } = useTableHeight(heightObj);
@@ -30,28 +29,16 @@ const { tableHeight } = useTableHeight(heightObj);
         ref="editDrawer"
         v-model="isShowHistory"
         :show-close="false"
+        :title="`${title} - 历史详情`"
         direction="btt"
         size="85%"
-        style="background-color:#F3F4FB;"
-        :title="`${title} - 历史详情`">
+        style="background-color:#F3F4FB;">
       <div class="sticky top-0" style="background-color:#F3F4FB; min-height: 20px; z-index: 2"></div>
       <div class="px-5">
-        <el-card>12341</el-card>
-        <el-card :body-style="{ height: tableHeight + 'px' }">
-          <div class="h-full overflow-hidden">
-            <vxe-table height="100%">
-              <vxe-column type="seq"></vxe-column>
-              <vxe-column type="seq"></vxe-column>
-              <vxe-column type="seq"></vxe-column>
-              <vxe-column type="seq"></vxe-column>
-              <vxe-column type="seq"></vxe-column>
-            </vxe-table>
-          </div>
-        </el-card>
+        <PriceChart :asin="rowData.asin" :country="rowData.country_code" />
+        
       </div>
-      
     </el-drawer>
-
   </div>
 
 </template>