949 lines
26 KiB
Vue
949 lines
26 KiB
Vue
<template>
|
||
<view class="custom-service-analysis">
|
||
<!-- 报表标题 -->
|
||
<view class="report-header">
|
||
<text class="report-title">按管理方自定义服务区等级的经营状态分析</text>
|
||
<view class="report-period">
|
||
<text class="period-label">分析周期:</text>
|
||
<text class="period-value">{{ analysisPeriod }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 分析模式选择 -->
|
||
<view class="analysis-mode-section">
|
||
<view class="section-title">
|
||
<text class="title-text">自定义分析模式</text>
|
||
<text class="title-desc">管理方可根据管理逻辑自定义数据分析维度</text>
|
||
</view>
|
||
<view class="mode-selector">
|
||
<view class="mode-card"
|
||
:class="{ active: activeMode === 'performance' }"
|
||
@click="switchMode('performance')">
|
||
<view class="mode-icon performance"></view>
|
||
<text class="mode-title">综合效益分析</text>
|
||
<text class="mode-desc">基于营业额、利润率、客流量综合评分</text>
|
||
</view>
|
||
<view class="mode-card"
|
||
:class="{ active: activeMode === 'potential' }"
|
||
@click="switchMode('potential')">
|
||
<view class="mode-icon potential"></view>
|
||
<text class="mode-title">发展潜力分析</text>
|
||
<text class="mode-desc">基于增长率、区域位置、基础设施建设</text>
|
||
</view>
|
||
<view class="mode-card"
|
||
:class="{ active: activeMode === 'custom' }"
|
||
@click="switchMode('custom')">
|
||
<view class="mode-icon custom"></view>
|
||
<text class="mode-title">自定义权重分析</text>
|
||
<text class="mode-desc">管理方自定义各指标权重进行综合评价</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 自定义等级展示 -->
|
||
<view class="custom-levels-section">
|
||
<view class="section-title">
|
||
<text class="title-text">服务区自定义等级分布</text>
|
||
<text class="title-desc">{{ getModeDescription() }}</text>
|
||
</view>
|
||
<view class="level-cards">
|
||
<view class="level-card" v-for="(level, index) in currentLevels" :key="index"
|
||
:class="'level-' + level.grade">
|
||
<view class="level-header">
|
||
<view class="level-grade">{{ level.grade }}级</view>
|
||
<view class="level-count">{{ level.count }}个</view>
|
||
</view>
|
||
<view class="level-metrics">
|
||
<view class="metric-item">
|
||
<text class="metric-label">平均营业额</text>
|
||
<text class="metric-value">¥{{ formatMoney(level.avgRevenue) }}</text>
|
||
</view>
|
||
<view class="metric-item">
|
||
<text class="metric-label">平均利润率</text>
|
||
<text class="metric-value">{{ level.avgProfitRate }}%</text>
|
||
</view>
|
||
<view class="metric-item">
|
||
<text class="metric-label">数量占比</text>
|
||
<text class="metric-value">{{ level.percentage }}%</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 自定义分析图表 -->
|
||
<view class="chart-card">
|
||
<view class="chart-header">
|
||
<text class="chart-title">自定义等级{{ getChartTitle() }}</text>
|
||
<text class="chart-subtitle">{{ getChartDescription() }}</text>
|
||
</view>
|
||
<view class="chart-content">
|
||
<view class="radar-chart-container">
|
||
<QiunDataCharts
|
||
type="radar"
|
||
:opts="radarChartOpts"
|
||
:chartData="radarChartData"
|
||
:canvas2d="true"
|
||
:inScrollView="true"
|
||
canvasId="customRadarChart"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 综合评价矩阵 -->
|
||
<view class="matrix-section">
|
||
<view class="section-title">
|
||
<text class="title-text">综合评价矩阵</text>
|
||
<text class="title-desc">多维度交叉分析服务区表现</text>
|
||
</view>
|
||
<view class="matrix-grid">
|
||
<view class="matrix-legend">
|
||
<view class="legend-item excellent">优秀</view>
|
||
<view class="legend-item good">良好</view>
|
||
<view class="legend-item average">一般</view>
|
||
<view class="legend-item poor">较差</view>
|
||
</view>
|
||
<view class="matrix-chart-container">
|
||
<QiunDataCharts
|
||
type="bubble"
|
||
:opts="bubbleChartOpts"
|
||
:chartData="bubbleChartData"
|
||
:canvas2d="true"
|
||
:inScrollView="true"
|
||
canvasId="bubbleMatrixChart"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 权重配置(仅在自定义模式下显示) -->
|
||
<view class="weight-config-section" v-if="activeMode === 'custom'">
|
||
<view class="section-title">
|
||
<text class="title-text">自定义权重配置</text>
|
||
<text class="title-desc">调整各指标权重重新计算综合评分</text>
|
||
</view>
|
||
<view class="weight-sliders">
|
||
<view class="weight-item" v-for="(weight, index) in customWeights" :key="index">
|
||
<view class="weight-header">
|
||
<text class="weight-label">{{ weight.label }}</text>
|
||
<text class="weight-value">{{ weight.value }}%</text>
|
||
</view>
|
||
<view class="weight-bar">
|
||
<view class="weight-progress" :style="{ width: weight.value + '%' }"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 服务区详细评分卡片 -->
|
||
<view class="chart-card">
|
||
<view class="chart-header">
|
||
<text class="chart-title">服务区详细评分</text>
|
||
<view class="table-actions">
|
||
<text class="action-btn" @click="recalculateScores">重新计算</text>
|
||
<text class="action-btn" @click="exportData">导出数据</text>
|
||
</view>
|
||
</view>
|
||
<view class="score-cards">
|
||
<view class="score-card" v-for="(item, index) in scoreData" :key="index">
|
||
<view class="card-header">
|
||
<view class="service-info">
|
||
<text class="service-name">{{ item.serviceAreaName }}</text>
|
||
<text class="level-tag"
|
||
:class="item.customLevel === 'S' ? 'level-s' :
|
||
item.customLevel === 'A' ? 'level-a' :
|
||
item.customLevel === 'B' ? 'level-b' : 'level-c'">
|
||
{{ item.customLevel }}级
|
||
</text>
|
||
</view>
|
||
<view class="total-score">
|
||
<text class="score-value"
|
||
:class="item.totalScore >= 90 ? 'excellent' :
|
||
item.totalScore >= 80 ? 'good' :
|
||
item.totalScore >= 70 ? 'average' : 'poor'">
|
||
{{ item.totalScore }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
<view class="card-content">
|
||
<view class="scores-grid">
|
||
<view class="score-item">
|
||
<text class="score-label">营业额得分</text>
|
||
<text class="score-number">{{ item.revenueScore }}</text>
|
||
</view>
|
||
<view class="score-item">
|
||
<text class="score-label">利润率得分</text>
|
||
<text class="score-number">{{ item.profitScore }}</text>
|
||
</view>
|
||
<view class="score-item">
|
||
<text class="score-label">客流量得分</text>
|
||
<text class="score-number">{{ item.trafficScore }}</text>
|
||
</view>
|
||
<view class="score-item">
|
||
<text class="score-label">增长率得分</text>
|
||
<text class="score-number">{{ item.growthScore }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
|
||
|
||
export default {
|
||
components: {
|
||
QiunDataCharts
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
analysisPeriod: '2024年10月',
|
||
activeMode: 'performance',
|
||
|
||
// 自定义等级数据
|
||
customLevels: {
|
||
performance: [
|
||
{ grade: 'S', count: 8, avgRevenue: 9876, avgProfitRate: 22.5, percentage: 9 },
|
||
{ grade: 'A', count: 18, avgRevenue: 6543, avgProfitRate: 18.2, percentage: 21 },
|
||
{ grade: 'B', count: 35, avgRevenue: 4321, avgProfitRate: 14.1, percentage: 41 },
|
||
{ grade: 'C', count: 24, avgRevenue: 2876, avgProfitRate: 10.3, percentage: 29 }
|
||
],
|
||
potential: [
|
||
{ grade: 'S', count: 12, avgRevenue: 7654, avgProfitRate: 15.8, percentage: 14 },
|
||
{ grade: 'A', count: 22, avgRevenue: 5432, avgProfitRate: 13.2, percentage: 26 },
|
||
{ grade: 'B', count: 28, avgRevenue: 3876, avgProfitRate: 11.5, percentage: 33 },
|
||
{ grade: 'C', count: 23, avgRevenue: 2543, avgProfitRate: 8.7, percentage: 27 }
|
||
],
|
||
custom: [
|
||
{ grade: 'S', count: 10, avgRevenue: 8765, avgProfitRate: 19.8, percentage: 12 },
|
||
{ grade: 'A', count: 20, avgRevenue: 5987, avgProfitRate: 16.3, percentage: 24 },
|
||
{ grade: 'B', count: 30, avgRevenue: 3987, avgProfitRate: 12.8, percentage: 35 },
|
||
{ grade: 'C', count: 25, avgRevenue: 2654, avgProfitRate: 9.2, percentage: 29 }
|
||
]
|
||
},
|
||
|
||
// 自定义权重
|
||
customWeights: [
|
||
{ label: '营业额', value: 30 },
|
||
{ label: '利润率', value: 25 },
|
||
{ label: '客流量', value: 20 },
|
||
{ label: '增长率', value: 15 },
|
||
{ label: '经营面积', value: 10 }
|
||
],
|
||
|
||
// 评分数据
|
||
scoreData: [
|
||
{
|
||
serviceAreaName: '昆明服务区',
|
||
customLevel: 'S',
|
||
totalScore: 92.5,
|
||
revenueScore: 95,
|
||
profitScore: 88,
|
||
trafficScore: 94,
|
||
growthScore: 93
|
||
},
|
||
{
|
||
serviceAreaName: '曲靖服务区',
|
||
customLevel: 'A',
|
||
totalScore: 85.2,
|
||
revenueScore: 87,
|
||
profitScore: 82,
|
||
trafficScore: 86,
|
||
growthScore: 86
|
||
},
|
||
{
|
||
serviceAreaName: '大理服务区',
|
||
customLevel: 'B',
|
||
totalScore: 76.8,
|
||
revenueScore: 72,
|
||
profitScore: 68,
|
||
trafficScore: 82,
|
||
growthScore: 85
|
||
},
|
||
{
|
||
serviceAreaName: '玉溪服务区',
|
||
customLevel: 'A',
|
||
totalScore: 81.3,
|
||
revenueScore: 84,
|
||
profitScore: 79,
|
||
trafficScore: 78,
|
||
growthScore: 84
|
||
},
|
||
{
|
||
serviceAreaName: '红河服务区',
|
||
customLevel: 'B',
|
||
totalScore: 73.5,
|
||
revenueScore: 76,
|
||
profitScore: 72,
|
||
trafficScore: 70,
|
||
growthScore: 76
|
||
}
|
||
],
|
||
|
||
// 气泡图数据
|
||
bubbleData: [
|
||
{ name: '昆明服务区', x: 92, y: 88, r: 18, level: 'S' },
|
||
{ name: '曲靖服务区', x: 85, y: 82, r: 15, level: 'A' },
|
||
{ name: '大理服务区', x: 72, y: 68, r: 12, level: 'B' },
|
||
{ name: '玉溪服务区', x: 84, y: 79, r: 14, level: 'A' },
|
||
{ name: '红河服务区', x: 76, y: 72, r: 11, level: 'B' },
|
||
{ name: '保山服务区', x: 68, y: 75, r: 10, level: 'C' },
|
||
{ name: '昭通服务区', x: 62, y: 65, r: 9, level: 'C' },
|
||
{ name: '文山服务区', x: 78, y: 71, r: 13, level: 'B' }
|
||
]
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
// 当前模式的等级数据
|
||
currentLevels() {
|
||
return this.customLevels[this.activeMode] || this.customLevels.performance;
|
||
},
|
||
|
||
// 雷达图数据
|
||
radarChartData() {
|
||
return {
|
||
categories: ['营业额', '利润率', '客流量', '增长率', '综合评分'],
|
||
series: this.currentLevels.map((level, index) => ({
|
||
name: level.grade + '级服务区',
|
||
data: [
|
||
this.getNormalizedScore(level.avgRevenue, 10000),
|
||
this.getNormalizedScore(level.avgProfitRate, 25),
|
||
this.getNormalizedScore(level.count, 40),
|
||
this.getNormalizedScore(level.percentage, 40),
|
||
this.getNormalizedScore((5 - index) * 20, 100)
|
||
]
|
||
}))
|
||
}
|
||
},
|
||
|
||
// 雷达图配置
|
||
radarChartOpts() {
|
||
return {
|
||
color: ['#576EFF', '#52C41A', '#FAAD14', '#FF7875'],
|
||
padding: [15, 15, 15, 15],
|
||
dataLabel: false,
|
||
legend: {
|
||
show: true,
|
||
position: 'top'
|
||
},
|
||
extra: {
|
||
radar: {
|
||
gridType: 'radar',
|
||
gridColor: '#E0E0E0',
|
||
gridCount: 4,
|
||
opacity: 0.8,
|
||
max: 100,
|
||
border: false
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
// 气泡图数据
|
||
bubbleChartData() {
|
||
return {
|
||
series: [
|
||
{
|
||
name: 'S级服务区',
|
||
data: this.bubbleData.filter(item => item.level === 'S').map(item => [item.x, item.y, item.r])
|
||
},
|
||
{
|
||
name: 'A级服务区',
|
||
data: this.bubbleData.filter(item => item.level === 'A').map(item => [item.x, item.y, item.r])
|
||
},
|
||
{
|
||
name: 'B级服务区',
|
||
data: this.bubbleData.filter(item => item.level === 'B').map(item => [item.x, item.y, item.r])
|
||
},
|
||
{
|
||
name: 'C级服务区',
|
||
data: this.bubbleData.filter(item => item.level === 'C').map(item => [item.x, item.y, item.r])
|
||
}
|
||
]
|
||
}
|
||
},
|
||
|
||
// 气泡图配置
|
||
bubbleChartOpts() {
|
||
return {
|
||
color: ['#576EFF', '#52C41A', '#FAAD14', '#FF7875'],
|
||
padding: [15, 15, 15, 15],
|
||
dataLabel: false,
|
||
legend: {
|
||
show: false
|
||
},
|
||
xAxis: {
|
||
min: 50,
|
||
max: 100,
|
||
gridType: 'dash',
|
||
dashLength: 2,
|
||
titleText: '综合评分',
|
||
titleFontSize: 22
|
||
},
|
||
yAxis: {
|
||
min: 50,
|
||
max: 100,
|
||
gridType: 'dash',
|
||
dashLength: 2,
|
||
titleText: '经营效率',
|
||
titleFontSize: 22
|
||
},
|
||
extra: {
|
||
bubble: {
|
||
opacity: 0.8,
|
||
border: 2,
|
||
borderColor: '#FFFFFF'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
switchMode(mode) {
|
||
this.activeMode = mode;
|
||
},
|
||
|
||
getModeDescription() {
|
||
const descriptions = {
|
||
performance: '基于营业额、利润率、客流量等经营指标的综合效益分级',
|
||
potential: '基于增长率、区域位置、发展潜力等指标的发展潜力分级',
|
||
custom: '基于管理方自定义权重的综合评价分级'
|
||
};
|
||
return descriptions[this.activeMode] || '';
|
||
},
|
||
|
||
getChartTitle() {
|
||
const titles = {
|
||
performance: '综合效益对比',
|
||
potential: '发展潜力对比',
|
||
custom: '综合评价对比'
|
||
};
|
||
return titles[this.activeMode] || '';
|
||
},
|
||
|
||
getChartDescription() {
|
||
const descriptions = {
|
||
performance: '各等级服务区在关键经营指标上的表现对比',
|
||
potential: '各等级服务区在发展潜力维度上的表现对比',
|
||
custom: '各等级服务区在自定义权重下的综合表现对比'
|
||
};
|
||
return descriptions[this.activeMode] || '';
|
||
},
|
||
|
||
getNormalizedScore(value, maxValue) {
|
||
return Math.round((value / maxValue) * 100);
|
||
},
|
||
|
||
getLevelClass(level) {
|
||
const classMap = {
|
||
'S': 'level-s',
|
||
'A': 'level-a',
|
||
'B': 'level-b',
|
||
'C': 'level-c'
|
||
};
|
||
return classMap[level] || '';
|
||
},
|
||
|
||
getScoreClass(score) {
|
||
if (score >= 90) return 'excellent';
|
||
if (score >= 80) return 'good';
|
||
if (score >= 70) return 'average';
|
||
return 'poor';
|
||
},
|
||
|
||
formatNumber(num) {
|
||
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||
},
|
||
|
||
formatMoney(amount) {
|
||
return amount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||
},
|
||
|
||
recalculateScores() {
|
||
console.log('重新计算自定义评分');
|
||
// 这里可以重新计算评分逻辑
|
||
},
|
||
|
||
exportData() {
|
||
console.log('导出自定义分析数据');
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
@primary-color: #667eea;
|
||
@success-color: #52c41a;
|
||
@warning-color: #faad14;
|
||
@error-color: #ff4d4f;
|
||
@info-color: #1890ff;
|
||
@text-primary: #333;
|
||
@text-secondary: #666;
|
||
@text-light: #999;
|
||
@bg-white: #ffffff;
|
||
@bg-light: #f8f9fb;
|
||
@border-radius: 16rpx;
|
||
@shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||
|
||
.custom-service-analysis {
|
||
.report-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 32rpx;
|
||
padding: 0 8rpx;
|
||
|
||
.report-title {
|
||
font-size: 36rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.report-period {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.period-label {
|
||
font-size: 24rpx;
|
||
color: @text-secondary;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.period-value {
|
||
font-size: 24rpx;
|
||
color: @primary-color;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
.section-title {
|
||
margin-bottom: 24rpx;
|
||
|
||
.title-text {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.title-desc {
|
||
font-size: 22rpx;
|
||
color: @text-light;
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
|
||
.analysis-mode-section {
|
||
background: @bg-white;
|
||
border-radius: @border-radius;
|
||
padding: 24rpx;
|
||
box-shadow: @shadow;
|
||
margin-bottom: 32rpx;
|
||
|
||
.mode-selector {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
|
||
.mode-card {
|
||
flex: 1;
|
||
background: @bg-light;
|
||
border-radius: 12rpx;
|
||
padding: 20rpx 16rpx;
|
||
text-align: center;
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
border: 2rpx solid transparent;
|
||
|
||
&.active {
|
||
background: @bg-white;
|
||
border-color: @primary-color;
|
||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
|
||
}
|
||
|
||
.mode-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin: 0 auto 16rpx;
|
||
border-radius: 50%;
|
||
position: relative;
|
||
|
||
&.performance {
|
||
background: linear-gradient(135deg, #576EFF, #7C8FFF);
|
||
&::after { content: '📊'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
||
}
|
||
|
||
&.potential {
|
||
background: linear-gradient(135deg, #52C41A, #73D13D);
|
||
&::after { content: '🚀'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
||
}
|
||
|
||
&.custom {
|
||
background: linear-gradient(135deg, #FAAD14, #FFC53D);
|
||
&::after { content: '⚙️'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 24rpx; }
|
||
}
|
||
}
|
||
|
||
.mode-title {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.mode-desc {
|
||
font-size: 20rpx;
|
||
color: @text-secondary;
|
||
line-height: 1.3;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.custom-levels-section {
|
||
margin-bottom: 32rpx;
|
||
|
||
.level-cards {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 16rpx;
|
||
|
||
.level-card {
|
||
background: @bg-white;
|
||
border-radius: @border-radius;
|
||
padding: 20rpx;
|
||
box-shadow: @shadow;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 4rpx;
|
||
}
|
||
|
||
&.level-S::before { background: linear-gradient(90deg, #576EFF, #7C8FFF); }
|
||
&.level-A::before { background: linear-gradient(90deg, #52C41A, #73D13D); }
|
||
&.level-B::before { background: linear-gradient(90deg, #FAAD14, #FFC53D); }
|
||
&.level-C::before { background: linear-gradient(90deg, #FF7875, #FF9C99); }
|
||
|
||
.level-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 16rpx;
|
||
|
||
.level-grade {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: @text-primary;
|
||
}
|
||
|
||
.level-count {
|
||
font-size: 24rpx;
|
||
color: @text-secondary;
|
||
background: @bg-light;
|
||
padding: 4rpx 12rpx;
|
||
border-radius: 12rpx;
|
||
}
|
||
}
|
||
|
||
.level-metrics {
|
||
.metric-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 8rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.metric-label {
|
||
font-size: 20rpx;
|
||
color: @text-secondary;
|
||
}
|
||
|
||
.metric-value {
|
||
font-size: 20rpx;
|
||
color: @text-primary;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.chart-card {
|
||
background: @bg-white;
|
||
border-radius: @border-radius;
|
||
padding: 24rpx;
|
||
box-shadow: @shadow;
|
||
margin-bottom: 24rpx;
|
||
|
||
.chart-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
margin-bottom: 20rpx;
|
||
|
||
.chart-title {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
}
|
||
|
||
.chart-subtitle {
|
||
font-size: 22rpx;
|
||
color: @text-light;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.table-actions {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
|
||
.action-btn {
|
||
font-size: 24rpx;
|
||
color: @primary-color;
|
||
padding: 8rpx 16rpx;
|
||
border: 1rpx solid @primary-color;
|
||
border-radius: 8rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.chart-content {
|
||
.radar-chart-container,
|
||
.matrix-chart-container {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
.score-cards {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
|
||
.score-card {
|
||
background: #f8f9fa;
|
||
border-radius: 12rpx;
|
||
padding: 20rpx;
|
||
border: 1rpx solid #e9ecef;
|
||
|
||
.card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 16rpx;
|
||
|
||
.service-info {
|
||
flex: 1;
|
||
|
||
.service-name {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.level-tag {
|
||
display: inline-block;
|
||
padding: 6rpx 12rpx;
|
||
border-radius: 8rpx;
|
||
font-size: 20rpx;
|
||
color: white;
|
||
font-weight: 500;
|
||
|
||
&.level-s {
|
||
background: #576EFF;
|
||
}
|
||
|
||
&.level-a {
|
||
background: #52C41A;
|
||
}
|
||
|
||
&.level-b {
|
||
background: #FAAD14;
|
||
}
|
||
|
||
&.level-c {
|
||
background: #FF7875;
|
||
}
|
||
}
|
||
}
|
||
|
||
.total-score {
|
||
text-align: center;
|
||
|
||
.score-value {
|
||
display: block;
|
||
font-size: 36rpx;
|
||
font-weight: 700;
|
||
margin-bottom: 4rpx;
|
||
|
||
&.excellent {
|
||
color: #576EFF;
|
||
}
|
||
|
||
&.good {
|
||
color: #52C41A;
|
||
}
|
||
|
||
&.average {
|
||
color: #FAAD14;
|
||
}
|
||
|
||
&.poor {
|
||
color: #FF7875;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.card-content {
|
||
.scores-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 12rpx;
|
||
|
||
.score-item {
|
||
background: white;
|
||
padding: 16rpx;
|
||
border-radius: 8rpx;
|
||
border: 1rpx solid #f0f0f0;
|
||
text-align: center;
|
||
|
||
.score-label {
|
||
display: block;
|
||
font-size: 22rpx;
|
||
color: @text-secondary;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.score-number {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: @text-primary;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.matrix-section {
|
||
background: @bg-white;
|
||
border-radius: @border-radius;
|
||
padding: 24rpx;
|
||
box-shadow: @shadow;
|
||
margin-bottom: 32rpx;
|
||
|
||
.matrix-grid {
|
||
.matrix-legend {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 24rpx;
|
||
margin-bottom: 20rpx;
|
||
|
||
.legend-item {
|
||
font-size: 20rpx;
|
||
color: @text-secondary;
|
||
padding: 4rpx 12rpx;
|
||
border-radius: 12rpx;
|
||
|
||
&.excellent {
|
||
background: rgba(87, 110, 255, 0.1);
|
||
color: #576EFF;
|
||
}
|
||
|
||
&.good {
|
||
background: rgba(82, 196, 26, 0.1);
|
||
color: #52C41A;
|
||
}
|
||
|
||
&.average {
|
||
background: rgba(250, 173, 20, 0.1);
|
||
color: #FAAD14;
|
||
}
|
||
|
||
&.poor {
|
||
background: rgba(255, 120, 117, 0.1);
|
||
color: #FF7875;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.weight-config-section {
|
||
background: @bg-white;
|
||
border-radius: @border-radius;
|
||
padding: 24rpx;
|
||
box-shadow: @shadow;
|
||
margin-bottom: 32rpx;
|
||
|
||
.weight-sliders {
|
||
.weight-item {
|
||
margin-bottom: 24rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.weight-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
|
||
.weight-label {
|
||
font-size: 24rpx;
|
||
color: @text-primary;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.weight-value {
|
||
font-size: 24rpx;
|
||
color: @primary-color;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
|
||
.weight-bar {
|
||
width: 100%;
|
||
height: 12rpx;
|
||
background: #f0f0f0;
|
||
border-radius: 6rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
.weight-progress {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, @primary-color, #7C8FFF);
|
||
border-radius: 6rpx;
|
||
transition: width 0.3s ease;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |