feat(portal-shell): v2.0 P0 shadcn standardization + security + streaming + error handling

- shadcn/ui 标准化:废弃纸感令牌,统一 bg-background/text-foreground 等
- Tailwind v4 + @theme inline,移除 tailwind.config.js
- React 19 use() + Suspense 流式渲染,首屏骨架秒出
- 三级错误边界:Route → Section → Widget 层层兜底
- 错误上报:useErrorReport → sendBeacon → /api/log mock 端点
- 三层安全边界:L1 角色门禁 / L2 权限点门禁 / L3 数据范围
- 权限位图 base36 压缩:67 权限点 → ~14 字符,JWT 体积减少 ≥ 99%
- notify 统一 Toast 封装,禁止业务直接 import sonner
- PluginBoundary 替代 PluginLoader(错误边界 + Suspense + Skeleton 三件套)

验证:typecheck 0 错误 / lint 0 错误 / build 6 路由生成成功
This commit is contained in:
SpecialX
2026-07-17 16:10:05 +08:00
parent f7e52b5b7f
commit 9cedf0c437
140 changed files with 10872 additions and 3192 deletions

View File

@@ -1,55 +1,62 @@
/**
* portal-shell 全局样式
* portal-shell 全局样式Tailwind v4 + shadcn 标准令牌)
*
* 引入 @edu/ui-tokens 三层设计令牌primitive → semantic → tailwind-theme
* 业务代码使用 Tailwind 类bg-background / text-foreground / bg-card ...)或 hsl(var(--*)) 引用。
*
* 禁止规则ESLint + project_rules §3.10
* - 禁止 #hex 字面量(用 hsl(var(--*)) 或 Tailwind bg-* 类)
* - 禁止字体名字面量(用 var(--font-family-*))
* - 禁止 font-size: Npx用 var(--font-size-*) 或 Tailwind text-* 类)
*
* 对齐CICD 项目 src/app/globals.css
*/
@import "tailwindcss";
@import "@edu/ui-tokens/all.css";
@plugin "tailwindcss-animate";
@plugin "@tailwindcss/typography";
@custom-variant dark (&:where(.dark, .dark *));
@tailwind base;
@tailwind components;
@tailwind utilities;
/* 排除非源码目录,防止文档中的 Tailwind 任意值语法字符串被误识别为类名 */
@source not "../../docs";
@source not "../../scripts";
@source not "../../tests";
/* Reduced Motion */
@layer base {
html,
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
}
/* Base Styles */
@layer base {
* {
@apply border-border;
}
body {
background: var(--bg-paper);
color: var(--color-ink);
@apply bg-background text-foreground;
font-family: var(--font-family-sans);
font-feature-settings: "rlig" 1, "calt" 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-family-serif);
font-weight: var(--font-weight-semibold);
letter-spacing: var(--letter-spacing-tight);
}
}
@layer components {
/* 纸感分隔线 */
.rule {
border-top: 1px solid var(--color-rule);
}
.rule-thin {
border-top: 2px solid var(--color-rule);
}
/* 左侧竖线标记 */
.mark-left {
border-left: 2px solid var(--color-rule);
padding-left: var(--space-md);
font-family: var(--font-family-sans);
font-weight: var(--weight-semibold);
letter-spacing: -0.01em;
}
}