From 404fcd55a34018429865449bcd3c7547eb7b9614 Mon Sep 17 00:00:00 2001 From: Wenjie Zhang Date: Tue, 26 May 2026 19:39:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正消息匹配转义和复制兜底日志,并统一卡片操作入口与主题链接颜色。 --- web/src/components/AgentChatComponent.vue | 4 - web/src/components/MessageInputComponent.vue | 2 +- .../components/UserManagementComponent.vue | 146 ++++++++++-------- web/src/components/common/MarkdownPreview.vue | 4 +- .../model-management/AgentManagePanel.vue | 4 +- web/src/stores/theme.js | 3 + 6 files changed, 91 insertions(+), 72 deletions(-) diff --git a/web/src/components/AgentChatComponent.vue b/web/src/components/AgentChatComponent.vue index 4c5ab302..39502d02 100644 --- a/web/src/components/AgentChatComponent.vue +++ b/web/src/components/AgentChatComponent.vue @@ -451,10 +451,6 @@ const supportsFiles = computed(() => { const currentAgentState = computed(() => { return currentChatId.value ? getThreadState(currentChatId.value)?.agentState || null : null }) -const currentThreadFiles = computed(() => { - if (!currentChatId.value) return [] - return threadFilesMap.value[currentChatId.value] || [] -}) const currentThreadAttachments = computed(() => { if (!currentChatId.value) return [] return threadAttachmentsMap.value[currentChatId.value] || [] diff --git a/web/src/components/MessageInputComponent.vue b/web/src/components/MessageInputComponent.vue index f3f02a75..24b1dfd5 100644 --- a/web/src/components/MessageInputComponent.vue +++ b/web/src/components/MessageInputComponent.vue @@ -293,7 +293,7 @@ const splitTextByQuery = (text, query) => { if (!text) return [] if (!query) return [{ text, isMatch: false }] - const escapedQuery = query.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') const regex = new RegExp(`(${escapedQuery})`, 'gi') const parts = text.split(regex) diff --git a/web/src/components/UserManagementComponent.vue b/web/src/components/UserManagementComponent.vue index 2640fdd1..5a18d088 100644 --- a/web/src/components/UserManagementComponent.vue +++ b/web/src/components/UserManagementComponent.vue @@ -107,6 +107,41 @@
ID: {{ user.uid || '-' }}
+ + + + + + +
@@ -123,36 +158,6 @@ {{ formatTime(user.last_login) }}
- -
- - - - 编辑 - - - - - - 删除 - - -
@@ -262,7 +267,17 @@ import { reactive, onMounted, watch, computed } from 'vue' import { message, Modal } from 'ant-design-vue' import { useUserStore } from '@/stores/user' import { departmentApi } from '@/apis' -import { Plus, Pencil, Trash2, User, UserLock, UserStar, RefreshCw, Search } from 'lucide-vue-next' +import { + Plus, + Pencil, + Trash2, + User, + UserLock, + UserStar, + RefreshCw, + Search, + MoreVertical +} from 'lucide-vue-next' import { formatDateTime } from '@/utils/time' const userStore = useUserStore() @@ -422,6 +437,10 @@ watch( // 格式化时间显示 const formatTime = (timeStr) => formatDateTime(timeStr) +const isUserDeleteDisabled = (user) => + user.id === userStore.userId || + (user.role === 'superadmin' && userStore.userRole !== 'superadmin') + // 获取用户列表 const fetchUsers = async () => { try { @@ -773,7 +792,6 @@ onMounted(async () => { border: 1px solid var(--gray-150); border-radius: 8px; padding: 12px; - padding-bottom: 6px; transition: all 0.2s ease; box-shadow: 0 1px 3px var(--shadow-1); @@ -784,10 +802,16 @@ onMounted(async () => { } .card-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 8px; margin-bottom: 10px; .user-info-main { display: flex; + flex: 1; + min-width: 0; gap: 12px; align-items: center; @@ -878,6 +902,22 @@ onMounted(async () => { } } } + + .card-menu-trigger { + display: inline-flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + flex-shrink: 0; + color: var(--gray-600); + + &:hover, + &:focus { + color: var(--gray-700); + background: var(--gray-50); + } + } } .card-content { @@ -915,38 +955,6 @@ onMounted(async () => { } } } - - .card-actions { - display: flex; - justify-content: flex-end; - gap: 6px; - padding-top: 6px; - border-top: 1px solid var(--gray-25); - - .action-btn { - display: flex; - align-items: center; - gap: 4px; - padding: 4px 8px; - border-radius: 6px; - transition: all 0.2s ease; - font-size: 12px; - - span { - font-size: 12px; - } - - &:hover { - background: var(--gray-25); - } - - &.ant-btn-dangerous:hover { - background: var(--gray-25); - border-color: var(--color-error-500); - color: var(--color-error-500); - } - } - } } } } @@ -965,6 +973,16 @@ onMounted(async () => { } } +.user-card-menu-item { + display: inline-flex; + align-items: center; + gap: 8px; + + &.danger { + color: var(--color-error-700); + } +} + @keyframes spin { from { transform: rotate(0deg); diff --git a/web/src/components/common/MarkdownPreview.vue b/web/src/components/common/MarkdownPreview.vue index 6a463b0b..e2ad230e 100644 --- a/web/src/components/common/MarkdownPreview.vue +++ b/web/src/components/common/MarkdownPreview.vue @@ -131,7 +131,9 @@ const copySvgAsPng = async (svgEl, btn) => { try { await navigator.clipboard.writeText(svgContent) console.log('PNG 复制失败,已回退复制 SVG 源码') - } catch {} + } catch (fallbackErr) { + console.error('复制 SVG 源码失败:', fallbackErr) + } } finally { URL.revokeObjectURL(url) } diff --git a/web/src/components/model-management/AgentManagePanel.vue b/web/src/components/model-management/AgentManagePanel.vue index 6f994ffb..dae22669 100644 --- a/web/src/components/model-management/AgentManagePanel.vue +++ b/web/src/components/model-management/AgentManagePanel.vue @@ -554,8 +554,8 @@ defineExpose({ &:hover, &:focus { - color: var(--main-700); - background: var(--main-50); + color: var(--gray-700); + background: var(--gray-50); } } diff --git a/web/src/stores/theme.js b/web/src/stores/theme.js index ee40336e..3fdb6d8c 100644 --- a/web/src/stores/theme.js +++ b/web/src/stores/theme.js @@ -12,6 +12,9 @@ export const useThemeStore = defineStore('theme', () => { fontFamily: "'HarmonyOS Sans SC', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;", colorPrimary: '#24839b', + colorLink: 'var(--main-color)', + colorLinkHover: 'var(--main-600)', + colorLinkActive: 'var(--main-800)', borderRadius: 8, wireframe: false }