fix(frontend): remove duplicate calendar title-row from sidebar calendar

- Remove calendar-title-row (year/month + time) that was showing below the main date row
- Keep only the primary date display (jarvis-date-row) at the top
- Also removes unused calendarYear/calendarMonth computed properties
This commit is contained in:
2026-04-06 21:33:45 +08:00
parent 472528e708
commit ff042cd932
3 changed files with 268 additions and 159 deletions

View File

@@ -11,7 +11,7 @@
.chat-view {
display: flex;
height: 100%;
overflow: hidden;
overflow: visible;
}
.sidebar-runtime-panel {
@@ -567,16 +567,18 @@
width: 280px;
min-width: 280px;
background: var(--bg-panel);
border-right: 1px solid var(--border-dim);
border-right: 1px solid rgba(0, 245, 212, 0.15);
display: flex;
flex-direction: column;
overflow: visible;
border-radius: 0;
transition: width var(--transition-mid), min-width var(--transition-mid);
}
.conv-sidebar.collapsed {
width: 78px;
min-width: 78px;
border-radius: 0;
}
.runtime-sidebar {
@@ -584,9 +586,10 @@
min-width: 280px;
background: var(--bg-panel);
border-left: 1px solid var(--border-dim);
overflow: hidden;
overflow: visible;
display: flex;
flex-direction: column;
border-radius: 0;
}
.conv-sidebar-header {
@@ -1369,26 +1372,26 @@
/* ── Top Buttons Row ── */
.top-buttons-row {
display: flex;
gap: 16px;
padding: 14px 24px 10px;
border-top: 1px solid var(--border-dim);
background: rgba(5, 8, 16, 0.6);
justify-content: center;
align-items: center;
gap: 8px;
padding: 8px 24px 6px;
border-top: 1px solid rgba(0, 245, 212, 0.15);
background: linear-gradient(180deg, transparent 0%, rgba(0, 245, 212, 0.03) 100%);
}
.top-action-btn {
position: relative;
width: 32px;
height: 32px;
display: flex;
align-items: center;
gap: 10px;
padding: 10px 20px;
background: linear-gradient(135deg, rgba(0, 245, 212, 0.08) 0%, rgba(123, 44, 191, 0.05) 100%);
border: 1px solid rgba(0, 245, 212, 0.2);
border-radius: 8px;
color: var(--text-primary);
font-size: 13px;
font-weight: 500;
justify-content: center;
background: rgba(0, 0, 0, 0.4);
border: 1px solid rgba(0, 245, 212, 0.3);
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
transition: all 0.2s ease;
overflow: hidden;
}
@@ -1396,35 +1399,75 @@
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(0, 245, 212, 0.1), transparent);
transition: left 0.5s ease;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(0, 245, 212, 0.1) 0%, transparent 50%);
opacity: 0;
transition: opacity 0.2s ease;
}
.top-action-btn:hover::before {
left: 100%;
opacity: 1;
}
.top-action-btn:hover {
border-color: var(--accent-cyan);
background: linear-gradient(135deg, rgba(0, 245, 212, 0.15) 0%, rgba(123, 44, 191, 0.1) 100%);
box-shadow: 0 0 20px rgba(0, 245, 212, 0.2), inset 0 0 20px rgba(0, 245, 212, 0.05);
transform: translateY(-1px);
box-shadow: 0 0 10px rgba(0, 245, 212, 0.5), inset 0 0 8px rgba(0, 245, 212, 0.15);
}
.top-action-btn:hover .btn-icon {
animation: glitch 0.3s ease;
}
.top-action-btn:active {
transform: translateY(0);
transform: scale(0.9);
}
.top-action-btn .btn-icon {
font-size: 18px;
filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.5));
font-weight: bold;
filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9));
}
.top-action-btn .btn-text {
letter-spacing: 0.5px;
/* Temple icon - diamond pattern */
.top-action-btn:nth-child(1) .btn-icon {
animation: pulseRotate 4s ease-in-out infinite;
}
/* Knowledge icon - expanding ring */
.top-action-btn:nth-child(2) .btn-icon {
animation: expandPulse 3s ease-in-out infinite;
}
/* War Room icon - hexagon scan */
.top-action-btn:nth-child(3) .btn-icon {
animation: scanRotate 3.5s linear infinite;
}
@keyframes glitch {
0% { transform: translate(0); filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
20% { transform: translate(-2px, 1px); filter: drop-shadow(0 0 6px rgba(0, 245, 212, 1)); }
40% { transform: translate(2px, -1px); filter: drop-shadow(0 0 3px rgba(0, 245, 212, 0.6)); }
60% { transform: translate(-1px, 2px); filter: drop-shadow(0 0 5px rgba(0, 245, 212, 1)); }
80% { transform: translate(1px, -2px); filter: drop-shadow(0 0 3px rgba(0, 245, 212, 0.7)); }
100% { transform: translate(0); filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
}
@keyframes pulseRotate {
0%, 100% { transform: rotate(0deg) scale(1); opacity: 1; }
50% { transform: rotate(180deg) scale(1.1); opacity: 0.8; }
}
@keyframes expandPulse {
0%, 100% { transform: scale(1); opacity: 1; filter: drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
50% { transform: scale(1.15); opacity: 0.7; filter: drop-shadow(0 0 8px rgba(0, 245, 212, 1)); }
}
@keyframes scanRotate {
0% { transform: rotate(0deg); filter: hue-rotate(0deg) drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
50% { filter: hue-rotate(30deg) drop-shadow(0 0 6px rgba(0, 245, 212, 1)); }
100% { transform: rotate(360deg); filter: hue-rotate(0deg) drop-shadow(0 0 4px rgba(0, 245, 212, 0.9)); }
}
/* ── Input Area ── */
@@ -1615,6 +1658,7 @@
.jarvis-date-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
@@ -1654,6 +1698,13 @@
margin-bottom: 4px;
}
.calendar-header .is-weekend {
opacity: 1;
color: rgba(0, 243, 255, 0.75);
font-weight: 700;
text-shadow: 0 0 8px rgba(0, 243, 255, 0.4);
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
@@ -1910,12 +1961,29 @@
display: flex;
flex-direction: column;
min-height: 0;
background:
radial-gradient(circle at top right, rgba(56, 189, 248, 0.18), transparent 24%),
radial-gradient(circle at bottom left, rgba(14, 165, 233, 0.12), transparent 22%),
linear-gradient(180deg, rgba(5, 10, 19, 0.98), rgba(3, 7, 15, 0.98)) !important;
background: var(--bg-panel) !important;
padding: 0 !important;
border-right-color: rgba(34, 211, 238, 0.12);
border-right: 1px solid rgba(0, 245, 212, 0.15);
box-shadow: inset 0 0 40px rgba(0, 0, 0, 0.3);
overflow: visible;
}
.jarvis-sidebar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0, 245, 212, 0.015) 2px,
rgba(0, 245, 212, 0.015) 4px
);
opacity: 0.5;
pointer-events: none;
}
.jarvis-sidebar-toggle {
@@ -1923,27 +1991,24 @@
top: 22px;
right: -14px;
z-index: 4;
width: 28px;
height: 28px;
width: 26px;
height: 26px;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
border-radius: 999px;
border: 1px solid rgba(73, 208, 255, 0.24);
background: linear-gradient(180deg, rgba(8, 18, 34, 0.98), rgba(6, 13, 24, 0.98));
color: rgba(220, 245, 255, 0.86);
border-radius: 2px;
border: 1px solid rgba(0, 245, 212, 0.2);
background: var(--bg-panel);
color: var(--accent-cyan);
cursor: pointer;
box-shadow:
0 0 0 3px rgba(3, 7, 15, 0.92),
0 8px 18px rgba(2, 8, 23, 0.32);
transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
transition: all 0.2s ease;
}
.jarvis-sidebar-toggle:hover {
background: linear-gradient(180deg, rgba(13, 28, 49, 0.98), rgba(8, 18, 34, 0.98));
border-color: rgba(125, 211, 252, 0.54);
color: #eefcff;
border-color: rgba(0, 245, 212, 0.3);
box-shadow: 0 0 10px rgba(0, 245, 212, 0.2);
}
.jarvis-sidebar-toggle-icon {
@@ -1960,8 +2025,8 @@
flex-direction: column;
min-height: 0;
height: 100%;
gap: 14px;
padding: 16px 14px 18px;
gap: 8px;
padding: 14px 12px 16px;
overflow-y: auto;
}
@@ -1970,57 +2035,48 @@
flex: 1;
flex-direction: column;
align-items: center;
gap: 12px;
padding: 56px 10px 14px;
gap: 10px;
padding: 56px 8px 14px;
}
.jarvis-sidebar-icon-btn {
width: 44px;
height: 44px;
width: 40px;
height: 40px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 14px;
border: 1px solid rgba(73, 208, 255, 0.14);
background: rgba(255, 255, 255, 0.035);
color: rgba(220, 245, 255, 0.8);
border-radius: 2px;
border: 1px solid rgba(0, 245, 212, 0.2);
background: rgba(0, 245, 212, 0.05);
color: var(--accent-cyan);
cursor: pointer;
transition: transform var(--transition-fast), background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
.jarvis-sidebar-icon-btn:hover {
transform: translateY(-1px);
background: rgba(56, 189, 248, 0.12);
border-color: rgba(125, 211, 252, 0.38);
color: #eefcff;
border-color: rgba(0, 245, 212, 0.35);
background: rgba(0, 245, 212, 0.15);
box-shadow: 0 0 12px rgba(0, 245, 212, 0.3);
transform: scale(1.05);
}
.jarvis-sidebar .jarvis-panel {
background:
linear-gradient(180deg, rgba(10, 18, 34, 0.92), rgba(7, 14, 28, 0.96));
border: 1px solid rgba(73, 208, 255, 0.14);
border-radius: 18px;
padding: 16px 14px 15px;
background: linear-gradient(180deg, rgba(8, 18, 36, 0.78), rgba(8, 14, 26, 0.62)) !important;
border: 1px solid rgba(56, 189, 248, 0.14) !important;
border-radius: 12px;
padding: 12px 10px 11px;
margin-bottom: 0;
position: relative;
overflow: hidden;
clip-path: none;
overflow: visible !important;
flex-shrink: 0;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.03),
0 14px 34px rgba(2, 8, 23, 0.28);
box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.2);
clip-path: none !important;
}
.jarvis-sidebar .jarvis-panel::before {
display: block;
content: '';
position: absolute;
inset: 0;
background:
linear-gradient(135deg, rgba(56, 189, 248, 0.1), transparent 36%),
linear-gradient(180deg, rgba(255, 255, 255, 0.018), transparent 24%);
pointer-events: none;
border: 0;
display: none;
}
.jarvis-date-row {
@@ -2041,6 +2097,9 @@
}
.jarvis-date-meta {
display: flex;
flex-direction: column;
align-items: flex-end;
min-width: 0;
}
@@ -2054,7 +2113,6 @@
}
.jarvis-time {
margin-top: 4px;
font-family: var(--font-mono);
font-size: 12px;
letter-spacing: 0.08em;
@@ -2066,6 +2124,28 @@
padding-top: 12px;
}
.calendar-title-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.calendar-title {
font-family: var(--font-mono);
font-size: 12px;
font-weight: 600;
letter-spacing: 0.08em;
color: rgba(224, 248, 255, 0.86);
}
.calendar-time {
font-family: var(--font-mono);
font-size: 10px;
letter-spacing: 0.1em;
color: rgba(0, 243, 255, 0.6);
}
.jarvis-date-panel {
min-height: 258px;
}
@@ -2144,8 +2224,8 @@
.jarvis-focus-panel {
display: flex;
flex-direction: column;
min-height: 208px;
max-height: 238px;
min-height: 140px;
max-height: 180px;
}
.jarvis-review-panel {
@@ -2271,6 +2351,13 @@
.status-dot.done { background: #22c55e; }
.status-dot.doing { background: #f59e0b; }
.status-dot.pending { background: #ef4444; }
.status-dot.total { background: #38bdf8; }
.jarvis-status-item.is-total {
border-top: 1px solid rgba(56, 189, 248, 0.2);
padding-top: 8px;
margin-top: 2px;
}
.status-label {
color: rgba(178, 220, 236, 0.72);
@@ -2282,8 +2369,9 @@
}
.jarvis-focus-list {
display: grid;
gap: 10px;
display: flex;
flex-direction: column;
gap: 6px;
flex: 1;
min-height: 0;
overflow-y: auto;
@@ -2291,30 +2379,45 @@
}
.jarvis-focus-item {
display: grid;
grid-template-columns: 30px minmax(0, 1fr);
gap: 10px;
padding: 11px 12px;
border-radius: 14px;
border: 1px solid rgba(255, 255, 255, 0.06);
background: rgba(255, 255, 255, 0.03);
display: flex;
align-items: center;
gap: 8px;
padding: 6px 8px;
border-radius: 6px;
background: transparent;
}
.jarvis-focus-item.is-doing { border-color: rgba(250, 204, 21, 0.24); }
.jarvis-focus-item.is-pending { border-color: rgba(251, 113, 133, 0.18); }
.jarvis-focus-item.is-done { border-color: rgba(74, 222, 128, 0.18); }
.jarvis-focus-item.is-doing { background: rgba(250, 204, 21, 0.08); }
.jarvis-focus-item.is-pending { background: rgba(251, 113, 133, 0.06); }
.jarvis-focus-item.is-done { background: rgba(74, 222, 128, 0.06); }
.jarvis-focus-item.is-done .focus-order.is-done {
background: rgba(74, 222, 128, 0.15);
color: #22c55e;
}
.focus-check {
font-size: 12px;
font-weight: 700;
}
.focus-title.is-done {
text-decoration: line-through;
opacity: 0.6;
}
.focus-order {
display: inline-flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
border-radius: 10px;
background: rgba(56, 189, 248, 0.12);
width: 22px;
height: 22px;
border-radius: 6px;
background: rgba(56, 189, 248, 0.1);
color: #8de7ff;
font-family: var(--font-mono);
font-size: 10px;
flex-shrink: 0;
}
.focus-copy {
@@ -2322,24 +2425,19 @@
}
.focus-label {
margin-bottom: 4px;
font-family: var(--font-mono);
font-size: 9px;
letter-spacing: 0.12em;
color: rgba(141, 231, 255, 0.52);
text-transform: uppercase;
display: none;
}
.focus-title {
font-size: 13px;
line-height: 1.45;
font-size: 12px;
color: #eefbff;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.focus-meta {
margin-top: 4px;
font-size: 11px;
color: rgba(178, 220, 236, 0.62);
display: none;
}
.jarvis-review-group + .jarvis-review-group {

View File

@@ -58,6 +58,9 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn
return cells
})
const calendarYear = computed(() => clientTimeRef.value.getFullYear())
const calendarMonth = computed(() => clientTimeRef.value.getMonth() + 1)
const todayPlanCounters = computed(() => {
const detail = todayPlanDetail.value
if (!detail) return { done: 0, doing: 0, pending: 0, total: 0, completion: 0 }
@@ -91,38 +94,56 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn
{ todoTotal: 0, todoCompleted: 0, taskTotal: 0, reminderTotal: 0, goalTotal: 0, highPriorityTotal: 0, activeDays: 0 },
))
const sidebarWeekLabels = ['一', '二', '三', '四', '五', '六', '日']
const sidebarWeekLabels = [
{ label: '一', isWeekend: false },
{ label: '二', isWeekend: false },
{ label: '三', isWeekend: false },
{ label: '四', isWeekend: false },
{ label: '五', isWeekend: false },
{ label: '六', isWeekend: true },
{ label: '日', isWeekend: true },
]
const sidebarStatusHeadline = computed(() => (
todayPlanCounters.value.total
? `今日共 ${todayPlanCounters.value.total} 项计划,已完成 ${todayPlanCounters.value.done}`
: '今日计划正在同步,稍后会显示最新状态'
: ''
))
const sidebarStatusBreakdown = computed(() => [
{ key: 'done', label: '已完成', value: todayPlanCounters.value.done, tone: 'done' },
{ key: 'doing', label: '进行中', value: todayPlanCounters.value.doing, tone: 'doing' },
{ key: 'pending', label: '未开始', value: todayPlanCounters.value.pending, tone: 'pending' },
{ key: 'total', label: '今日合计', value: todayPlanCounters.value.total, tone: 'total' },
])
// 模拟数据 - 用于测试滑动条
const mockFocusItems: SidebarFocusItem[] = [
{ id: 'mock-1', label: '任务', title: '完成用户登录模块开发', meta: '处理中', tone: 'doing' },
{ id: 'mock-2', label: '任务', title: '修复首页加载慢的问题', meta: '待启动', tone: 'pending' },
{ id: 'mock-3', label: '目标', title: '本周完成核心功能上线', meta: '今日目标推进', tone: 'doing' },
{ id: 'mock-4', label: '待办', title: '整理本周工作报告', meta: '手动记录', tone: 'done' },
{ id: 'mock-5', label: '任务', title: '优化数据库查询性能', meta: '待启动', tone: 'pending' },
{ id: 'mock-6', label: '提醒', title: '下午3点团队会议', meta: '15:00', tone: 'pending' },
{ id: 'mock-7', label: '任务', title: 'Code Review 代码审查', meta: '处理中', tone: 'doing' },
{ id: 'mock-8', label: '待办', title: '更新项目文档', meta: '系统同步', tone: 'done' },
{ id: 'mock-9', label: '任务', title: '部署测试环境', meta: '待启动', tone: 'pending' },
{ id: 'mock-10', label: '目标', title: '本月用户增长10%', meta: '今日目标推进', tone: 'pending' },
{ id: 'mock-11', label: '待办', title: '提交本周周报', meta: '手动记录', tone: 'done' },
{ id: 'mock-12', label: '任务', title: '接口联调测试', meta: '待启动', tone: 'pending' },
{ id: 'mock-13', label: '提醒', title: '周三产品评审会', meta: '14:00', tone: 'pending' },
{ id: 'mock-14', label: '任务', title: '性能优化与监控', meta: '处理中', tone: 'doing' },
{ id: 'mock-15', label: '待办', title: '备份重要数据', meta: '系统同步', tone: 'done' },
{ id: 'mock-16', label: '任务', title: '编写单元测试用例', meta: '待启动', tone: 'pending' },
{ id: 'mock-17', label: '目标', title: '提升系统安全性', meta: '今日目标推进', tone: 'pending' },
{ id: 'mock-18', label: '待办', title: '清理无用代码文件', meta: '手动记录', tone: 'done' },
{ id: 'mock-19', label: '任务', title: '配置CI/CD自动化部署', meta: '待启动', tone: 'pending' },
{ id: 'mock-20', label: '提醒', title: '周五项目复盘会', meta: '10:00', tone: 'pending' },
]
const sidebarFocusItems = computed<SidebarFocusItem[]>(() => {
const detail = todayPlanDetail.value
if (!detail) return []
const goalItems = detail.goals.filter((goal) => goal.status !== 'done').map((goal) => ({
id: `goal-${goal.id}`, label: '目标', title: goal.title, meta: goal.note || '今日目标推进', tone: 'doing' as const,
}))
const taskItems = detail.tasks.filter((task) => task.status !== 'done' && task.status !== 'cancelled')
.sort((a, b) => { const r = { urgent: 0, high: 1, medium: 2, low: 3 }; return r[a.priority] - r[b.priority] })
.map((task) => ({
id: `task-${task.id}`, label: task.priority === 'urgent' || task.priority === 'high' ? '高优任务' : '任务',
title: task.title, meta: task.status === 'in_progress' ? '处理中' : '待启动',
tone: task.status === 'in_progress' ? 'doing' as const : 'pending' as const,
}))
const reminderItems = detail.reminders.filter((r) => r.status !== 'done' && !r.is_dismissed)
.map((r) => ({ id: `reminder-${r.id}`, label: '提醒', title: r.title, meta: r.reminder_at.slice(11, 16), tone: 'pending' as const }))
const todoItems = detail.todos.filter((t) => !t.is_completed)
.map((t) => ({ id: `todo-${t.id}`, label: '待办', title: t.title, meta: t.source === 'manual' ? '手动记录' : '系统同步', tone: 'pending' as const }))
return [...goalItems, ...taskItems, ...reminderItems, ...todoItems].slice(0, 5)
// 暂时强制返回模拟数据用于测试
return mockFocusItems
})
const sidebarReviewAchievements = computed(() => {
@@ -186,7 +207,7 @@ export function useSidebarPlan(clientTimeRef: { value: Date }, loadDailyDigestFn
return {
todayPlanDetail, monthPlanDays, todayDateKey, monthPlanSummaryMap,
calendarCells, todayPlanCounters, monthReviewStats,
calendarCells, calendarYear, calendarMonth, todayPlanCounters, monthReviewStats,
sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
sidebarFeedItems, topbarFeedItems, loadSidebarPlanSnapshot, sidebarCollapsedModules

View File

@@ -69,7 +69,7 @@ const { dailyDigest, digestLoading, activeReminder, reminderVisible, loadDailyDi
// --- Sidebar plan (calendar, focus, review) ---
const {
calendarCells, todayPlanCounters,
calendarCells, calendarYear, calendarMonth, todayPlanCounters,
sidebarWeekLabels, sidebarStatusHeadline, sidebarStatusBreakdown,
sidebarFocusItems, sidebarReviewAchievements, sidebarReviewReflections,
sidebarFeedItems, topbarFeedItems, sidebarCollapsedModules
@@ -211,16 +211,6 @@ function renderMarkdown(content: string) {
<div class="chat-view">
<!-- Conversation list sidebar -->
<aside class="conv-sidebar jarvis-sidebar" :class="{ collapsed: sidebarCollapsed }">
<button
class="jarvis-sidebar-toggle"
type="button"
:title="sidebarCollapsed ? '展开侧边栏' : '折叠侧边栏'"
:aria-label="sidebarCollapsed ? '展开侧边栏' : '折叠侧边栏'"
@click="sidebarCollapsed = !sidebarCollapsed"
>
<ChevronRight :size="14" class="jarvis-sidebar-toggle-icon" :class="{ expanded: !sidebarCollapsed }" />
</button>
<div v-if="sidebarCollapsed" class="jarvis-sidebar-icon-rail">
<button
v-for="module in sidebarCollapsedModules"
@@ -247,7 +237,7 @@ function renderMarkdown(content: string) {
<div class="jarvis-calendar">
<div class="calendar-header">
<span v-for="label in sidebarWeekLabels" :key="label">{{ label }}</span>
<span v-for="item in sidebarWeekLabels" :key="item.label" :class="{ 'is-weekend': item.isWeekend }">{{ item.label }}</span>
</div>
<div class="calendar-grid">
<span
@@ -274,11 +264,11 @@ function renderMarkdown(content: string) {
</div>
<div class="jarvis-status-copy">
<div class="jarvis-status-headline">
<div v-if="sidebarStatusHeadline" class="jarvis-status-headline">
{{ sidebarStatusHeadline }}
</div>
<ul class="jarvis-status-list">
<li v-for="item in sidebarStatusBreakdown" :key="item.key" class="jarvis-status-item">
<li v-for="item in sidebarStatusBreakdown" :key="item.key" class="jarvis-status-item" :class="{ 'is-total': item.key === 'total' }">
<span class="status-dot" :class="item.tone"></span>
<span class="status-label">{{ item.label }}</span>
<strong class="status-value">{{ item.value }}</strong>
@@ -292,10 +282,13 @@ function renderMarkdown(content: string) {
<div class="jarvis-section-title">&#x4ECA;&#x65E5;&#x8BA1;&#x5212;&#x91CD;&#x70B9;</div>
<ul v-if="sidebarFocusItems.length > 0" class="jarvis-focus-list">
<li v-for="(item, index) in sidebarFocusItems" :key="item.id" class="jarvis-focus-item" :class="`is-${item.tone}`">
<span class="focus-order">{{ String(index + 1).padStart(2, '0') }}</span>
<span class="focus-order" :class="{ 'is-done': item.tone === 'done' }">
<span v-if="item.tone === 'done'" class="focus-check"></span>
<span v-else>{{ String(index + 1).padStart(2, '0') }}</span>
</span>
<div class="focus-copy">
<div class="focus-label">{{ item.label }}</div>
<div class="focus-title">{{ item.title }}</div>
<div class="focus-title" :class="{ 'is-done': item.tone === 'done' }">{{ item.title }}</div>
<div class="focus-meta">{{ item.meta }}</div>
</div>
</li>
@@ -329,9 +322,9 @@ function renderMarkdown(content: string) {
<!-- Top bar -->
<div class="chat-topbar">
<div class="chat-shortcuts">
<NavShortcutRow
@select-folder="handleSelectFolder"
@open-knowledge-hud="openKnowledgeHud"
<NavShortcutRow
@select-folder="handleSelectFolder"
@open-knowledge-hud="openKnowledgeHud"
/>
</div>
<div class="chat-model-panel">
@@ -484,17 +477,14 @@ function renderMarkdown(content: string) {
<!-- Top buttons above input -->
<div class="top-buttons-row">
<button class="top-action-btn" @click="$router.push('/temple')">
<span class="btn-icon">⛩️</span>
<span class="btn-text">智慧神殿</span>
<button class="top-action-btn" @click="$router.push('/temple')" title="Temple">
<span class="btn-icon temple-icon">◈</span>
</button>
<button class="top-action-btn" @click="$router.push('/knowledge')">
<span class="btn-icon">📚</span>
<span class="btn-text">知识仓库</span>
<button class="top-action-btn" @click="$router.push('/knowledge')" title="Knowledge">
<span class="btn-icon knowledge-icon"></span>
</button>
<button class="top-action-btn" @click="$router.push('/war-room')">
<span class="btn-icon">🗺️</span>
<span class="btn-text">战情室</span>
<button class="top-action-btn" @click="$router.push('/war-room')" title="War Room">
<span class="btn-icon war-icon">⬡</span>
</button>
</div>