From 684a79be6f555a9fc8b1f2e659be22584abc5c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Mon, 17 Aug 2026 14:38:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BF=AB=E6=8D=B7=E5=85=A5=E5=8F=A3=E5=B7=B2?= =?UTF-8?q?=E7=BB=8F=E6=8C=AA=E5=88=B0=E9=A1=B6=E9=83=A8=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E6=A0=8F=E4=BA=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 顶部在「工具」和「账号」之间多了一个 快捷 菜单:已钉的入口会列在里面(带图标和未读数),点一项就能跳转。底下还有「添加快捷入口」,用来打开原来的选择面板。有未读时,菜单名旁边会有一个小红点。 概览侧栏里的快捷入口和「添加」按钮已经去掉,之前钉过的项会继续出现在顶部菜单里。 --- .../checksum/build-frontend--DEV--RUNNER-npm- | 2 +- .../checksum/windows-common-generate-bindings | 2 +- frontend/src/App.vue | 48 ++--- frontend/src/components/DatePicker.vue | 2 +- frontend/src/components/TitleBar.vue | 35 +++- frontend/src/main.js | 10 +- frontend/src/polish.css | 172 ++++++++++-------- frontend/src/views/Tickets.vue | 6 +- 8 files changed, 152 insertions(+), 125 deletions(-) diff --git a/.task/checksum/build-frontend--DEV--RUNNER-npm- b/.task/checksum/build-frontend--DEV--RUNNER-npm- index e008a24..1a829c9 100644 --- a/.task/checksum/build-frontend--DEV--RUNNER-npm- +++ b/.task/checksum/build-frontend--DEV--RUNNER-npm- @@ -1 +1 @@ -cd84020b5c141a3842ad91546a552d0 +bcd40faf16720fe7180c537d7deb93f9 diff --git a/.task/checksum/windows-common-generate-bindings b/.task/checksum/windows-common-generate-bindings index 843ebf7..5bd0fc9 100644 --- a/.task/checksum/windows-common-generate-bindings +++ b/.task/checksum/windows-common-generate-bindings @@ -1 +1 @@ -d56685eca1698f613f797ff4d81f460a +caf892d1dc4259ca637eae8b231784f9 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 34f9408..4a7f6eb 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -2,7 +2,7 @@ import { computed, onMounted, onUnmounted, ref, watch } from 'vue' import { useRoute, useRouter } from 'vue-router' import { useI18n } from 'vue-i18n' -import { LayoutDashboard, ScrollText, Settings, X, Database, SlidersHorizontal, Home, ListTodo, TicketCheck, CalendarDays, CalendarCheck2, Sparkles, UserRound, ClipboardList, Wrench, Rocket, ChevronDown, Bell, StickyNote, ListFilter, Palette, Bot, Users, NotebookPen, CloudUpload, Power, Image, Activity, Package, Shield, Plus, Pin, PinOff } from 'lucide-vue-next' +import { LayoutDashboard, ScrollText, Settings, X, Database, SlidersHorizontal, Home, ListTodo, TicketCheck, CalendarDays, CalendarCheck2, Sparkles, UserRound, ClipboardList, Wrench, Rocket, ChevronDown, Bell, StickyNote, ListFilter, Palette, Bot, Users, NotebookPen, CloudUpload, Power, Image, Activity, Package, Shield, Plus, Pin } from 'lucide-vue-next' import { useAppStore } from './store' import DatabaseSetup from './components/DatabaseSetup.vue' import BrowserBlocked from './components/BrowserBlocked.vue' @@ -108,7 +108,7 @@ const navGroups = [ ] } ] -// ---- 概览快捷入口:把其它分区菜单钉到「概览」二级导航 ---- +// ---- 顶栏快捷入口:把常用菜单钉到 TitleBar「快捷」下拉 ---- const SHORTCUT_KEY = 'cc-nav-shortcuts' const loadShortcuts = () => { try { @@ -128,7 +128,7 @@ const catalogByTo = computed(() => { } return map }) -// 可钉到概览的项:非概览内置、且当前用户可见 +// 可钉到顶栏的项:非概览内置、且当前用户可见 const pinnableItems = computed(() => { const overviewTos = new Set(navGroups[0].items.map(it => it.to)) const out = [] @@ -146,7 +146,6 @@ function addShortcut(to) { if (navShortcuts.value.includes(to)) return navShortcuts.value = [...navShortcuts.value, to] saveShortcuts() - shortcutPicker.value = false } function removeShortcut(to) { navShortcuts.value = navShortcuts.value.filter(x => x !== to) @@ -157,18 +156,19 @@ function toggleShortcut(to) { else addShortcut(to) } +// 钉到顶栏「快捷」菜单的项(带徽标数字,供 TitleBar 渲染) +const pinnedShortcuts = computed(() => navShortcuts.value + .map(to => catalogByTo.value.get(to)) + .filter(it => it && (!it.adminOnly || store.syncStatus.userId === 1)) + .map(it => ({ + to: it.to, + label: it.label, + icon: it.icon, + badge: it.badge ? (store.badges[it.badge] || 0) : 0 + }))) + // adminOnly 项只对云端管理员(id=1)展示 -const visibleItems = g => { - let items = g.items.filter(it => !it.adminOnly || store.syncStatus.userId === 1) - if (g.id === 'overview') { - const extras = navShortcuts.value - .map(to => catalogByTo.value.get(to)) - .filter(it => it && (!it.adminOnly || store.syncStatus.userId === 1)) - .map(it => ({ ...it, shortcut: true })) - items = [...items, ...extras] - } - return items -} +const visibleItems = g => g.items.filter(it => !it.adminOnly || store.syncStatus.userId === 1) const itemActive = it => it.match ? it.match(route) : route.path === it.to.split('?')[0] // 导航徽标:badge 显示数字,dot 只显示小圆点;一级 rail 在组内任一非零时亮点 const badgeVal = it => it.badge ? (store.badges[it.badge] || 0) : 0 @@ -186,7 +186,6 @@ watch(() => route.fullPath, () => { const g = groupOfRoute() if (g) activeGroupId.value = g railFlyout.value = null - if (g !== 'overview') shortcutPicker.value = false for (const grp of navGroups) { for (const it of grp.items) if (it.children && itemActive(it)) expandedParents.value[it.label] = true } @@ -288,7 +287,7 @@ watch(activeTask, task => {