Files
Edu/apps/teacher-portal/src/components/ParentPortalRemote.tsx
SpecialX d49d211425 feat(teacher-portal): 完成参考项目差距闭环 P3-P7 全量实现
- P3 考试/作业/成绩 mutation + 详情页 + 批改界面 + 乐观更新 + 多 Tab 同步
- P4 知识图谱 SVG 可视化 + 学情分析仪表盘 + parent-portal Remote
- P5 WebSocket 通知中心 + AI 出题(SSE) + AI 教案 + AI 学情报告
- P6 可观测性硬化:Sentry + WebVitals + OTel + A11y + 性能配置 + Cookie 迁移
- P7 参考项目差距闭环:新增 35 个页面覆盖 13 个缺失模块
  - attendance(考勤 4 页)/questions(题库)/textbooks(教材 2 页)
  - classes/[id] 详情 + classes/schedule 课表
  - course-plans(2 页)/diagnostic(2 页)/error-book/practice
  - exams/[id]/build 组卷 + exams/[id]/analytics 考后分析
  - exams/[id]/edit-rich 富文本编辑 + exams/[id]/proctoring 监考
  - grades/entry 批量录入 + grades/stats 统计 + grades/analytics 分析 + grades/report-card 报告卡
  - homework/submissions 列表 + assignments/[id]/submissions 批量批改
  - homework/submissions/[submissionId] 单份批改 + scan-grading 扫描批改
  - lesson-plans 编辑器 + library + calendar + heatmap 5 页
  - elective 选修课 3 页 /leave 请假 /schedule-changes 调课
- P7 基础设施:61 GraphQL operations + 5 handlers + 13 fixtures + 11 viewports
- 集成 browser.ts/server.ts 注册所有 p7 handlers(fallthrough 顺序)
- viewports.ts 扩展 11 个新导航项
- 验证:tsc --noEmit 零错误 + eslint 零错误
- 文档:workline.md 新增 §5 P7 参考项目差距闭环(含完整文件清单)
2026-07-13 14:27:04 +08:00

91 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
/**
* ParentPortalRemote - parent-portal MF Remote 接入组件
*
* 职责ARB-002 §2.3
* - NEXT_PUBLIC_MF_ENABLED=true通过 Module Federation 动态加载 parent-portal Remote
* - NEXT_PUBLIC_MF_ENABLED=false展示"需启用微前端模式"提示
* - 使用 next/dynamic 懒加载ssr: falseRemote 仅 CSR
* - ErrorBoundary 兜底Remote 加载/渲染失败时降级展示
*
* 维护者ai13teacher-portal
*/
import dynamic from "next/dynamic";
import { ErrorBoundary } from "@edu/ui-components";
const MF_ENABLED = process.env.NEXT_PUBLIC_MF_ENABLED === "true";
/** 动态加载 parent-portal Remote仅 CSR加载失败返回降级组件 */
const ParentRemote = dynamic(
() =>
import("parent/ParentApp")
.then((mod) => mod.default)
.catch(() => FallbackRemote),
{
ssr: false,
loading: () => (
<p className="text-sm text-ink-muted p-6"></p>
),
},
);
/** Remote 加载失败时的降级组件 */
function FallbackRemote(): React.ReactNode {
return (
<div className="p-8 text-center">
<p className="text-lg font-serif text-ink"></p>
<p className="mt-2 text-sm text-ink-muted">
parent-portal 4002 ParentApp
</p>
</div>
);
}
/** MF 未启用时的提示 */
function MfDisabledNotice(): React.ReactNode {
return (
<div className="p-8 border border-rule rounded-card bg-surface text-center">
<p className="text-lg font-serif text-ink">
</p>
<p className="mt-2 text-sm text-ink-muted">
NEXT_PUBLIC_MF_ENABLED=true
parent-portal next.config.js remotes
</p>
</div>
);
}
export default function ParentPortalRemote(): React.ReactNode {
if (!MF_ENABLED) {
return <MfDisabledNotice />;
}
return (
<ErrorBoundary
fallback={(error, reset) => (
<div
role="alert"
className="flex flex-col items-center justify-center gap-4 p-8"
>
<h2 className="text-lg font-serif text-ink">
</h2>
<p className="text-sm text-ink-muted">{error.message}</p>
<button
type="button"
onClick={reset}
className="px-4 py-2 text-sm text-ink-on-accent bg-accent rounded-button hover:bg-accent-hover"
>
</button>
</div>
)}
>
<ParentRemote />
</ErrorBoundary>
);
}