feat(teacher-portal): 完整实现 teacher-portal 微前端

包含 settings/students/api、graphql、mocks、ui-tokens 设计令牌等
This commit is contained in:
SpecialX
2026-07-10 19:10:20 +08:00
parent 14d836beb0
commit 1eacd1ed87
48 changed files with 3897 additions and 1056 deletions

View File

@@ -0,0 +1,13 @@
/**
* ui-tokens 全量样式入口
*
* 导入顺序Layer 1 Primitive → Layer 2 Semanticlight + dark→ Layer 3 Tailwind
*
* 用法apps/teacher-portal/src/app/globals.css
* @import '@edu/ui-tokens/all.css';
*/
@import './primitive.css';
@import './semantic-light.css';
@import './semantic-dark.css';
@import './tailwind-theme.css';

View File

@@ -0,0 +1,112 @@
/**
* Layer 1: Primitive Tokens原始色板/字号/间距/阴影)
*
* 业务代码不直接引用本层令牌,仅 Layer 2 Semantic 引用。
* 维护者ai13teacher-portal
* 关联project_rules §3.10 设计令牌规范
*
* 命名规范:
* - 颜色:--color-<hue>-<level>HSL 分量,供 Layer 2 组合)
* - 字号:--font-size-<n>1-9 阶梯)
* - 间距:--space-<n>4px 基准阶梯)
* - 阴影:--shadow-<n>
* - 字重:--font-weight-<name>
* - 圆角:--radius-<name>
*/
:root {
/* ============ 颜色原始色板HSL 分量,非完整颜色) ============ */
/* 中性色(纸张/墨色) */
--color-paper-h: 40;
--color-paper-s: 20%;
--color-paper-l-50: 50%;
--color-paper-l-98: 98%;
--color-paper-l-99: 99%;
--color-ink-h: 25;
--color-ink-s: 3%;
--color-ink-l-15: 15%;
--color-ink-l-45: 45%;
--color-ink-l-60: 60%;
/* 强调色(深蓝) */
--color-accent-h: 220;
--color-accent-s: 60%;
--color-accent-l-35: 35%;
--color-accent-l-50: 50%;
/* 分隔线(暖灰) */
--color-rule-h: 30;
--color-rule-s: 10%;
--color-rule-l-85: 85%;
--color-rule-l-90: 90%;
/* 语义原始色 */
--color-success-h: 142;
--color-success-s: 71%;
--color-success-l-45: 45%;
--color-warning-h: 38;
--color-warning-s: 92%;
--color-warning-l-50: 50%;
--color-danger-h: 0;
--color-danger-s: 84%;
--color-danger-l-60: 60%;
--color-info-h: 199;
--color-info-s: 89%;
--color-info-l-48: 48%;
/* ============ 字号阶梯1-91 最小 9 最大) ============ */
--font-size-1: 0.75rem; /* 12px - 辅助说明 */
--font-size-2: 0.875rem; /* 14px - 次要正文 */
--font-size-3: 1rem; /* 16px - 正文 body */
--font-size-4: 1.125rem; /* 18px - 强调正文 */
--font-size-5: 1.25rem; /* 20px - 小标题 */
--font-size-6: 1.5rem; /* 24px - 区块标题 */
--font-size-7: 1.875rem; /* 30px - 页面标题 */
--font-size-8: 2.25rem; /* 36px - Hero */
--font-size-9: 3rem; /* 48px - 大数字 */
/* ============ 间距阶梯4px 基准) ============ */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.25rem; /* 20px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-10: 2.5rem; /* 40px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
--space-20: 5rem; /* 80px */
/* ============ 阴影 ============ */
--shadow-1: 0 1px 2px 0 hsl(25 3% 15% / 0.05);
--shadow-2: 0 1px 3px 0 hsl(25 3% 15% / 0.1), 0 1px 2px -1px hsl(25 3% 15% / 0.1);
--shadow-3: 0 4px 6px -1px hsl(25 3% 15% / 0.1), 0 2px 4px -2px hsl(25 3% 15% / 0.1);
--shadow-4: 0 10px 15px -3px hsl(25 3% 15% / 0.1), 0 4px 6px -4px hsl(25 3% 15% / 0.1);
/* ============ 字重 ============ */
--font-weight-regular: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* ============ 圆角 ============ */
--radius-sm: 0.25rem; /* 4px */
--radius-md: 0.375rem; /* 6px */
--radius-lg: 0.5rem; /* 8px */
--radius-full: 9999px;
/* ============ 行高 ============ */
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
/* ============ 字间距 ============ */
--letter-spacing-tight: -0.01em;
--letter-spacing-normal: 0;
--letter-spacing-wide: 0.025em;
}

View File

@@ -0,0 +1,66 @@
/**
* Layer 2: Semantic Tokens - Dark Theme暗色语义令牌
*
* 维护者ai13teacher-portal
* 关联project_rules §3.10
*
* 暗色主题覆盖,通过 [data-theme="dark"] 或 prefers-color-scheme: dark 激活。
*/
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
color-scheme: dark;
--bg-paper: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-15));
--bg-surface: hsl(var(--color-ink-h) var(--color-ink-s) 20%);
--bg-subtle: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
--color-ink: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-98));
--color-ink-muted: hsl(var(--color-paper-h) var(--color-paper-s) 70%);
--color-ink-subtle: hsl(var(--color-paper-h) var(--color-paper-s) 60%);
--color-ink-on-accent: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
--color-accent: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-50));
--color-accent-hover: hsl(var(--color-accent-h) var(--color-accent-s) 60%);
--color-accent-subtle: hsl(var(--color-accent-h) var(--color-accent-s) 25%);
--color-rule: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
--color-rule-strong: hsl(var(--color-ink-h) var(--color-ink-s) 30%);
--color-border: var(--color-rule);
--color-input-bg: var(--bg-surface);
--shadow-sm: 0 1px 2px 0 hsl(0 0% 0% / 0.3);
--shadow-md: 0 1px 3px 0 hsl(0 0% 0% / 0.4), 0 1px 2px -1px hsl(0 0% 0% / 0.4);
--shadow-lg: 0 4px 6px -1px hsl(0 0% 0% / 0.4), 0 2px 4px -2px hsl(0 0% 0% / 0.4);
--shadow-xl: 0 10px 15px -3px hsl(0 0% 0% / 0.5), 0 4px 6px -4px hsl(0 0% 0% / 0.5);
}
}
[data-theme="dark"] {
color-scheme: dark;
--bg-paper: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-15));
--bg-surface: hsl(var(--color-ink-h) var(--color-ink-s) 20%);
--bg-subtle: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
--color-ink: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-98));
--color-ink-muted: hsl(var(--color-paper-h) var(--color-paper-s) 70%);
--color-ink-subtle: hsl(var(--color-paper-h) var(--color-paper-s) 60%);
--color-ink-on-accent: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
--color-accent: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-50));
--color-accent-hover: hsl(var(--color-accent-h) var(--color-accent-s) 60%);
--color-accent-subtle: hsl(var(--color-accent-h) var(--color-accent-s) 25%);
--color-rule: hsl(var(--color-ink-h) var(--color-ink-s) 25%);
--color-rule-strong: hsl(var(--color-ink-h) var(--color-ink-s) 30%);
--color-border: var(--color-rule);
--color-input-bg: var(--bg-surface);
--shadow-sm: 0 1px 2px 0 hsl(0 0% 0% / 0.3);
--shadow-md: 0 1px 3px 0 hsl(0 0% 0% / 0.4), 0 1px 2px -1px hsl(0 0% 0% / 0.4);
--shadow-lg: 0 4px 6px -1px hsl(0 0% 0% / 0.4), 0 2px 4px -2px hsl(0 0% 0% / 0.4);
--shadow-xl: 0 10px 15px -3px hsl(0 0% 0% / 0.5), 0 4px 6px -4px hsl(0 0% 0% / 0.4);
}

View File

@@ -0,0 +1,82 @@
/**
* Layer 2: Semantic Tokens - Light Theme亮色语义令牌
*
* 业务代码唯一引用入口:业务 TSX/CSS 引用 var(--color-*) / var(--font-*) 等。
* 维护者ai13teacher-portal
* 关联project_rules §3.10、03-long-term-architecture.md §1.5
*
* 引用 Layer 1 Primitive 组合成完整语义值。
*/
:root {
color-scheme: light;
/* ============ 背景与表面 ============ */
--bg-paper: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-98));
--bg-surface: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
--bg-subtle: hsl(var(--color-rule-h) var(--color-rule-s) var(--color-rule-l-90));
/* ============ 文字 ============ */
--color-ink: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-15));
--color-ink-muted: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-45));
--color-ink-subtle: hsl(var(--color-ink-h) var(--color-ink-s) var(--color-ink-l-60));
--color-ink-on-accent: hsl(var(--color-paper-h) var(--color-paper-s) var(--color-paper-l-99));
/* ============ 强调色 ============ */
--color-accent: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-35));
--color-accent-hover: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-accent-l-50));
--color-accent-subtle: hsl(var(--color-accent-h) var(--color-accent-s) var(--color-rule-l-90));
/* ============ 分隔线 ============ */
--color-rule: hsl(var(--color-rule-h) var(--color-rule-s) var(--color-rule-l-90));
--color-rule-strong: hsl(var(--color-rule-h) var(--color-rule-s) var(--color-rule-l-85));
/* ============ 语义色 ============ */
--color-success: hsl(var(--color-success-h) var(--color-success-s) var(--color-success-l-45));
--color-warning: hsl(var(--color-warning-h) var(--color-warning-s) var(--color-warning-l-50));
--color-danger: hsl(var(--color-danger-h) var(--color-danger-s) var(--color-danger-l-60));
--color-info: hsl(var(--color-info-h) var(--color-info-s) var(--color-info-l-48));
/* ============ 边框/输入 ============ */
--color-border: var(--color-rule);
--color-border-focus: var(--color-accent);
--color-input-bg: var(--bg-surface);
/* ============ 字体族(通过 var 引用,禁止字面量) ============ */
--font-family-sans: var(--font-inter, system-ui), -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-family-serif: var(--font-fraunces, Georgia), "Times New Roman", serif;
--font-family-mono: var(--font-jetbrains-mono, "SF Mono"), Monaco, Consolas, monospace;
/* ============ 语义字号 ============ */
--font-size-body: var(--font-size-3);
--font-size-small: var(--font-size-2);
--font-size-tiny: var(--font-size-1);
--font-size-heading-1: var(--font-size-7);
--font-size-heading-2: var(--font-size-6);
--font-size-heading-3: var(--font-size-5);
--font-size-display: var(--font-size-9);
--font-size-large-number: var(--font-size-8);
/* ============ 语义间距 ============ */
--space-xs: var(--space-1);
--space-sm: var(--space-2);
--space-md: var(--space-4);
--space-lg: var(--space-6);
--space-xl: var(--space-8);
--space-2xl: var(--space-12);
/* ============ 语义阴影 ============ */
--shadow-sm: var(--shadow-1);
--shadow-md: var(--shadow-2);
--shadow-lg: var(--shadow-3);
--shadow-xl: var(--shadow-4);
/* ============ 语义圆角 ============ */
--radius-default: var(--radius-md);
--radius-card: var(--radius-lg);
--radius-button: var(--radius-md);
/* ============ 过渡 ============ */
--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
}

View File

@@ -0,0 +1,31 @@
/**
* Layer 3: Tailwind Theme MappingTailwind 主题映射)
*
* 将 Layer 2 Semantic 令牌映射为 Tailwind 类名bg-* / text-* / font-* 等)。
* 维护者ai13teacher-portal
* 关联project_rules §3.10、03-long-term-architecture.md §1.5
*
* Tailwind 3.4 通过 tailwind.config.js 的 theme.extend 映射;
* Tailwind 4 将改用 @theme inline 指令(未来升级时本文件可转为 @theme 块)。
*
* 使用方式(业务组件):
* <div className="bg-paper text-ink font-serif">...</div>
* <p className="text-sm text-ink-muted">...</p>
*
* 对应 tailwind.config.js 中:
* colors: { paper: 'var(--bg-paper)', ink: 'var(--color-ink)', ... }
* fontFamily: { sans: 'var(--font-family-sans)', serif: 'var(--font-family-serif)', ... }
*/
/* 显式引用语义令牌,确保 CSS 变量在构建产物中可用 */
@layer base {
:root {
/* Tailwind 颜色类映射(与 tailwind.config.js theme.extend.colors 对齐) */
--tw-color-paper: var(--bg-paper);
--tw-color-surface: var(--bg-surface);
--tw-color-ink: var(--color-ink);
--tw-color-ink-muted: var(--color-ink-muted);
--tw-color-accent: var(--color-accent);
--tw-color-rule: var(--color-rule);
}
}