style(ops): 优化工单状态分布和工牌队列统计图表样式
状态分布饼图: - 使用 Ant Design 色板统一配色 - legend 显示数量和百分比(rich text) - 中心数字加大加粗,饼块增大圆角 - emphasis 放大效果增强 工牌队列柱状图: - 最大值柱子高亮深色,其余渐变浅色 - 柱顶显示数值标签 - tooltip 改为卡片式样式 - hover 加深色强调效果,圆角加大 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -400,58 +400,73 @@ function getTimeTrendChartOptions(): ECOption {
|
|||||||
function getStatusDistributionChartOptions(): ECOption {
|
function getStatusDistributionChartOptions(): ECOption {
|
||||||
const { statusDistribution } = statsData.value;
|
const { statusDistribution } = statsData.value;
|
||||||
const STATUS_COLORS: Record<string, string> = {
|
const STATUS_COLORS: Record<string, string> = {
|
||||||
待处理: '#f5a623',
|
待处理: '#faad14',
|
||||||
排队中: '#8b5cf6',
|
排队中: '#722ed1',
|
||||||
已派单: '#3b82f6',
|
已派单: '#1677ff',
|
||||||
已到岗: '#06b6d4',
|
已到岗: '#13c2c2',
|
||||||
已完成: '#10b981',
|
已完成: '#52c41a',
|
||||||
已取消: '#f43f5e',
|
已取消: '#ff4d4f',
|
||||||
已暂停: '#94a3b8',
|
已暂停: '#8c8c8c',
|
||||||
};
|
};
|
||||||
const total = statusDistribution.reduce((sum, item) => sum + item.value, 0);
|
const total = statusDistribution.reduce((sum, item) => sum + item.value, 0);
|
||||||
return {
|
return {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
backgroundColor: 'rgba(255, 255, 255, 0.96)',
|
backgroundColor: 'rgba(255, 255, 255, 0.96)',
|
||||||
borderColor: '#e5e7eb',
|
borderColor: '#f0f0f0',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
textStyle: { color: '#374151', fontSize: 13 },
|
padding: [8, 12],
|
||||||
|
textStyle: { color: '#262626', fontSize: 13 },
|
||||||
formatter: (params: any) => {
|
formatter: (params: any) => {
|
||||||
const marker = `<span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:${params.color};margin-right:6px;"></span>`;
|
const marker = `<span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:${params.color};margin-right:6px;"></span>`;
|
||||||
return `${marker}${params.name}<br/><span style="font-weight:600">${params.value}</span>个 · ${params.percent}%`;
|
return `${marker}${params.name}<br/><span style="font-size:16px;font-weight:600">${params.value}</span> 个 <span style="color:#8c8c8c;margin-left:4px">${params.percent}%</span>`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
right: '2%',
|
right: '4%',
|
||||||
top: 'center',
|
top: 'center',
|
||||||
itemWidth: 8,
|
itemWidth: 10,
|
||||||
itemHeight: 8,
|
itemHeight: 10,
|
||||||
itemGap: 12,
|
itemGap: 14,
|
||||||
icon: 'circle',
|
icon: 'circle',
|
||||||
textStyle: { fontSize: 12, color: '#6b7280' },
|
textStyle: { fontSize: 12, color: '#595959' },
|
||||||
|
formatter: (name: string) => {
|
||||||
|
const item = statusDistribution.find((d) => d.name === name);
|
||||||
|
if (!item) return name;
|
||||||
|
const pct = total > 0 ? ((item.value / total) * 100).toFixed(1) : '0';
|
||||||
|
return `${name} {val|${item.value}} {pct|${pct}%}`;
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: '#595959',
|
||||||
|
rich: {
|
||||||
|
val: { fontSize: 13, fontWeight: 600, color: '#262626', padding: [0, 4, 0, 8] },
|
||||||
|
pct: { fontSize: 11, color: '#8c8c8c' },
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
graphic: [
|
graphic: [
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
left: '28%',
|
left: '23%',
|
||||||
top: '40%',
|
top: '38%',
|
||||||
style: {
|
style: {
|
||||||
text: `${total}`,
|
text: `${total}`,
|
||||||
fontSize: 22,
|
fontSize: 26,
|
||||||
fontWeight: '600',
|
fontWeight: '700',
|
||||||
fill: '#1f2937',
|
fill: '#262626',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
left: '28%',
|
left: '23%',
|
||||||
top: '54%',
|
top: '55%',
|
||||||
style: {
|
style: {
|
||||||
text: '近7天工单',
|
text: '近7天工单',
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fill: '#9ca3af',
|
fill: '#bfbfbf',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -460,30 +475,31 @@ function getStatusDistributionChartOptions(): ECOption {
|
|||||||
{
|
{
|
||||||
name: '工单状态分布',
|
name: '工单状态分布',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['50%', '72%'],
|
radius: ['48%', '70%'],
|
||||||
center: ['30%', '50%'],
|
center: ['25%', '50%'],
|
||||||
avoidLabelOverlap: false,
|
avoidLabelOverlap: false,
|
||||||
label: { show: false },
|
label: { show: false },
|
||||||
emphasis: {
|
emphasis: {
|
||||||
scale: true,
|
scale: true,
|
||||||
scaleSize: 6,
|
scaleSize: 8,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
fontSize: 13,
|
fontSize: 14,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
color: '#374151',
|
color: '#262626',
|
||||||
formatter: '{b}\n{c}个',
|
formatter: '{b}\n{c}个',
|
||||||
|
lineHeight: 20,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderColor: '#fff',
|
borderColor: '#fff',
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderRadius: 4,
|
borderRadius: 6,
|
||||||
},
|
},
|
||||||
data: statusDistribution.map((item) => ({
|
data: statusDistribution.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: STATUS_COLORS[item.name] || '#d1d5db',
|
color: STATUS_COLORS[item.name] || '#d9d9d9',
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
@@ -682,25 +698,32 @@ function getFunctionTypeRankingChartOptions(): ECOption {
|
|||||||
function getBadgeQueueChartOptions(): ECOption {
|
function getBadgeQueueChartOptions(): ECOption {
|
||||||
const queue = statsData.value.badgeQueueStats;
|
const queue = statsData.value.badgeQueueStats;
|
||||||
if (!queue || queue.dates.length === 0) return {};
|
if (!queue || queue.dates.length === 0) return {};
|
||||||
|
const maxVal = Math.max(...queue.queueData, 1);
|
||||||
return {
|
return {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.96)',
|
||||||
|
borderColor: '#f0f0f0',
|
||||||
|
borderWidth: 1,
|
||||||
|
padding: [8, 12],
|
||||||
|
textStyle: { color: '#262626', fontSize: 13 },
|
||||||
formatter: (params: any) => {
|
formatter: (params: any) => {
|
||||||
const param = params[0];
|
const param = params[0];
|
||||||
return `${param.name}<br/>队列数量: ${param.value}`;
|
return `<span style="color:#8c8c8c">${param.name}</span><br/><span style="font-size:16px;font-weight:600;color:#722ed1">${param.value}</span> <span style="color:#8c8c8c">个排队</span>`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: '3%',
|
left: '3%',
|
||||||
right: '4%',
|
right: '4%',
|
||||||
bottom: '3%',
|
bottom: '3%',
|
||||||
top: '10%',
|
top: '15%',
|
||||||
containLabel: true,
|
containLabel: true,
|
||||||
},
|
},
|
||||||
xAxis: [{
|
xAxis: [{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: queue.dates,
|
data: queue.dates,
|
||||||
axisLine: { lineStyle: { color: '#d9d9d9' } },
|
axisLine: { lineStyle: { color: '#f0f0f0' } },
|
||||||
|
axisTick: { show: false },
|
||||||
axisLabel: { color: '#8c8c8c', fontSize: 11 },
|
axisLabel: { color: '#8c8c8c', fontSize: 11 },
|
||||||
}],
|
}],
|
||||||
yAxis: [{
|
yAxis: [{
|
||||||
@@ -708,24 +731,47 @@ function getBadgeQueueChartOptions(): ECOption {
|
|||||||
name: '队列数',
|
name: '队列数',
|
||||||
nameTextStyle: { color: '#8c8c8c', fontSize: 12 },
|
nameTextStyle: { color: '#8c8c8c', fontSize: 12 },
|
||||||
axisLine: { show: false },
|
axisLine: { show: false },
|
||||||
|
axisTick: { show: false },
|
||||||
axisLabel: { color: '#8c8c8c' },
|
axisLabel: { color: '#8c8c8c' },
|
||||||
splitLine: { lineStyle: { color: '#f0f0f0', type: 'dashed' } },
|
splitLine: { lineStyle: { color: '#f5f5f5', type: 'dashed' } },
|
||||||
}],
|
}],
|
||||||
series: [{
|
series: [{
|
||||||
name: '队列数量',
|
name: '队列数量',
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: '50%',
|
barWidth: '40%',
|
||||||
data: queue.queueData,
|
data: queue.queueData.map((val) => ({
|
||||||
itemStyle: {
|
value: val,
|
||||||
color: {
|
itemStyle: {
|
||||||
type: 'linear',
|
color: {
|
||||||
x: 0, y: 0, x2: 0, y2: 1,
|
type: 'linear',
|
||||||
colorStops: [
|
x: 0, y: 0, x2: 0, y2: 1,
|
||||||
{ offset: 0, color: '#722ed1' },
|
colorStops: [
|
||||||
{ offset: 1, color: '#b37feb' },
|
{ offset: 0, color: val === maxVal ? '#531dab' : '#722ed1' },
|
||||||
],
|
{ offset: 1, color: val === maxVal ? '#9254de' : '#d3adf7' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
borderRadius: [6, 6, 0, 0],
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#722ed1',
|
||||||
|
formatter: (params: any) => params.value > 0 ? params.value : '',
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
color: {
|
||||||
|
type: 'linear',
|
||||||
|
x: 0, y: 0, x2: 0, y2: 1,
|
||||||
|
colorStops: [
|
||||||
|
{ offset: 0, color: '#391085' },
|
||||||
|
{ offset: 1, color: '#722ed1' },
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
borderRadius: [4, 4, 0, 0],
|
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user