refactor(web): 统一使用新的颜色系统变量替换旧变量

重构整个前端项目中的颜色变量,使用新的标准化颜色系统(--color-*-500)替换旧的--chart-*和--color-*变量。主要变更包括:

1. 替换所有组件中的颜色变量为新的标准命名格式
2. 更新图表颜色工具函数,移除旧的getChartColor方法
3. 调整暗色模式下的颜色变量值
4. 优化仪表盘统计卡片样式
5. 修复错误消息显示逻辑
6. 简化知识库类型选择卡片样式

同时更新了后端API错误处理逻辑,提供更详细的错误信息。移除不再使用的代码和样式。
This commit is contained in:
Wenjie Zhang 2025-11-25 22:34:44 +08:00
parent fb3b864565
commit 33ef9f0e15
37 changed files with 400 additions and 477 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -224,15 +224,18 @@ async def save_partial_message(conv_mgr, thread_id, full_msg=None, error_message
error_type: 错误类型标识
"""
try:
extra_metadata = {
"error_type": error_type,
"is_error": True,
"error_message": error_message or f"发生错误: {error_type}"
}
if full_msg:
# 保存部分生成的AI消息
msg_dict = full_msg.model_dump() if hasattr(full_msg, "model_dump") else {}
content = full_msg.content if hasattr(full_msg, "content") else str(full_msg)
extra_metadata = msg_dict | {"error_type": error_type}
else:
# 保存纯错误消息
content = error_message or f"发生错误: {error_type}"
extra_metadata = {"error_type": error_type, "is_error": True}
content = ""
saved_msg = conv_mgr.add_message_by_thread_id(
thread_id=thread_id,
@ -517,14 +520,24 @@ async def chat_agent(
# Input guard
if conf.enable_content_guard and await content_guard.check(query):
yield make_chunk(status="error", message="输入内容包含敏感词", meta=meta)
yield make_chunk(
status="error",
error_type="content_guard_blocked",
error_message="输入内容包含敏感词",
meta=meta
)
return
try:
agent = agent_manager.get_agent(agent_id)
except Exception as e:
logger.error(f"Error getting agent {agent_id}: {e}, {traceback.format_exc()}")
yield make_chunk(message=f"Error getting agent {agent_id}: {e}", status="error")
yield make_chunk(
status="error",
error_type="agent_error",
error_message=f"智能体 {agent_id} 获取失败: {str(e)}",
meta=meta
)
return
messages = [human_message]
@ -671,7 +684,12 @@ async def chat_agent(
finally:
new_db.close()
yield make_chunk(message=error_msg, status="error")
yield make_chunk(
status="error",
error_type=error_type,
error_message=error_msg,
meta=meta
)
return StreamingResponse(stream_messages(), media_type="application/json")
@ -880,6 +898,8 @@ async def get_agent_history(
"content": msg.content,
"created_at": msg.created_at.isoformat() if msg.created_at else None,
"error_type": msg.extra_metadata.get("error_type") if msg.extra_metadata else None,
"error_message": msg.extra_metadata.get("error_message") if msg.extra_metadata else None,
"extra_metadata": msg.extra_metadata, # 保留完整的metadata以备前端需要
"message_type": msg.message_type, # 添加消息类型字段
"image_content": msg.image_content, # 添加图片内容字段
}

View File

@ -560,27 +560,24 @@ async def get_agent_analytics(
agent_tool_usage.append({"agent_id": agent_id, "tool_usage_count": tool_usage_count})
# 表现最佳的智能体(综合评分
# 表现最佳的智能体(按对话数排序
top_performing_agents = []
for i, (agent_id, conv_count) in enumerate(agents):
# 综合评分 = 对话数权重 + 满意度权重
# 获取满意度数据
satisfaction_data = next(
(s for s in agent_satisfaction if s["agent_id"] == agent_id), {"satisfaction_rate": 0}
)
score = conv_count * 0.3 + satisfaction_data["satisfaction_rate"] * 0.7
top_performing_agents.append(
{
"agent_id": agent_id,
"score": round(score, 2),
"conversation_count": conv_count,
"satisfaction_rate": satisfaction_data["satisfaction_rate"],
}
)
# 按评分排序取前5名
top_performing_agents.sort(key=lambda x: x["score"], reverse=True)
# 按对话数排序取前5名
top_performing_agents.sort(key=lambda x: x["conversation_count"], reverse=True)
top_performing_agents = top_performing_agents[:5]
return AgentAnalytics(

View File

@ -40,76 +40,64 @@
--gray-10: #fbfcfc;
--gray-0: #ffffff;
/* Standard Color System - 标准5档色阶系统 */
--color-primary-50: #e1f6fb; /* 主色调-最浅 */
--color-primary-100: #a3d8e8; /* 主色调-浅 */
--color-primary-500: #3996ae; /* 主色调-标准 */
--color-primary-700: #046a82; /* 主色调-深 */
--color-primary-900: #023944; /* 主色调-最深 */
/* 保留原有的 main 变量 */
--main-color: #016179;
/* 鲜艳一点的 */
--main-bright: #0188a6;
--secondry-color: #4e616d;
--error-color: #ba1a1a;
--color-primary: #1c7796;
--color-primary-bg: #d6eef1;
--color-success: #45b30e;
--color-success-light: #f6ffed;
--color-error: #c73234;
--color-error-light: #fff2f0;
--color-info: #0058d4;
--color-info-light: #e6f7ff;
--color-warning: #faad14;
--color-warning-light: #fffbe6;
/* Chart Colors - 图表颜色系统 */
--chart-primary: var(--main-500); /* 主色调 - 用于主要数据 */
--chart-primary-light: var(--main-400); /* 主色调浅色 - 用于渐变 */
--chart-primary-dark: var(--main-600); /* 主色调深色 - 用于强调 */
--color-secondary-50: #f5f7f7; /* 次要色-最浅 */
--color-secondary-100: #eff2f2; /* 次要色-浅 */
--color-secondary-500: #4e616d; /* 次要色-标准 */
--color-secondary-700: #3a4a56; /* 次要色-深 */
--color-secondary-900: #2c3843; /* 次要色-最深 */
--chart-success: #52c41a; /* 成功色 - 绿色 */
--chart-success-light: #95de64; /* 成功色浅色 */
--chart-success-dark: #389e0d; /* 成功色深色 */
--color-success-50: #f6ffed; /* 成功色-最浅 */
--color-success-100: #b7eb8f; /* 成功色-浅 */
--color-success-500: #52c41a; /* 成功色-标准 */
--color-success-700: #389e0d; /* 成功色-深 */
--color-success-900: #135200; /* 成功色-最深 */
--chart-warning: #faad14; /* 警告色 - 橙色 */
--chart-warning-light: #ffd666; /* 警告色浅色 */
--chart-warning-dark: #d48806; /* 警告色深色 */
--color-error-50: #fff2f0; /* 错误色-最浅 */
--color-error-100: #ffccc7; /* 错误色-浅 */
--color-error-500: #ff4d4f; /* 错误色-标准 */
--color-error-700: #cf1322; /* 错误色-深 */
--color-error-900: #820014; /* 错误色-最深 */
--chart-error: #f5222d; /* 错误色 - 红色 */
--chart-error-light: #ff7875; /* 错误色浅色 */
--chart-error-dark: #cf1322; /* 错误色深色 */
--color-warning-50: #fffbe6; /* 警告色-最浅 */
--color-warning-100: #ffe58f; /* 警告色-浅 */
--color-warning-500: #faad14; /* 警告色-标准 */
--color-warning-700: #d48806; /* 警告色-深 */
--color-warning-900: #ad6800; /* 警告色-最深 */
--chart-info: #1890ff; /* 信息色 - 蓝色 */
--chart-info-light: #69c0ff; /* 信息色浅色 */
--chart-info-dark: #096dd9; /* 信息色深色 */
--color-info-50: #e6f7ff; /* 信息色-最浅 */
--color-info-100: #bae7ff; /* 信息色-浅 */
--color-info-500: #1890ff; /* 信息色-标准 */
--color-info-700: #096dd9; /* 信息色-深 */
--color-info-900: #0050b3; /* 信息色-最深 */
--chart-secondary: #722ed1; /* 次要色 - 紫色 */
--chart-secondary-light: #b37feb; /* 次要色浅色 */
--chart-secondary-dark: #531dab; /* 次要色深色 */
--chart-accent: #13c2c2; /* 强调色 - 青色 */
--chart-accent-light: #5cdbd3; /* 强调色浅色 */
--chart-accent-dark: #08979c; /* 强调色深色 */
--color-accent-50: #e6fffb; /* 强调色-最浅 */
--color-accent-100: #87e8de; /* 强调色-浅 */
--color-accent-500: #13c2c2; /* 强调色-标准 */
--color-accent-700: #08979c; /* 强调色-深 */
--color-accent-900: #006d75; /* 强调色-最深 */
/* Chart Palette - 图表调色板 */
--chart-palette-1: var(--chart-primary);
--chart-palette-2: #11cbe3; /* 浅一点的青蓝 */
--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; /* 深灰(中性补充) */
/* Stats Card Colors - 统计卡片颜色系统 */
--stats-primary-bg: #eff6ff; /* 主色调背景 */
--stats-primary-color: #2563eb; /* 主色调文字 */
--stats-success-bg: #f0fdf4; /* 成功色背景 */
--stats-success-color: #16a34a; /* 成功色文字 */
--stats-info-bg: #f0f9ff; /* 信息色背景 */
--stats-info-color: #0284c7; /* 信息色文字 */
--stats-warning-bg: #fffbeb; /* 警告色背景 */
--stats-warning-color: #d97706; /* 警告色文字 */
--stats-secondary-bg: #faf5ff; /* 次要色背景 */
--stats-secondary-color: #9333ea; /* 次要色文字 */
--stats-error-bg: #fef2f2; /* 错误色背景 */
--stats-error-color: #dc2626; /* 错误色文字 */
--chart-palette-1: var(--main-500);
--chart-palette-2: #5AD8A6;
--chart-palette-3: #F6BD16;
--chart-palette-4: #F27C7C;
--chart-palette-5: #9581CC;
--chart-palette-6: #6DC8EC;
--chart-palette-7: #FF9D4D;
--chart-palette-8: #92D050;
--chart-palette-9: #E885BA;
--chart-palette-10: #8C8C8C;
--bg-sider: var(--main-5);
--color-text: var(--c-black);
@ -122,11 +110,6 @@
--shadow-4: rgba(0, 0, 0, 0.16);
--shadow-5: rgba(0, 0, 0, 0.20);
/* Extended Chart Variables - 扩展图表变量 */
--chart-primary-lighter: var(--chart-primary-light);
--chart-info-lighter: var(--chart-info-light);
--chart-primary-shadow: rgba(28, 119, 150, 0.3);
--chart-info-shadow: rgba(24, 144, 255, 0.3);
--min-width: 400px;

View File

@ -38,63 +38,64 @@
--gray-10: #080808;
--gray-0: #030303;
/* Standard Color System - 深色模式5档色阶系统 */
--color-primary-50: #023944; /* 主色调-最深 */
--color-primary-100: #035065; /* 主色调-深 */
--color-primary-500: #4a9fb8; /* 主色调-标准 */
--color-primary-700: #5faec2; /* 主色调-浅 */
--color-primary-900: #82c3d6; /* 主色调-最浅 */
/* 保留原有的 main 变量 */
--main-color: #4a9fb8;
--main-bright: #5faec2;
--secondry-color: #8fa5b0;
--error-color: #ff6b6b;
--color-primary: #4a9fb8;
--color-primary-bg: #1a3a42;
--color-success: #52c41a;
--color-success-light: #162312;
--color-error: #ff4d4f;
--color-error-light: #2a1215;
--color-info: #3d8fff;
--color-info-light: #111b26;
--color-warning: #faad14;
--color-warning-light: #2b2111;
/* Chart Colors - 深色模式图表颜色 */
--chart-primary: var(--main-500);
--chart-primary-light: var(--main-600);
--chart-primary-dark: var(--main-400);
--color-secondary-50: #151616; /* 次要色-最深 */
--color-secondary-100: #1e1f1f; /* 次要色-深 */
--color-secondary-500: #8fa5b0; /* 次要色-标准 */
--color-secondary-700: #9fb5c0; /* 次要色-浅 */
--color-secondary-900: #b8c8d0; /* 次要色-最浅 */
--chart-success: #52c41a;
--chart-success-light: #73d13d;
--chart-success-dark: #389e0d;
--color-success-50: #162312; /* 成功色-最深 */
--color-success-100: #273921; /* 成功色-深 */
--color-success-500: #52c41a; /* 成功色-标准 */
--color-success-700: #73d13d; /* 成功色-浅 */
--color-success-900: #95de64; /* 成功色-最浅 */
--chart-warning: #faad14;
--chart-warning-light: #ffc53d;
--chart-warning-dark: #d48806;
--color-error-50: #2a1215; /* 错误色-最深 */
--color-error-100: #58181c; /* 错误色-深 */
--color-error-500: #ff4d4f; /* 错误色-标准 */
--color-error-700: #ff7875; /* 错误色-浅 */
--color-error-900: #ffa39e; /* 错误色-最浅 */
--chart-error: #ff4d4f;
--chart-error-light: #ff7875;
--chart-error-dark: #cf1322;
--color-warning-50: #2b2111; /* 警告色-最深 */
--color-warning-100: #614700; /* 警告色-深 */
--color-warning-500: #faad14; /* 警告色-标准 */
--color-warning-700: #ffc53d; /* 警告色-浅 */
--color-warning-900: #ffd666; /* 警告色-最浅 */
--chart-info: #1890ff;
--chart-info-light: #40a9ff;
--chart-info-dark: #096dd9;
--color-info-50: #111b26; /* 信息色-最深 */
--color-info-100: #111d2c; /* 信息色-深 */
--color-info-500: #3d8fff; /* 信息色-标准 */
--color-info-700: #40a9ff; /* 信息色-浅 */
--color-info-900: #69c0ff; /* 信息色-最浅 */
--chart-secondary: #722ed1;
--chart-secondary-light: #9254de;
--chart-secondary-dark: #531dab;
--color-accent-50: #0f2e2e; /* 强调色-最深 */
--color-accent-100: #164e63; /* 强调色-深 */
--color-accent-500: #13c2c2; /* 强调色-标准 */
--color-accent-700: #36cfc9; /* 强调色-浅 */
--color-accent-900: #5cdbd3; /* 强调色-最浅 */
--chart-accent: #13c2c2;
--chart-accent-light: #36cfc9;
--chart-accent-dark: #08979c;
--chart-palette-1: var(--main-300);
--chart-palette-2: #3EA896;
--chart-palette-3: #D6AD37;
--chart-palette-4: #CF6666;
--chart-palette-5: #8672B4;
--chart-palette-6: #529AB8;
--chart-palette-7: #D48242;
--chart-palette-8: #82B354;
--chart-palette-9: #C46E9E;
--chart-palette-10: #7A7A7A;
/* Stats Card Colors - 深色模式统计卡片 */
--stats-primary-bg: #1e3a8a;
--stats-primary-color: #93c5fd;
--stats-success-bg: #14532d;
--stats-success-color: #86efac;
--stats-info-bg: #0c4a6e;
--stats-info-color: #7dd3fc;
--stats-warning-bg: #78350f;
--stats-warning-color: #fcd34d;
--stats-secondary-bg: #581c87;
--stats-secondary-color: #d8b4fe;
--stats-error-bg: #7f1d1d;
--stats-error-color: #fca5a5;
--bg-sider: #141414;
--color-text: #ffffff;
@ -113,11 +114,6 @@
--shadow-4: rgba(0, 0, 0, 0.5);
--shadow-5: rgba(0, 0, 0, 0.6);
/* Extended Chart Variables - 扩展图表变量 */
--chart-primary-lighter: var(--chart-primary-light);
--chart-info-lighter: var(--chart-info-light);
--chart-primary-shadow: rgba(74, 159, 184, 0.4);
--chart-info-shadow: rgba(24, 144, 255, 0.4);
--color-trans-light: rgba(0, 0, 0, 0.85);
--color-trans-dark: rgba(255, 255, 255, 0.85);
@ -129,14 +125,14 @@
--markmap-a-hover-color: var(--main-600);
--markmap-code-bg: var(--gray-50);
--markmap-code-color: var(--gray-700);
--markmap-highlight-bg: var(--color-warning-light);
--markmap-highlight-bg: var(--color-warning-50);
--markmap-table-border: 1px solid currentColor;
--markmap-font: 300 16px / 20px sans-serif;
--markmap-circle-open-bg: var(--main-0);
--markmap-text-color: var(--gray-700);
--markmap-highlight-node-bg: var(--color-error-light);
--markmap-highlight-node-bg: var(--color-error-50);
}
:root.dark .md-editor {
--md-bk-color: var(--gray-0);
}
}

View File

@ -7,8 +7,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-primary)' },
{ offset: 1, color: 'var(--chart-primary-light)' }
{ offset: 0, color: 'var(--chart-primary-500)' },
{ offset: 1, color: 'var(--chart-primary-100)' }
]
};
@ -16,8 +16,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-success)' },
{ offset: 1, color: 'var(--chart-success-light)' }
{ offset: 0, color: 'var(--color-success-500)' },
{ offset: 1, color: 'var(--color-success-100)' }
]
};
@ -25,8 +25,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-warning)' },
{ offset: 1, color: 'var(--chart-warning-light)' }
{ offset: 0, color: 'var(--color-warning-500)' },
{ offset: 1, color: 'var(--color-warning-100)' }
]
};
@ -34,8 +34,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-error)' },
{ offset: 1, color: 'var(--chart-error-light)' }
{ offset: 0, color: 'var(--color-error-500)' },
{ offset: 1, color: 'var(--color-error-100)' }
]
};
@ -43,8 +43,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-info)' },
{ offset: 1, color: 'var(--chart-info-light)' }
{ offset: 0, color: 'var(--color-info-500)' },
{ offset: 1, color: 'var(--color-info-100)' }
]
};
@ -52,8 +52,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-secondary)' },
{ offset: 1, color: 'var(--chart-secondary-light)' }
{ offset: 0, color: 'var(--color-accent-500)' },
{ offset: 1, color: 'var(--color-accent-100)' }
]
};
@ -61,8 +61,8 @@
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'var(--chart-accent)' },
{ offset: 1, color: 'var(--chart-accent-light)' }
{ offset: 0, color: 'var(--color-accent-500)' },
{ offset: 1, color: 'var(--color-accent-100)' }
]
};
}
@ -245,6 +245,11 @@
color: var(--gray-1000);
}
/* 强制设置所有统计卡片数字为粗体 */
.dashboard-card .ant-statistic-content-value {
font-weight: 700 !important;
}
.dashboard-card .ant-table {
background-color: var(--gray-0);
border-radius: 8px;

View File

@ -21,35 +21,35 @@
/* 高亮样式 */
.node-highlighted {
stroke: var(--color-error) !important;
stroke-width: 3px !important;
stroke: var(--color-error-500);
stroke-width: 3px;
}
.edge-highlighted {
stroke: var(--color-error) !important;
stroke-width: 3px !important;
stroke: var(--color-error-500);
stroke-width: 3px;
}
/* 选中样式 */
.node-selected {
stroke: var(--color-info) !important;
stroke-width: 4px !important;
stroke: var(--color-info-500);
stroke-width: 4px;
}
.edge-selected {
stroke: var(--color-info) !important;
stroke-width: 4px !important;
stroke: var(--color-info-500);
stroke-width: 4px;
}
/* 悬停样式 */
.node-focused {
stroke: var(--color-success) !important;
stroke-width: 2px !important;
stroke: var(--color-success-500);
stroke-width: 2px;
}
.edge-focused {
stroke: var(--color-success) !important;
stroke-width: 2px !important;
stroke: var(--color-success-500);
stroke-width: 2px;
}
/* 加载动画 */

View File

@ -734,9 +734,9 @@ watch(() => props.isOpen, (newVal) => {
.system-prompt-display {
min-height: 60px;
background: var(--gray-50);
border: 1px solid var(--gray-200);
border: 1px dashed var(--gray-200);
border-radius: 6px;
padding: 8px 12px;
padding: 6px;
cursor: pointer;
position: relative;
transition: all 0.2s ease;
@ -774,10 +774,10 @@ watch(() => props.isOpen, (newVal) => {
top: 8px;
right: 12px;
font-size: 12px;
color: var(--gray-400);
color: var(--gray-800);
opacity: 0;
transition: opacity 0.2s ease;
background: rgba(255, 255, 255, 0.9);
background: var(--gray-0);
padding: 2px 6px;
border-radius: 4px;
}
@ -890,8 +890,8 @@ watch(() => props.isOpen, (newVal) => {
.option-card {
border: 1px solid var(--gray-300);
border-radius: 6px;
padding: 10px 12px;
border-radius: 8px;
padding: 8px 12px;
cursor: pointer;
transition: all 0.2s ease;
background: var(--gray-0);
@ -946,30 +946,6 @@ watch(() => props.isOpen, (newVal) => {
//
.tools-modal {
:deep(.ant-modal-content) {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
border: 1px solid var(--gray-200);
}
:deep(.ant-modal-header) {
background: var(--gray-0);
border-bottom: 1px solid var(--gray-200);
padding: 16px 20px;
.ant-modal-title {
font-size: 16px;
font-weight: 600;
color: var(--gray-900);
}
}
:deep(.ant-modal-body) {
padding: 20px;
background: var(--gray-0);
}
.tools-modal-content {
.tools-search {
margin-bottom: 16px;
@ -1010,7 +986,6 @@ watch(() => props.isOpen, (newVal) => {
overflow-y: auto;
border-radius: 8px;
margin-bottom: 16px;
background: var(--gray-0);
//
@media (max-width: 480px) {
@ -1085,19 +1060,19 @@ watch(() => props.isOpen, (newVal) => {
}
&.selected {
background: var(--main-30);
// border-color: var(--main-color);
background: var(--main-50);
border-color: var(--main-200);
.tool-content {
.tool-name {
color: var(--main-color);
color: var(--main-800);
}
.tool-indicator {
color: var(--main-color);
color: var(--main-800);
}
}
.tool-description {
color: var(--gray-700);
color: var(--gray-900);
}
}

View File

@ -34,10 +34,12 @@
<div v-else-if="parsedData.reasoning_content" class="empty-block"></div>
<!-- 错误提示块 -->
<div v-if="message.error_type" class="error-hint">
<span v-if="message.error_type === 'interrupted'">回答生成已中断</span>
<div v-if="displayError" class="error-hint">
<span v-if="getErrorMessage">{{ getErrorMessage }}</span>
<span v-else-if="message.error_type === 'interrupted'">回答生成已中断</span>
<span v-else-if="message.error_type === 'unexpect'">生成过程中出现异常</span>
<span v-else-if="message.error_type === 'content_guard_blocked'">检测到敏感内容已中断输出</span>
<span v-else>{{ message.error_type || '未知错误' }}</span>
</div>
<div v-if="validToolCalls && validToolCalls.length > 0" class="tool-calls-container">
@ -153,6 +155,38 @@ const emit = defineEmits(['retry', 'retryStoppedMessage', 'openRefs']);
const reasoningActiveKey = ref(['hide']);
const expandedToolCalls = ref(new Set()); //
//
const displayError = computed(() => {
//
return !!(props.message.error_type || props.message.extra_metadata?.error_type);
});
const getErrorMessage = computed(() => {
// 使 error_message
if (props.message.error_message) {
return props.message.error_message;
}
// extra_metadata
if (props.message.extra_metadata?.error_message) {
return props.message.extra_metadata.error_message;
}
//
switch (props.message.error_type) {
case 'interrupted':
return '回答生成已中断';
case 'content_guard_blocked':
return '检测到敏感内容,已中断输出';
case 'unexpect':
return '生成过程中出现异常';
case 'agent_error':
return '智能体获取失败';
default:
return null;
}
});
// store
const agentStore = useAgentStore();
const infoStore = useInfoStore();
@ -297,12 +331,12 @@ const toggleToolCall = (toolCallId) => {
}
.err-msg {
color: var(--color-error);
color: var(--color-error-500);
border: 1px solid currentColor;
padding: 0.5rem 1rem;
border-radius: 8px;
text-align: left;
background: var(--color-error-light);
background: var(--color-error-50);
margin-bottom: 10px;
cursor: pointer;
}
@ -374,9 +408,9 @@ const toggleToolCall = (toolCallId) => {
display: flex;
align-items: center;
gap: 8px;
background-color: var(--color-error-light);
background-color: var(--color-error-50);
// border: 1px solid #f87171;
color: var(--color-error);
color: var(--color-error-500);
span {
line-height: 1.5;
}
@ -457,15 +491,15 @@ const toggleToolCall = (toolCallId) => {
}
.tool-loader.tool-success {
color: var(--color-success);
color: var(--color-success-500);
}
.tool-loader.tool-error {
color: var(--color-error);
color: var(--color-error-500);
}
.tool-loader.tool-loading {
color: var(--color-info);
color: var(--color-info-500);
}
}
@ -528,7 +562,7 @@ const toggleToolCall = (toolCallId) => {
}
.retry-link {
color: var(--color-info);
color: var(--color-info-500);
cursor: pointer;
margin-left: 4px;
@ -539,10 +573,10 @@ const toggleToolCall = (toolCallId) => {
.ant-btn-icon-only {
&:has(.anticon-stop) {
background-color: var(--color-error) !important;
background-color: var(--color-error-500) !important;
&:hover {
background-color: var(--chart-error-light) !important;
background-color: var(--color-error-100) !important;
}
}
}
@ -760,4 +794,4 @@ const toggleToolCall = (toolCallId) => {
font-size: 14px;
}
}
</style>
</style>

View File

@ -341,13 +341,13 @@ const emitRefresh = () => {
transition: all 0.15s ease;
&.completed {
background: var(--stats-success-bg);
color: var(--stats-success-color);
background: var(--color-success-50);
color: var(--color-success-700);
}
&.in_progress {
background: var(--stats-warning-bg);
color: var(--stats-warning-color);
background: var(--color-warning-50);
color: var(--color-warning-700);
}
&.pending {

View File

@ -286,7 +286,7 @@ const handleRemoveAttachment = (fileId) => {
transition: all 0.15s ease;
&:hover:not(:disabled) {
color: var(--color-error);
color: var(--color-error-500);
}
&:disabled {

View File

@ -549,7 +549,7 @@ const printAgentConfig = async () => {
}
.error {
color: var(--error-color);
color: var(--color-error-500);
}
.log-container {

View File

@ -121,10 +121,10 @@
</a-button>
<span v-else-if="column.key === 'type'" :class="['span-type', text]">{{ text?.toUpperCase() }}</span>
<div v-else-if="column.key === 'status'" style="display: flex; align-items: center; justify-content: flex-end;">
<CheckCircleFilled v-if="text === 'done'" style="color: var(--color-success);"/>
<CloseCircleFilled v-else-if="text === 'failed'" style="color: var(--color-error);"/>
<HourglassFilled v-else-if="text === 'processing'" style="color: var(--color-info);"/>
<ClockCircleFilled v-else-if="text === 'waiting'" style="color: var(--color-warning);"/>
<CheckCircleFilled v-if="text === 'done'" style="color: var(--color-success-500);"/>
<CloseCircleFilled v-else-if="text === 'failed'" style="color: var(--color-error-500);"/>
<HourglassFilled v-else-if="text === 'processing'" style="color: var(--color-info-500);"/>
<ClockCircleFilled v-else-if="text === 'waiting'" style="color: var(--color-warning-500);"/>
</div>
<a-tooltip v-else-if="column.key === 'created_at'" :title="formatRelativeTime(text)" placement="left">
@ -670,11 +670,11 @@ import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue';
}
.my-table .rechunk-btn:hover {
color: var(--color-warning);
color: var(--color-warning-500);
}
.my-table .del-btn:hover {
color: var(--error-color);
color: var(--color-error-500);
}
.my-table .del-btn:disabled {

View File

@ -733,6 +733,6 @@ const chunkData = async () => {
.zip-support-tip {
font-size: 12px;
color: var(--color-warning);
color: var(--color-warning-500);
}
</style>

View File

@ -97,7 +97,7 @@ defineEmits(['index-nodes', 'export-data'])
font-size: 14px;
&.warning {
color: var(--color-warning);
color: var(--color-warning-500);
}
}
@ -111,7 +111,7 @@ defineEmits(['index-nodes', 'export-data'])
font-weight: 600;
&.warning {
color: var(--color-warning);
color: var(--color-warning-500);
}
}

View File

@ -594,7 +594,7 @@ const registerEvents = () => {
const graph = sigmaInstance.getGraph()
if (graph.hasEdge(edge)) {
//
graph.setEdgeAttribute(edge, 'color', getCSSVariable('--color-error'))
graph.setEdgeAttribute(edge, 'color', getCSSVariable('--color-error-500'))
graph.setEdgeAttribute(edge, 'size', (graph.getEdgeAttribute(edge, 'size') || 1) * 1.5)
sigmaInstance.refresh()
console.log('悬停在边上:', edge)
@ -1271,11 +1271,11 @@ defineExpose({
}
&.node-panel {
border-left: 4px solid var(--color-success); // 绿
border-left: 4px solid var(--color-success-500); // 绿
}
&.edge-panel {
border-left: 4px solid var(--color-info); //
border-left: 4px solid var(--color-info-500); //
}
}
@ -1304,11 +1304,11 @@ defineExpose({
flex-shrink: 0;
&.node-indicator {
background: var(--color-success);
background: var(--color-success-500);
}
&.edge-indicator {
background: var(--color-info);
background: var(--color-info-500);
}
}

View File

@ -309,7 +309,7 @@ onUnmounted(() => {
} */
/*
.chunk-item.highlighted {
border-color: var(--color-success);
border-color: var(--color-success-500);
background: var(--main-50);
} */

View File

@ -180,9 +180,9 @@ const handleSelectModel = async (provider, name) => {
<style lang="less" scoped>
//
@status-success: var(--color-success);
@status-error: var(--color-error);
@status-warning: var(--chart-warning);
@status-success: var(--color-success-500);
@status-error: var(--color-error-500);
@status-warning: var(--color-warning-500);
@status-default: var(--gray-500);
@border-radius: 8px;
@scrollbar-width: 6px;

View File

@ -527,8 +527,8 @@ defineExpose({
}
.result-rerank-score {
background-color: var(--stats-warning-bg);
color: var(--stats-warning-color);
background-color: var(--color-warning-50);
color: var(--color-warning-700);
}
}

View File

@ -491,8 +491,8 @@ function canCancel(task) {
}
.task-card-error {
background: var(--color-error-light);
color: var(--color-error);
background: var(--color-error-50);
color: var(--color-error-500);
}
.task-card-footer {
@ -535,7 +535,7 @@ function canCancel(task) {
}
.completion-badge--success {
color: var(--color-success);
color: var(--color-success-500);
}
.completion-badge--success .completion-icon {
@ -545,12 +545,12 @@ function canCancel(task) {
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--stats-success-bg);
background: var(--color-success-50);
font-size: 14px;
}
.completion-badge--failed {
color: var(--color-error);
color: var(--color-error-500);
}
.completion-badge--failed .completion-icon {
@ -560,7 +560,7 @@ function canCancel(task) {
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--stats-error-bg);
background: var(--color-error-50);
font-size: 14px;
}

View File

@ -1,6 +1,6 @@
<template>
<div class="user-info-component">
<a-dropdown :trigger="['click']" v-if="userStore.isLoggedIn">
<a-dropdown :trigger="['hover']" v-if="userStore.isLoggedIn">
<div class="user-info-dropdown" :data-align="showRole ? 'left' : 'center'">
<div class="user-avatar">
<img v-if="userStore.avatar" :src="userStore.avatar" :alt="userStore.username" class="avatar-image" />
@ -30,6 +30,10 @@
<span class="menu-text">{{ themeStore.isDark ? '切换到浅色模式' : '切换到深色模式 (Beta)' }}</span>
</a-menu-item>
<a-menu-divider />
<a-menu-item key="setting" @click="goToSetting">
<Settings size="16"/>
<span class="menu-text">系统设置</span>
</a-menu-item>
<a-menu-item key="logout" @click="logout">
<LogOut size="16"/>
<span class="menu-text">退出登录</span>
@ -162,7 +166,7 @@ import { useUserStore } from '@/stores/user';
//
//
import { message } from 'ant-design-vue';
import { CircleUser, UserRoundCheck, BookOpen, Sun, Moon, User, LogOut, Upload } from 'lucide-vue-next';
import { CircleUser, UserRoundCheck, BookOpen, Sun, Moon, User, LogOut, Upload, Settings } from 'lucide-vue-next';
import { useThemeStore } from '@/stores/theme'
const router = useRouter();
@ -239,6 +243,11 @@ const toggleTheme = () => {
themeStore.toggleTheme()
}
//
const goToSetting = () => {
router.push('/setting');
}
//
const openProfile = async () => {
profileModalVisible.value = true;
@ -421,15 +430,15 @@ const handleAvatarChange = async (info) => {
border: 2px solid var(--gray-0);
&.superadmin {
background-color: var(--color-warning);
background-color: var(--color-warning-500);
}
&.admin {
background-color: var(--color-info); /* 蓝色,管理员 */
background-color: var(--color-info-500); /* 蓝色,管理员 */
}
&.user {
background-color: var(--color-success); /* 绿色,普通用户 */
background-color: var(--color-success-500); /* 绿色,普通用户 */
}
}

View File

@ -645,8 +645,8 @@ onMounted(() => {
&.ant-btn-dangerous:hover {
background: var(--gray-25);
border-color: var(--color-error);
color: var(--color-error);
border-color: var(--color-error-500);
color: var(--color-error-500);
}
}
}
@ -698,7 +698,7 @@ onMounted(() => {
}
.error-text {
color: var(--color-error);
color: var(--color-error-500);
font-size: 12px;
margin-top: 4px;
line-height: 1.3;

View File

@ -7,7 +7,7 @@
<a-statistic
title="智能体总数"
:value="agentStats?.total_agents || 0"
:value-style="{ color: 'var(--chart-info)' }"
:value-style="{ color: 'var(--color-info-500)' }"
suffix="个"
/>
</a-col>
@ -15,7 +15,7 @@
<a-statistic
title="总对话数"
:value="totalConversations"
:value-style="{ color: 'var(--chart-secondary)' }"
:value-style="{ color: 'var(--color-accent-500)' }"
suffix="次"
/>
</a-col>
@ -23,7 +23,7 @@
<a-statistic
title="工具调用总数"
:value="totalToolUsage"
:value-style="{ color: 'var(--chart-warning)' }"
:value-style="{ color: 'var(--color-warning-500)' }"
suffix="次"
/>
</a-col>
@ -65,22 +65,13 @@
<template v-if="column.key === 'agent_id'">
<a-tag color="blue">{{ record.agent_id }}</a-tag>
</template>
<template v-if="column.key === 'score'">
<a-progress
:percent="record.score"
size="small"
:stroke-color="getScoreColor(record.score)"
:show-info="true"
:format="(percent) => `${percent}分`"
/>
</template>
<template v-if="column.key === 'satisfaction_rate'">
<a-statistic
:value="record.satisfaction_rate"
suffix="%"
:value-style="{
color: record.satisfaction_rate >= 80 ? 'var(--chart-success)' :
record.satisfaction_rate >= 60 ? 'var(--chart-warning)' : 'var(--chart-error)',
color: record.satisfaction_rate >= 80 ? 'var(--color-success-500)' :
record.satisfaction_rate >= 60 ? 'var(--color-warning-500)' : 'var(--color-error-500)',
fontSize: '14px'
}"
/>
@ -98,7 +89,7 @@
<script setup>
import { ref, onMounted, watch, nextTick, computed } from 'vue'
import * as echarts from 'echarts'
import { getColorByIndex, getChartColor } from '@/utils/chartColors'
import { getColorByIndex } from '@/utils/chartColors'
import { useThemeStore } from '@/stores/theme'
// CSS
@ -136,23 +127,18 @@ const performerColumns = [
{
title: '智能体ID',
key: 'agent_id',
width: '25%'
},
{
title: '综合评分',
key: 'score',
width: '20%'
width: '30%'
},
{
title: '满意度',
key: 'satisfaction_rate',
width: '20%',
width: '25%',
align: 'center'
},
{
title: '对话数',
key: 'conversation_count',
width: '15%',
width: '20%',
align: 'center'
}
]
@ -172,12 +158,6 @@ const topPerformers = computed(() => {
return props.agentStats?.top_performing_agents || []
})
//
const getScoreColor = (score) => {
if (score >= 80) return getChartColor('primary')
if (score >= 60) return getChartColor('warning')
return getChartColor('accent')
}
//
@ -288,14 +268,14 @@ const initConversationToolChart = () => {
return item ? item.conversation_count : 0
}),
itemStyle: {
color: getChartColor('primary'),
color: getColorByIndex(0),
borderRadius: [4, 4, 0, 0]
},
emphasis: {
itemStyle: {
color: getChartColor('primary'),
color: getColorByIndex(0),
shadowBlur: 10,
shadowColor: getCSSVariable('--chart-info-shadow')
shadowColor: getCSSVariable('--color-info-50')
}
}
},
@ -307,14 +287,14 @@ const initConversationToolChart = () => {
return item ? item.tool_usage_count : 0
}),
itemStyle: {
color: getChartColor('accent'),
color: getColorByIndex(1),
borderRadius: [4, 4, 0, 0]
},
emphasis: {
itemStyle: {
color: getChartColor('primary'),
color: getColorByIndex(1),
shadowBlur: 10,
shadowColor: getCSSVariable('--chart-info-shadow')
shadowColor: getCSSVariable('--color-info-50')
}
}
}
@ -431,4 +411,8 @@ defineExpose({
transition: all 0.3s ease;
}
:deep(.ant-statistic-content-value) {
font-weight: bold !important;
}
</style>

View File

@ -304,10 +304,10 @@ watch(() => props.agentId, () => {
}
.reason-content {
background: var(--color-warning-light);
background: var(--color-warning-50);
padding: 10px;
border-radius: 6px;
border-left: 3px solid var(--color-warning);
border-left: 3px solid var(--color-warning-500);
font-size: 13px;
line-height: 1.4;
color: var(--gray-800);

View File

@ -7,7 +7,7 @@
<a-statistic
title="知识库总数"
:value="knowledgeStats?.total_databases || 0"
:value-style="{ color: 'var(--chart-info)' }"
:value-style="{ color: 'var(--color-info-500)' }"
suffix="个"
/>
</a-col>
@ -15,7 +15,7 @@
<a-statistic
title="文件总数"
:value="knowledgeStats?.total_files || 0"
:value-style="{ color: 'var(--chart-success)' }"
:value-style="{ color: 'var(--color-success-500)' }"
suffix="个"
/>
</a-col>
@ -23,7 +23,7 @@
<a-statistic
title="存储容量"
:value="formattedStorageSize"
:value-style="{ color: 'var(--chart-warning)' }"
:value-style="{ color: 'var(--color-warning-500)' }"
/>
</a-col>
</a-row>
@ -103,7 +103,7 @@
<script setup>
import { ref, onMounted, watch, nextTick, computed } from 'vue'
import * as echarts from 'echarts'
import { getColorByIndex, getChartColor, getColorPalette } from '@/utils/chartColors'
import { getColorByIndex, getColorPalette } from '@/utils/chartColors'
import { useThemeStore } from '@/stores/theme'
// CSS
@ -356,7 +356,7 @@ const initFileTypeChart = () => {
data: [
{ name: '暂无数据', value: 1 }
],
color: [getCSSVariable('--chart-info-lighter')]
color: [getCSSVariable('--color-info-500')]
}]
}

View File

@ -124,57 +124,57 @@ const getSatisfactionClass = () => {
&.primary {
.stat-icon {
background-color: var(--stats-primary-bg);
color: var(--stats-primary-color);
background-color: var(--color-primary-50);
color: var(--main-color);
}
}
&.success {
.stat-icon {
background-color: var(--stats-success-bg);
color: var(--stats-success-color);
background-color: var(--color-success-50);
color: var(--color-success-700);
}
}
&.info {
.stat-icon {
background-color: var(--stats-info-bg);
color: var(--stats-info-color);
background-color: var(--color-info-50);
color: var(--color-info-700);
}
}
&.warning {
.stat-icon {
background-color: var(--stats-warning-bg);
color: var(--stats-warning-color);
background-color: var(--color-warning-50);
color: var(--color-warning-700);
}
}
&.secondary {
.stat-icon {
background-color: var(--stats-secondary-bg);
color: var(--stats-secondary-color);
background-color: var(--color-accent-50);
color: var(--color-accent-700);
}
}
&.satisfaction-high {
.stat-icon {
background-color: var(--stats-success-bg);
color: var(--stats-success-color);
background-color: var(--color-success-50);
color: var(--color-success-700);
}
}
&.satisfaction-medium {
.stat-icon {
background-color: var(--stats-warning-bg);
color: var(--stats-warning-color);
background-color: var(--color-warning-50);
color: var(--color-warning-700);
}
}
&.satisfaction-low {
.stat-icon {
background-color: var(--stats-error-bg);
color: var(--stats-error-color);
background-color: var(--color-error-50);
color: var(--color-error-700);
}
}
@ -226,11 +226,11 @@ const getSatisfactionClass = () => {
height: 14px;
&.up {
color: var(--stats-success-color);
color: var(--color-success-700);
}
&.down {
color: var(--stats-error-color);
color: var(--color-error-700);
}
}

View File

@ -7,14 +7,14 @@
<a-statistic
title="总调用次数"
:value="toolStats?.total_calls || 0"
:value-style="{ color: 'var(--chart-info)' }"
:value-style="{ color: 'var(--color-info-500)' }"
/>
</a-col>
<a-col :span="8">
<a-statistic
title="失败调用"
:value="toolStats?.failed_calls || 0"
:value-style="{ color: 'var(--chart-error)' }"
:value-style="{ color: 'var(--color-error-500)' }"
suffix="次"
/>
</a-col>
@ -24,8 +24,8 @@
:value="toolStats?.success_rate || 0"
suffix="%"
:value-style="{
color: (toolStats?.success_rate || 0) >= 90 ? 'var(--chart-success)' :
(toolStats?.success_rate || 0) >= 70 ? 'var(--chart-warning)' : 'var(--chart-error)'
color: (toolStats?.success_rate || 0) >= 90 ? 'var(--color-success-500)' :
(toolStats?.success_rate || 0) >= 70 ? 'var(--color-warning-500)' : 'var(--color-error-500)'
}"
/>
</a-col>
@ -78,7 +78,7 @@
<script setup>
import { ref, onMounted, watch, nextTick, computed } from 'vue'
import * as echarts from 'echarts'
import { getColorByIndex, getChartColor, getColorPalette } from '@/utils/chartColors'
import { getColorByIndex, getColorPalette } from '@/utils/chartColors'
import { useThemeStore } from '@/stores/theme'
// CSS
@ -205,14 +205,14 @@ const initToolsChart = () => {
type: 'bar',
data: data.map(item => item.count),
itemStyle: {
color: getChartColor('primary'),
color: getColorByIndex(0),
borderRadius: [0, 4, 4, 0]
},
emphasis: {
itemStyle: {
color: getChartColor('primary'),
color: getColorByIndex(0),
shadowBlur: 10,
shadowColor: getCSSVariable('--chart-info-shadow')
shadowColor: getCSSVariable('--color-info-50')
}
}
}]
@ -331,15 +331,3 @@ defineExpose({
cleanup
})
</script>
<style scoped lang="less">
// ToolStatsComponent
.error-analysis {
h4 {
margin-bottom: 16px;
color: var(--gray-1000);
font-weight: 500;
}
}
</style>

View File

@ -30,8 +30,6 @@
<script setup>
import { ref, onMounted, watch, nextTick } from 'vue'
import * as echarts from 'echarts'
import { getChartColor } from '@/utils/chartColors'
import { dashboardApi } from '@/apis/dashboard_api'
import { useThemeStore } from '@/stores/theme'
// CSS
@ -121,7 +119,7 @@ const initActivityChart = () => {
data: props.userStats.daily_active_users.map(item => item.active_users),
smooth: true,
lineStyle: {
color: getChartColor('primary'),
color: getCSSVariable('--main-color'),
width: 3
},
areaStyle: {
@ -132,24 +130,24 @@ const initActivityChart = () => {
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: getCSSVariable('--chart-primary-light')
offset: 0, color: getCSSVariable('--main-500')
}, {
offset: 1, color: getCSSVariable('--chart-primary-lighter')
offset: 1, color: getCSSVariable('--main-0')
}]
}
},
itemStyle: {
color: getChartColor('primary'),
color: getCSSVariable('--main-color'),
borderWidth: 2,
borderColor: getCSSVariable('--gray-0')
},
emphasis: {
itemStyle: {
color: getChartColor('primary'),
color: getCSSVariable('--main-color'),
borderWidth: 3,
borderColor: getCSSVariable('--gray-0'),
shadowBlur: 10,
shadowColor: getCSSVariable('--chart-primary-shadow')
shadowColor: getCSSVariable('--shadow-1')
}
}
}]

View File

@ -4,7 +4,7 @@ import { RouterLink, RouterView, useRoute } from 'vue-router'
import {
GithubOutlined,
} from '@ant-design/icons-vue'
import { Bot, Waypoints, LibraryBig, Settings, BarChart3, CircleCheck } from 'lucide-vue-next';
import { Bot, Waypoints, LibraryBig, BarChart3, CircleCheck } from 'lucide-vue-next';
import { onLongPress } from '@vueuse/core'
import { useConfigStore } from '@/stores/config'
@ -188,19 +188,10 @@ const mainList = [{
<!-- 用户信息组件 -->
<div class="nav-item user-info">
<a-tooltip placement="right">
<template #title>用户信息</template>
<UserInfoComponent />
</a-tooltip>
<UserInfoComponent />
</div>
<RouterLink class="nav-item setting" to="/setting" active-class="active">
<a-tooltip placement="right">
<template #title>设置</template>
<Settings />
</a-tooltip>
</RouterLink>
</div>
</div>
<div class="header-mobile">
<RouterLink to="/agent" class="nav-item" active-class="active">对话</RouterLink>
<RouterLink to="/database" class="nav-item" active-class="active">知识</RouterLink>
@ -347,7 +338,7 @@ div.header, #app-router-view {
}
&.warning {
color: var(--color-error);
color: var(--color-error-500);
}
&:hover {
@ -376,7 +367,7 @@ div.header, #app-router-view {
margin-top: 4px;
.star-icon {
color: var(--color-warning);
color: var(--color-warning-500);
font-size: 12px;
margin-right: 2px;
}
@ -415,13 +406,8 @@ div.header, #app-router-view {
}
}
}
&.setting {
margin: 8px 0;
&:hover {
cursor: pointer;
}
&.user-info {
margin-bottom: 8px;
}
}
@ -537,7 +523,7 @@ div.header, #app-router-view {
font-size: 15px;
}
&.github, &.setting {
&.github {
padding: 8px 12px;
.icon {
@ -548,9 +534,7 @@ div.header, #app-router-view {
&.active {
color: var(--main-color);
}
}
&.github {
a {
display: flex;
align-items: center;
@ -562,7 +546,7 @@ div.header, #app-router-view {
margin-left: 6px;
.star-icon {
color: var(--color-warning);
color: var(--color-warning-500);
font-size: 14px;
margin-right: 2px;
}

View File

@ -21,28 +21,27 @@ const buildColorPalette = () => {
return v && v.trim() ? v.trim() : fallback
}
// Base chart colors
// Base chart colors - using new color system
const baseVars = [
['--chart-primary', '#3996ae'],
['--chart-success', '#52c41a'],
['--chart-warning', '#faad14'],
['--chart-error', '#f5222d'],
['--chart-secondary', '#722ed1'],
['--chart-accent', '#13c2c2'],
['--main-500', '#3996ae'],
['--color-success-500', '#52c41a'],
['--color-warning-500', '#faad14'],
['--color-error-500', '#ff4d4f'],
['--color-accent-500', '#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'],
['--chart-palette-1', '#265C96'],
['--chart-palette-2', '#009485'],
['--chart-palette-3', '#E8A035'],
['--chart-palette-4', '#D64B55'],
['--chart-palette-5', '#7D54C4'],
['--chart-palette-6', '#2D9CDB'],
['--chart-palette-7', '#F28B30'],
['--chart-palette-8', '#65C466'],
['--chart-palette-9', '#C2589E'],
['--chart-palette-10', '#4F4F4F'],
]
const baseColors = baseVars.map(([n, f]) => pick(n, f))
@ -59,8 +58,8 @@ const buildColorPalette = () => {
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'
'#3996ae', '#52c41a', '#faad14', '#ff4d4f', '#13c2c2',
'#265C96', '#009485', '#E8A035', '#D64B55', '#7D54C4'
]
isInitialized = true
}
@ -91,33 +90,6 @@ export const getColorPalette = () => {
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
* 截断图例文本以便更好地显示

View File

@ -437,7 +437,7 @@ const handlePreview = () => {
}
.default-icon {
color: var(--color-warning);
color: var(--color-warning-500);
font-size: 14px;
margin-left: 4px;
}
@ -763,7 +763,7 @@ const handlePreview = () => {
}
.default-icon {
color: var(--color-warning);
color: var(--color-warning-500);
font-size: 14px;
}
}
@ -834,7 +834,7 @@ const handlePreview = () => {
}
.default-icon {
color: var(--color-warning);
color: var(--color-warning-500);
font-size: 16px;
flex-shrink: 0;
}

View File

@ -696,4 +696,5 @@ onUnmounted(() => {
}
}
}
</style>
</style>

View File

@ -11,7 +11,7 @@
<a-modal :open="state.openNewDatabaseModel" title="新建知识库" @ok="createDatabase" @cancel="cancelCreateDatabase" class="new-database-modal" width="800px">
<!-- 知识库类型选择 -->
<h3>知识库类型<span style="color: var(--error-color)">*</span></h3>
<h3>知识库类型<span style="color: var(--color-error-500)">*</span></h3>
<div class="kb-type-cards">
<div
v-for="(typeInfo, typeKey) in supportedKbTypes"
@ -25,9 +25,6 @@
<span class="type-title">{{ getKbTypeLabel(typeKey) }}</span>
</div>
<div class="card-description">{{ typeInfo.description }}</div>
<div class="card-features">
<span class="feature-tag">{{ getKbTypeFeature(typeKey) }}</span>
</div>
</div>
</div>
@ -41,7 +38,7 @@
/>
</div> -->
<h3>知识库名称<span style="color: var(--error-color)">*</span></h3>
<h3>知识库名称<span style="color: var(--color-error-500)">*</span></h3>
<a-input v-model:value="newDatabase.name" placeholder="新建知识库名称" size="large" />
<h3>嵌入模型</h3>
@ -398,14 +395,6 @@ const getKbTypeColor = (type) => {
return colors[type] || 'blue'
}
const getKbTypeFeature = (type) => {
const features = {
lightrag: '图结构索引',
chroma: '轻量向量',
milvus: '生产级部署'
}
return features[type] || ''
}
//
const formatCreatedTime = (createdAt) => {
@ -612,6 +601,10 @@ onMounted(() => {
justify-content: space-between;
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
.reranker-title {
display: flex;
align-items: center;
@ -653,6 +646,10 @@ onMounted(() => {
margin-top: 6px;
font-size: 12px;
color: var(--gray-500);
&:last-child {
margin-top: 0;
}
}
}
}
@ -685,15 +682,15 @@ onMounted(() => {
//
&:nth-child(1):hover {
border-color: var(--chart-secondary-light);
border-color: var(--color-accent-100);
}
&:nth-child(2):hover {
border-color: var(--chart-warning-light);
border-color: var(--color-warning-100);
}
&:nth-child(3):hover {
border-color: var(--chart-error-light);
border-color: var(--color-error-100);
}
&.active {
@ -703,58 +700,38 @@ onMounted(() => {
.type-icon {
color: var(--main-color);
}
.feature-tag {
background: rgba(24, 144, 255, 0.1);
color: var(--main-color);
}
}
//
&:nth-child(1) {
&.active {
border-color: var(--chart-secondary-light);
border-color: var(--color-accent-100);
background: rgba(114, 46, 209, 0.05);
.type-icon {
color: var(--chart-secondary);
}
.feature-tag {
background: rgba(114, 46, 209, 0.1);
color: var(--chart-secondary);
color: var(--color-accent-500);
}
}
}
&:nth-child(2) {
&.active {
border-color: var(--chart-warning-light);
border-color: var(--color-warning-100);
background: rgba(250, 140, 22, 0.05);
.type-icon {
color: var(--chart-warning);
}
.feature-tag {
background: rgba(250, 140, 22, 0.1);
color: var(--chart-warning);
color: var(--color-warning-500);
}
}
}
&:nth-child(3) {
&.active {
border-color: var(--chart-error-light);
border-color: var(--color-error-100);
background: rgba(245, 34, 45, 0.05);
.type-icon {
color: var(--chart-error);
}
.feature-tag {
background: rgba(245, 34, 45, 0.1);
color: var(--chart-error);
color: var(--color-error-500);
}
}
}
@ -786,18 +763,6 @@ onMounted(() => {
margin-bottom: 12px;
// min-height: 40px;
}
.card-features {
.feature-tag {
display: inline-block;
padding: 4px 8px;
background: rgba(24, 144, 255, 0.08);
color: var(--main-color);
border-radius: 6px;
font-size: 12px;
font-weight: 500;
}
}
}
}
@ -920,7 +885,7 @@ onMounted(() => {
align-items: center;
background: var(--main-30);
border-radius: 12px;
border: 1px solid var(--gray-200);
border: 1px solid var(--gray-150);
color: var(--main-color);
position: relative;
}

View File

@ -393,16 +393,16 @@ const openLink = (url) => {
display: inline-block;
&.loading {
background-color: var(--color-warning);
background-color: var(--color-warning-500);
animation: pulse 1.5s infinite ease-in-out;
}
&.open {
background-color: var(--color-success);
background-color: var(--color-success-500);
}
&.closed {
background-color: var(--color-error);
background-color: var(--color-error-500);
}
}

View File

@ -92,6 +92,7 @@ import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/user'
import { useInfoStore } from '@/stores/info'
import { useAgentStore } from '@/stores/agent'
import { useThemeStore } from '@/stores/theme'
import UserInfoComponent from '@/components/UserInfoComponent.vue'
import {
BookText,
@ -109,6 +110,7 @@ const router = useRouter()
const userStore = useUserStore()
const infoStore = useInfoStore()
const agentStore = useAgentStore()
const themeStore = useThemeStore()
const goToChat = async () => {
//
@ -332,11 +334,21 @@ const actionLinks = computed(() => {
svg {
margin-right: 6px;
transition: transform 0.3s ease;
fill: currentColor;
}
.stars-count {
font-weight: 600;
}
//
:global(.dark) & {
color: var(--gray-400);
&:hover {
color: var(--gray-300);
}
}
}
.hero-section {

View File

@ -716,10 +716,10 @@ onUnmounted(() => {
.error-message {
margin-top: 16px;
padding: 10px 12px;
background-color: var(--stats-error-bg);
border: 1px solid color-mix(in srgb, var(--color-error) 25%, transparent);
background-color: var(--color-error-50);
border: 1px solid color-mix(in srgb, var(--color-error-500) 25%, transparent);
border-radius: 8px;
color: var(--stats-error-color);
color: var(--color-error-700);
font-size: 14px;
}
@ -808,10 +808,10 @@ onUnmounted(() => {
left: 0;
right: 0;
padding: 12px 20px;
background: linear-gradient(135deg, var(--color-error), var(--chart-error-light));
background: linear-gradient(135deg, var(--color-error-500), var(--color-error-100));
color: var(--gray-0);
z-index: 1000;
box-shadow: 0 2px 8px color-mix(in srgb, var(--color-error) 30%, transparent);
box-shadow: 0 2px 8px color-mix(in srgb, var(--color-error-500) 30%, transparent);
.alert-content {
display: flex;

View File

@ -293,9 +293,9 @@ const getModelStatusIcon = (modelId) => {
const getModelStatusColor = (modelId) => {
const status = state.modelStatuses[modelId]
if (!status) return 'var(--gray-500)'
if (status.status === 'available') return 'var(--color-success)'
if (status.status === 'unavailable') return 'var(--color-error)'
if (status.status === 'error') return 'var(--color-warning)'
if (status.status === 'available') return 'var(--color-success-500)'
if (status.status === 'unavailable') return 'var(--color-error-500)'
if (status.status === 'error') return 'var(--color-warning-500)'
return 'var(--gray-500)'
}
//