feat(portal-shell): integrate next-intl + merge messages from teacher-portal (P1-4)
- Add next-intl v4.13.2 with cookie-based locale (no i18n routing) - Create src/i18n/request.ts reading NEXT_LOCALE cookie - Merge zh-CN/en messages from teacher-portal + add shell.dev.templates namespace - Wrap next.config.js with withNextIntl plugin (Turbopack resolveAlias) - Refactor RootLayout to async + NextIntlClientProvider + getLocale/getMessages - Replace ThemeI18nProvider with ThemeProvider (theme-only, i18n removed) - Remove locale/setLocale from PluginStore - Rework locale-switcher to useLocale/useTranslations + router.refresh - Update dev/templates page to use getTranslations (Server Component) - Fix WorkbenchPageShell test (loading prop + center instead of children) Verified: locale switch via NEXT_LOCALE cookie changes <html lang> and messages zh-CN: 保存/取消/切换侧栏 | en: Save/Cancel/Toggle sidebar typecheck 0 errors | lint 0 errors 2 warnings (generated) | vitest 231 passed
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
> 版本:3.0
|
||||
> 日期:2026-07-20
|
||||
> 状态:**P0 已完成 + P1-1/P1-2/P1-3 已完成(2026-07-22 验收)+ P1 进行中;架构审计完成 + 重设计方案定稿**
|
||||
> 状态:**P0 已完成 + P1-1/P1-2/P1-3/P1-4 已完成(2026-07-22 验收)+ P1 进行中;架构审计完成 + 重设计方案定稿**
|
||||
> 本文档地位:**portal-shell 前端工作的唯一权威指导文档**。所有后续 AI/人工在此模块的工作必须先读本文件,以其为准。
|
||||
>
|
||||
> 关联文档(按效力排序):
|
||||
@@ -757,7 +757,7 @@ export default async function ExamsPage(): Promise<React.ReactElement> {
|
||||
- **P0-7**:`eslint .` → 0 errors, 2 warnings(均在 `__generated__/types.ts` 生成文件);[eslint.config.js](file:///e:/Desktop/Edu/apps/portal-shell/eslint.config.js) 含 `no-restricted-imports`
|
||||
- **P0-8**:`git status` 干净(commit `cfb7b00`);`.env.local` 与 `tsconfig.tsbuildinfo` 已在 [.gitignore](file:///e:/Desktop/Edu/apps/portal-shell/.gitignore)
|
||||
|
||||
### P1 · 框架与数据源接通(1–2 周)— 进行中(P1-1/P1-2 ✅ 2026-07-22 验收)
|
||||
### P1 · 框架与数据源接通(1–2 周)— 进行中(P1-1/P1-2/P1-3/P1-4 ✅ 2026-07-22 验收)
|
||||
|
||||
**目标**:AppFrame + 导航 + 真实数据仪表盘 + 页面模板 + MSW + i18n,页面迁移的"流水线"建成。
|
||||
|
||||
@@ -766,7 +766,7 @@ export default async function ExamsPage(): Promise<React.ReactElement> {
|
||||
| P1-1 | `src/app/shell/layout.tsx` AppFrame(TopBar 静态挂载 + Sidebar 导航菜单 `navigation.ts` + 权限过滤) | 4 角色各见各菜单;导航项与 route-permissions 表一致(单测) | ✅ |
|
||||
| P1-2 | 仪表盘改接真实查询:`teacherDashboard`/`studentDashboard`/`parentDashboard`/`adminDashboard` + `warnings`/`errorBookStats` | 起全栈,4 角色仪表盘显示真实聚合数据(截图);widget 假契约查询(grades/homeworks/schedule/attendance/exams/announcements)全部下线或改造 | ✅ |
|
||||
| P1-3 | 页面模板四件套(list/detail/form/workbench)+ 三态规范 | Storybook 或示例页 4 张(/shell/dev/templates/*,仅 dev 可见;注:Next.js 私有文件夹 `_xxx` 不参与路由,故使用 `dev` 而非 `_dev`) | ✅ |
|
||||
| P1-4 | next-intl 接入 + messages 合并迁移 | 切换 locale 页面文案切换(截图);`useT` 自造函数删除 | ⏳ |
|
||||
| P1-4 | next-intl 接入 + messages 合并迁移 | 切换 locale 页面文案切换(截图);`useT` 自造函数删除 | ✅ |
|
||||
| P1-5 | MSW 兜底层(迁移旧 handlers,覆盖 dashboard/users/exams/grades 四域起步) | `NEXT_PUBLIC_MSW=1` 无后端启动,仪表盘 + users 页有数据(截图);生产构建 bundle 无 mocks | ⏳ |
|
||||
| P1-6 | 31 widget 令牌清债(271 处机械替换)+ `border border` 去重 + 未知类检测进 arch:scan | `grep -c "text-heading-\|mt-sm\|py-xs\|p-md" src/widgets` = 0;`pnpm lint:tokens` 通过 | ⏳ |
|
||||
| P1-7 | codegen 恢复 typescript-operations(config + data-ana 两域先行关闭 skipDocumentsValidation) | 生成操作级类型;lib/api 对应域删除手写 interface;typecheck 通过 | ⏳ |
|
||||
@@ -823,6 +823,27 @@ export default async function ExamsPage(): Promise<React.ReactElement> {
|
||||
- **单测**:`vitest run --reporter=verbose page-templates` → 19/19 passed(覆盖 4 个模板的三态、字段渲染、提交按钮禁用、errorSummary alert 等)
|
||||
- **质量校验**:`tsc --noEmit` 通过;`eslint src/shared/components/page-templates src/app/shell/dev src/shared/lib/route-permissions.ts` 通过;`vitest run` 全量 21 test files / 231 tests 全部通过(212 原有 + 19 新增)
|
||||
|
||||
**P1-4 验收证据(2026-07-22)**:
|
||||
|
||||
- **next-intl v4.13.2 接入(无 i18n 路由模式)**:
|
||||
- [next.config.js](file:///e:/Desktop/Edu/apps/portal-shell/next.config.js):`createNextIntlPlugin("./src/i18n/request.ts")` 包装 `nextConfig`,Turbopack resolveAlias 注入 `next-intl/config`
|
||||
- [src/i18n/request.ts](file:///e:/Desktop/Edu/apps/portal-shell/src/i18n/request.ts):`getRequestConfig` 从 `NEXT_LOCALE` cookie 读取 locale(缺省 `zh-CN`),动态 import 对应 messages JSON
|
||||
- [src/app/layout.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/app/layout.tsx):`async RootLayout` + `getLocale()` / `getMessages()` + `<NextIntlClientProvider>` 注入全局 messages;`<html lang={locale}>` 随 cookie 切换
|
||||
- **messages 合并迁移**:
|
||||
- [src/messages/zh-CN.json](file:///e:/Desktop/Edu/apps/portal-shell/src/messages/zh-CN.json):从 teacher-portal 合并 + 新增 `shell.dev.templates` 命名空间(title/description/list/detail/form/workbench 及其 listExample 等子键)
|
||||
- [src/messages/en.json](file:///e:/Desktop/Edu/apps/portal-shell/src/messages/en.json):与 zh-CN.json 结构完全对称
|
||||
- **自造 i18n 删除**:
|
||||
- [src/providers/ThemeI18nProvider.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/providers/ThemeI18nProvider.tsx) 已删除(含 `useT()` 函数 + `DEFAULT_MESSAGES` 常量)
|
||||
- [src/providers/ThemeProvider.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/providers/ThemeProvider.tsx):新建,仅保留主题切换(`usePluginStore(s => s.theme)` + `document.documentElement.classList` 切换 `.dark`)
|
||||
- [src/shell/PluginStore.ts](file:///e:/Desktop/Edu/apps/portal-shell/src/shell/PluginStore.ts):移除 `locale` / `setLocale` 字段
|
||||
- `grep -rn "useT(\|ThemeI18nProvider\|DEFAULT_MESSAGES" src` → 无匹配(自造函数全删除)
|
||||
- **locale-switcher 改造**:[src/widgets/topbar/locale-switcher/index.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/widgets/topbar/locale-switcher/index.tsx) 使用 `useLocale()` + `useTranslations()` + cookie 写入 + `router.refresh()` 触发 RSC 重新渲染
|
||||
- **dev/templates 页面演示**:[src/app/shell/dev/templates/page.tsx](file:///e:/Desktop/Edu/apps/portal-shell/src/app/shell/dev/templates/page.tsx) 使用 `getTranslations("shell.dev.templates")`(Server Component)
|
||||
- **locale 切换 HTTP 验证**(dev server `next dev --turbopack -p 4010`):
|
||||
- `GET /login`(无 cookie)→ `<html lang="zh-CN">` + `NextIntlClientProvider locale="zh-CN"` + 中文文案("保存"/"取消"/"切换侧栏")
|
||||
- `GET /login`(`Cookie: NEXT_LOCALE=en`)→ `<html lang="en">` + `NextIntlClientProvider locale="en"` + 英文文案("Save"/"Cancel"/"Toggle sidebar")
|
||||
- **质量校验**:`tsc --noEmit` 通过;`eslint src` → 0 errors, 2 warnings(`__generated__/types.ts` 生成文件);`vitest run` 全量 21 test files / 231 tests 全部通过
|
||||
|
||||
### P2 · 教师域页面(2–3 周,可与 P3 部分并行)
|
||||
|
||||
- 范围:§9.1 全表(~50 页)。顺序建议:exams → homework → grades → lesson-plans → questions/textbooks → attendance/classes/students → diagnostic/error-book/analytics → elective/course-plans → ai-* → practice/schedule-changes/leave。
|
||||
|
||||
Reference in New Issue
Block a user