Web 端
Web 控制台。React 19 + Vite + IBM Carbon Design System,TypeScript strict 全量。前端一律用同源相对路径 /api/... 调后端——开发由 Vite proxy 转发,生产由 nginx 转发,EdgeOne 由边缘函数转发,因此没有客户端 API base URL。
技术栈
- React 19 +
react-router-dom7 + Vite 8 +@vitejs/plugin-react - UI 库:
@carbon/react(IBM Carbon Design System)+@carbon/icons-react、@carbon/ai-chat,字体 IBM Plex Sans - Sass 样式(
src/app.scss全局),Carbon 主题g10 - TypeScript strict 全量(
allowJs已关);API 类型引生成的src/types/api.d.ts(见gen:types脚本),不要手写接口类型 - 内置 i18n(
src/i18n:LanguageProvider + locales);状态层仅AuthContext,无外部状态库 - Node ≥ 20.19
脚本
| 脚本 | 命令 | 用途 |
|---|---|---|
dev | vite | 开发服务器(:5173) |
build | tsc --noEmit && vite build | 生产构建(含类型门禁) |
preview | vite preview | 预览构建产物 |
typecheck | tsc --noEmit ×2 | 类型门禁(必须全绿) |
gen:types | swagger → openapi-typescript | 后端契约变更后重新生成 src/types/api.d.ts |
本地运行
cd web
npm install
npm run dev # http://localhost:5173
/api 由 Vite dev-server 代理,目标取 VITE_API_PROXY_TARGET,默认 http://localhost:8080。
目录约定
src/ 按职责分包:auth/(api.ts 三助手 + AuthContext 唯一状态层)、components/(AppShell 等)、pages/(业务页面)、config/(路由表 appRoutes.tsx + 导航 navigation.ts;下游经 *.override.tsx 文件注入缝扩展,见 AGENTS.md)、i18n/、types/(生成的 API 类型)。页面与路由清单以代码为准,此处不逐项罗列。
鉴权
- 登录:
POST /api/auth/login→{token, user}存localStorage(键ocm.token);启动水合调GET /api/auth/me,401 弃 token,5xx/网络错误保留 token。 - 无 refresh token;会话中遇 401 不自动登出。
- token 每次请求附
Authorization: Bearer <token>,无全局拦截器。
权限(重要)
客户端只做可见性控制,不做安全边界:
- 登录响应携带
user.permissions,AuthContext暴露can(perm)(通配感知),侧边栏与按钮按can(...)门控。 - 没有路由级权限守卫——后端才是鉴权权威;新增管理功能必须在后端加权限校验。
- 权限/角色/用户组是数据而非代码:管理员可在控制台自定义,无需改前端。
数据导入页
支持 8 种导入类型与教务处拆分(契约见课表导入);有活动 job 时每 3 秒轮询。交互细节以 pages/ImportsPage.tsx 为准。
EdgeOne 部署
web/edgeone.json— SPA 重写规则。web/edge-functions/api/[[default]].js— 边缘函数反代/api/*到后端,origin 取context.env.API_ORIGIN(未设返回 502),并做尾斜杠规范化与 host 头清理。
Docker
Dockerfile(生产,多阶段):node:24-alpine构建,nginx:stable-alpine运行(:80);nginx 配置抽为web/nginx/default.conf(/api/代理到backend:8080+ SPA fallback),生产构建期注入VITE_ICP_NUMBER/VITE_DOCS_URL。Dockerfile.dev:node:24-alpine,:5173,npm run dev -- --host 0.0.0.0;源码由 compose 挂载。
环境变量
| 变量 | 读取处 | 用途 | 默认 |
|---|---|---|---|
VITE_API_PROXY_TARGET | vite.config.ts(Node 侧 process.env) | dev 下 /api 代理目标 | http://localhost:8080 |
VITE_ICP_NUMBER | import.meta.env(构建期内联) | 登录页底部备案号 | 空(不显示) |
VITE_DOCS_URL | import.meta.env(构建期内联) | 登录页「Docs」链接 | 空(隐藏) |
API_ORIGIN | EdgeOne 边缘函数 context.env | 反代的后端 origin | 无(未设 502) |
注意区分:VITE_API_PROXY_TARGET 是 Node 侧变量;VITE_ICP_NUMBER/VITE_DOCS_URL 是客户端内联变量;API_ORIGIN 是 EdgeOne 服务端变量。