From 95a8f5af0c51ab7df4b9cb8e5c1c1457c084fcd7 Mon Sep 17 00:00:00 2001 From: XiaoCow666 Date: Thu, 1 Oct 2026 15:40:07 +0800 Subject: [PATCH 1/6] docs: define flat UI refresh design --- .../2026-10-01-flat-ui-refresh-design.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 docs/superpowers/specs/2026-10-01-flat-ui-refresh-design.md diff --git a/docs/superpowers/specs/2026-10-01-flat-ui-refresh-design.md b/docs/superpowers/specs/2026-10-01-flat-ui-refresh-design.md new file mode 100644 index 0000000..2b17948 --- /dev/null +++ b/docs/superpowers/specs/2026-10-01-flat-ui-refresh-design.md @@ -0,0 +1,57 @@ +# CodeSense 纯色界面改版设计 + +日期:2026-10-01 +Figma 草图:https://www.figma.com/design/NKLZ19BDlAbwveKe6tHV6k + +## 目标 + +将 CodeSense 的产品界面统一为简洁、舒适、灵活的纯色视觉语言,重点解决代码提交页 AI 编程助手在窄屏上知识卡过高、回复正文过窄、引用内容挤压的问题。保留现有功能、文案语义和服务端渲染方式。 + +## 范围 + +- 产品自有 CSS 和 Jinja 模板中的蓝紫色系、渐变背景及相关悬停状态;不修改 Bootstrap、Monaco 等第三方资源。 +- 共用导航、按钮、卡片、表单、提示、状态标签与 AI 消息的颜色、边框、间距和焦点状态。 +- 代码提交页的桌面与窄屏助手布局,以及知识证据面板的紧凑展示。 +- 已存在渐变的登录、注册、个人资料、学生与教师首页、班级、帮助、反馈、分析等页面。按同一视觉规则调整,避免只修截图中的一页。 + +当前 `origin/main` 中自有样式约有 57 处渐变声明,分布于 27 个文件。这是基线清单,实施时重新扫描并逐一处理。 + +## 视觉基础 + +| 用途 | 颜色 | +| --- | --- | +| 页面背景 | `#F5F7F8` | +| 内容表面 | `#FFFFFF` | +| 主文字 | `#23343D` | +| 次文字 | `#64757D` | +| 分隔线 | `#DDE5E6` | +| 主要操作 | `#237B75` | +| 强调浅底 | `#EAF4F2` | +| 输入浅底 | `#F0F3F3` | + +保留语义性成功、警告、错误颜色,但降低饱和度并保证对比度。主要操作使用青绿色纯色;信息层级主要通过字号、留白、细边框和文字重量表达。中文正文优先使用系统可用的无衬线字族,代码继续使用等宽字族。按钮和卡片采用适度圆角,不使用大面积阴影或装饰性渐变。交互状态以纯色、边框和清晰的键盘焦点体现。 + +## 页面与组件 + +1. 在共享样式中定义语义化视觉变量,并让通用控件引用变量。页面局部样式可以扩展,但不再各自发明主色和渐变。 +2. 保持 Flask/Jinja、Bootstrap 和现有 JavaScript 架构。复用现有模板宏与 CSS 组件;不为视觉改版引入 React 运行时或重写路由。 +3. 代码提交页桌面布局保留编辑器与助手并列,助手提供足够阅读宽度;较窄视口改为顺序布局,避免侧栏被压到无法阅读。 +4. AI 助手顶部使用简洁标题栏。知识焦点默认显示短摘要和证据数量,证据列表可展开;回复正文占可用宽度,长词、代码、表格、引用均不得造成横向溢出。输入区在助手底部保持可见。 +5. 知识证据在其他页面仍维持完整展示;紧凑模式只改变代码提交页的呈现,不删减证据数据或来源。 + +## 适配与可访问性 + +- 在 1440、768、390 和约 320 CSS 像素宽度检查关键页面;内容可换行,操作按钮有足够点击面积。 +- 保持焦点可见、文字与控件对比度充足;尊重减少动画偏好。 +- 证据展开状态有语义化控件和可访问名称;现有快捷提问、发送、清空、流式消息和证据重试继续可用。 + +## 验收 + +- 产品自有 CSS/模板不再出现 `linear-gradient(` 或 `radial-gradient(` 声明;第三方静态资源除外。 +- AI 助手在窄屏不出现截图中的三列挤压和横向滚动,知识列表展开后可完整阅读。 +- 全站共用控件和至少登录、学生首页、教师首页、代码提交四个代表性页面视觉一致。 +- 现有相关行为测试通过;浏览器检查桌面与窄屏,确认布局和交互状态。 + +## 发布 + +先在独立工作区完成代码与验证,再将变更并入主分支。线上部署需要单独验证静态资源缓存和真实页面显示;Figma 是设计参照,不替代浏览器验收。 From 74e750a0028f5844945f0f92c96bc60c23437707 Mon Sep 17 00:00:00 2001 From: XiaoCow666 Date: Thu, 1 Oct 2026 15:42:06 +0800 Subject: [PATCH 2/6] docs: plan flat UI refresh --- .../plans/2026-10-01-flat-ui-refresh.md | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 docs/superpowers/plans/2026-10-01-flat-ui-refresh.md diff --git a/docs/superpowers/plans/2026-10-01-flat-ui-refresh.md b/docs/superpowers/plans/2026-10-01-flat-ui-refresh.md new file mode 100644 index 0000000..bac4e26 --- /dev/null +++ b/docs/superpowers/plans/2026-10-01-flat-ui-refresh.md @@ -0,0 +1,107 @@ +# CodeSense 纯色界面改版实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 将 CodeSense 的自有页面改为统一的纯色、轻量、适应窄屏的界面,并修复 AI 编程助手的拥挤排版。 + +**Architecture:** 继续使用 Flask/Jinja、Bootstrap 和现有 JavaScript。通过共享语义色变量及现有模板宏实现可复用组件;页面局部 CSS 只承担布局和具体内容展示。保持原有路由与数据接口不变。 + +**Tech Stack:** Flask、Jinja2、CSS、原生 JavaScript、pytest、浏览器视觉检查。 + +**Spec:** `docs/superpowers/specs/2026-10-01-flat-ui-refresh-design.md` + +## Global Constraints + +- 自有产品 CSS/模板不得保留 `linear-gradient(` 或 `radial-gradient(`;不修改第三方 vendor 文件。 +- 设计色:页面 `#F5F7F8`、表面 `#FFFFFF`、主文字 `#23343D`、次文字 `#64757D`、线条 `#DDE5E6`、操作 `#237B75`、强调浅底 `#EAF4F2`、输入浅底 `#F0F3F3`。 +- 不新增 React 构建或运行时;保持现有服务端渲染及 AI 聊天功能。 +- 重点检查 1440、768、390、320 CSS 像素宽度。 + +## Review Focus + +1. 知识证据为空或检索失败时,紧凑面板仍显示下一步与重试入口。 +2. 长代码、表格、URL 和中文段落在 AI 回复中不撑破侧栏。 +3. 展开证据后来源与引用均可读,键盘可操作。 +4. 流式输出、快捷问题、发送与清空按钮保持可用。 +5. 对比度、焦点样式和减少动画偏好在浅色界面仍清晰。 + +--- + +### Task 1: 共享视觉基础 + +**Files:** +- Modify: `static/modern.css` +- Modify: `templates/layout.html` +- Test: `tests/test_flat_ui_contract.py` + +**Interfaces:** +- Produces CSS variables `--cs-bg`, `--cs-surface`, `--cs-ink`, `--cs-muted`, `--cs-line`, `--cs-accent`, `--cs-accent-soft`, `--cs-input` for subsequent page CSS. + +- [ ] **Step 1: Write a failing static contract test** in `tests/test_flat_ui_contract.py` that reads `static/modern.css` and asserts the exact semantic variable/value pairs below. Check shared button, focus, surface and body rules reference these variables. + +```python +EXPECTED = { + "--cs-bg": "#F5F7F8", "--cs-surface": "#FFFFFF", + "--cs-ink": "#23343D", "--cs-muted": "#64757D", + "--cs-line": "#DDE5E6", "--cs-accent": "#237B75", + "--cs-accent-soft": "#EAF4F2", "--cs-input": "#F0F3F3", +} +``` +- [ ] **Step 2: Run** `python -m pytest tests/test_flat_ui_contract.py -q`; expect failure from missing variables. +- [ ] **Step 3: Implement** the variables in `:root` and replace general navigation, button, card, form and focus colors with semantic variables. Preserve existing layout and semantic error/success states. +- [ ] **Step 4: Run** the contract test and `python -m pytest tests/test_app.py -q`; inspect failures before proceeding. +- [ ] **Step 5: Commit** `static/modern.css`, `templates/layout.html`, and the test. + +### Task 2: AI 助手和知识证据 + +**Files:** +- Modify: `templates/submit_code.html` +- Modify: `templates/components/knowledge_evidence.html` +- Modify: `static/css/knowledge-evidence.css` +- Modify: `static/css/codesense-markdown.css` +- Test: `tests/test_knowledge_evidence_ui.py` +- Test: `tests/test_flat_ui_contract.py` + +**Interfaces:** +- Consumes Task 1 CSS variables. +- Keeps `knowledge_evidence_panel(...)` macro signature and existing chat element IDs used by JavaScript. + +- [ ] **Step 1: Add a failing UI contract test** asserting the compact knowledge panel contains ` Date: Thu, 1 Oct 2026 15:45:22 +0800 Subject: [PATCH 3/6] style: add flat semantic theme foundations --- static/modern.css | 45 ++++++++++++++++++++-------------- tests/test_flat_ui_contract.py | 26 ++++++++++++++++++++ 2 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 tests/test_flat_ui_contract.py diff --git a/static/modern.css b/static/modern.css index 11aac06..1ba9944 100644 --- a/static/modern.css +++ b/static/modern.css @@ -1,19 +1,26 @@ /* modern.css - CodeSense 酷森思现代化样式 */ :root { + --cs-bg: #F5F7F8; + --cs-surface: #FFFFFF; + --cs-ink: #23343D; + --cs-muted: #64757D; + --cs-line: #DDE5E6; + --cs-accent: #237B75; + --cs-accent-soft: #EAF4F2; + --cs-input: #F0F3F3; /* 主色调 */ - --primary-color: #2563eb; - /* 深蓝色 */ - --primary-hover: #1d4ed8; + --primary-color: var(--cs-accent); + --primary-hover: #1C625D; --secondary-color: #f59e0b; /* 金色点缀 */ /* 中性色 */ - --dark: #1f2937; - --dark-light: #374151; - --medium: #9ca3af; - --light: #f3f4f6; - --white: #ffffff; + --dark: var(--cs-ink); + --dark-light: #40545D; + --medium: var(--cs-muted); + --light: var(--cs-bg); + --white: var(--cs-surface); /* 功能色 */ --success: #10b981; @@ -52,8 +59,8 @@ body { font-family: var(--font-sans); - background-color: var(--light); - color: var(--dark); + background-color: var(--cs-bg); + color: var(--cs-ink); line-height: 1.5; } @@ -77,7 +84,8 @@ a:hover { /* 导航栏 */ .navbar { - background-color: var(--white); + background-color: var(--cs-surface); + border-bottom: 1px solid var(--cs-line); box-shadow: var(--shadow-sm); padding: var(--spacing-md) 0; position: sticky; @@ -136,7 +144,7 @@ a:hover { .navbar-link:hover, .navbar-link.active { color: var(--primary-color); - background-color: rgba(37, 99, 235, 0.05); + background-color: var(--cs-accent-soft); } .navbar-user { @@ -199,7 +207,7 @@ a:hover { } :where(a, button, input, select, textarea):focus-visible { - outline: 3px solid rgba(37, 99, 235, 0.55); + outline: 3px solid var(--cs-accent); outline-offset: 3px; } @@ -231,7 +239,8 @@ a:hover { /* 卡片 */ .card { - background-color: var(--white); + background-color: var(--cs-surface); + border: 1px solid var(--cs-line); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); padding: var(--spacing-lg); @@ -260,7 +269,7 @@ a:hover { .card-badge { display: inline-block; padding: 4px 8px; - background-color: rgba(37, 99, 235, 0.1); + background-color: var(--cs-accent-soft); color: var(--primary-color); border-radius: var(--radius-sm); font-size: 0.875rem; @@ -299,7 +308,7 @@ a:hover { } .btn-primary { - background-color: var(--primary-color); + background-color: var(--cs-accent); color: var(--white); } @@ -308,12 +317,12 @@ a:hover { } .btn-secondary { - background-color: rgba(37, 99, 235, 0.1); + background-color: var(--cs-accent-soft); color: var(--primary-color); } .btn-secondary:hover { - background-color: rgba(37, 99, 235, 0.15); + background-color: #DCEDE9; } .btn-success { diff --git a/tests/test_flat_ui_contract.py b/tests/test_flat_ui_contract.py new file mode 100644 index 0000000..689b241 --- /dev/null +++ b/tests/test_flat_ui_contract.py @@ -0,0 +1,26 @@ +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +CSS = ROOT / "static" / "modern.css" + +EXPECTED_COLORS = { + "--cs-bg": "#F5F7F8", + "--cs-surface": "#FFFFFF", + "--cs-ink": "#23343D", + "--cs-muted": "#64757D", + "--cs-line": "#DDE5E6", + "--cs-accent": "#237B75", + "--cs-accent-soft": "#EAF4F2", + "--cs-input": "#F0F3F3", +} + + +def test_shared_theme_exposes_flat_semantic_colors(): + css = CSS.read_text(encoding="utf-8") + for name, value in EXPECTED_COLORS.items(): + assert f"{name}: {value};" in css + assert "background-color: var(--cs-bg);" in css + assert "background-color: var(--cs-surface);" in css + assert "background-color: var(--cs-accent);" in css + assert "outline: 3px solid var(--cs-accent);" in css From 7529a92fda993e71273f82588236905ff6410749 Mon Sep 17 00:00:00 2001 From: XiaoCow666 Date: Thu, 1 Oct 2026 15:49:20 +0800 Subject: [PATCH 4/6] style: redesign code studio assistant and evidence --- static/css/code-studio-assistant.css | 236 +++++++++++++++++++ static/css/knowledge-evidence.css | 77 +++++- templates/components/knowledge_evidence.html | 18 ++ templates/submit_code.html | 3 +- tests/test_knowledge_evidence_ui.py | 26 +- 5 files changed, 345 insertions(+), 15 deletions(-) create mode 100644 static/css/code-studio-assistant.css diff --git a/static/css/code-studio-assistant.css b/static/css/code-studio-assistant.css new file mode 100644 index 0000000..2f6c49a --- /dev/null +++ b/static/css/code-studio-assistant.css @@ -0,0 +1,236 @@ +/* Code Studio assistant: a quiet reading column beside the editor. */ +.code-studio-container { + min-width: 0; +} + +.code-studio-container > * { + min-width: 0; +} + +.code-studio-assistant { + height: clamp(560px, calc(100vh - 190px), 760px); + min-height: 0; + max-height: none; + background: var(--cs-surface); + border: 1px solid var(--cs-line); + border-radius: 14px; + box-shadow: none; +} + +.code-studio-assistant .ai-assistant-header { + min-height: 60px; + padding: 0.9rem 1.25rem; + background: var(--cs-surface); + color: var(--cs-ink); + border-bottom: 1px solid var(--cs-line); +} + +.code-studio-assistant .ai-assistant-header h5 { + font-size: 1rem; +} + +.code-studio-assistant #clear-chat { + color: var(--cs-muted); + background: transparent; + border: 0; + box-shadow: none; +} + +.code-studio-assistant #clear-chat:hover { + color: var(--cs-accent); + background: var(--cs-accent-soft); +} + +.code-studio-assistant .ai-chat-messages { + min-width: 0; + min-height: 0; + padding: 1.25rem; + background: var(--cs-surface); + overscroll-behavior: contain; +} + +.code-studio-assistant .ai-message-wrapper { + min-width: 0; + gap: 0.55rem; + flex-wrap: wrap; + margin-bottom: 1rem; +} + +.code-studio-assistant .ai-message-avatar { + width: 30px; + height: 30px; + font-size: 0.95rem; + background: var(--cs-accent-soft); + color: var(--cs-accent); + box-shadow: none; + margin: 0; +} + +.code-studio-assistant .ai-message-content { + min-width: 0; + max-width: calc(100% - 40px); + padding: 0.7rem 0.85rem; + background: var(--cs-surface); + color: var(--cs-ink); + border: 1px solid var(--cs-line); + border-radius: 10px; + box-shadow: none; + overflow-wrap: anywhere; +} + +.code-studio-assistant .assistant-message .ai-message-content { + flex: 1 1 calc(100% - 40px); + max-width: calc(100% - 40px); + border: 0; + padding: 0.15rem 0; +} + +.code-studio-assistant .user-message .ai-message-content { + max-width: min(82%, 32rem); + background: var(--cs-accent-soft); + color: var(--cs-ink); + border: 0; +} + +.code-studio-assistant .knowledge-evidence-receipt-mount { + flex: 0 0 calc(100% - 40px); + width: calc(100% - 40px); + min-width: 0; + margin-left: 40px; +} + +.code-studio-assistant .knowledge-evidence-receipt { + min-width: 0; + padding: 0.7rem 0.85rem; + background: var(--cs-bg); + border-radius: 9px; + color: var(--cs-muted); + font-size: 0.78rem; + overflow-wrap: anywhere; +} + +.code-studio-assistant .knowledge-evidence-receipt__title { + margin: 0 0 0.35rem; + color: var(--cs-ink); + font-size: 0.82rem; + font-weight: 600; +} + +.code-studio-assistant .knowledge-evidence-receipt__status p { + margin: 0.25rem 0 0; +} + +.code-studio-assistant .knowledge-evidence-receipt__details { + display: grid; + gap: 0.35rem; + margin-top: 0.5rem; +} + +.code-studio-assistant .knowledge-evidence-receipt__detail summary { + cursor: pointer; + overflow-wrap: anywhere; +} + +.code-studio-assistant .knowledge-evidence-receipt__body { + padding: 0.4rem 0 0.6rem 1rem; +} + +.code-studio-assistant .ai-chat-input-area { + padding: 0.85rem 1.25rem; + border-top: 1px solid var(--cs-line); +} + +.code-studio-assistant .ai-chat-input-wrapper { + gap: 0.6rem; +} + +.code-studio-assistant .ai-chat-textarea { + min-width: 0; + border: 1px solid var(--cs-line); + border-radius: 9px; + background: var(--cs-input); + font-size: 0.88rem; +} + +.code-studio-assistant .ai-send-button { + width: 48px; + height: 48px; + border-radius: 9px; + background: var(--cs-accent); + box-shadow: none; +} + +.code-studio-assistant .ai-send-button:hover:not(:disabled) { + background: #1c625d; + transform: none; + box-shadow: none; +} + +.code-studio-assistant .ai-welcome-message { + padding: 2rem 0.5rem; +} + +.code-studio-assistant .ai-welcome-icon { + font-size: 2rem; +} + +.code-studio-assistant .ai-quick-prompts { + grid-template-columns: repeat(auto-fit, minmax(min(100%, 130px), 1fr)); +} + +.code-studio-assistant .ai-quick-prompt-btn { + border: 1px solid var(--cs-line); + border-radius: 8px; + color: var(--cs-accent); + box-shadow: none; +} + +.code-studio-assistant .ai-quick-prompt-btn:hover { + color: var(--cs-ink); + background: var(--cs-accent-soft); + border-color: var(--cs-accent); + transform: none; + box-shadow: none; +} + +.code-studio-assistant .ai-message-content pre, +.code-studio-assistant .ai-message-content table { + max-width: 100%; + overflow-x: auto; +} + +@media (max-width: 991px) { + .code-studio-assistant { + height: min(720px, 82vh); + min-height: 520px; + } +} + +@media (max-width: 480px) { + .code-studio-assistant .ai-chat-messages { + padding: 1rem; + } + + .code-studio-assistant .ai-chat-input-area { + padding: 0.75rem 1rem; + } + + .code-studio-assistant .ai-message-content, + .code-studio-assistant .assistant-message .ai-message-content { + max-width: calc(100% - 36px); + } + + .code-studio-assistant .knowledge-evidence-receipt-mount { + flex-basis: calc(100% - 36px); + width: calc(100% - 36px); + margin-left: 36px; + } +} + +@media (prefers-reduced-motion: reduce) { + .code-studio-assistant .ai-message-wrapper, + .code-studio-assistant .ai-send-button { + animation: none; + transition: none; + } +} diff --git a/static/css/knowledge-evidence.css b/static/css/knowledge-evidence.css index fd6f8d3..aeb6047 100644 --- a/static/css/knowledge-evidence.css +++ b/static/css/knowledge-evidence.css @@ -1,8 +1,8 @@ :root { - --knowledge-ink: #14213D; - --knowledge-blue: #2F80ED; - --knowledge-paper: #F7FAFC; - --knowledge-teal: #0F766E; + --knowledge-ink: var(--cs-ink); + --knowledge-blue: var(--cs-accent); + --knowledge-paper: var(--cs-surface); + --knowledge-teal: var(--cs-accent); --knowledge-amber: #B45309; } @@ -11,15 +11,68 @@ padding: 1.35rem 1.5rem; color: var(--knowledge-ink); background: var(--knowledge-paper); - border: 1px solid rgba(20, 33, 61, 0.16); - border-left: 4px solid var(--knowledge-blue); + border: 1px solid var(--cs-line); border-radius: 0.7rem; - box-shadow: 0 8px 24px rgba(20, 33, 61, 0.07); + box-shadow: none; } .knowledge-evidence-panel--compact { - margin: 1rem 0; - padding: 1rem 1.1rem; + margin: 1rem 1.25rem 0; + padding: 0; + background: var(--cs-accent-soft); + border: 0; +} + +.knowledge-evidence-panel__compact-summary { + display: grid; + gap: 0.25rem; + padding: 0.85rem 1rem; + cursor: pointer; + list-style: none; +} + +.knowledge-evidence-panel__compact-summary::-webkit-details-marker { + display: none; +} + +.knowledge-evidence-panel__compact-heading { + color: var(--cs-ink); + font-size: 0.92rem; + font-weight: 650; +} + +.knowledge-evidence-panel__compact-topics { + color: var(--cs-muted); + font-size: 0.8rem; + overflow-wrap: anywhere; +} + +.knowledge-evidence-panel__compact-action { + color: var(--cs-accent); + font-size: 0.78rem; + font-weight: 650; +} + +.knowledge-evidence-panel__compact-disclosure[open] .knowledge-evidence-panel__compact-action [aria-hidden] { + display: inline-block; + transform: rotate(180deg); +} + +.knowledge-evidence-panel__compact-content { + padding: 0 1rem 1rem; +} + +.knowledge-evidence-panel__compact-content .knowledge-evidence-panel__status { + margin-top: 0; + padding: 0.7rem 0.8rem; +} + +.knowledge-evidence-panel__compact-content .knowledge-evidence-panel__details { + margin-top: 0.6rem; +} + +.knowledge-evidence-panel__compact-content .knowledge-evidence-detail { + border-color: var(--cs-line); } .knowledge-evidence-panel__header { @@ -114,6 +167,7 @@ } .knowledge-evidence-detail summary:focus-visible, +.knowledge-evidence-panel__compact-summary:focus-visible, .knowledge-evidence-panel a:focus-visible, .knowledge-evidence-panel button:focus-visible { outline: 3px solid rgba(47, 128, 237, 0.45); @@ -251,6 +305,11 @@ border-radius: 0.55rem; } + .knowledge-evidence-panel--compact { + margin: 0.85rem 1rem 0; + padding: 0; + } + .knowledge-evidence-panel__header { display: block; } diff --git a/templates/components/knowledge_evidence.html b/templates/components/knowledge_evidence.html index bb6b120..18ed5e5 100644 --- a/templates/components/knowledge_evidence.html +++ b/templates/components/knowledge_evidence.html @@ -3,6 +3,19 @@ {% set evidence_items = evidence_view.get('evidence', []) %}
+ {% if compact %} +
+ + + {% if heading %}{{ heading }}{% else %}作业知识焦点{% endif %} + + + {% if evidence_items %}{% for item in evidence_items[:3] %}{{ item.get('title') or '知识点' }}{% if not loop.last %} · {% endif %}{% endfor %}{% else %}{{ evidence_view.get('status_label', '暂无线索') }}{% endif %} + + 查看 {{ evidence_items|length }} 条证据 + +
+ {% else %}

作业知识工作区

@@ -14,6 +27,7 @@

{{ evidence_view.get('status_label', '证据状态不可用') }}

+ {% endif %}
{{ evidence_view.get('summary', '当前无法确认知识证据状态。') }} @@ -79,5 +93,9 @@

仅用于检索诊断,不作为评分依据。

{% endif %} + {% if compact %} +
+
+ {% endif %}
{% endmacro %} diff --git a/templates/submit_code.html b/templates/submit_code.html index d938f4c..90ff272 100644 --- a/templates/submit_code.html +++ b/templates/submit_code.html @@ -754,6 +754,7 @@ } } + {% endblock %} {% block content %} @@ -887,7 +888,7 @@

{{ assignment.title }}

-
+
AI编程助手 diff --git a/tests/test_knowledge_evidence_ui.py b/tests/test_knowledge_evidence_ui.py index 6f8ea20..3f20f41 100644 --- a/tests/test_knowledge_evidence_ui.py +++ b/tests/test_knowledge_evidence_ui.py @@ -40,11 +40,10 @@ def test_evidence_styles_define_tokens_focus_mobile_and_reduced_motion(): ) for token in ( - "#14213D", - "#2F80ED", - "#F7FAFC", - "#0F766E", - "#B45309", + "var(--cs-ink)", + "var(--cs-accent)", + "var(--cs-accent-soft)", + "var(--cs-line)", ): assert token in css assert ":focus-visible" in css @@ -53,6 +52,23 @@ def test_evidence_styles_define_tokens_focus_mobile_and_reduced_motion(): assert "@media (prefers-reduced-motion: reduce)" in css +def test_compact_evidence_is_a_keyboard_operable_disclosure(): + macro = (ROOT / "templates" / "components" / "knowledge_evidence.html").read_text( + encoding="utf-8" + ) + submit = (ROOT / "templates" / "submit_code.html").read_text(encoding="utf-8") + + assert 'class="knowledge-evidence-panel__compact-disclosure"' in macro + assert 'class="knowledge-evidence-panel__compact-summary"' in macro + assert " Date: Thu, 1 Oct 2026 16:10:28 +0800 Subject: [PATCH 5/6] Refresh first-party pages with flat teal interface --- static/css/action-center.css | 42 ++--- static/css/code-editor.css | 14 +- static/css/code-studio-assistant.css | 9 + static/css/code_submit.css | 14 +- static/css/codesense-markdown.css | 12 +- static/css/cpp-editor.css | 8 +- static/css/knowledge-evidence.css | 4 +- static/css/modern-editor.css | 12 +- static/css/thinking.css | 200 ++++++++++---------- static/img/favicon.svg | 2 +- static/js/code_questions.js | 4 +- static/js/thinking.js | 2 +- static/modern.css | 112 ++++++----- templates/about.html | 2 +- templates/add_assignment.html | 2 +- templates/admin_dashboard.html | 2 +- templates/admin_profile.html | 4 +- templates/admin_trend_monitor.html | 16 +- templates/all_submissions.html | 2 +- templates/api_docs.html | 2 +- templates/classes/class_comparison.html | 2 +- templates/classes/class_detail.html | 4 +- templates/components/simple_editor.html | 6 +- templates/contact.html | 4 +- templates/cot_demo.html | 12 +- templates/edit_profile.html | 2 +- templates/editor_demo.html | 2 +- templates/email_register.html | 2 +- templates/feedback.html | 2 +- templates/forgot_password.html | 2 +- templates/grades.html | 2 +- templates/help.html | 2 +- templates/layout.html | 4 +- templates/login.html | 238 ++++++------------------ templates/notifications.html | 4 +- templates/parsons_demo.html | 4 +- templates/profile.html | 2 +- templates/public_profile.html | 8 +- templates/register.html | 22 +-- templates/register_teacher.html | 4 +- templates/resend_verification.html | 2 +- templates/reset_password.html | 2 +- templates/sprofile.html | 18 +- templates/staff_details.html | 2 +- templates/student_details.html | 18 +- templates/student_home.html | 16 +- templates/submission_detail.html | 4 +- templates/submission_evaluating.html | 14 +- templates/submission_history.html | 4 +- templates/submit_code.html | 62 +++--- templates/teacher_ai_suggestions.html | 8 +- templates/teacher_home.html | 24 +-- templates/thinking/arena.html | 2 +- templates/users.html | 16 +- templates/verify_email.html | 2 +- tests/test_flat_ui_contract.py | 32 ++++ tests/test_knowledge_evidence_ui.py | 13 ++ 57 files changed, 495 insertions(+), 537 deletions(-) diff --git a/static/css/action-center.css b/static/css/action-center.css index 4b7aa98..f2a0791 100644 --- a/static/css/action-center.css +++ b/static/css/action-center.css @@ -1,12 +1,10 @@ .action-center-page { max-width: 980px; margin: 0 auto; - color: #e8eefc; - --action-navy: #0b1530; - --action-panel: #111e3e; - --action-line: #4ea1ff; - --action-muted: #a8b6d2; - --action-soft: rgba(78, 161, 255, 0.12); + color: var(--cs-ink, #23343D); + --action-line: #DDE5E6; + --action-muted: #5B6E70; + --action-soft: #EAF4F2; } .action-center-header { @@ -16,13 +14,13 @@ gap: 1.5rem; padding: 2.2rem clamp(1.25rem, 4vw, 3rem); border-radius: 1.25rem; - background: linear-gradient(120deg, var(--action-navy), #172a54 70%, #1d3a71); - box-shadow: 0 1rem 2.5rem rgba(13, 31, 70, 0.18); + background: #F1F7F5; + border: 1px solid var(--action-line); } .action-center-eyebrow { margin: 0 0 0.7rem; - color: var(--action-line); + color: #237B75; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.16em; @@ -30,7 +28,7 @@ .action-center-header h1 { margin: 0; - color: #fff; + color: var(--cs-ink, #23343D); font-size: clamp(2rem, 5vw, 3.2rem); letter-spacing: -0.04em; } @@ -46,14 +44,14 @@ display: grid; min-width: 8rem; padding: 0.9rem 1rem; - border: 1px solid rgba(255, 255, 255, 0.18); + border: 1px solid var(--action-line); border-radius: 0.9rem; color: var(--action-muted); text-align: right; } .action-center-totals strong { - color: #fff; + color: var(--cs-ink, #23343D); font-size: 2rem; line-height: 1; } @@ -61,7 +59,7 @@ .action-center-status { margin: 1.1rem 0 0; padding: 0.75rem 1rem; - border-left: 3px solid var(--action-line); + border-left: 3px solid #237B75; color: #334155; background: var(--action-soft); } @@ -77,16 +75,16 @@ padding: 0.5rem 0.8rem; border: 1px solid #cbd5e1; border-radius: 999px; - color: #1e3a8a; + color: #23343D; background: #fff; text-decoration: none; } .action-center-filter:hover, .action-center-filter[aria-current="page"] { - border-color: var(--action-line); - color: #08204d; - background: #dbeafe; + border-color: #237B75; + color: #1C625D; + background: #EAF4F2; } .action-center-filter:focus-visible, @@ -105,7 +103,7 @@ .action-center-item { overflow: hidden; - border: 1px solid #dbe4f0; + border: 1px solid #DDE5E6; border-radius: 0.9rem; background: #fff; box-shadow: 0 0.4rem 1rem rgba(15, 23, 42, 0.06); @@ -116,7 +114,7 @@ grid-template-columns: 0.35rem minmax(0, 1fr) auto; align-items: stretch; min-height: 5.5rem; - color: #172554; + color: #23343D; text-decoration: none; } @@ -129,7 +127,7 @@ } .action-center-item--next .action-center-item-rail { - background: var(--action-line); + background: #237B75; } .action-center-item-body { @@ -152,7 +150,7 @@ } .action-center-item-priority { - color: #1d4ed8; + color: #1C625D; font-weight: 800; } @@ -163,7 +161,7 @@ .action-center-item-arrow { align-self: center; padding: 0 1rem; - color: #2563eb; + color: #237B75; font-size: 1.4rem; } diff --git a/static/css/code-editor.css b/static/css/code-editor.css index 5af7c55..bef09a4 100644 --- a/static/css/code-editor.css +++ b/static/css/code-editor.css @@ -28,7 +28,7 @@ .editor-language { font-weight: 600; - color: #3b82f6; + color: #2E8E86; display: flex; align-items: center; } @@ -65,8 +65,8 @@ } .editor-btn.active { - background-color: #dbeafe; - color: #2563eb; + background-color: #EAF4F2; + color: #237B75; } /* 下拉菜单 */ @@ -155,7 +155,7 @@ height: 40px; border: 3px solid #e5e7eb; border-radius: 50%; - border-top-color: #3b82f6; + border-top-color: #2E8E86; animation: spin 1s linear infinite; } @@ -228,8 +228,8 @@ } .code-editor.dark-theme .editor-btn.active { - background-color: #1e3a8a; - color: #60a5fa; + background-color: #23343D; + color: #78ADA6; } .code-editor.dark-theme .editor-textarea { @@ -256,7 +256,7 @@ .code-editor.dark-theme .spinner { border-color: #374151; - border-top-color: #60a5fa; + border-top-color: #78ADA6; } .code-editor.dark-theme .loading-text { diff --git a/static/css/code-studio-assistant.css b/static/css/code-studio-assistant.css index 2f6c49a..35d775e 100644 --- a/static/css/code-studio-assistant.css +++ b/static/css/code-studio-assistant.css @@ -49,6 +49,10 @@ overscroll-behavior: contain; } +.code-studio-assistant .ai-chat-messages > .knowledge-evidence-panel--compact { + margin: 0 0 1.25rem; +} + .code-studio-assistant .ai-message-wrapper { min-width: 0; gap: 0.55rem; @@ -99,6 +103,11 @@ margin-left: 40px; } +.code-studio-assistant #code-studio-analysis-evidence { + width: 100%; + margin: 0.75rem 0 0; +} + .code-studio-assistant .knowledge-evidence-receipt { min-width: 0; padding: 0.7rem 0.85rem; diff --git a/static/css/code_submit.css b/static/css/code_submit.css index 0938407..72a83b2 100644 --- a/static/css/code_submit.css +++ b/static/css/code_submit.css @@ -63,7 +63,7 @@ width: 18px; height: 18px; border: 2px solid #f3f3f3; - border-top: 2px solid #3498db; + border-top: 2px solid #397F79; border-radius: 50%; animation: spin 1s linear infinite; margin-right: 5px; @@ -116,7 +116,7 @@ #ask-question-btn { padding: 6px 15px; - background-color: #007bff; + background-color: #237B75; color: white; border: none; border-radius: 4px; @@ -130,7 +130,7 @@ } #ask-question-btn:hover { - background-color: #0069d9; + background-color: #1C625D; } /* 指导内容样式 */ @@ -340,9 +340,9 @@ pre:hover .copy-button { } .waiting-message { - color: #0d6efd; + color: #237B75; padding: 0.5rem; - border-left: 3px solid #0d6efd; + border-left: 3px solid #237B75; background-color: rgba(13, 110, 253, 0.1); margin: 0.5rem 0; } @@ -425,7 +425,7 @@ pre:hover .copy-button { .simple-mode textarea.editor-textarea:focus { color: #212529; background-color: #fff; - border-color: #86b7fe; + border-color: #A9D0CA; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } @@ -453,7 +453,7 @@ pre:hover .copy-button { #ai-assistance .card-title i { margin-right: 0.5rem; - color: #0d6efd; + color: #237B75; } #get-ai-advice { diff --git a/static/css/codesense-markdown.css b/static/css/codesense-markdown.css index e5e29ab..65366bd 100644 --- a/static/css/codesense-markdown.css +++ b/static/css/codesense-markdown.css @@ -14,9 +14,9 @@ --cs-md-border-strong: #d7dee9; --cs-md-surface: #ffffff; --cs-md-surface-soft: #f8fafc; - --cs-md-surface-blue: #f3f7ff; - --cs-md-accent: #2563eb; - --cs-md-accent-soft: #dbeafe; + --cs-md-surface-blue: #EAF4F2; + --cs-md-accent: #237B75; + --cs-md-accent-soft: #EAF4F2; --cs-md-success: #059669; --cs-md-warning: #d97706; --cs-md-danger: #dc2626; @@ -93,7 +93,7 @@ } .cs-markdown h2 { - background: linear-gradient(90deg, var(--cs-md-surface-blue), rgba(243, 247, 255, 0)); + background: var(--cs-accent-soft); border-left: 3px solid var(--cs-md-accent); border-radius: 0 6px 6px 0; font-size: 1.2rem; @@ -168,8 +168,8 @@ .cs-markdown blockquote.cs-md-callout-note, .cs-markdown blockquote.cs-md-callout-info { - background: #eff6ff; - border-left-color: #3b82f6; + background: #F5F7F8; + border-left-color: #2E8E86; } .cs-markdown blockquote.cs-md-callout-tip, diff --git a/static/css/cpp-editor.css b/static/css/cpp-editor.css index 7bef830..7e9a063 100644 --- a/static/css/cpp-editor.css +++ b/static/css/cpp-editor.css @@ -28,7 +28,7 @@ .editor-language { font-weight: 600; - color: #3b82f6; + color: #2E8E86; display: flex; align-items: center; } @@ -63,8 +63,8 @@ } .editor-btn.active { - background-color: #dbeafe; - color: #2563eb; + background-color: #EAF4F2; + color: #237B75; } /* 编辑器容器 */ @@ -118,7 +118,7 @@ height: 40px; border: 3px solid #e5e7eb; border-radius: 50%; - border-top-color: #3b82f6; + border-top-color: #2E8E86; animation: spin 1s linear infinite; } diff --git a/static/css/knowledge-evidence.css b/static/css/knowledge-evidence.css index aeb6047..39f9f31 100644 --- a/static/css/knowledge-evidence.css +++ b/static/css/knowledge-evidence.css @@ -236,7 +236,7 @@ .knowledge-evidence-retry:hover { color: #fff; - background: #1d64c8; + background: #1C625D; } .knowledge-evidence-receipt__retry { @@ -253,7 +253,7 @@ } .knowledge-evidence-receipt__retry:hover { - background: #1d64c8; + background: #1C625D; } .knowledge-evidence-receipt__retry:disabled { diff --git a/static/css/modern-editor.css b/static/css/modern-editor.css index 6eebd59..fb2204f 100644 --- a/static/css/modern-editor.css +++ b/static/css/modern-editor.css @@ -52,7 +52,7 @@ .modern-editor-language i { margin-right: 0.5rem; font-size: 1rem; - color: #6366f1; + color: #237B75; } .dark-theme .modern-editor-language { @@ -83,13 +83,13 @@ .modern-editor-tool:hover { background-color: #f3f4f6; - color: #6366f1; + color: #237B75; border-color: #d1d5db; } .modern-editor-tool:focus { outline: none; - box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3); + box-shadow: 0 0 0 2px rgba(35, 123, 117, 0.3); } .dark-theme .modern-editor-tool { @@ -99,7 +99,7 @@ .dark-theme .modern-editor-tool:hover { background-color: #3e3e3e; - color: #6366f1; + color: #237B75; } /* 编辑器容器 */ @@ -221,9 +221,9 @@ /* 提高textarea的可访问性样式 */ .modern-editor textarea.form-control:focus-visible { - outline: 2px solid #6366f1; + outline: 2px solid #237B75; outline-offset: 2px; - border-color: #6366f1; + border-color: #237B75; } /* 高对比度模式支持 */ diff --git a/static/css/thinking.css b/static/css/thinking.css index e11e234..7c59c9a 100644 --- a/static/css/thinking.css +++ b/static/css/thinking.css @@ -43,7 +43,7 @@ gap: 8px; } -.arena-title i { color: #2563eb; } +.arena-title i { color: #237B75; } .arena-timer { font-family: 'JetBrains Mono', monospace; @@ -62,9 +62,9 @@ min-width: 0; margin-bottom: 16px; padding: 14px 18px; - border: 1px solid #dbe4f0; + border: 1px solid #DDE5E6; border-radius: 10px; - background: linear-gradient(135deg, #f8fbff 0%, #ffffff 100%); + background: var(--cs-surface); color: #334155; } @@ -83,7 +83,7 @@ .session-lifecycle-kicker { font-size: 13px; font-weight: 700; - color: #1e3a8a; + color: #23343D; } .session-lifecycle-badge { @@ -109,8 +109,8 @@ } .session-lifecycle[data-session-status="completed"] .session-lifecycle-badge { - background: #dbeafe; - color: #1d4ed8; + background: #EAF4F2; + color: #1C625D; } .session-lifecycle-meta, @@ -152,7 +152,7 @@ width: 0; height: 100%; border-radius: inherit; - background: #2563eb; + background: #237B75; transition: width 180ms ease; } @@ -217,9 +217,9 @@ } .step-circle.active { - background: #2563eb; + background: #237B75; color: #fff; - border-color: #2563eb; + border-color: #237B75; } .step-circle.completed { @@ -244,7 +244,7 @@ white-space: nowrap; } -.step-label.active { color: #2563eb; font-weight: 600; } +.step-label.active { color: #237B75; font-weight: 600; } .step-label.completed { color: #10b981; } /* --- Main Content --- */ @@ -419,7 +419,7 @@ gap: 6px; } -.panel-header h3 i { color: #2563eb; font-size: 14px; } +.panel-header h3 i { color: #237B75; font-size: 14px; } .stage2-header-meta { display: flex; @@ -435,8 +435,8 @@ .stage2-answer-progress { padding: 3px 8px; border-radius: 999px; - background: #eff6ff; - color: #1d4ed8; + background: #F5F7F8; + color: #1C625D; font-weight: 600; white-space: nowrap; } @@ -445,10 +445,10 @@ display: inline-flex; align-items: center; gap: 4px; - border: 1px solid #dbeafe; + border: 1px solid #EAF4F2; border-radius: 999px; - background: #eff6ff; - color: #2563eb; + background: #F5F7F8; + color: #237B75; padding: 4px 8px; font-size: 11px; line-height: 1; @@ -458,12 +458,12 @@ } .panel-collapse-toggle:hover { - background: #dbeafe; - border-color: #93c5fd; + background: #EAF4F2; + border-color: #A9D0CA; } .panel-collapse-toggle:focus-visible { - outline: 2px solid #60a5fa; + outline: 2px solid #78ADA6; outline-offset: 2px; } @@ -531,8 +531,8 @@ .description-textarea:focus { outline: none; - border-color: #2563eb; - box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); + border-color: #237B75; + box-shadow: 0 0 0 3px rgba(35, 123, 117, 0.1); } .description-textarea::placeholder { color: #9ca3af; } @@ -587,7 +587,7 @@ } .block-solution { - border-color: #2563eb; + border-color: #237B75; border-style: dashed; } @@ -611,7 +611,7 @@ .code-block { background: #fff; border: 1px solid #e5e7eb; - border-left: 3px solid #2563eb; + border-left: 3px solid #237B75; border-radius: 4px; padding: 8px 12px; margin-bottom: 4px; @@ -625,7 +625,7 @@ } .code-block:hover { - border-color: #2563eb; + border-color: #237B75; box-shadow: 0 2px 4px rgba(0,0,0,0.08); } @@ -679,9 +679,9 @@ } .indent-btn:hover { - background: #2563eb; + background: #237B75; color: #fff; - border-color: #2563eb; + border-color: #237B75; } /* --- Stage 3: Chat --- */ @@ -721,7 +721,7 @@ background: #f3f4f6; } -.chat-avatar.teacher { background: #eff6ff; } +.chat-avatar.teacher { background: #F5F7F8; } .chat-avatar.student { background: #f0fdf4; } .chat-avatar.bad-student { background: #fef3c7; } @@ -749,7 +749,7 @@ } .chat-bubble.user-msg { - background: #2563eb; + background: #237B75; color: #fff; border-bottom-right-radius: 2px; } @@ -816,7 +816,7 @@ font-family: inherit; } -.chat-input:focus { border-color: #2563eb; } +.chat-input:focus { border-color: #237B75; } .chat-input::placeholder { color: #9ca3af; } /* --- Stage 3: Public Forum --- */ @@ -855,10 +855,10 @@ .forum-goal-card { flex: 0 0 auto; padding: 14px 16px; - border: 1px solid #dbeafe; + border: 1px solid #EAF4F2; border-radius: 14px; - background: linear-gradient(135deg, #f8fbff 0%, #ffffff 72%); - box-shadow: 0 4px 14px rgba(37, 99, 235, 0.06); + background: var(--cs-surface); + box-shadow: 0 4px 14px rgba(35, 123, 117, 0.06); } .forum-goal-summary { @@ -880,8 +880,8 @@ right: 0; padding: 3px 7px; border-radius: 999px; - background: #eff6ff; - color: #2563eb; + background: #F5F7F8; + color: #237B75; font-size: 10px; font-weight: 700; } @@ -892,7 +892,7 @@ .forum-goal-summary:focus-visible, .stage3-guide-summary:focus-visible { - outline: 2px solid #2563eb; + outline: 2px solid #237B75; outline-offset: 3px; border-radius: 6px; } @@ -913,7 +913,7 @@ } .forum-goal-kicker { - color: #2563eb; + color: #237B75; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; @@ -925,7 +925,7 @@ .forum-goal-head h4 { margin: 4px 0 0; - color: #172554; + color: #23343D; font-size: 15px; line-height: 1.35; } @@ -934,8 +934,8 @@ flex: 0 0 auto; padding: 4px 9px; border-radius: 999px; - background: #dbeafe; - color: #1d4ed8; + background: #EAF4F2; + color: #1C625D; font-size: 11px; font-weight: 700; white-space: nowrap; @@ -964,7 +964,7 @@ .forum-goal-progress-bar { height: 100%; border-radius: inherit; - background: linear-gradient(90deg, #2563eb, #22c55e); + background: var(--cs-accent); transition: width 0.35s ease; } @@ -978,7 +978,7 @@ } .forum-goal-progress-meta span:first-child { - color: #1d4ed8; + color: #1C625D; font-weight: 800; } @@ -986,8 +986,8 @@ margin-top: 10px; padding: 8px 10px; border-radius: 9px; - background: #eff6ff; - color: #1e3a8a; + background: #F5F7F8; + color: #23343D; font-size: 12px; line-height: 1.5; } @@ -1024,14 +1024,14 @@ } .forum-goal-step.is-active { - border-color: #93c5fd; - background: #f8fbff; - color: #1e40af; + border-color: #A9D0CA; + background: #F5F7F8; + color: #1C625D; } .forum-goal-step.is-active::before { content: '→'; - color: #2563eb; + color: #237B75; } .forum-goal-step.is-done { @@ -1068,7 +1068,7 @@ align-items: flex-start; gap: 4px; padding: 12px 14px; - border: 1px solid #dbe4f0; + border: 1px solid #DDE5E6; border-radius: 10px; background: #f8fafc; color: #1e293b; @@ -1078,20 +1078,20 @@ } .forum-target-btn:hover { - border-color: #93c5fd; - background: #eff6ff; + border-color: #A9D0CA; + background: #F5F7F8; } .forum-target-btn:focus-visible { - outline: 2px solid #2563eb; + outline: 2px solid #237B75; outline-offset: 2px; } .forum-target-btn.is-selected, .forum-target-btn[aria-pressed="true"] { - border-color: #2563eb; - background: #dbeafe; - box-shadow: 0 0 0 1px #2563eb; + border-color: #237B75; + background: #EAF4F2; + box-shadow: 0 0 0 1px #237B75; } .forum-target-label { @@ -1170,11 +1170,11 @@ } .forum-avatar.role-user { - background: #eff6ff; + background: #F5F7F8; } .forum-avatar.role-teacher_agent { - background: #eef2ff; + background: #EAF4F2; } .forum-avatar.role-student_agent { @@ -1192,8 +1192,8 @@ } .forum-event.is-user .forum-card { - background: #eff6ff; - border-color: #bfdbfe; + background: #F5F7F8; + border-color: #CDE5E1; } .forum-meta { @@ -1233,8 +1233,8 @@ } .forum-kind.kind-user_message { - background: #dbeafe; - color: #1d4ed8; + background: #EAF4F2; + color: #1C625D; } .forum-kind.kind-agent_message { @@ -1265,7 +1265,7 @@ .forum-reply-action { border: none; background: transparent; - color: #2563eb; + color: #237B75; font-size: 12px; font-weight: 600; cursor: pointer; @@ -1273,7 +1273,7 @@ } .forum-reply-action:hover { - color: #1d4ed8; + color: #1C625D; text-decoration: underline; } @@ -1325,7 +1325,7 @@ } .stage3-guide-summary > span:first-child i { - color: #2563eb; + color: #237B75; } .stage3-guide-summary-hint { @@ -1416,7 +1416,7 @@ .code-fix-input:focus { outline: none; - border-color: #2563eb; + border-color: #237B75; } /* --- Buttons --- */ @@ -1436,12 +1436,12 @@ } .arena-btn-primary { - background: #2563eb; + background: #237B75; color: #fff; } .arena-btn-primary:hover { - background: #1d4ed8; + background: #1C625D; } .arena-btn-primary:disabled { @@ -1472,7 +1472,7 @@ height: 34px; padding: 0; border-radius: 50%; - background: #2563eb; + background: #237B75; color: #fff; border: none; cursor: pointer; @@ -1483,18 +1483,18 @@ flex-shrink: 0; } -.arena-btn-send:hover { background: #1d4ed8; } +.arena-btn-send:hover { background: #1C625D; } .arena-btn-send:disabled { opacity: 0.4; cursor: not-allowed; } /* --- Hint --- */ .hint-bubble { - background: #eff6ff; - border: 1px solid #bfdbfe; + background: #F5F7F8; + border: 1px solid #CDE5E1; border-radius: 6px; padding: 10px 14px; margin: 8px 0; font-size: 13px; - color: #1e40af; + color: #1C625D; line-height: 1.5; display: flex; align-items: flex-start; @@ -1502,7 +1502,7 @@ } .hint-bubble i { - color: #2563eb; + color: #237B75; flex-shrink: 0; margin-top: 2px; } @@ -1515,7 +1515,7 @@ margin-bottom: 0; } .hint-bubble code { - background: rgba(37, 99, 235, 0.1); + background: rgba(35, 123, 117, 0.1); padding: 2px 4px; border-radius: 4px; font-family: var(--arena-mono, monospace); @@ -1736,7 +1736,7 @@ .algorithm-summary-panel { background: #f8fafc; border: 1px solid #e2e8f0; - border-left: 4px solid #2563eb; + border-left: 4px solid #237B75; border-radius: 6px; margin-bottom: 12px; overflow: hidden; @@ -1748,7 +1748,7 @@ border-bottom: 1px solid #e2e8f0; font-size: 13px; font-weight: 600; - color: #1e3a8a; + color: #23343D; display: flex; align-items: center; justify-content: space-between; @@ -1845,10 +1845,10 @@ gap: 12px; margin: 2px 0 10px; padding: 10px 12px; - border: 1px solid #dbeafe; + border: 1px solid #EAF4F2; border-radius: 8px; - background: linear-gradient(90deg, #eff6ff, #f8fbff); - color: #1e3a8a; + background: var(--cs-accent-soft); + color: #23343D; } .stage1-answer-toolbar > div { @@ -1874,18 +1874,18 @@ flex: 0 0 auto; padding: 3px 8px; border-radius: 999px; - background: #dbeafe; - color: #1d4ed8 !important; + background: #EAF4F2; + color: #1C625D !important; font-size: 11px !important; white-space: nowrap; } .stage1-collapsible-panel { margin-bottom: 12px; - border: 1px solid #bfdbfe; - border-left: 4px solid #3b82f6; + border: 1px solid #CDE5E1; + border-left: 4px solid #2E8E86; border-radius: 8px; - background: #eff6ff; + background: #F5F7F8; overflow: hidden; } @@ -1898,7 +1898,7 @@ padding: 10px 12px; border: 0; background: transparent; - color: #1e3a8a; + color: #23343D; font: inherit; font-size: 13px; font-weight: 600; @@ -1912,7 +1912,7 @@ .stage1-collapse-header:focus-visible, .algorithm-summary-header:focus-visible { - outline: 2px solid #60a5fa; + outline: 2px solid #78ADA6; outline-offset: -2px; } @@ -1923,7 +1923,7 @@ .stage1-collapse-header i:first-child, .stage1-collapse-header > span > i { margin-right: 5px; - color: #2563eb; + color: #237B75; } .stage1-collapse-header small { @@ -1934,7 +1934,7 @@ .stage1-collapsible-body { padding: 0 14px 12px; - color: #1e40af; + color: #1C625D; font-size: 13px; line-height: 1.65; } @@ -2000,7 +2000,7 @@ padding: 10px 12px; border: 0; background: transparent; - color: #38bdf8; + color: #6AB5A9; cursor: pointer; font-family: inherit; font-size: 13px; @@ -2008,7 +2008,7 @@ text-align: left; } .dev-debug-toggle:focus-visible { - outline: 2px solid #38bdf8; + outline: 2px solid #6AB5A9; outline-offset: -2px; } .dev-debug-title { @@ -2064,10 +2064,10 @@ transform: scale(0.97); } .dev-debug-btn-primary { - background: #2563eb; + background: #237B75; } .dev-debug-btn-primary:hover { - background: #3b82f6; + background: #2E8E86; } .dev-debug-btn-success { background: #16a34a; @@ -2125,7 +2125,7 @@ margin-top: 4px; } .dev-debug-trace-key { - color: #7dd3fc; + color: #A9D0CA; font-weight: 600; } .dev-debug-trace-value { @@ -2221,9 +2221,9 @@ } .quiz-choice-option.selected { - border-color: #3b82f6; - background: #eff6ff; - box-shadow: 0 0 0 1px #3b82f6; + border-color: #2E8E86; + background: #F5F7F8; + box-shadow: 0 0 0 1px #2E8E86; } .quiz-choice-option input[type="radio"] { @@ -2272,8 +2272,8 @@ } .quiz-fill-input:focus { - border-color: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15); + border-color: #2E8E86; + box-shadow: 0 0 0 2px rgba(46, 142, 134, 0.15); } .quiz-step-feedback { @@ -2472,10 +2472,10 @@ } .mobile-tab-btn.active { - color: #2563eb; - border-bottom-color: #2563eb; + color: #237B75; + border-bottom-color: #237B75; font-weight: 600; - background: rgba(37, 99, 235, 0.03); + background: rgba(35, 123, 117, 0.03); } /* 主布局转换为单栏 */ diff --git a/static/img/favicon.svg b/static/img/favicon.svg index a08773f..47508c8 100644 --- a/static/img/favicon.svg +++ b/static/img/favicon.svg @@ -1,5 +1,5 @@ CodeSense - + diff --git a/static/js/code_questions.js b/static/js/code_questions.js index ed4d9b4..910e8a8 100644 --- a/static/js/code_questions.js +++ b/static/js/code_questions.js @@ -735,7 +735,7 @@ function addQuestionStyles() { .answer-header i { margin-right: 8px; - color: #0d6efd; + color: #237B75; } .ai-answer.error .answer-header i { @@ -762,7 +762,7 @@ function addQuestionStyles() { height: 8px; width: 8px; margin: 0 2px; - background-color: #0d6efd; + background-color: #237B75; border-radius: 50%; opacity: 0.6; animation: typing 1s infinite; diff --git a/static/js/thinking.js b/static/js/thinking.js index 227a3cf..44bfd76 100644 --- a/static/js/thinking.js +++ b/static/js/thinking.js @@ -507,7 +507,7 @@ qLabel.style.display = 'flex'; qLabel.style.alignItems = 'flex-start'; qLabel.style.gap = '6px'; - qLabel.innerHTML = `${i + 1} ${escapeHtml(q)}`; + qLabel.innerHTML = `${i + 1} ${escapeHtml(q)}`; const qTextarea = document.createElement('textarea'); qTextarea.className = 'description-textarea qa-answer-textarea'; diff --git a/static/modern.css b/static/modern.css index 1ba9944..ed3d5ec 100644 --- a/static/modern.css +++ b/static/modern.css @@ -9,6 +9,8 @@ --cs-accent: #237B75; --cs-accent-soft: #EAF4F2; --cs-input: #F0F3F3; + --bs-primary: var(--cs-accent); + --bs-primary-rgb: 35, 123, 117; /* 主色调 */ --primary-color: var(--cs-accent); --primary-hover: #1C625D; @@ -26,7 +28,7 @@ --success: #10b981; --warning: #f59e0b; --danger: #ef4444; - --info: #3b82f6; + --info: #2E8E86; /* 字体 */ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; @@ -50,6 +52,33 @@ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); } +/* Bootstrap's compiled utilities keep their original blue without these bridges. */ +.bg-primary, +.badge.bg-primary { + background-color: var(--cs-accent) !important; +} + +.text-primary, +.link-primary { + color: var(--cs-accent) !important; +} + +.border-primary { + border-color: var(--cs-accent) !important; +} + +.btn-outline-primary { + color: var(--cs-accent); + border-color: var(--cs-accent); +} + +.btn-outline-primary:hover, +.btn-outline-primary:focus-visible { + color: var(--cs-surface); + background-color: var(--cs-accent); + border-color: var(--cs-accent); +} + /* 重置样式 */ * { margin: 0; @@ -114,6 +143,7 @@ a:hover { } .navbar-brand-logo { + filter: hue-rotate(-45deg) saturate(.75); width: auto; height: 34px; margin-right: 0 !important; @@ -369,7 +399,7 @@ a:hover { .form-control:focus { outline: none; border-color: var(--primary-color); - box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15); + box-shadow: 0 0 0 3px rgba(35, 123, 117, 0.15); } .form-error { @@ -461,7 +491,7 @@ a:hover { } .badge-primary { - background-color: rgba(37, 99, 235, 0.1); + background-color: rgba(35, 123, 117, 0.1); color: var(--primary-color); } @@ -514,7 +544,7 @@ a:hover { } .alert-info { - background-color: rgba(59, 130, 246, 0.1); + background-color: rgba(46, 142, 134, 0.1); color: var(--info); border-left: 3px solid var(--info); } @@ -708,7 +738,7 @@ a:hover { ========================================================================== */ .maturity-hero { - background: linear-gradient(135deg, #1e293b 0%, #334155 100%); + background: var(--cs-ink); color: white; padding: 3rem 2rem; border-radius: 1rem; @@ -725,7 +755,7 @@ a:hover { right: -10%; width: 300px; height: 300px; - background: radial-gradient(circle, rgba(59, 130, 246, 0.2) 0%, transparent 70%); + background: transparent; border-radius: 50%; } @@ -740,9 +770,7 @@ a:hover { font-weight: 800; margin: 0; line-height: 1; - background: linear-gradient(to bottom, #fff, #94a3b8); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; + color: var(--cs-surface); } .maturity-label { @@ -895,9 +923,9 @@ a:hover { max-width: 720px; margin: 4rem auto; padding: 3rem 2rem; - border: 1px solid #dbeafe; + border: 1px solid #EAF4F2; border-radius: 1.25rem; - background: linear-gradient(145deg, #eff6ff, #ffffff 62%); + background: var(--cs-surface); box-shadow: var(--shadow-md); text-align: center; } @@ -990,9 +1018,9 @@ a:hover { .review-queue-filter:hover, .review-queue-filter.is-active { - color: #1d4ed8; - border-color: #93c5fd; - background: #eff6ff; + color: #1C625D; + border-color: #A9D0CA; + background: #F5F7F8; } .review-queue-table-wrap { @@ -1058,12 +1086,12 @@ a:hover { .ai-feedback-signal legend { float: none; width: auto; - color: #4c1d95; + color: #23343D; font-weight: 600; } .review-dashboard-card { - border-left: 4px solid #2563eb; + border-left: 4px solid #237B75; } @media (max-width: 640px) { @@ -1092,9 +1120,9 @@ a:hover { .learning-graph-panel { margin: 0 0 2rem; padding: 1.5rem; - border: 1px solid #dbe7f5; + border: 1px solid #DDE5E6; border-radius: var(--radius-lg); - background: linear-gradient(135deg, #f8fbff 0%, #ffffff 66%); + background: var(--cs-surface); box-shadow: 0 8px 24px rgba(30, 64, 175, 0.06); } @@ -1114,7 +1142,7 @@ a:hover { .learning-graph-panel__eyebrow { margin: 0 0 0.25rem; - color: #2563eb; + color: #237B75; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; @@ -1122,7 +1150,7 @@ a:hover { .learning-graph-panel__title { margin: 0; - color: #172554; + color: #23343D; font-size: 1.35rem; font-weight: 750; } @@ -1136,7 +1164,7 @@ a:hover { } .teacher-learning-actions { - border: 1px solid #dbe7f5; + border: 1px solid #DDE5E6; border-radius: var(--radius-lg); background: #ffffff; box-shadow: var(--shadow-sm); @@ -1155,7 +1183,7 @@ a:hover { padding: 1rem; border: 1px solid #e2e8f0; border-radius: 0.75rem; - background: #f8fbff; + background: #F5F7F8; } .teacher-learning-action-card h3, @@ -1198,8 +1226,8 @@ a:hover { padding: 1.25rem; border: 1px solid #dbe5f2; border-radius: 1rem; - background: linear-gradient(135deg, #f8fbff 0%, #ffffff 78%); - box-shadow: 0 0.5rem 1.5rem rgba(37, 99, 235, 0.06); + background: var(--cs-surface); + box-shadow: 0 0.5rem 1.5rem rgba(35, 123, 117, 0.06); } .student-learning-memory-panel__header { @@ -1240,7 +1268,7 @@ a:hover { gap: 0.35rem; border-radius: 999px; padding: 0.35rem 0.65rem; - color: #1f4f8f; + color: #1C625D; background: #eaf2ff; font-size: 0.8rem; white-space: nowrap; @@ -1364,10 +1392,10 @@ a:hover { .learning-graph-panel__privacy { flex: 0 0 auto; padding: 0.35rem 0.65rem; - border: 1px solid #bfdbfe; + border: 1px solid #CDE5E1; border-radius: 999px; - color: #1d4ed8; - background: #eff6ff; + color: #1C625D; + background: #F5F7F8; font-size: 0.75rem; white-space: nowrap; } @@ -1387,7 +1415,7 @@ a:hover { } .learning-graph-panel__summary strong { - color: #1e40af; + color: #1C625D; font-size: 1rem; } @@ -1445,7 +1473,7 @@ a:hover { height: 100%; min-width: 0; border-radius: inherit; - background: linear-gradient(90deg, #60a5fa, #2563eb); + background: var(--cs-accent); } .learning-graph-next { @@ -1470,23 +1498,23 @@ a:hover { justify-content: space-between; gap: 1rem; padding: 0.7rem 0.8rem; - border: 1px solid #dbeafe; + border: 1px solid #EAF4F2; border-radius: 0.65rem; - color: #1e3a8a; - background: #eff6ff; + color: #23343D; + background: #F5F7F8; text-decoration: none; } .learning-graph-recommendation:hover, .learning-graph-recommendation:focus-visible { - color: #1e3a8a; - border-color: #93c5fd; - background: #dbeafe; + color: #23343D; + border-color: #A9D0CA; + background: #EAF4F2; } .learning-graph-recommendation.is-static:hover { - color: #1e3a8a; - background: #eff6ff; + color: #23343D; + background: #F5F7F8; } .learning-graph-recommendation strong, @@ -1516,7 +1544,7 @@ a:hover { } .learning-graph-coverage-value { - color: #1d4ed8; + color: #1C625D; font-size: 1.7rem; font-weight: 750; line-height: 1; @@ -1556,7 +1584,7 @@ a:hover { align-items: flex-start; gap: 0.75rem; padding: 1rem; - border: 1px dashed #bfdbfe; + border: 1px dashed #CDE5E1; border-radius: 0.75rem; color: #475569; background: rgba(239, 246, 255, 0.65); @@ -1565,12 +1593,12 @@ a:hover { .learning-graph-empty > i { margin-top: 0.15rem; - color: #2563eb; + color: #237B75; font-size: 1.25rem; } .learning-graph-empty strong { - color: #1e3a8a; + color: #23343D; } .learning-graph-panel__note { diff --git a/templates/about.html b/templates/about.html index 5a57eb3..cfafab5 100644 --- a/templates/about.html +++ b/templates/about.html @@ -11,7 +11,7 @@ } .hero-section { - background: linear-gradient(135deg, var(--primary-color) 0%, #0056b3 100%); + background: var(--cs-accent); color: white; padding: 4rem 2rem; border-radius: 1rem; diff --git a/templates/add_assignment.html b/templates/add_assignment.html index dbdee9c..a4e0877 100644 --- a/templates/add_assignment.html +++ b/templates/add_assignment.html @@ -34,7 +34,7 @@ .form-control:focus { border-color: var(--primary-color); - box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); + box-shadow: 0 0 0 3px rgba(35, 123, 117, 0.15); outline: none; } diff --git a/templates/admin_dashboard.html b/templates/admin_dashboard.html index 0bc7882..4daafd4 100644 --- a/templates/admin_dashboard.html +++ b/templates/admin_dashboard.html @@ -301,7 +301,7 @@
过去30天活跃度
// 调试信息输出函数(仅控制台显示,不影响页面) function log(message, type = 'info') { const styles = { - info: 'color: #0066cc; background: #f0f8ff;', + info: 'color: #237B75; background: #f0f8ff;', error: 'color: #cc0000; background: #fff0f0;', warning: 'color: #cc6600; background: #fff8f0;', success: 'color: #006600; background: #f0fff0;' diff --git a/templates/admin_profile.html b/templates/admin_profile.html index 704549d..90c71b4 100644 --- a/templates/admin_profile.html +++ b/templates/admin_profile.html @@ -21,7 +21,7 @@ left: 0; right: 0; bottom: 0; - background: linear-gradient(135deg, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.4) 100%); + background: rgba(35, 52, 61, 0.24); z-index: 1; } @@ -175,7 +175,7 @@ .badge-role { background-color: #e7f0ff; - color: #0056b3; + color: #1C625D; padding: 0.4rem 0.8rem; border-radius: 20px; font-weight: 500; diff --git a/templates/admin_trend_monitor.html b/templates/admin_trend_monitor.html index 409f8e8..04d4bb8 100644 --- a/templates/admin_trend_monitor.html +++ b/templates/admin_trend_monitor.html @@ -5,7 +5,7 @@ {% block extra_css %} {% endblock %} @@ -344,10 +344,10 @@

恭喜您!目前没有显著瓶颈

skillsData.student.efficiency, skillsData.student.readability ], - backgroundColor: 'rgba(59, 130, 246, 0.4)', - borderColor: 'rgba(59, 130, 246, 1)', + backgroundColor: 'rgba(46, 142, 134, 0.4)', + borderColor: 'rgba(46, 142, 134, 1)', borderWidth: 2, - pointBackgroundColor: 'rgba(59, 130, 246, 1)', + pointBackgroundColor: 'rgba(46, 142, 134, 1)', }, ...(skillsData.class_average ? [{ label: '全班平均', @@ -377,13 +377,13 @@

恭喜您!目前没有显著瓶颈

datasets: [{ label: '综合能力值', data: metaHistory, - borderColor: '#3b82f6', - backgroundColor: 'rgba(59, 130, 246, 0.1)', + borderColor: '#2E8E86', + backgroundColor: 'rgba(46, 142, 134, 0.1)', fill: true, tension: 0.4, pointRadius: 6, pointBackgroundColor: '#fff', - pointBorderColor: '#3b82f6', + pointBorderColor: '#2E8E86', pointBorderWidth: 3 }] }; diff --git a/templates/staff_details.html b/templates/staff_details.html index 2cf4da9..287bc53 100644 --- a/templates/staff_details.html +++ b/templates/staff_details.html @@ -5,7 +5,7 @@ {% block extra_css %}