=test_update_homework_tests_and_work_log
Some checks failed
CI / build-deploy (push) Has been cancelled
Some checks failed
CI / build-deploy (push) Has been cancelled
This commit is contained in:
@@ -1,76 +0,0 @@
|
||||
# Auth UI Implementation Details
|
||||
|
||||
**Date**: 2025-12-23
|
||||
**Author**: Senior Frontend Engineer
|
||||
**Module**: Auth (`src/modules/auth`)
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述 (Overview)
|
||||
|
||||
本文档记录了登录 (`/login`) 和注册 (`/register`) 页面的前端实现细节。遵循 Vertical Slice Architecture 和 Pixel-Perfect UI 规范。
|
||||
|
||||
## 2. 架构设计 (Architecture)
|
||||
|
||||
### 2.1 目录结构
|
||||
所有认证相关的业务逻辑和组件均封装在 `src/modules/auth` 下,保持了高内聚。
|
||||
|
||||
```
|
||||
src/
|
||||
├── app/
|
||||
│ └── (auth)/ # 路由层 (Server Components)
|
||||
│ ├── layout.tsx # 统一的 AuthLayout 容器
|
||||
│ ├── login/page.tsx
|
||||
│ └── register/page.tsx
|
||||
│
|
||||
├── modules/
|
||||
│ └── auth/ # 业务模块
|
||||
│ └── components/ # 模块私有组件
|
||||
│ ├── auth-layout.tsx # 左右分屏布局
|
||||
│ ├── login-form.tsx # 登录表单 (Client Component)
|
||||
│ └── register-form.tsx # 注册表单 (Client Component)
|
||||
```
|
||||
|
||||
### 2.2 渲染策略
|
||||
* **Server Components**: 页面入口 (`page.tsx`) 和布局 (`layout.tsx`) 默认为服务端组件,负责元数据 (`Metadata`) 和静态结构渲染。
|
||||
* **Client Components**: 表单组件 (`*-form.tsx`) 标记为 `'use client'`,处理交互逻辑(状态管理、表单提交、Loading 状态)。
|
||||
|
||||
## 3. UI/UX 细节
|
||||
|
||||
### 3.1 布局 (Layout)
|
||||
采用 **Split Screen (分屏)** 设计:
|
||||
* **左侧 (Desktop Only)**:
|
||||
* 深色背景 (`bg-zinc-900`),强调品牌沉浸感。
|
||||
* 包含 Logo (`Next_Edu`) 和用户证言 (`Blockquote`)。
|
||||
* 使用 `hidden lg:flex` 实现响应式显隐。
|
||||
* **右侧**:
|
||||
* 居中对齐的表单容器。
|
||||
* 移动端优先 (`w-full`),桌面端限制最大宽度 (`sm:w-[350px]`)。
|
||||
|
||||
### 3.2 交互 (Interactions)
|
||||
* **Loading State**: 表单提交时按钮进入 `disabled` 状态并显示 `Loader2` 旋转动画。
|
||||
* **Micro-animations**:
|
||||
* 按钮 Hover 效果。
|
||||
* 链接 Hover 下划线 (`hover:underline`).
|
||||
* **Feedback**: 模拟了 3 秒的异步请求延迟,用于演示加载状态。
|
||||
|
||||
## 4. 错误处理 (Error Handling)
|
||||
|
||||
### 4.1 模块级错误边界
|
||||
* **Scoped Error Boundary**: `src/app/(auth)/error.tsx` 仅处理 Auth 模块内的运行时错误。
|
||||
* 显示友好的 "Authentication Error" 提示。
|
||||
* 提供 "Try again" 按钮重置状态。
|
||||
|
||||
### 4.2 模块级 404
|
||||
* **Scoped Not Found**: `src/app/(auth)/not-found.tsx` 处理 Auth 模块内的无效路径。
|
||||
* 引导用户返回 `/login` 页面,防止用户迷失。
|
||||
|
||||
## 5. 组件复用
|
||||
* 使用了 `src/shared/components/ui` 中的标准 Shadcn 组件:
|
||||
* `Button`, `Input`, `Label` (新增).
|
||||
* 图标库统一使用 `lucide-react`.
|
||||
|
||||
## 5. 后续计划 (Next Steps)
|
||||
* [ ] 集成 `next-auth` (Auth.js) 进行实际的身份验证。
|
||||
* [ ] 添加 Zod Schema 进行前端表单验证。
|
||||
* [ ] 对接后端 API (`src/modules/auth/actions.ts`).
|
||||
@@ -1,164 +0,0 @@
|
||||
# 学校基础数据模块(School)实现文档与更新记录
|
||||
|
||||
**日期**: 2026-01-07
|
||||
**作者**: Frontend Team
|
||||
**状态**: 已实现
|
||||
|
||||
## 1. 范围
|
||||
|
||||
本文档覆盖管理端「School」域的基础数据维护页面(Schools / Departments / Academic Year / Grades),并记录相关实现约束与关键更新,遵循 [003_frontend_engineering_standards.md](file:///c:/Users/xiner/Desktop/CICD/docs/architecture/003_frontend_engineering_standards.md) 的工程规范(Vertical Slice、Server/Client 边界、质量门禁)。
|
||||
|
||||
## 2. 路由入口(Admin)
|
||||
|
||||
School 域路由位于 `src/app/(dashboard)/admin/school/*`,均显式声明 `export const dynamic = "force-dynamic"` 以避免构建期预渲染触发数据库访问。
|
||||
|
||||
- `/admin/school`:入口重定向到 Classes(当前落点不在 `school` 模块内)
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/page.tsx)
|
||||
- `/admin/school/schools`:学校维护(增删改)
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/schools/page.tsx)
|
||||
- `/admin/school/departments`:部门维护(增删改)
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/departments/page.tsx)
|
||||
- `/admin/school/academic-year`:学年维护(增删改 + 设为当前学年)
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/academic-year/page.tsx)
|
||||
- `/admin/school/grades`:年级维护(增删改 + 指派年级组长/教研组长)
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/grades/page.tsx)
|
||||
- `/admin/school/grades/insights`:年级维度作业统计(跨班级聚合)
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/grades/insights/page.tsx)
|
||||
|
||||
## 3. 模块结构(Vertical Slice)
|
||||
|
||||
School 模块位于 `src/modules/school`:
|
||||
|
||||
```
|
||||
src/modules/school/
|
||||
├── components/
|
||||
│ ├── schools-view.tsx
|
||||
│ ├── departments-view.tsx
|
||||
│ ├── academic-year-view.tsx
|
||||
│ └── grades-view.tsx
|
||||
├── actions.ts
|
||||
├── data-access.ts
|
||||
├── schema.ts
|
||||
└── types.ts
|
||||
```
|
||||
|
||||
边界约束:
|
||||
- `data-access.ts` 包含 `import "server-only"`,仅用于服务端查询与 DTO 组装。
|
||||
- `actions.ts` 包含 `"use server"`,写操作统一通过 Server Actions 并 `revalidatePath`。
|
||||
- `components/*` 为 Client 交互层(表单、Dialog、筛选、行级操作),调用 Server Actions 并用 `sonner` toast 反馈。
|
||||
|
||||
## 4. 数据访问(data-access.ts)
|
||||
|
||||
实现:[data-access.ts](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/data-access.ts)
|
||||
|
||||
- `getSchools(): Promise<SchoolListItem[]>`
|
||||
- `getDepartments(): Promise<DepartmentListItem[]>`
|
||||
- `getAcademicYears(): Promise<AcademicYearListItem[]>`
|
||||
- `getGrades(): Promise<GradeListItem[]>`
|
||||
- join `schools` 获取 `school.name`
|
||||
- 收集 `gradeHeadId/teachingHeadId` 并批量查询 `users` 以组装 `StaffOption`
|
||||
- `getStaffOptions(): Promise<StaffOption[]>`
|
||||
- 角色过滤 `teacher/admin`
|
||||
- 排序 `name/email`,用于 Select 列表可用性
|
||||
- `getGradesForStaff(staffId: string): Promise<GradeListItem[]>`
|
||||
- 用于按负责人(年级组长/教研组长)反查关联年级
|
||||
|
||||
返回 DTO 类型定义位于:[types.ts](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/types.ts)
|
||||
|
||||
## 5. 写操作(actions.ts)
|
||||
|
||||
实现:[actions.ts](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/actions.ts)
|
||||
|
||||
通用约束:
|
||||
- 输入校验:统一使用 [schema.ts](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/schema.ts) 的 Zod schema
|
||||
- 返回结构:统一使用 [ActionState](file:///c:/Users/xiner/Desktop/CICD/src/shared/types/action-state.ts)
|
||||
- 刷新策略:对目标页面路径执行 `revalidatePath`
|
||||
|
||||
Departments:
|
||||
- `createDepartmentAction(formData)`
|
||||
- `updateDepartmentAction(departmentId, formData)`
|
||||
- `deleteDepartmentAction(departmentId)`
|
||||
|
||||
Academic Year:
|
||||
- `createAcademicYearAction(formData)`
|
||||
- `updateAcademicYearAction(academicYearId, formData)`
|
||||
- `deleteAcademicYearAction(academicYearId)`
|
||||
- 当 `isActive=true` 时,通过事务把其它学年置为非激活,保证唯一激活学年
|
||||
|
||||
Schools:
|
||||
- `createSchoolAction(formData)`
|
||||
- `updateSchoolAction(schoolId, formData)`
|
||||
- `deleteSchoolAction(schoolId)`
|
||||
- 删除后会同时刷新 `/admin/school/schools` 与 `/admin/school/grades`
|
||||
|
||||
Grades:
|
||||
- `createGradeAction(formData)`
|
||||
- `updateGradeAction(gradeId, formData)`
|
||||
- `deleteGradeAction(gradeId)`
|
||||
|
||||
## 6. UI 组件(components/*)
|
||||
|
||||
Schools:
|
||||
- 实现:[schools-view.tsx](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/components/schools-view.tsx)
|
||||
- 交互:列表 + Dialog 表单(新增/编辑)+ 删除确认(AlertDialog)
|
||||
|
||||
Departments:
|
||||
- 实现:[departments-view.tsx](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/components/departments-view.tsx)
|
||||
- 交互:列表 + Dialog 表单(新增/编辑)+ 删除确认(AlertDialog)
|
||||
|
||||
Academic Year:
|
||||
- 实现:[academic-year-view.tsx](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/components/academic-year-view.tsx)
|
||||
- 交互:列表 + Dialog 表单(新增/编辑)+ 删除确认(AlertDialog)+ 设为当前学年(isActive)
|
||||
|
||||
Grades:
|
||||
- 实现:[grades-view.tsx](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/components/grades-view.tsx)
|
||||
- 交互:列表展示 + URL 驱动筛选(搜索/学校/负责人/排序)+ Dialog 表单(新增/编辑)+ 删除确认(AlertDialog)
|
||||
- 负责人指派:
|
||||
- 年级组长(gradeHeadId)
|
||||
- 教研组长(teachingHeadId)
|
||||
|
||||
## 7. 关键交互与规则(Grades)
|
||||
|
||||
页面入口(RSC 组装)在服务端并发拉取三类数据:
|
||||
- 年级列表:`getGrades()`
|
||||
- 学校选项:`getSchools()`
|
||||
- 负责人候选:`getStaffOptions()`
|
||||
|
||||
实现:[page.tsx](file:///c:/Users/xiner/Desktop/CICD/src/app/(dashboard)/admin/school/grades/page.tsx)
|
||||
|
||||
### 7.1 URL State(筛选/排序)
|
||||
|
||||
Grades 列表页的筛选状态 URL 化(`nuqs`):
|
||||
- `q`:关键字(匹配 grade/school)
|
||||
- `school`:学校过滤(`all` 或具体 schoolId)
|
||||
- `head`:负责人过滤(全部 / 两者缺失 / 缺年级组长 / 缺教研组长)
|
||||
- `sort`:排序(默认/名称/更新时间等)
|
||||
|
||||
实现:[grades-view.tsx](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/components/grades-view.tsx)
|
||||
|
||||
### 7.2 表单校验
|
||||
|
||||
Grades 的新增/编辑表单在客户端做轻量校验:
|
||||
- 必填:`schoolId`、`name`
|
||||
- `order`:非负整数
|
||||
- 去重:同一学校下年级名称不允许重复(忽略大小写 + 规范化空格)
|
||||
|
||||
说明:
|
||||
- 服务端写入前仍会经过 `UpsertGradeSchema` 校验(schema.ts),避免仅依赖客户端校验。
|
||||
|
||||
### 7.3 负责人选择(Radix Select)
|
||||
|
||||
Radix Select 约束:`SelectItem` 的 `value` 不能为 `""`(空字符串),否则会触发运行时错误。
|
||||
|
||||
当前实现策略:
|
||||
- UI 中 “未设置” 选项使用占位值 `__none__`
|
||||
- 在 `onValueChange` 中将 `__none__` 映射回 `""` 存入本地表单 state
|
||||
- 提交时依旧传递空字符串,由 `UpsertGradeSchema` 将其归一为 `null`
|
||||
|
||||
实现:[grades-view.tsx](file:///c:/Users/xiner/Desktop/CICD/src/modules/school/components/grades-view.tsx)
|
||||
|
||||
## 2. 更新记录(2026-01-07)
|
||||
|
||||
- 修复 Add Grades 弹窗报错:将 4 处 `<SelectItem value=\"\">` 替换为占位值 `__none__`,并在 `onValueChange` 中映射回 `\"\"`,保持“可清空选择/显示 placeholder”的行为不变。
|
||||
- 修复新建年级按钮不可用:创建/编辑表单在状态变化时触发实时校验更新,避免校验状态滞后导致提交被禁用。
|
||||
- 质量门禁:本地通过 `npm run lint` 与 `npm run typecheck`。
|
||||
@@ -242,6 +242,35 @@
|
||||
|
||||
- **目的**: 创建考试基础信息。
|
||||
- **关键组件**: `ExamForm`
|
||||
- **AI 生成执行逻辑**:
|
||||
- **入口**:
|
||||
- 选择 `Assembly Mode` 为 `AI Generation`
|
||||
- 表单增加 `aiQuestionCount` 与 `aiPrompt`,提交时走 `createAiExamAction`
|
||||
- **请求数据组装**:
|
||||
- 复用基础字段:`title`、`subject`、`grade`、`difficulty`、`totalScore`、`durationMin`、`scheduledAt`
|
||||
- 可选字段:`aiQuestionCount`、`aiPrompt`
|
||||
- **服务端校验**:
|
||||
- `AiExamCreateSchema` 校验基础字段与 AI 字段
|
||||
- 解析失败直接返回 `Invalid form data`
|
||||
- **AI 调用**:
|
||||
- 通过 `createAiChatCompletion` 发送系统提示与用户输入
|
||||
- 使用 `env.AI_MODEL`,默认 `gpt-4o-mini`
|
||||
- 期望输出 JSON,仅包含 `sections` 或 `questions`
|
||||
- **响应解析**:
|
||||
- `extractJson` 支持从纯 JSON 或代码块中提取
|
||||
- `AiExamResponseSchema` 校验题型与字段结构
|
||||
- 无题目返回 `AI returned no questions`
|
||||
- **题目裁剪与分值归一化**:
|
||||
- 若设置题量,按顺序裁剪题目或分组
|
||||
- `normalizeScores` 按 `totalScore` 归一化各题分值
|
||||
- **题目落库**:
|
||||
- 将 AI 题目转换为题库格式 `{ text, options }`
|
||||
- 写入 `questions` 表,并记录 `authorId`
|
||||
- **结构与关联写入**:
|
||||
- 生成 `structure`(按分组或平铺题目)
|
||||
- 写入 `exams` 表,同时写入 `exam_questions`
|
||||
- **后续跳转**:
|
||||
- 创建成功后跳转 `/teacher/exams/[id]/build` 继续编辑
|
||||
|
||||
### 3.17 组卷 `/teacher/exams/[id]/build`
|
||||
实现:[exams/[id]/build/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/teacher/exams/%5Bid%5D/build/page.tsx)
|
||||
|
||||
154
docs/design/010_qa_test_plan_and_feedback.md
Normal file
154
docs/design/010_qa_test_plan_and_feedback.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# 项目全量测试方案与执行反馈
|
||||
|
||||
**日期**: 2026-03-18
|
||||
**角色**: 首席测试师
|
||||
**范围**: `src/app` 页面路由、`src/modules` 业务模块、`src/app/api` 接口路由、工程质量门禁
|
||||
|
||||
---
|
||||
|
||||
## 1. 测试目标
|
||||
|
||||
- 建立一份可复用的全量测试方案,覆盖核心业务与工程质量门禁。
|
||||
- 对当前代码库执行可落地的全量检查,输出可追溯反馈。
|
||||
- 明确已验证范围、未验证范围、风险与后续建议。
|
||||
|
||||
---
|
||||
|
||||
## 2. 测试对象与覆盖边界
|
||||
|
||||
### 2.1 业务域
|
||||
|
||||
- 认证与会话:登录/注册、会话注入、路由守卫
|
||||
- 教师端:工作台、班级、作业、考试、题库、教材
|
||||
- 学生端:仪表盘、课程、作业、教材、课表
|
||||
- 管理端:学校、年级、班级、部门、学年、洞察
|
||||
- 家长端:仪表盘
|
||||
- 设置与个人资料
|
||||
|
||||
### 2.2 技术域
|
||||
|
||||
- 页面路由编译与渲染入口(`src/app/**/page.tsx`)
|
||||
- API 路由编译与入口(`src/app/api/**/route.ts`)
|
||||
- 业务模块(`src/modules/**`)
|
||||
- 类型系统与静态检查(TypeScript + ESLint)
|
||||
- 生产构建可通过性(Next.js build)
|
||||
|
||||
### 2.3 本次可执行边界说明
|
||||
|
||||
- 已执行:静态与构建级全量验证(lint、typecheck、build)。
|
||||
- 已执行:页面路由与 API 路由清单级覆盖核对(基于代码库现状)。
|
||||
- 未执行:依赖真实数据库与外部 AI 服务的端到端交互验证(当前环境未提供专用测试库与固定测试账号)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 测试策略
|
||||
|
||||
### 3.1 质量门禁(必须通过)
|
||||
|
||||
1. ESLint 静态规范检查
|
||||
2. TypeScript 类型检查
|
||||
3. Next.js 生产构建
|
||||
|
||||
### 3.2 全量覆盖策略(按层)
|
||||
|
||||
1. 路由层:统计并核对全部页面与 API 路由入口文件是否可参与编译
|
||||
2. 业务层:通过构建期依赖解析与类型系统覆盖模块间调用链
|
||||
3. 集成层:以 `next build` 验证服务端组件、路由结构、导入关系、打包一致性
|
||||
4. 回归层:输出缺口与风险,给出后续补测清单
|
||||
|
||||
### 3.3 通过标准
|
||||
|
||||
- `npm run lint` 退出码为 0
|
||||
- `npm run typecheck` 退出码为 0
|
||||
- `npm run build` 退出码为 0
|
||||
- 无新增阻断级缺陷(Blocker/Critical)
|
||||
|
||||
---
|
||||
|
||||
## 4. 测试用例总表(主干)
|
||||
|
||||
| 用例ID | 级别 | 用例名称 | 执行方式 | 通过标准 |
|
||||
|---|---|---|---|---|
|
||||
| QA-GATE-001 | P0 | 代码规范检查 | `npm run lint` | 命令成功退出 |
|
||||
| QA-GATE-002 | P0 | 类型系统检查 | `npm run typecheck` | 命令成功退出 |
|
||||
| QA-GATE-003 | P0 | 生产构建检查 | `npm run build` | 构建成功 |
|
||||
| QA-ROUTE-001 | P0 | 页面路由入口覆盖 | 路由文件清单核对 | 页面入口均存在 |
|
||||
| QA-API-001 | P0 | API 路由入口覆盖 | 路由文件清单核对 | API 入口均存在 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 路由覆盖清单(本次统计)
|
||||
|
||||
### 5.1 页面路由入口
|
||||
|
||||
- 共统计 `46` 个页面入口文件(`src/app/**/page.tsx`)。
|
||||
- 覆盖角色:认证、教师、学生、管理端、家长、通用页面。
|
||||
|
||||
### 5.2 API 路由入口
|
||||
|
||||
- 共统计 `4` 个 API 入口文件(`src/app/api/**/route.ts`)。
|
||||
- 覆盖接口:`auth`、`ai/chat`、`onboarding/status`、`onboarding/complete`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 执行记录与反馈
|
||||
|
||||
### 6.1 执行环境
|
||||
|
||||
- 操作系统:Windows
|
||||
- 项目目录:`E:\Desktop\CICD`
|
||||
- 包管理器:npm
|
||||
|
||||
### 6.2 结果总览
|
||||
|
||||
| 检查项 | 命令 | 结果 | 备注 |
|
||||
|---|---|---|---|
|
||||
| 代码规范 | `npm run lint` | 通过 | 退出码 0 |
|
||||
| 类型检查 | `npm run typecheck` | 通过 | 退出码 0 |
|
||||
| 生产构建 | `npm run build` | 通过 | 退出码 0,构建期间出现 baseline-browser-mapping 数据过期提示 |
|
||||
| 接口集成测试 | `npm run test:integration` | 通过 | 3 个测试文件,10 条用例通过 |
|
||||
| E2E 冒烟测试 | `npm run test:e2e:smoke` | 通过 | 本地优先使用系统 Chrome,2 条用例通过 |
|
||||
| E2E 全路由回归 | `npm run test:e2e:full-routes` | 通过 | 38 条用例通过,覆盖静态页面路由守卫与可达性 |
|
||||
|
||||
### 6.3 缺陷与风险
|
||||
|
||||
- 阻断级缺陷:0
|
||||
- 严重缺陷:0
|
||||
- 主要风险:跨角色真实业务数据写入链路仍需测试库与固定账号支撑,当前已完成路由级全覆盖回归。
|
||||
- 次要风险:构建日志出现 `baseline-browser-mapping` 数据过期提示,建议在依赖维护窗口升级该依赖数据包。
|
||||
|
||||
### 6.4 结论
|
||||
|
||||
- 当前代码库在静态检查、类型系统与生产构建三道门禁均通过,可进入下一阶段联调或发布候选流程。
|
||||
- 本次已完成企业级测试基线的第一阶段落地:集成测试框架、E2E 框架、CI 质量门禁已接入。
|
||||
- 本次已完成“代码级全量可构建性 + API 集成验证”并通过,未发现新增回归错误。
|
||||
- 若要达到“发布级全链路验收”,仍需补充测试库与固定账号下的完整业务 E2E 场景。
|
||||
|
||||
---
|
||||
|
||||
## 7. 后续补测计划
|
||||
|
||||
- 增加端到端测试(Playwright)覆盖关键教师流:创建考试 → 派发作业 → 提交批改。
|
||||
- 增加 API 集成测试(鉴权、参数校验、错误码)。
|
||||
- 增加数据层测试(测试库 + 回滚策略)验证查询过滤与 RBAC 边界。
|
||||
|
||||
---
|
||||
|
||||
## 8. 企业级实现落地清单(本次新增)
|
||||
|
||||
- 测试基础设施:
|
||||
- 新增 Vitest 配置:`vitest.config.ts`
|
||||
- 新增 Playwright 配置:`playwright.config.ts`
|
||||
- 新增集成测试初始化:`tests/setup/integration.setup.ts`
|
||||
- 集成测试用例:
|
||||
- `tests/integration/api-ai-chat.route.test.ts`
|
||||
- `tests/integration/api-onboarding-status.route.test.ts`
|
||||
- `tests/integration/api-onboarding-complete.route.test.ts`
|
||||
- E2E 冒烟用例:
|
||||
- `tests/e2e/smoke-auth.spec.ts`
|
||||
- E2E 全路由回归用例:
|
||||
- `tests/e2e/full-route-regression.spec.ts`
|
||||
- 工程脚本:
|
||||
- `package.json` 新增 `test`、`test:ci`、`test:integration`、`test:e2e`、`test:e2e:smoke`、`test:e2e:full-routes`
|
||||
- CI 门禁:
|
||||
- `.gitea/workflows/ci.yml` 新增 Playwright Chromium 安装、集成测试、E2E 全量回归测试步骤
|
||||
@@ -1,261 +0,0 @@
|
||||
# Next_Edu Design System Specs
|
||||
|
||||
**Version**: 1.4.0 (Updated)
|
||||
**Status**: ACTIVE
|
||||
**Role**: Chief Creative Director
|
||||
**Philosophy**: "Data as Art" - Clean, Minimalist, Information-Dense.
|
||||
|
||||
---
|
||||
|
||||
## 1. 核心理念 (Core Philosophy)
|
||||
|
||||
Next_Edu 旨在对抗教育系统常见的信息过载。我们的设计风格深受 **International Typographic Style (国际主义设计风格)** 影响。
|
||||
|
||||
* **Precision (精准)**: 每一个像素的留白都有其目的。
|
||||
* **Clarity (清晰)**: 通过排版和对比度区分层级,而非装饰性的色块。
|
||||
* **Efficiency (效率)**: 专为高密度数据操作优化,减少视觉噪音。
|
||||
|
||||
---
|
||||
|
||||
## 2. 视觉基础 (Visual Foundation)
|
||||
|
||||
### 2.1 色彩系统 (Color System)
|
||||
|
||||
我们放弃 Hex 直选,全面采用 **HSL 语义化变量** 以支持完美的多主题适配。
|
||||
|
||||
#### **Base (基调)**
|
||||
* **Neutral**: Zinc (锌色). 冷峻、纯净,无偏色。
|
||||
* **Brand**: Deep Indigo (深靛蓝).
|
||||
* `Primary`: 专业、权威,避免幼稚的高饱和蓝。
|
||||
* 语义: `hsl(var(--primary))`
|
||||
|
||||
#### **Functional (功能色)**
|
||||
| 语义 | 色系 | 用途 |
|
||||
| :--- | :--- | :--- |
|
||||
| **Destructive** | Red | 删除、危险操作、系统错误 |
|
||||
| **Warning** | Amber | 需注意的状态、非阻断性警告 |
|
||||
| **Success** | Emerald | 操作成功、状态正常 |
|
||||
| **Info** | Blue | 一般性提示、帮助信息 |
|
||||
|
||||
#### **Surface Hierarchy (层级)**
|
||||
1. **Background**: 应用底层背景。
|
||||
2. **Card**: 内容承载容器,轻微提升层级。
|
||||
3. **Popover**: 悬浮层、下拉菜单,最高层级。
|
||||
4. **Muted**: 用于次级信息或禁用状态背景。
|
||||
|
||||
### 2.2 排版 (Typography)
|
||||
|
||||
* **Font Family**: `Geist Sans` > `Inter` > `System UI`.
|
||||
* *Requirement*: 必须开启 `tabular-nums` (等宽数字) 特性,确保表格数据对齐。
|
||||
* **Scale**:
|
||||
* **Base Body**: 14px (0.875rem) - 提升信息密度。
|
||||
* **H1 (Page Title)**: 24px, Tracking -0.02em, Weight 600.
|
||||
* **H2 (Section Title)**: 20px, Tracking -0.01em, Weight 600.
|
||||
* **H3 (Card Title)**: 16px, Weight 600.
|
||||
* **Tiny/Caption**: 12px, Text-Muted-Foreground.
|
||||
|
||||
### 2.3 质感 (Look & Feel)
|
||||
|
||||
* **Borders**: `1px solid var(--border)`. 界面骨架,以此分割区域而非背景色块。
|
||||
* **Radius**:
|
||||
* `sm` (4px): Badges, Checkboxes.
|
||||
* `md` (8px): **Default**. Buttons, Inputs, Cards.
|
||||
* `lg` (12px): Modals, Dialogs.
|
||||
* **Shadows**:
|
||||
* Default: None (Flat).
|
||||
* Hover: `shadow-sm` (仅用于可交互元素).
|
||||
* Dropdown/Popover: `shadow-md`.
|
||||
* *Ban*: 禁止使用大面积弥散阴影。
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心布局 (App Shell)
|
||||
|
||||
### 3.1 架构 (Architecture)
|
||||
我们采用了 `SidebarProvider` + `AppSidebar` 的组合模式,确保了布局的灵活性和移动端的完美适配。
|
||||
|
||||
* **Provider**: `SidebarProvider` (src/modules/layout/components/sidebar-provider.tsx)
|
||||
* 管理侧边栏状态 (`expanded`, `isMobile`).
|
||||
* 负责在移动端渲染 Sheet (Drawer)。
|
||||
* 负责在桌面端渲染 Sticky Sidebar。
|
||||
* **Key Prop**: `sidebar` (显式传递侧边栏组件)。
|
||||
|
||||
### 3.2 布局结构
|
||||
```
|
||||
+-------------------------------------------------------+
|
||||
| Sidebar | Header (Sticky) |
|
||||
| |-------------------------------------------|
|
||||
| (Collap- | Main Content |
|
||||
| sible) | |
|
||||
| | +-------------------------------------+ |
|
||||
| | | Card | |
|
||||
| | | +---------------------------------+ | |
|
||||
| | | | Data Table | | |
|
||||
| | | +---------------------------------+ | |
|
||||
| | +-------------------------------------+ |
|
||||
| | |
|
||||
+-------------------------------------------------------+
|
||||
```
|
||||
|
||||
### 3.3 详细规范
|
||||
|
||||
#### **Sidebar (侧边栏)**
|
||||
* **Width**: Expanded `260px` | Collapsed `64px` | Mobile `Sheet (Drawer)`.
|
||||
* **Behavior**:
|
||||
* Desktop: 固定左侧,支持折叠。
|
||||
* Mobile: 默认隐藏,点击汉堡菜单从左侧滑出。
|
||||
* **Navigation Item**:
|
||||
* Height: `36px` (Compact).
|
||||
* State:
|
||||
* `Inactive`: `text-muted-foreground hover:text-foreground`.
|
||||
* `Active`: `bg-sidebar-accent text-sidebar-accent-foreground font-medium`.
|
||||
|
||||
#### **Header (顶栏)**
|
||||
* **Height**: `64px` (h-16).
|
||||
* **Layout**: `flex items-center justify-between px-6 border-b`.
|
||||
* **Components**:
|
||||
1. **Breadcrumb**: 动态路径导航 (Dynamic Breadcrumb).
|
||||
* **Implementation**: 基于 `usePathname()` 自动解析路由段。
|
||||
* **Mapping**: 通过 `NAV_CONFIG` 或 `BREADCRUMB_MAP` 映射路径到友好标题 (e.g., `/teacher/textbooks` -> "Textbooks").
|
||||
* **Filtering**: 自动过滤根角色路径 (e.g., `/teacher`) 以保持简洁。
|
||||
2. **Global Search**: `Cmd+K` 触发,居中或靠右。
|
||||
3. **User Nav**: 头像 + 下拉菜单。
|
||||
|
||||
#### **Main Content (内容区)**
|
||||
* **Padding**: `p-6` (Desktop) / `p-4` (Mobile).
|
||||
* **Max Width**: `max-w-[1600px]` (默认) 或 `w-full` (针对超宽报表)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 导航与角色系统 (Navigation & Roles)
|
||||
|
||||
Next_Edu 支持多角色(Multi-Tenant / Role-Based)导航系统。
|
||||
|
||||
### 4.1 配置文件
|
||||
导航结构已从 UI 组件中解耦,统一配置在:
|
||||
`src/modules/layout/config/navigation.ts`
|
||||
|
||||
### 4.2 支持的角色 (Roles)
|
||||
系统内置支持以下角色,每个角色拥有独立的侧边栏菜单结构:
|
||||
* **Admin**: 系统管理员,拥有所有管理权限 (School Management, User Management, Finance)。
|
||||
* **Teacher**: 教师,关注班级管理 (My Classes)、成绩录入 (Gradebook) 和日程。
|
||||
* **Student**: 学生,关注课程学习 (My Learning) 和作业提交。
|
||||
* **Parent**: 家长,关注子女动态和学费缴纳。
|
||||
|
||||
### 4.3 开发与调试
|
||||
* **View As (Dev Mode)**: 在开发环境下,侧边栏顶部提供 "View As" 下拉菜单,允许开发者实时切换角色视角,预览不同角色的导航结构。
|
||||
* **Implementation**: `AppSidebar` 组件通过读取 `NAV_CONFIG[currentRole]` 动态渲染菜单项。
|
||||
|
||||
---
|
||||
|
||||
## 5. 错误处理与边界情况 (Error Handling & Boundaries)
|
||||
|
||||
系统必须优雅地处理错误和边缘情况,避免白屏或无反馈。
|
||||
|
||||
### 5.1 全局错误边界 (Global Error Boundary)
|
||||
* **Scope**: 捕获渲染期间的未处理异常。
|
||||
* **UI**: 显示友好的错误页面(非技术堆栈信息),提供 "Try Again" 按钮重置状态。
|
||||
* **Implementation**: 使用 React `ErrorBoundary` 或 Next.js `error.tsx`。
|
||||
|
||||
### 5.2 404 Not Found
|
||||
* **Design**: 必须保留 App Shell (Sidebar + Header),仅在 Main Content 区域显示 404 提示。
|
||||
* **Content**: "Page not found" 文案 + 返回 Dashboard 的主操作按钮。
|
||||
|
||||
### 5.3 空状态 (Empty States)
|
||||
当列表或表格无数据时,**严禁**只显示空白。
|
||||
* **Component**: `EmptyState`。
|
||||
* **Composition**:
|
||||
1. **Icon**: 线性风格图标 (muted foreground).
|
||||
2. **Title**: 简短说明 (e.g., "No students found").
|
||||
3. **Description**: 解释原因或下一步操作 (e.g., "Add a student to get started").
|
||||
4. **Action**: (可选) "Create New" 按钮。
|
||||
|
||||
### 5.4 加载状态 (Loading States)
|
||||
* **Initial Load**: 使用 `Skeleton` 骨架屏,模拟内容布局,避免 CLS (Content Layout Shift)。禁止使用全屏 Spinner。
|
||||
* **Action Loading**: 按钮点击后进入 `disabled` + `spinner` 状态。
|
||||
* **Table Loading**: 表格内容区域显示 3-5 行 Skeleton Rows。
|
||||
|
||||
### 5.5 表单验证 (Form Validation)
|
||||
* **Style**: 错误信息显示在输入框下方,字号 `text-xs`,颜色 `text-destructive`。
|
||||
* **Input**: 边框变红 (`border-destructive`)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 职责边界与协作 (Responsibility Boundaries)
|
||||
|
||||
**[IMPORTANT] 严禁越界修改 (Strict No-Modification Policy)**
|
||||
|
||||
为了维护大型项目的可维护性,UI 工程师和开发人员必须遵守以下边界规则:
|
||||
|
||||
### 6.1 模块化原则 (Modularity)
|
||||
* **Scope**: 开发者仅应对分配给自己的模块负责。例如,负责 "Dashboard" 的开发者**不应**修改 "Sidebar" 或 "Auth" 模块的代码。
|
||||
* **Dependencies**: 如果你的模块依赖于其他模块的变更,**必须**先与该模块的负责人沟通,或在 PR 中明确标注。
|
||||
|
||||
### 6.2 共享组件 (Shared Components)
|
||||
* **Immutable Core**: `src/shared/components/ui` 下的基础组件(如 Button, Card)视为**核心库**。
|
||||
* **Extension**: 如果基础组件不能满足需求,优先考虑组合(Composition)或创建新的业务组件,而不是修改核心组件的源码。
|
||||
* **Modification Request**: 只有在发现严重 Bug 或需要全局样式调整时,才允许修改核心组件,且必须经过 Design Lead 审批。
|
||||
|
||||
### 6.3 样式一致性 (Consistency)
|
||||
* **Global CSS**: `globals.css` 定义了系统的物理法则。严禁在局部组件中随意覆盖全局 CSS 变量。
|
||||
* **Tailwind Config**: 禁止随意在组件中添加任意值(Arbitrary Values, e.g., `w-[123px]`),必须使用 Design Token。
|
||||
|
||||
---
|
||||
|
||||
## 7. 组件设计规范 (Component Specs)
|
||||
|
||||
### 7.1 Card (卡片)
|
||||
卡片是信息组织的基本单元。
|
||||
* **Class**: `bg-card text-card-foreground border rounded-lg shadow-none`.
|
||||
* **Header**: `p-6 pb-2`. Title (`font-semibold leading-none tracking-tight`).
|
||||
* **Content**: `p-6 pt-0`.
|
||||
|
||||
### 7.2 Data Table (数据表格)
|
||||
教务系统的核心组件。
|
||||
* **Density**:
|
||||
* `Default`: Row Height `48px` (h-12).
|
||||
* `Compact`: Row Height `36px` (h-9).
|
||||
* **Header**: `bg-muted/50 text-muted-foreground text-xs uppercase font-medium`.
|
||||
* **Stripes**: 默认关闭。仅在列数 > 8 时开启 `even:bg-muted/50`。
|
||||
* **Actions**: 行操作按钮应默认隐形 (`opacity-0`),Hover 时显示 (`group-hover:opacity-100`),减少视觉干扰。
|
||||
|
||||
### 7.3 Feedback (反馈与通知)
|
||||
* **Toast**: 使用 `Sonner` 组件。
|
||||
* 位置: 默认右下角 (Bottom Right).
|
||||
* 样式: 极简黑白风格 (跟随主题),支持撤销操作。
|
||||
* 调用: `toast("Event has been created", { description: "Sunday, December 03, 2023 at 9:00 AM" })`.
|
||||
* **Skeleton**: 加载状态必须使用 Skeleton 骨架屏,禁止使用全屏 Spinner。
|
||||
* **Badge**: 状态指示器。
|
||||
* `default`: 主要状态 (Primary).
|
||||
* `secondary`: 次要状态 (Neutral).
|
||||
* `destructive`: 错误/警告状态 (Error).
|
||||
* `outline`: 描边风格 (Subtle).
|
||||
|
||||
---
|
||||
|
||||
## 8. 开发指南 (Developer Guide)
|
||||
|
||||
### 8.1 CSS Variables
|
||||
所有颜色和圆角均通过 CSS 变量控制,定义在 `globals.css` 中。禁止在代码中 Hardcode 颜色值 (如 `#FFFFFF`, `rgb(0,0,0)` )。
|
||||
|
||||
### 8.2 Tailwind Utility 优先
|
||||
优先使用 Tailwind Utility Classes。
|
||||
* ✅ `text-sm text-muted-foreground`
|
||||
* ❌ `.custom-text-class { font-size: 14px; color: #666; }`
|
||||
|
||||
### 8.3 Dark Mode
|
||||
设计系统原生支持深色模式。只要正确使用语义化颜色变量(如 `bg-background`, `text-foreground`),Dark Mode 将自动完美适配,无需额外编写 `dark:` 修饰符(除非为了特殊调整)。
|
||||
|
||||
### 8.4 组件库引用
|
||||
所有 UI 组件位于 `src/shared/components/ui`。
|
||||
* `Button`: 基础按钮
|
||||
* `Input`: 输入框
|
||||
* `Select`: 下拉选择器 (New)
|
||||
* `Sheet`: 侧边栏/抽屉
|
||||
* `Sonner`: Toast 通知
|
||||
* `Badge`: 徽章/标签
|
||||
* `Skeleton`: 加载占位符
|
||||
* `DropdownMenu`: 下拉菜单
|
||||
* `Avatar`: 头像
|
||||
* `Label`: 表单标签
|
||||
* `EmptyState`: 空状态占位 (New)
|
||||
Reference in New Issue
Block a user