热门产品前端页面
This commit is contained in:
@@ -43,19 +43,27 @@ export function delProductSalesScript(scriptId) {
|
||||
})
|
||||
}
|
||||
|
||||
// 记录话术访问频率
|
||||
export function recordVisit(productId) {
|
||||
return request({
|
||||
url: '/klp/productSalesScript/recordVisit/' + productId,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
// // 记录话术访问频率
|
||||
// export function recordVisit(productId) {
|
||||
// return request({
|
||||
// url: '/klp/productSalesScript/recordVisit/' + productId,
|
||||
// method: 'post'
|
||||
// })
|
||||
// }
|
||||
|
||||
// 获取热门产品排行
|
||||
export function getHotProducts(limit = 10) {
|
||||
// // 获取热门产品排行
|
||||
// export function getHotProducts(limit = 10) {
|
||||
// return request({
|
||||
// url: '/klp/productSalesScript/hotProducts',
|
||||
// method: 'get',
|
||||
// params: { limit }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 获取产品咨询热度排行
|
||||
export function getProductRanking() {
|
||||
return request({
|
||||
url: '/klp/productSalesScript/hotProducts',
|
||||
method: 'get',
|
||||
params: { limit }
|
||||
url: '/klp/productSalesScript/dashboard/ranking',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
619
klp-ui/src/views/wms/hotProduct/index.vue
Normal file
619
klp-ui/src/views/wms/hotProduct/index.vue
Normal file
@@ -0,0 +1,619 @@
|
||||
<template>
|
||||
<div class="hot-product-page">
|
||||
<!-- 页面标题 -->
|
||||
<div class="page-header">
|
||||
<h2 class="page-title">
|
||||
<i class="el-icon-trophy"></i>
|
||||
热门产品排行
|
||||
</h2>
|
||||
<div class="page-subtitle">基于产品咨询访问频率的热门产品分析</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计卡片 -->
|
||||
<el-row :gutter="20" class="statistics-row">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
|
||||
<i class="el-icon-view"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ totalViews }}</div>
|
||||
<div class="stat-label">总访问量</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||||
<i class="el-icon-goods"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ totalProducts }}</div>
|
||||
<div class="stat-label">热门产品数</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
|
||||
<i class="el-icon-star-on"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ avgViews }}</div>
|
||||
<div class="stat-label">平均访问量</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
|
||||
<i class="el-icon-trend-charts"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-number">{{ maxViews }}</div>
|
||||
<div class="stat-label">最高访问量</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<el-row :gutter="20" class="main-content">
|
||||
<!-- 左侧:排行榜 -->
|
||||
<el-col :span="16">
|
||||
<el-card shadow="hover" class="ranking-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="header-title">
|
||||
<i class="el-icon-medal"></i>
|
||||
产品咨询热度排行榜
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<el-button type="text" @click="refreshData" :loading="loading">
|
||||
<i class="el-icon-refresh"></i>
|
||||
刷新
|
||||
</el-button>
|
||||
<el-button type="text" @click="exportData">
|
||||
<i class="el-icon-download"></i>
|
||||
导出
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ranking-list">
|
||||
<div
|
||||
v-for="(item, index) in productRanking"
|
||||
:key="item.productId"
|
||||
class="ranking-item"
|
||||
:class="{ 'top-three': index < 3 }"
|
||||
>
|
||||
<div class="ranking-number" :class="`rank-${index + 1}`">
|
||||
{{ item.ranking }}
|
||||
</div>
|
||||
<div class="product-info">
|
||||
<div class="product-name">{{ item.productName }}</div>
|
||||
<div class="product-code">{{ item.productCode }}</div>
|
||||
</div>
|
||||
<div class="view-count">
|
||||
<div class="count-number">{{ item.viewCount }}</div>
|
||||
<div class="count-label">次访问</div>
|
||||
</div>
|
||||
<div class="trend-indicator">
|
||||
<i class="el-icon-arrow-up" v-if="index < 3"></i>
|
||||
<i class="el-icon-minus" v-else></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:图表 -->
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="chart-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="header-title">
|
||||
<i class="el-icon-pie-chart"></i>
|
||||
访问量分布
|
||||
</span>
|
||||
</div>
|
||||
<div ref="pieChart" class="chart-container"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 底部图表 -->
|
||||
<el-row :gutter="20" class="bottom-charts">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover" class="chart-card">
|
||||
<div slot="header" class="card-header">
|
||||
<span class="header-title">
|
||||
<i class="el-icon-data-line"></i>
|
||||
访问量趋势图
|
||||
</span>
|
||||
</div>
|
||||
<div ref="barChart" class="chart-container-large"></div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" @click="refreshData" :loading="loading">
|
||||
<i class="el-icon-refresh"></i>
|
||||
刷新数据
|
||||
</el-button>
|
||||
<el-button @click="exportData">
|
||||
<i class="el-icon-download"></i>
|
||||
导出排行榜
|
||||
</el-button>
|
||||
<el-button @click="openSettings">
|
||||
<i class="el-icon-setting"></i>
|
||||
设置
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
import { getProductRanking } from '@/api/wms/productSalesScript'
|
||||
|
||||
export default {
|
||||
name: 'HotProduct',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
productRanking: [],
|
||||
totalViews: 0,
|
||||
totalProducts: 0,
|
||||
avgViews: 0,
|
||||
maxViews: 0,
|
||||
charts: {
|
||||
pie: null,
|
||||
bar: null
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadData()
|
||||
this.initCharts()
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
Object.values(this.charts).forEach(chart => {
|
||||
if (chart) {
|
||||
chart.dispose()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.loading = true
|
||||
try {
|
||||
const response = await getProductRanking()
|
||||
this.productRanking = response.data || []
|
||||
this.calculateStatistics()
|
||||
this.renderCharts()
|
||||
} catch (error) {
|
||||
console.error('加载数据失败:', error)
|
||||
this.$message.error('加载数据失败')
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
calculateStatistics() {
|
||||
if (this.productRanking.length === 0) {
|
||||
this.totalViews = 0
|
||||
this.totalProducts = 0
|
||||
this.avgViews = 0
|
||||
this.maxViews = 0
|
||||
return
|
||||
}
|
||||
|
||||
this.totalViews = this.productRanking.reduce((sum, item) => sum + (item.viewCount || 0), 0)
|
||||
this.totalProducts = this.productRanking.length
|
||||
this.avgViews = Math.round(this.totalViews / this.totalProducts)
|
||||
this.maxViews = Math.max(...this.productRanking.map(item => item.viewCount || 0))
|
||||
},
|
||||
|
||||
initCharts() {
|
||||
this.charts.pie = echarts.init(this.$refs.pieChart)
|
||||
this.charts.bar = echarts.init(this.$refs.barChart)
|
||||
},
|
||||
|
||||
renderCharts() {
|
||||
this.renderPieChart()
|
||||
this.renderBarChart()
|
||||
},
|
||||
|
||||
renderPieChart() {
|
||||
const data = this.productRanking.slice(0, 5) // 只显示前5名
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
top: 'middle'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '访问量',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
center: ['60%', '50%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '18',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: data.map((item, index) => ({
|
||||
name: item.productName,
|
||||
value: item.viewCount,
|
||||
itemStyle: {
|
||||
color: this.getRankColor(index + 1)
|
||||
}
|
||||
}))
|
||||
}
|
||||
]
|
||||
}
|
||||
this.charts.pie.setOption(option)
|
||||
},
|
||||
|
||||
renderBarChart() {
|
||||
const data = this.productRanking.slice(0, 10) // 显示前10名
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: data.map(item => item.productName),
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
rotate: 30,
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '访问次数'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '访问量',
|
||||
type: 'bar',
|
||||
data: data.map((item, index) => ({
|
||||
value: item.viewCount,
|
||||
itemStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: this.getRankColor(index + 1) },
|
||||
{ offset: 1, color: this.getRankColor(index + 1, 0.7) }
|
||||
])
|
||||
}
|
||||
})),
|
||||
barWidth: '60%',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
fontSize: 12
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
this.charts.bar.setOption(option)
|
||||
},
|
||||
|
||||
getRankColor(rank, alpha = 1) {
|
||||
const colors = {
|
||||
1: `rgba(255, 215, 0, ${alpha})`, // 金色
|
||||
2: `rgba(192, 192, 192, ${alpha})`, // 银色
|
||||
3: `rgba(205, 127, 50, ${alpha})`, // 铜色
|
||||
4: `rgba(100, 149, 237, ${alpha})`, // 蓝色
|
||||
5: `rgba(50, 205, 50, ${alpha})` // 绿色
|
||||
}
|
||||
return colors[rank] || `rgba(128, 128, 128, ${alpha})`
|
||||
},
|
||||
|
||||
handleResize() {
|
||||
Object.values(this.charts).forEach(chart => {
|
||||
if (chart) {
|
||||
chart.resize()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
refreshData() {
|
||||
this.loadData()
|
||||
},
|
||||
|
||||
exportData() {
|
||||
// 导出功能
|
||||
const data = this.productRanking.map(item => ({
|
||||
'排名': item.ranking,
|
||||
'产品名称': item.productName,
|
||||
'产品编号': item.productCode,
|
||||
'访问次数': item.viewCount
|
||||
}))
|
||||
|
||||
// 这里可以调用导出Excel的方法
|
||||
this.$message.success('导出功能开发中...')
|
||||
},
|
||||
|
||||
openSettings() {
|
||||
this.$message.info('设置功能开发中...')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hot-product-page {
|
||||
padding: 20px;
|
||||
background: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin: 0 0 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-title i {
|
||||
margin-right: 10px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.statistics-row {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 15px;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.stat-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.ranking-card, .chart-card {
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-title i {
|
||||
margin-right: 8px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ranking-list {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.ranking-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
margin-bottom: 10px;
|
||||
background: #fafafa;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
border-left: 4px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.ranking-item:hover {
|
||||
background: #f0f9ff;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.ranking-item.top-three {
|
||||
background: linear-gradient(135deg, #fff9e6 0%, #fff2cc 100%);
|
||||
border-left-color: #ffd700;
|
||||
}
|
||||
|
||||
.ranking-number {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-right: 20px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.rank-1 {
|
||||
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
|
||||
}
|
||||
|
||||
.rank-2 {
|
||||
background: linear-gradient(135deg, #c0c0c0 0%, #e5e5e5 100%);
|
||||
}
|
||||
|
||||
.rank-3 {
|
||||
background: linear-gradient(135deg, #cd7f32 0%, #daa520 100%);
|
||||
}
|
||||
|
||||
.ranking-number:not(.rank-1):not(.rank-2):not(.rank-3) {
|
||||
background: linear-gradient(135deg, #409eff 0%, #67c23a 100%);
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.product-code {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.view-count {
|
||||
text-align: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.count-number {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.count-label {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.trend-indicator {
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.trend-indicator i {
|
||||
font-size: 16px;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chart-container-large {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bottom-charts {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.action-buttons .el-button {
|
||||
margin: 0 10px;
|
||||
padding: 12px 24px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.action-buttons .el-button i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,165 +0,0 @@
|
||||
<template>
|
||||
<div class="hot-products-chart">
|
||||
<el-card shadow="hover">
|
||||
<div v-if="!hotProducts || hotProducts.length === 0" class="no-data-placeholder">
|
||||
暂无热门产品数据
|
||||
</div>
|
||||
<div v-show="hotProducts && hotProducts.length > 0" ref="chart" class="chart-container"></div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
export default {
|
||||
name: 'HotProducts',
|
||||
props: {
|
||||
hotProducts: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chartInstance: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
hotProducts: {
|
||||
deep: true,
|
||||
handler(newVal) {
|
||||
if (newVal && newVal.length > 0) {
|
||||
this.$nextTick(() => {
|
||||
this.renderChart(newVal)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('resize', this.handleResize)
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.chartInstance) {
|
||||
this.chartInstance.dispose()
|
||||
this.chartInstance = null
|
||||
}
|
||||
window.removeEventListener('resize', this.handleResize)
|
||||
},
|
||||
methods: {
|
||||
renderChart(data) {
|
||||
const chartDom = this.$refs.chart
|
||||
if (!chartDom) return
|
||||
|
||||
if (!this.chartInstance) {
|
||||
this.chartInstance = echarts.init(chartDom)
|
||||
}
|
||||
|
||||
this.chartInstance.resize()
|
||||
|
||||
const productNames = data.map(item => item.productName)
|
||||
const visitCounts = data.map(item => item.visitCount)
|
||||
|
||||
const option = {
|
||||
title: {
|
||||
text: '热门产品排行(访问频率)',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
color: '#333',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 18
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
formatter: function(params) {
|
||||
const data = params[0]
|
||||
const rank = data.dataIndex + 1
|
||||
return `${rank}. ${data.name}<br/>访问次数: ${data.value}次`
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: productNames,
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
rotate: 30,
|
||||
color: '#666'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLine: {
|
||||
show: true
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
type: 'dashed'
|
||||
}
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '访问次数',
|
||||
type: 'bar',
|
||||
data: visitCounts,
|
||||
barWidth: '60%',
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
color: '#333',
|
||||
formatter: function(params) {
|
||||
return params.value + '次'
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
color: function(params) {
|
||||
const colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9']
|
||||
return colors[params.dataIndex % colors.length]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
this.chartInstance.setOption(option)
|
||||
},
|
||||
handleResize() {
|
||||
if (this.chartInstance) {
|
||||
this.chartInstance.resize()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hot-products-chart {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
.no-data-placeholder {
|
||||
height: 350px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
@@ -28,12 +28,6 @@
|
||||
<CustomerRegion :customer-data="customerClusterData" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 第二行图表 -->
|
||||
<el-row :gutter="20" class="chart-row">
|
||||
<el-col :span="12">
|
||||
<HotProducts :hot-products="hotProductsData" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 定时刷新设置抽屉 -->
|
||||
<el-drawer
|
||||
title="定时刷新设置"
|
||||
@@ -62,7 +56,6 @@ import OrderSummary from './components/OrderSummary.vue'
|
||||
import OrderCompletion from './components/OrderCompletion.vue'
|
||||
import ProductSales from './components/ProductSales.vue'
|
||||
import CustomerRegion from './components/CustomerRegion.vue'
|
||||
import HotProducts from './components/HotProducts.vue'
|
||||
import { getDashboardData } from '@/api/wms/order'
|
||||
|
||||
export default {
|
||||
@@ -72,7 +65,6 @@ export default {
|
||||
OrderCompletion,
|
||||
ProductSales,
|
||||
CustomerRegion,
|
||||
HotProducts,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -83,7 +75,6 @@ export default {
|
||||
},
|
||||
productSalesData: [],
|
||||
customerClusterData: [],
|
||||
hotProductsData: [],
|
||||
// 新增定时刷新相关数据
|
||||
drawerVisible: false,
|
||||
autoRefresh: false,
|
||||
@@ -114,7 +105,6 @@ export default {
|
||||
}
|
||||
this.productSalesData = data.productRank
|
||||
this.customerClusterData = data.customerRegion
|
||||
this.hotProductsData = data.hotProducts || []
|
||||
this.materialAnalysisData = {
|
||||
categories: data.orderMaterial.map(item => item.materialName),
|
||||
usageFrequency: data.orderMaterial.map(item => item.usedCount),
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
|
||||
|
||||
<script>
|
||||
import { listProductSalesScript, getProductSalesScript, delProductSalesScript, addProductSalesScript, updateProductSalesScript, recordVisit } from "@/api/wms/productSalesScript";
|
||||
import { listProductSalesScript, getProductSalesScript, delProductSalesScript, addProductSalesScript, updateProductSalesScript } from "@/api/wms/productSalesScript";
|
||||
import ProductSelect from '@/components/KLPService/ProductSelect';
|
||||
import VditorEditor from '@/components/VditorEditor.vue';
|
||||
|
||||
@@ -269,22 +269,6 @@ export default {
|
||||
this.title = "修改产品销售话术";
|
||||
});
|
||||
},
|
||||
/** 查看按钮操作 */
|
||||
handleView(row) {
|
||||
this.reset();
|
||||
const scriptId = row.scriptId || this.ids
|
||||
getProductSalesScript(scriptId).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "查看产品销售话术";
|
||||
});
|
||||
// 记录访问频率
|
||||
if (row.productId) {
|
||||
recordVisit(row.productId).catch(err => {
|
||||
console.warn('记录访问频率失败:', err);
|
||||
});
|
||||
}
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
|
||||
Reference in New Issue
Block a user