style(dashboard): 更新图表调色盘和样式优化
- 修改 base.css 中的图表调色盘颜色,提升视觉效果 - 在多个组件中引入统一的颜色工具函数,确保颜色一致性 - 优化仪表板组件的样式,提升用户体验和可读性 - 移除冗余的颜色定义,简化代码结构
This commit is contained in:
parent
e13f98f16f
commit
e592c75662
@ -82,7 +82,7 @@
|
|||||||
|
|
||||||
/* Chart Palette - 图表调色板 */
|
/* Chart Palette - 图表调色板 */
|
||||||
--chart-palette-1: var(--chart-primary);
|
--chart-palette-1: var(--chart-primary);
|
||||||
--chart-palette-2: #028ea0; /* 浅一点的青蓝 */
|
--chart-palette-2: #11cbe3; /* 浅一点的青蓝 */
|
||||||
--chart-palette-3: #00b8a9; /* 明亮青绿(邻近色) */
|
--chart-palette-3: #00b8a9; /* 明亮青绿(邻近色) */
|
||||||
--chart-palette-4: #f2c94c; /* 柔和金黄(对比色) */
|
--chart-palette-4: #f2c94c; /* 柔和金黄(对比色) */
|
||||||
--chart-palette-5: #eb5757; /* 温暖红橙(强调) */
|
--chart-palette-5: #eb5757; /* 温暖红橙(强调) */
|
||||||
|
|||||||
@ -341,11 +341,12 @@
|
|||||||
|
|
||||||
/* 使用更具体的选择器来覆盖 Ant Design 的默认样式 */
|
/* 使用更具体的选择器来覆盖 Ant Design 的默认样式 */
|
||||||
.dashboard-card .ant-card-head {
|
.dashboard-card .ant-card-head {
|
||||||
border-bottom: 1px solid var(--gray-200) !important;
|
/* border-bottom: 1px solid var(--gray-200) !important; */
|
||||||
min-height: 56px !important;
|
min-height: 56px !important;
|
||||||
padding: 0 20px !important;
|
padding: 0 20px !important;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
background-color: var(--gray-0) !important;
|
background-color: var(--gray-0) !important;
|
||||||
|
/* border: 1px solo; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-card .ant-card-head-title {
|
.dashboard-card .ant-card-head-title {
|
||||||
@ -356,11 +357,16 @@
|
|||||||
|
|
||||||
.dashboard-card .ant-card-body {
|
.dashboard-card .ant-card-body {
|
||||||
padding: 20px !important;
|
padding: 20px !important;
|
||||||
|
padding-top: 0px !important;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background-color: var(--gray-0) !important;
|
background-color: var(--gray-0) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-card .ant-card-extra {
|
||||||
|
padding-top: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* 统计概览样式 */
|
/* 统计概览样式 */
|
||||||
.stats-overview {
|
.stats-overview {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|||||||
@ -98,6 +98,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch, nextTick, computed } from 'vue'
|
import { ref, onMounted, watch, nextTick, computed } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
|
import { getColorByIndex, getChartColor } from '@/utils/chartColors'
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -164,9 +165,9 @@ const topPerformers = computed(() => {
|
|||||||
|
|
||||||
// 颜色辅助函数
|
// 颜色辅助函数
|
||||||
const getScoreColor = (score) => {
|
const getScoreColor = (score) => {
|
||||||
if (score >= 80) return '#3996ae'
|
if (score >= 80) return getChartColor('primary')
|
||||||
if (score >= 60) return '#82c3d6'
|
if (score >= 60) return getChartColor('warning')
|
||||||
return '#a3d8e8'
|
return getChartColor('accent')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -252,12 +253,12 @@ const initConversationToolChart = () => {
|
|||||||
return item ? item.conversation_count : 0
|
return item ? item.conversation_count : 0
|
||||||
}),
|
}),
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#3996ae',
|
color: getChartColor('primary'),
|
||||||
borderRadius: [4, 4, 0, 0]
|
borderRadius: [4, 4, 0, 0]
|
||||||
},
|
},
|
||||||
emphasis: {
|
emphasis: {
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#028ea0',
|
color: getChartColor('primary'),
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowColor: 'rgba(2, 142, 160, 0.3)'
|
shadowColor: 'rgba(2, 142, 160, 0.3)'
|
||||||
}
|
}
|
||||||
@ -271,12 +272,12 @@ const initConversationToolChart = () => {
|
|||||||
return item ? item.tool_usage_count : 0
|
return item ? item.tool_usage_count : 0
|
||||||
}),
|
}),
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#00b8a9',
|
color: getChartColor('accent'),
|
||||||
borderRadius: [4, 4, 0, 0]
|
borderRadius: [4, 4, 0, 0]
|
||||||
},
|
},
|
||||||
emphasis: {
|
emphasis: {
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#028ea0',
|
color: getChartColor('primary'),
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowColor: 'rgba(2, 142, 160, 0.3)'
|
shadowColor: 'rgba(2, 142, 160, 0.3)'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
import { ref, computed, onMounted, onUnmounted, nextTick, defineExpose, watch } from 'vue'
|
import { ref, computed, onMounted, onUnmounted, nextTick, defineExpose, watch } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { dashboardApi } from '@/apis/dashboard_api'
|
import { dashboardApi } from '@/apis/dashboard_api'
|
||||||
|
import { getColorByIndex, truncateLegend } from '@/utils/chartColors'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
loading: { type: Boolean, default: false },
|
loading: { type: Boolean, default: false },
|
||||||
@ -81,62 +82,6 @@ let retryTimer = null
|
|||||||
const retryCount = ref(0)
|
const retryCount = ref(0)
|
||||||
const maxRetry = 20
|
const maxRetry = 20
|
||||||
|
|
||||||
// Build color palette from CSS variables in base.css
|
|
||||||
let colorPalette = []
|
|
||||||
const buildColorPalette = () => {
|
|
||||||
try {
|
|
||||||
const root = document.documentElement
|
|
||||||
const styles = getComputedStyle(root)
|
|
||||||
const pick = (name, fallback) => {
|
|
||||||
const v = styles.getPropertyValue(name)
|
|
||||||
return v && v.trim() ? v.trim() : fallback
|
|
||||||
}
|
|
||||||
const baseVars = [
|
|
||||||
['--chart-primary', '#3996ae'],
|
|
||||||
['--chart-success', '#52c41a'],
|
|
||||||
['--chart-warning', '#faad14'],
|
|
||||||
['--chart-error', '#f5222d'],
|
|
||||||
['--chart-secondary', '#722ed1'],
|
|
||||||
['--chart-accent', '#13c2c2'],
|
|
||||||
]
|
|
||||||
const paletteVars = [
|
|
||||||
['--chart-palette-1', '#3996ae'],
|
|
||||||
['--chart-palette-2', '#028ea0'],
|
|
||||||
['--chart-palette-3', '#00b8a9'],
|
|
||||||
['--chart-palette-4', '#f2c94c'],
|
|
||||||
['--chart-palette-5', '#eb5757'],
|
|
||||||
['--chart-palette-6', '#2f80ed'],
|
|
||||||
['--chart-palette-7', '#9b51e0'],
|
|
||||||
['--chart-palette-8', '#56ccf2'],
|
|
||||||
['--chart-palette-9', '#6fcf97'],
|
|
||||||
['--chart-palette-10', '#333333'],
|
|
||||||
]
|
|
||||||
const baseColors = baseVars.map(([n, f]) => pick(n, f))
|
|
||||||
const paletteColors = paletteVars.map(([n, f]) => pick(n, f))
|
|
||||||
// PRIORITY: palette first, then base
|
|
||||||
const merged = [...paletteColors, ...baseColors]
|
|
||||||
.filter(Boolean)
|
|
||||||
.filter((c, idx, arr) => arr.indexOf(c) === idx)
|
|
||||||
colorPalette = merged
|
|
||||||
} catch (e) {
|
|
||||||
// Fallback
|
|
||||||
colorPalette = [
|
|
||||||
'#3996ae', '#52c41a', '#faad14', '#f5222d', '#722ed1', '#13c2c2',
|
|
||||||
'#fa8c16', '#1890ff', '#95de64', '#69c0ff'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getColorByIndex = (index) => {
|
|
||||||
if (!colorPalette || colorPalette.length === 0) buildColorPalette()
|
|
||||||
return colorPalette[index % colorPalette.length]
|
|
||||||
}
|
|
||||||
|
|
||||||
const truncateLegend = (name) => {
|
|
||||||
if (!name) return ''
|
|
||||||
return name.length > 20 ? name.slice(0, 20) + '…' : name
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadCallStats = async () => {
|
const loadCallStats = async () => {
|
||||||
callStatsLoading.value = true
|
callStatsLoading.value = true
|
||||||
try {
|
try {
|
||||||
@ -178,7 +123,6 @@ const renderCallStatsChart = () => {
|
|||||||
callStatsChart.dispose()
|
callStatsChart.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!colorPalette || colorPalette.length === 0) buildColorPalette()
|
|
||||||
|
|
||||||
callStatsChart = echarts.init(container)
|
callStatsChart = echarts.init(container)
|
||||||
|
|
||||||
@ -295,7 +239,6 @@ const cleanup = () => {
|
|||||||
defineExpose({ cleanup })
|
defineExpose({ cleanup })
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
buildColorPalette()
|
|
||||||
loadCallStats()
|
loadCallStats()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -94,6 +94,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch, nextTick, computed } from 'vue'
|
import { ref, onMounted, watch, nextTick, computed } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
|
import { getColorByIndex, getChartColor, getColorPalette } from '@/utils/chartColors'
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -134,38 +135,8 @@ const formattedStorageSize = computed(() => {
|
|||||||
// return nodes > 0 ? size / (nodes * 1024) : 0 // 转换为KB
|
// return nodes > 0 ? size / (nodes * 1024) : 0 // 转换为KB
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// 颜色数组 - 基于主题色的协调调色板
|
// 使用统一的调色盘
|
||||||
const colorPalette = [
|
const getLegendColorByIndex = (index) => getColorByIndex(index)
|
||||||
'#3996ae', // 主色调
|
|
||||||
'#5faec2', // 主色调浅色
|
|
||||||
'#82c3d6', // 主色调更浅
|
|
||||||
'#a3d8e8', // 主色调最浅
|
|
||||||
'#24839a', // 主色调深色
|
|
||||||
'#046a82', // 主色调更深
|
|
||||||
'#035065', // 主色调最深
|
|
||||||
'#c4eaf5', // 极浅色
|
|
||||||
'#e1f6fb', // 背景色
|
|
||||||
'#f2fbfd' // 最浅背景色
|
|
||||||
]
|
|
||||||
|
|
||||||
const getColorByIndex = (index) => {
|
|
||||||
return colorPalette[index % colorPalette.length]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图例/分段颜色:与 base.css 中的 --chart-palette-* 保持一致(使用固定 HEX)
|
|
||||||
const legendPalette = [
|
|
||||||
'#3996ae', // --chart-palette-1 -> var(--chart-primary)
|
|
||||||
'#028ea0', // --chart-palette-2
|
|
||||||
'#00b8a9', // --chart-palette-3
|
|
||||||
'#f2c94c', // --chart-palette-4
|
|
||||||
'#eb5757', // --chart-palette-5
|
|
||||||
'#2f80ed', // --chart-palette-6
|
|
||||||
'#9b51e0', // --chart-palette-7
|
|
||||||
'#56ccf2', // --chart-palette-8
|
|
||||||
'#6fcf97', // --chart-palette-9
|
|
||||||
'#333333' // --chart-palette-10
|
|
||||||
]
|
|
||||||
const getLegendColorByIndex = (index) => legendPalette[index % legendPalette.length]
|
|
||||||
|
|
||||||
|
|
||||||
// 初始化数据库类型分布图 - 横向分段条
|
// 初始化数据库类型分布图 - 横向分段条
|
||||||
@ -293,7 +264,7 @@ const initFileTypeChart = () => {
|
|||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
data: data,
|
data: data,
|
||||||
color: legendPalette
|
color: getColorPalette()
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,6 +86,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch, nextTick, computed } from 'vue'
|
import { ref, onMounted, watch, nextTick, computed } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
|
import { getColorByIndex, getChartColor, getColorPalette } from '@/utils/chartColors'
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -197,12 +198,12 @@ const initToolsChart = () => {
|
|||||||
type: 'bar',
|
type: 'bar',
|
||||||
data: data.map(item => item.count),
|
data: data.map(item => item.count),
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#3996ae',
|
color: getChartColor('primary'),
|
||||||
borderRadius: [0, 4, 4, 0]
|
borderRadius: [0, 4, 4, 0]
|
||||||
},
|
},
|
||||||
emphasis: {
|
emphasis: {
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#028ea0',
|
color: getChartColor('primary'),
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
shadowColor: 'rgba(2, 142, 160, 0.3)'
|
shadowColor: 'rgba(2, 142, 160, 0.3)'
|
||||||
}
|
}
|
||||||
@ -257,7 +258,7 @@ const initErrorChart = () => {
|
|||||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
color: ['#3996ae', '#028ea0', '#00b8a9', '#f2c94c', '#eb5757', '#2f80ed', '#9b51e0', '#56ccf2', '#6fcf97', '#333333']
|
color: getColorPalette()
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch, nextTick } from 'vue'
|
import { ref, onMounted, watch, nextTick } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
|
import { getChartColor } from '@/utils/chartColors'
|
||||||
import { dashboardApi } from '@/apis/dashboard_api'
|
import { dashboardApi } from '@/apis/dashboard_api'
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
@ -105,7 +106,7 @@ const initActivityChart = () => {
|
|||||||
data: props.userStats.daily_active_users.map(item => item.active_users),
|
data: props.userStats.daily_active_users.map(item => item.active_users),
|
||||||
smooth: true,
|
smooth: true,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#3996ae',
|
color: getChartColor('primary'),
|
||||||
width: 3
|
width: 3
|
||||||
},
|
},
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
@ -123,13 +124,13 @@ const initActivityChart = () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#3996ae',
|
color: getChartColor('primary'),
|
||||||
borderWidth: 2,
|
borderWidth: 2,
|
||||||
borderColor: '#fff'
|
borderColor: '#fff'
|
||||||
},
|
},
|
||||||
emphasis: {
|
emphasis: {
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: '#24839a',
|
color: getChartColor('primary'),
|
||||||
borderWidth: 3,
|
borderWidth: 3,
|
||||||
borderColor: '#fff',
|
borderColor: '#fff',
|
||||||
shadowBlur: 10,
|
shadowBlur: 10,
|
||||||
|
|||||||
146
web/src/utils/chartColors.js
Normal file
146
web/src/utils/chartColors.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/**
|
||||||
|
* Chart Color Palette Utility
|
||||||
|
* 统一的图表调色盘工具函数
|
||||||
|
* 从 CSS 变量中动态获取颜色,确保与主题保持一致
|
||||||
|
*/
|
||||||
|
|
||||||
|
let colorPalette = []
|
||||||
|
let isInitialized = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build color palette from CSS variables in base.css
|
||||||
|
* 从 base.css 中的 CSS 变量构建调色盘
|
||||||
|
*/
|
||||||
|
const buildColorPalette = () => {
|
||||||
|
try {
|
||||||
|
const root = document.documentElement
|
||||||
|
const styles = getComputedStyle(root)
|
||||||
|
|
||||||
|
const pick = (name, fallback) => {
|
||||||
|
const v = styles.getPropertyValue(name)
|
||||||
|
return v && v.trim() ? v.trim() : fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base chart colors
|
||||||
|
const baseVars = [
|
||||||
|
['--chart-primary', '#3996ae'],
|
||||||
|
['--chart-success', '#52c41a'],
|
||||||
|
['--chart-warning', '#faad14'],
|
||||||
|
['--chart-error', '#f5222d'],
|
||||||
|
['--chart-secondary', '#722ed1'],
|
||||||
|
['--chart-accent', '#13c2c2'],
|
||||||
|
]
|
||||||
|
|
||||||
|
// Extended palette colors
|
||||||
|
const paletteVars = [
|
||||||
|
['--chart-palette-1', '#3996ae'],
|
||||||
|
['--chart-palette-2', '#028ea0'],
|
||||||
|
['--chart-palette-3', '#00b8a9'],
|
||||||
|
['--chart-palette-4', '#f2c94c'],
|
||||||
|
['--chart-palette-5', '#eb5757'],
|
||||||
|
['--chart-palette-6', '#2f80ed'],
|
||||||
|
['--chart-palette-7', '#9b51e0'],
|
||||||
|
['--chart-palette-8', '#56ccf2'],
|
||||||
|
['--chart-palette-9', '#6fcf97'],
|
||||||
|
['--chart-palette-10', '#333333'],
|
||||||
|
]
|
||||||
|
|
||||||
|
const baseColors = baseVars.map(([n, f]) => pick(n, f))
|
||||||
|
const paletteColors = paletteVars.map(([n, f]) => pick(n, f))
|
||||||
|
|
||||||
|
// Priority: palette first, then base colors
|
||||||
|
const merged = [...paletteColors, ...baseColors]
|
||||||
|
.filter(Boolean)
|
||||||
|
.filter((c, idx, arr) => arr.indexOf(c) === idx) // Remove duplicates
|
||||||
|
|
||||||
|
colorPalette = merged
|
||||||
|
isInitialized = true
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Failed to build color palette from CSS variables, using fallback:', e)
|
||||||
|
// Fallback palette
|
||||||
|
colorPalette = [
|
||||||
|
'#3996ae', '#52c41a', '#faad14', '#f5222d', '#722ed1', '#13c2c2',
|
||||||
|
'#fa8c16', '#1890ff', '#95de64', '#69c0ff'
|
||||||
|
]
|
||||||
|
isInitialized = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get color by index from the palette
|
||||||
|
* 根据索引从调色盘中获取颜色
|
||||||
|
* @param {number} index - Color index
|
||||||
|
* @returns {string} Color value
|
||||||
|
*/
|
||||||
|
export const getColorByIndex = (index) => {
|
||||||
|
if (!isInitialized || colorPalette.length === 0) {
|
||||||
|
buildColorPalette()
|
||||||
|
}
|
||||||
|
return colorPalette[index % colorPalette.length]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the entire color palette
|
||||||
|
* 获取完整的调色盘
|
||||||
|
* @returns {Array<string>} Color palette array
|
||||||
|
*/
|
||||||
|
export const getColorPalette = () => {
|
||||||
|
if (!isInitialized || colorPalette.length === 0) {
|
||||||
|
buildColorPalette()
|
||||||
|
}
|
||||||
|
return [...colorPalette] // Return a copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get specific chart colors by name
|
||||||
|
* 根据名称获取特定的图表颜色
|
||||||
|
* @param {string} colorName - Color name (primary, success, warning, error, secondary, accent)
|
||||||
|
* @returns {string} Color value
|
||||||
|
*/
|
||||||
|
export const getChartColor = (colorName) => {
|
||||||
|
const colorMap = {
|
||||||
|
primary: '#3996ae',
|
||||||
|
success: '#52c41a',
|
||||||
|
warning: '#faad14',
|
||||||
|
error: '#f5222d',
|
||||||
|
secondary: '#722ed1',
|
||||||
|
accent: '#13c2c2'
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const root = document.documentElement
|
||||||
|
const styles = getComputedStyle(root)
|
||||||
|
const cssVarName = `--chart-${colorName}`
|
||||||
|
const value = styles.getPropertyValue(cssVarName)
|
||||||
|
return value && value.trim() ? value.trim() : colorMap[colorName] || colorMap.primary
|
||||||
|
} catch (e) {
|
||||||
|
return colorMap[colorName] || colorMap.primary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truncate legend text for better display
|
||||||
|
* 截断图例文本以便更好地显示
|
||||||
|
* @param {string} name - Legend name
|
||||||
|
* @param {number} maxLength - Maximum length (default: 20)
|
||||||
|
* @returns {string} Truncated name
|
||||||
|
*/
|
||||||
|
export const truncateLegend = (name, maxLength = 20) => {
|
||||||
|
if (!name) return ''
|
||||||
|
return name.length > maxLength ? name.slice(0, maxLength) + '…' : name
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the color palette (call this when DOM is ready)
|
||||||
|
* 初始化调色盘(在 DOM 准备好时调用)
|
||||||
|
*/
|
||||||
|
export const initColorPalette = () => {
|
||||||
|
buildColorPalette()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-initialize when module is loaded
|
||||||
|
if (typeof window !== 'undefined' && document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initColorPalette)
|
||||||
|
} else if (typeof window !== 'undefined') {
|
||||||
|
initColorPalette()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user