From 6c38e982b3876cc27bcc360aa2e19d3aa1f87a47 Mon Sep 17 00:00:00 2001 From: ylj20011123 Date: Fri, 24 Oct 2025 16:06:12 +0800 Subject: [PATCH] update --- .../components/OrderTransactionAnalysis.vue | 257 +++++++++++++++--- .../RegionalServiceAreaAnalysis.vue | 200 ++++++++------ .../components/TransactionReport.vue | 28 +- .../js_sdk/u-charts/config-ucharts.js | 12 +- pages/DigitalIntelligenceDashboard/index.vue | 6 +- 5 files changed, 368 insertions(+), 135 deletions(-) diff --git a/pages/DigitalIntelligenceDashboard/components/OrderTransactionAnalysis.vue b/pages/DigitalIntelligenceDashboard/components/OrderTransactionAnalysis.vue index 1c46811..c3078c2 100644 --- a/pages/DigitalIntelligenceDashboard/components/OrderTransactionAnalysis.vue +++ b/pages/DigitalIntelligenceDashboard/components/OrderTransactionAnalysis.vue @@ -73,7 +73,8 @@ + :canvas2d="true" :inScrollView="true" canvasId="timeDistributionChart" + tooltipFormat="timeDistributionChartData" /> @@ -87,7 +88,21 @@ + :inScrollView="true" canvasId="regionDistributionChart" tooltipFormat="regionDistributionData" /> + + + + + + + + {{ item.name }} + {{ item.percentage }}% + + + + @@ -96,12 +111,12 @@ 商品销售量分析 - TOP 10 热销商品销量 + TOP 5 热销商品销量 + :inScrollView="true" canvasId="salesVolumeChart" tooltipFormat="SalesRankingOfProducts"/> @@ -191,6 +206,14 @@ export default { // 时间分布图表配置 timeDistributionOpts() { + // 获取数据的最大值来动态设置y轴,将字符串转换为数字 + const allData = [ + ...this.timeDistributionData.transactionData.map(item => Number(item) || 0), + ...this.timeDistributionData.amountData.map(item => Number(item) || 0) + ] + const maxValue = Math.max(...allData) + const yAxisMax = this.calculateYAxisMax(maxValue) + return { color: ['#576EFF', '#52C41A'], padding: [15, 15, 15, 15], @@ -204,15 +227,12 @@ export default { yAxis: { gridType: 'dash', dashLength: 2, - data: [ - { - min: 0 - }, - { - min: 0, - position: 'right' - } - ] + data: [{ + min: 0, + max: yAxisMax, + // 使用splitNumber控制刻度数量 + splitNumber: 6 + }] }, extra: { line: { @@ -224,36 +244,77 @@ export default { } }, + // 预定义颜色数组 + colorPalette() { + return [ + '#576EFF', '#52C41A', '#FAAD14', '#FF4D4F', '#722ED1', + '#13C2C2', '#EB2F96', '#F5222D', '#FA8C16', '#A0D911', + '#52C41A', '#1890FF', '#722ED1', '#EB2F96', '#13C2C2', + '#FAAD14', '#F5222D', '#FA8C16', '#A0D911', '#52C41A', + '#1890FF', '#722ED1', '#EB2F96', '#13C2C2', '#FAAD14', + '#F5222D', '#FA8C16', '#A0D911', '#52C41A', '#1890FF' + ] + }, + // 地域分布图表数据 regionDistributionData() { + // 预处理数据,计算百分比 + const total = this.regionData.reduce((sum, item) => sum + Number(item.value), 0) + return { series: [{ - data: this.regionData.map(item => ({ + data: this.regionData.map((item, index) => ({ name: item.name, - value: item.value + value: Number(item.value), + color: this.colorPalette[index % this.colorPalette.length], // 为每个数据项分配颜色 + data: { + percentage: (Number(item.value) / total * 100), + originalIndex: index // 保存原始索引用于颜色映射 + } })) }] } }, + // 自定义图例数据 + regionLegendData() { + // 预处理数据,计算百分比并分配颜色 + const total = this.regionData.reduce((sum, item) => sum + Number(item.value), 0) + + return this.regionData.map((item, index) => ({ + name: item.name, + value: Number(item.value), + percentage: ((Number(item.value) / total * 100).toFixed(1)), + color: this.colorPalette[index % this.colorPalette.length], // 基于原始索引分配颜色 + originalIndex: index // 保存原始索引 + })).sort((a, b) => b.value - a.value) // 按值从大到小排序 + }, + // 地域分布图表配置 regionDistributionOpts() { return { padding: [5, 5, 5, 5], - dataLabel: true, + dataLabel: false, legend: { - show: true + show: false // 关闭原生图例,使用自定义图例 }, extra: { pie: { activeOpacity: 0.5, activeRadius: 10, offsetAngle: 0, - labelWidth: 15, border: false, - borderWidth: 3, + borderWidth: 2, borderColor: '#FFFFFF' } + }, + // 启用tooltip显示详细信息 + tooltip: { + format: (item) => { + const legendItem = this.regionLegendData.find(legend => legend.name === item.name) + const percentage = legendItem ? legendItem.percentage : '0.0' + return `${item.name}: ${this.formatMoney(item.value)}元 (${percentage}%)` + } } } }, @@ -262,10 +323,10 @@ export default { salesVolumeChartData() { return { categories: this.salesVolumeData.map(item => - item.name.length > 6 ? item.name.substring(0, 6) + '...' : item.name + this.formatXAxisLabel(item.name) ), series: [{ - name: '销售量', + name: '销量', data: this.salesVolumeData.map(item => item.value) }] } @@ -273,35 +334,58 @@ export default { // 销售量图表配置 salesVolumeOpts() { + // 计算最大值并生成6个刻度,每个刻度都是100的倍数 + const maxSales = Math.max(...this.salesVolumeData.map(item => item.value)); + const roundedMax = Math.ceil(maxSales / 100) * 100; // 向上取整到100的倍数 + const yAxisInterval = Math.ceil(roundedMax / 5); // 分成5个间隔,总共6个刻度 + const finalInterval = Math.ceil(yAxisInterval / 100) * 100; // 确保间隔是100的倍数 + const finalMax = finalInterval * 5; // 最终最大值 + + // 生成Y轴刻度数据 + const yAxisData = []; + for (let i = 0; i <= 5; i++) { + yAxisData.push(i * finalInterval); + } + return { color: ['#576EFF'], - padding: [15, 15, 15, 15], + legend: { + show: true, + color: ['#576EFF'] + }, + padding: [20, 15, 35, 15], // 增加底部padding给X轴标签留空间 dataLabel: false, - enableScroll: true, + enableScroll: false, xAxis: { - itemCount: 4, - scrollShow: true, + itemCount: 5, // 减少显示的标签数量 scrollAlign: 'right', scrollColor: '#576EFF', scrollBackgroundColor: 'rgba(87, 110, 255, 0.1)', scrollWidth: 4, - scrollHeight: 8 + scrollHeight: 8, + rotate: 30, // 旋转30度避免重叠 + fontSize: 12, // 适当减小字体 + margin: 15 // 增加标签与轴线的距离 }, yAxis: { gridType: 'dash', dashLength: 2, data: [{ - min: 0 + min: 0, + max: finalMax, + data: yAxisData }] }, + categoriesReal: this.salesVolumeData.map(item => item.name), extra: { column: { type: 'group', - width: 30, + width: 12, // 与ProductReport保持一致 activeBgColor: '#000000', activeBgOpacity: 0.08, - linearType: 'custom', - barBorderCircle: true + barBorderCircle: true, + linearType: 'none', + linearOpacity: 0 } } } @@ -370,6 +454,44 @@ export default { // 拿到商品销售量分析 this.hanleGetShopSalesVolumeData() }, + + // 计算y轴最大值:根据实际最大值自动调整,确保6个刻度时每个都是100的倍数 + calculateYAxisMax(maxValue) { + if (maxValue === 0) return 600 // 默认值 + + // 为了确保6个刻度都是100的倍数,最大值应该是500的倍数 + // 例如:500 -> [0,100,200,300,400,500] + const baseInterval = 100 + const tickCount = 6 + + // 计算理想的间隔值 + const idealInterval = Math.ceil(maxValue / (tickCount - 1) / baseInterval) * baseInterval + + // y轴最大值 = 间隔 × (刻度数-1) + const yAxisMax = idealInterval * (tickCount - 1) + + return yAxisMax + }, + + // 图例点击交互 + onLegendTap(index) { + // 可以在这里添加图例交互逻辑,比如高亮对应的饼图区域 + const tappedLegend = this.regionLegendData[index] + console.log('点击图例:', tappedLegend) + + // 可以显示提示信息或执行其他交互 + uni.showToast({ + title: `${tappedLegend.name}: ${tappedLegend.percentage}%`, + icon: 'none' + }) + }, + + // 格式化X轴标签文字 + formatXAxisLabel(name) { + if (!name) return ''; + // 如果名称超过4个字符,截取并添加省略号 + return name.length > 4 ? name.substring(0, 4) + '...' : name; + }, // 拿到商品销售量分析 async hanleGetShopSalesVolumeData() { const req = { @@ -472,10 +594,15 @@ export default { if (list && list.length > 0) { list.forEach((item) => { let hour = Number(item.name) - if (hour % 4 === 0 || hour === 0) { + + // 控制x轴标签显示间隔:每4小时显示一个标签,以及0点 + if (hour === 0 || hour % 4 === 0) { categories.push(`${item.name}时`) + } else { + categories.push('') // 其他位置为空字符串,不显示标签 } - // let hour = Number(item.name) < 10 ? `0${item.name}:00` : `${item.name}:00` + + // 所有数据都保留 transactionData.push(item.data) amountData.push(item.key) }) @@ -485,12 +612,8 @@ export default { transactionData: transactionData, amountData: amountData } - // 最终数据格式 要这样 - // timeDistributionData: { - // categories: ['00:00', '02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'], - // transactionData: [234, 156, 89, 123, 567, 1234, 2345, 1876, 1567, 2890, 2456, 1876], - // amountData: [12345, 8234, 4567, 6789, 34567, 67890, 123456, 98765, 82345, 156789, 123456, 98765] - // } + // 24个完整数据点,但x轴只显示7个标签(0点、4点、8点、12点、16点、20点、24点) + // 所有数据点都支持点击交互 }, formatNumber(num) { return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") @@ -756,6 +879,64 @@ export default { .bar-chart-container { width: 100%; } + + // 自定义图例样式 + .custom-region-legend { + margin-top: 20rpx; + width: 100%; + + .legend-scroll { + width: 100%; + white-space: nowrap; + + .legend-items { + display: inline-flex; + gap: 16rpx; + padding: 0 8rpx; + + .legend-item { + display: flex; + align-items: center; + gap: 8rpx; + padding: 8rpx 12rpx; + background: rgba(0, 0, 0, 0.02); + border-radius: 8rpx; + border: 1rpx solid rgba(0, 0, 0, 0.1); + white-space: nowrap; + transition: all 0.2s ease; + + &:active { + background: rgba(87, 110, 255, 0.1); + border-color: #576EFF; + transform: scale(0.95); + } + + .legend-color { + width: 16rpx; + height: 16rpx; + border-radius: 4rpx; + flex-shrink: 0; + } + + .legend-name { + font-size: 24rpx; + color: @text-secondary; + max-width: 120rpx; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .legend-value { + font-size: 24rpx; + color: @text-primary; + font-weight: 600; + flex-shrink: 0; + } + } + } + } + } } } } diff --git a/pages/DigitalIntelligenceDashboard/components/RegionalServiceAreaAnalysis.vue b/pages/DigitalIntelligenceDashboard/components/RegionalServiceAreaAnalysis.vue index 4c21ce7..f26704f 100644 --- a/pages/DigitalIntelligenceDashboard/components/RegionalServiceAreaAnalysis.vue +++ b/pages/DigitalIntelligenceDashboard/components/RegionalServiceAreaAnalysis.vue @@ -11,19 +11,16 @@ - + 对比分析 - + 同比分析 - + 环比分析 @@ -64,14 +61,8 @@ - + @@ -84,21 +75,8 @@ - - - - - {{ item.name }} - {{ item.count }}个({{ item.percentage }}%) - - + @@ -116,29 +94,40 @@ {{ region.name }}区域 综合评分 - {{ Math.round((region.traffic + region.vehicles + region.revenue + region.profit + region.growth) / 5) }} + {{ Math.round((region.traffic + region.vehicles + region.revenue + + region.profit + region.growth) / 5) }} 客流量 - {{ region.traffic }} + {{ + region.traffic }} 车流量 - {{ region.vehicles }} + {{ + region.vehicles }} 营业额 - {{ region.revenue }} + {{ + region.revenue }} 利润率 - {{ region.profit }} + {{ + region.profit }} 增长率 - {{ region.growth }} + {{ + region.growth }} @@ -178,14 +167,8 @@ - + @@ -220,16 +203,14 @@ {{ item.regionName }} - + {{ item.serviceType }} - + {{ item.operationalStatus }} @@ -246,10 +227,9 @@ 利润率 - + {{ formatProfit(item.profitRate) }} @@ -263,6 +243,7 @@