From 2aefdd3ee1a3f72216062148cd2e3bc1ece7f440 Mon Sep 17 00:00:00 2001 From: Marvin Zhang Date: Fri, 30 May 2025 23:27:47 +0800 Subject: [PATCH] feat: add AI assistant SVG icon and integrate it into the header with a toggle button --- .../src/assets/svg/icons/ai-assistant.svg | 8 +++ .../src/components/ui/icon/Icon.vue | 19 ++++--- .../src/layouts/components/Header.vue | 54 ++++++++----------- frontend/crawlab-ui/src/utils/icon.ts | 2 +- 4 files changed, 39 insertions(+), 44 deletions(-) create mode 100644 frontend/crawlab-ui/src/assets/svg/icons/ai-assistant.svg diff --git a/frontend/crawlab-ui/src/assets/svg/icons/ai-assistant.svg b/frontend/crawlab-ui/src/assets/svg/icons/ai-assistant.svg new file mode 100644 index 00000000..836e21b2 --- /dev/null +++ b/frontend/crawlab-ui/src/assets/svg/icons/ai-assistant.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/frontend/crawlab-ui/src/components/ui/icon/Icon.vue b/frontend/crawlab-ui/src/components/ui/icon/Icon.vue index 52525bd5..2ee68a29 100644 --- a/frontend/crawlab-ui/src/components/ui/icon/Icon.vue +++ b/frontend/crawlab-ui/src/components/ui/icon/Icon.vue @@ -44,9 +44,9 @@ const updateIconSvgSrc = async () => { if (isSvg.value) { const { icon } = props; if (!Array.isArray(icon) || !icon[1]) return; - const res = await import(`@/assets/svg/icons/${icon[1]}.svg?url`); + const res = await import(`@/assets/svg/icons/${icon[1]}.svg`); if (res) { - iconSvgSrc.value = res.default; + iconSvgSrc.value = decodeURIComponent(res.default).replace('data:image/svg+xml,', ''); } } }; @@ -72,13 +72,7 @@ defineOptions({ name: 'ClIcon' }); /> +
+ +
+ +
+
+
@@ -205,19 +213,6 @@ defineOptions({ name: 'ClHeader' });
-
- - - {{ - t('components.ai.chatbot.button') - }} - - -
@@ -252,9 +247,9 @@ defineOptions({ name: 'ClHeader' }); .right { display: flex; align-items: center; + gap: 12px; .item { - margin-left: 20px; display: flex; align-items: center; @@ -269,6 +264,7 @@ defineOptions({ name: 'ClHeader' }); .lang { display: flex; align-items: center; + margin-left: 16px; &:hover { color: var(--cl-primary-color); @@ -279,27 +275,19 @@ defineOptions({ name: 'ClHeader' }); } } - .chat-toggle-btn { - display: flex; + .chat-toggle { + display: inline-flex; align-items: center; - border-radius: 20px; - padding: 8px 16px; - animation: fadeIn 0.3s ease-in-out; - background-color: var(--el-color-primary-dark-2); + justify-content: center; + transition: all 0.3s ease; + border-radius: 50%; + height: 36px; + width: 36px; + margin: 0 5px; - .button-text { - margin: 0 8px; - display: inline-block; - } - - .toggle-indicator { - margin-left: 4px; - transition: transform 0.3s; - } - - .robot-icon-badge { - display: flex; - align-items: center; + &:hover { + background-color: var(--el-color-primary-dark-2); + color: white; } } } diff --git a/frontend/crawlab-ui/src/utils/icon.ts b/frontend/crawlab-ui/src/utils/icon.ts index 4e9f0ef3..e13e49d4 100644 --- a/frontend/crawlab-ui/src/utils/icon.ts +++ b/frontend/crawlab-ui/src/utils/icon.ts @@ -294,7 +294,7 @@ export const getIconByRouteConcept = (concept: RouteConcept): Icon => { case 'permission': return ['fa', 'user-check']; case 'ai': - return ['fa', 'comment-dots']; + return ['svg', 'ai-assistant']; case 'models': return ['fa', 'hexagon-nodes']; case 'system':