更新
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<mxfile host="65bd71144e">
|
||||
<diagram id="multi-role-flow-ai" name="数据流图(多角色)">
|
||||
<mxGraphModel dx="1312" dy="773" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2800" pageHeight="1800" math="0" shadow="0">
|
||||
<mxGraphModel dx="1303" dy="773" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="2800" pageHeight="1800" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
@@ -10,16 +10,16 @@
|
||||
<mxCell id="3" value="入口:微信小程序/React 后台;主链路:Java服务编排 -> Python AI子服务(OCR/LLM/ASR) -> PostgreSQL/Redis/对象存储/Milvus/NebulaGraph(Neo4j);同步调度支持 REST/JAR" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;fontSize=13;fontColor=#666666;" parent="1" vertex="1">
|
||||
<mxGeometry x="30" y="52" width="1850" height="24" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="4" value="角色区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#d0d0d0;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#666666;" vertex="1" parent="1">
|
||||
<mxCell id="4" value="角色区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#d0d0d0;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#666666;" parent="1" vertex="1">
|
||||
<mxGeometry x="20" y="120" width="220" height="620" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="5" value="业务流程区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#edf4ff;strokeColor=#c0d7f2;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#4a6b8a;" vertex="1" parent="1">
|
||||
<mxGeometry x="90" y="100" width="790" height="1070" as="geometry"/>
|
||||
<mxCell id="5" value="业务流程区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#edf4ff;strokeColor=#c0d7f2;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#4a6b8a;" parent="1" vertex="1">
|
||||
<mxGeometry x="70" y="100" width="790" height="1070" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="6" value="AI 服务区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff7e6;strokeColor=#e9cf9a;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#8a6d3b;" vertex="1" parent="1">
|
||||
<mxCell id="6" value="AI 服务区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff7e6;strokeColor=#e9cf9a;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#8a6d3b;" parent="1" vertex="1">
|
||||
<mxGeometry x="860" y="240" width="420" height="860" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="7" value="数据存储区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f7f7f7;strokeColor=#cfcfcf;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#666666;" vertex="1" parent="1">
|
||||
<mxCell id="7" value="数据存储区" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f7f7f7;strokeColor=#cfcfcf;dashed=1;align=left;verticalAlign=top;spacingLeft=8;spacingTop=6;fontSize=12;fontColor=#666666;" parent="1" vertex="1">
|
||||
<mxGeometry x="1340" y="90" width="370" height="1480" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="10" value="学生" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontSize=15;fontStyle=1;" parent="1" vertex="1">
|
||||
@@ -148,8 +148,11 @@
|
||||
<mxCell id="100" value="用户/权限" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;endFill=1;strokeColor=#666666;" parent="1" source="20" target="60" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="101" value="作业/提交" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;endFill=1;strokeColor=#666666;" parent="1" source="21" target="61" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
<mxCell id="101" value="作业/提交" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;endFill=1;strokeColor=#666666;" parent="1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="580" y="322" as="sourcePoint"/>
|
||||
<mxPoint x="1360" y="305" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="102" value="批改确认结果/错题/讲解" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;endFill=1;strokeColor=#666666;" parent="1" source="22" target="62" edge="1">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# 问题陈述
|
||||
基于现有 `auth` 与 `upms` 模块完成前后端可联调实现(含 Web 管理端与小程序最小可用链路),从“占位/硬编码”升级为“数据库驱动 + 令牌会话治理 + 端侧鉴权一致”。
|
||||
## 当前状态(已确认)
|
||||
* `auth` 已有登录/刷新/当前用户接口,但服务实现为硬编码用户,未校验真实凭据,refresh 逻辑未做轮换与持久化(`backend/auth/src/main/java/com/k12study/auth/controller/AuthController.java (18-47)`, `backend/auth/src/main/java/com/k12study/auth/service/AuthService.java (18-74)`)。
|
||||
* `upms` 已有 routes/currentUser/areas/tenants/departments 接口,但全部为静态返回;且模块配置排除了数据源与 MyBatis 自动装配(`backend/upms/src/main/java/com/k12study/upms/service/impl/UpmsQueryServiceImpl.java (17-132)`, `backend/upms/src/main/resources/application.yml (1-18)`)。
|
||||
* 数据库脚本已提供认证与权限组织核心表(含 `auth.tb_auth_refresh_token`、`auth.tb_auth_login_audit`、`upms.tb_sys_*`、班级/文件/站内信相关表),但代码未接入(`init/pg/auth/10_create_auth_tables.sql (1-64)`, `init/pg/upms/10_create_upms_tables.sql (1-437)`)。
|
||||
* Web 端当前仅保存 accessToken,未使用 refreshToken,且路由初始化失败时会回退默认路由,缺少严格登录守卫(`frontend/src/pages/LoginPage.tsx (17-21)`, `frontend/src/utils/storage.ts (1-12)`, `frontend/src/router/AppRouter.tsx (56-83)`)。
|
||||
* 小程序端仅有 API/request 封装,无登录页、无 token 持久化与鉴权头注入(`app/src/api/auth.js (1-13)`, `app/src/utils/request.js (1-53)`)。
|
||||
* 目标能力与约束已在模块计划中明确(`docs/plan/modules/auth.md (1-40)`, `docs/plan/modules/upms.md (1-40)`)。
|
||||
## 实施方案
|
||||
### 1) 契约与模块边界收口
|
||||
统一 `auth/upms` 前后端契约与字段口径:
|
||||
1. `auth` 令牌 claims 扩展为 `userId/tenantId/tenantPath/deptId/deptPath/adcode/roleCodes/clientType/sessionId`,并在 API DTO 中显式化。
|
||||
2. `upms` 保留现有 5 个查询接口,同时补齐模块计划中已冻结的班级、文件、站内信接口。
|
||||
3. 将 Web 与 Mini 的端侧约束(`clientType + roleCodes`)纳入统一鉴权输入,避免服务内散落判断。
|
||||
### 2) 后端 Auth 实现
|
||||
1. 接入持久层(PostgreSQL + MyBatis Plus),补齐 `auth` 模块数据源配置与仓储层。
|
||||
2. 实现真实登录链路:账号/手机号凭据校验、用户状态校验、角色准入校验(Mini 仅 `STUDENT`)。
|
||||
3. 实现 refresh token 持久化与“一次一换”轮换:写入 `tb_auth_refresh_token`、刷新时撤销旧 token 并发放新 token。
|
||||
4. 实现登录与刷新审计:写入 `tb_auth_login_audit`,记录成功/失败与关键上下文。
|
||||
5. 加入学生端会话上限策略(上限 3,超限淘汰最久未活跃会话)。
|
||||
### 3) 后端 UPMS 实现
|
||||
1. 以数据库查询替换 `UpmsQueryServiceImpl` 静态数据,按租户上下文返回 routes/currentUser/areas/tenants/departments。
|
||||
2. 建立角色-菜单-权限聚合链路(必要时补齐 `user-role` 关系表与增量 SQL)。
|
||||
3. 增加班级、文件、站内信接口实现,统一租户隔离与对象存在性校验。
|
||||
4. 统一 `upms` 返回结构与前端类型,避免前端做业务字段兜底。
|
||||
### 4) 前端实现(Web + Mini)
|
||||
1. Web:重构会话层(access + refresh + 当前用户),增加登录守卫与 401 自动刷新/失效登出。
|
||||
2. Web:动态路由加载改为“鉴权成功后加载”,移除未登录默认路由回退。
|
||||
3. Web:补齐 `upms` 数据消费页(至少 currentUser/组织树/消息入口)的真实接口接入。
|
||||
4. Mini:补齐登录与 token 持久化,request 层注入 `Authorization`,处理 token 续期与失效。
|
||||
5. Mini:按 `clientType=MINI` + `role=STUDENT` 约束仅开放学生端能力。
|
||||
### 5) 联调与验收
|
||||
1. 在 `boot-dev`(本地聚合)与 `gateway + auth + upms`(分布式)两种模式分别完成联调验证。
|
||||
2. 验证项覆盖:登录/刷新/当前用户、动态路由、组织树、Mini 登录、站内信已读链路。
|
||||
3. 运行后端编译与前端构建,补充最小接口/服务测试,确认关键鉴权与租户隔离场景通过。
|
||||
## 交付顺序
|
||||
建议按“Auth 后端 -> UPMS 后端 -> Web 前端 -> Mini 前端 -> 双模式联调”执行,避免前端先行导致接口反复改动。
|
||||
38
docs/plan/modules/auth.md
Normal file
38
docs/plan/modules/auth.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# 问题陈述
|
||||
将 `auth` 从当前演示版 JWT 发放器升级为可用于 Web 教师/机构端与小程序学生端的统一认证中心,确保令牌生命周期、租户上下文与审计链路可落地。
|
||||
## 当前状态(已确认)
|
||||
* 架构与 API 对 `auth` 的约束是登录、刷新、当前用户三类基础接口。参考 `docs/architecture/api-design.md (12-16)`、`docs/architecture/logical-view.md (7-9)`。
|
||||
* 现有 `AuthController` 仅暴露 `/auth/tokens`、`/auth/tokens/refresh`、`/auth/users/current`。参考 `backend/auth/src/main/java/com/k12study/auth/controller/AuthController.java (1-49)`。
|
||||
* `AuthService` 当前为占位实现:默认 `admin`、不校验密码、refresh token 直接复用 access token 生成逻辑。参考 `backend/auth/src/main/java/com/k12study/auth/service/AuthService.java (18-74)`。
|
||||
* `init` 已提供 `auth.tb_auth_refresh_token` 与 `auth.tb_auth_login_audit`,但代码尚未接入。参考 `init/pg/auth/10_create_auth_tables.sql (1-54)`。
|
||||
* 当前需求已调整为“学生手机号绑定 + 手动登录”,不使用 openid/微信取号能力;现有代码尚未体现该约束。参考 `docs/AI智能学习系统功能清单.md (1-30)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `auth-credential`:账号密码、手机号绑定、手动登录、验证码/密码校验。
|
||||
* `auth-token`:access/refresh 双令牌、旋转、撤销、过期策略。
|
||||
* `auth-context`:输出标准 claims(userId/tenantId/tenantPath/deptId/adcode/roleCodes/clientType)。
|
||||
* `auth-audit`:登录审计、刷新审计、异常登录行为记录。
|
||||
### 2) 认证通道设计
|
||||
* Web(机构/教师):账号密码 + 可选验证码。
|
||||
* Mini(学生):手机号 + 手动输入凭证登录;“手机号+密码”与“手机号+短信验证码”为并列可选登录主流程,不依赖微信 code/openid。
|
||||
* 统一返回 token 结构,但按 `clientType` 写入不同策略(如 mini 更短 access TTL、更严格 refresh 轮换)。
|
||||
* 学生身份主键统一使用平台 `user_id` + 绑定手机号,不引入 openid 作为账号主索引。
|
||||
### 3) 令牌与隔离策略
|
||||
* access token 仅短期有效;refresh token 必须入库(`tb_auth_refresh_token`)并采用“每次刷新强制轮换”策略(one-time refresh token)与撤销机制。
|
||||
* claims 必须包含租户上下文与端侧上下文,供 gateway 与业务域执行“租户隔离 + 端能力限制”。
|
||||
* `currentUser` 不再回退静态默认用户,统一由 token + 用户表读取。
|
||||
### 4) 与小程序约束联动
|
||||
* 身份区分以 `role` 为准:小程序仅允许 `STUDENT` 角色登录;`TEACHER/ORG_ADMIN` 角色不发放 mini 可用令牌。
|
||||
* 为后续“课程仅展示课堂练习/课后作业”提供 `clientType=MINI` + `role=STUDENT` 的稳定判定依据。
|
||||
* 学生允许在不同家长手机登录,同一学生并发会话上限固定为 `3`,超限时淘汰最久未活跃会话。
|
||||
## 问题点与风险
|
||||
* 现有 refresh 流程不安全(refresh token 与 access token同构),无法实现撤销与会话治理。
|
||||
* 代码未接 `tb_auth_refresh_token`/`tb_auth_login_audit`,审计与风控链路缺失。
|
||||
* 若角色体系未在 token 与网关策略中一致生效,会导致小程序端角色越权风险。
|
||||
* JWT claims 字段不足(缺 tenant_path/adcode/clientType),会放大跨租户与跨端越权风险。
|
||||
* 跨设备登录场景下,若缺少设备会话治理(会话上限/异地提醒/强制下线),共享手机会增加账号滥用风险。
|
||||
## 已确定的实现决策
|
||||
* 学生手动登录提供双可选主流程:`手机号+密码` 与 `手机号+短信验证码`。
|
||||
* refresh token 采用“每次刷新强制轮换”策略。
|
||||
* 学生跨多家长手机登录并发会话上限固定为 `3`,超限淘汰最近最久未活跃会话。
|
||||
* 身份区分以 `role` 为准;小程序仅开放 `STUDENT` 角色,老师与机构角色不开放小程序登录。
|
||||
42
docs/plan/modules/course.md
Normal file
42
docs/plan/modules/course.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 问题陈述
|
||||
设计并拆分 `course` 模块,使其从“仅有 SQL 结构”升级为可支撑教师建课、班级投放、学生学习与小程序差异化可见性的课程域。
|
||||
## 当前状态(已确认)
|
||||
* 架构与 API 已定义 `course` 为独立业务域,含课程、章节、知识点、掌握度等接口与数据职责。参考 `docs/architecture/logical-view.md (12-18)`、`docs/architecture/api-design.md (34-41)`。
|
||||
* 当前 `backend` Maven 模块尚未包含 `course` 服务实现,仅有 `init/pg/course` SQL。参考 `backend/pom.xml (11-20)`、`init/pg/course/10_create_course_tables.sql (1-521)`。
|
||||
* `course` 表结构已覆盖课程主链路:课程/章节/节点/资源/知识点/学习会话/进度/事件,并内置节点类型 `IN_CLASS_ACTIVITY`、`AFTER_CLASS_TASK`、`MATERIAL`。参考 `init/pg/course/10_create_course_tables.sql (63-78)`、`init/pg/course/10_create_course_tables.sql (323-349)`。
|
||||
* 小程序端当前仍是骨架页,未接课程业务。参考 `app/src/app.json (1-13)`、`app/src/pages/home/index.js (1-6)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `course-core`:课程、章节、节点、发布状态(单版本模型,不引入发布快照版本化)。
|
||||
* `course-resource`:节点资源与文件引用。
|
||||
* `course-knowledge`:知识点、章节/节点关联、掌握度回写。
|
||||
* `course-learning`:学习会话、学习进度、学习事件。
|
||||
* `course-delivery`:课程对班级投放与可见规则(与 `upms-class` 联动)。
|
||||
### 2) 课程可见性与小程序约束
|
||||
* 教师端可管理全部节点类型(含 `MATERIAL/LESSON` 课件类节点)。
|
||||
* 小程序端仅 `STUDENT` 角色可访问课程能力,且 `LESSON` 节点在小程序全部隐藏。
|
||||
* 端侧可见性采用“字段内嵌”方案(不使用独立策略表):
|
||||
* 节点级字段:`visible_for_web_teacher`、`visible_for_mini_student`
|
||||
* 资源级字段:`resource_visible_scope`
|
||||
* 课程查询接口按 `clientType + roleCodes + classMembership` 组合过滤。
|
||||
### 3) 与班级和作业联动
|
||||
* 章节节点点击查询固定两步:
|
||||
1) 查询课件(`course.cl_node_resource`,小程序端不执行该步)。
|
||||
2) 查询课堂练习(`course.cl_node_homework_rel` + `question.hw_assignment`,`relation_type=IN_CLASS`)。
|
||||
* 课后作业由作业入口独立查询,不并入章节节点点击查询结果。
|
||||
* 课程投放以 `upms.tb_school_class_course_rel` 为准,课程域不重复维护班级主数据。
|
||||
* `course.cl_node_homework_rel` 与 `question.hw_assignment` 建立稳定联查规范,统一“课堂练习/课后作业”来源。
|
||||
* 学习进度、知识点掌握度更新时强制校验学生是否属于课程投放班级。
|
||||
### 4) 租户隔离策略
|
||||
* 全量查询与写入以 `tenant_id` 强约束,并在需要层级权限时附加 `tenant_path/dept_path`。
|
||||
* 对跨租户课程引用(节点关联作业、资源文件)做一致性校验。
|
||||
## 问题点与风险
|
||||
* 目前没有 `course` 运行服务与 API,实现成本集中在“从 0 到 1”。
|
||||
* 节点与资源的端侧可见性字段尚未实际落表,首期需补齐增量 SQL 与索引。
|
||||
* 种子数据为空,联调期将缺少可复现演示样本。参考 `init/pg/course/20_init_course_seed.sql (1-2)`。
|
||||
* 课程与班级关系存在跨模块依赖,若不先固定 authoritative source,容易出现双写冲突。
|
||||
## 已确定的实现决策
|
||||
* 端侧可见性采用“字段内嵌”方案。
|
||||
* 章节节点点击查询采用两步:查询课件(小程序不查)+ 查询课堂练习。
|
||||
* `LESSON` 节点在小程序全部隐藏。
|
||||
* 课程发布模型不做版本化,采用单版本状态流转(DRAFT/PUBLISHED/ARCHIVED)。
|
||||
32
docs/plan/modules/gateway.md
Normal file
32
docs/plan/modules/gateway.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# 问题陈述
|
||||
将 `gateway` 从“仅转发 auth/upms 的静态网关”升级为全域统一接入层,负责鉴权透传、租户隔离防线、端侧能力边界控制(尤其小程序学生端)。
|
||||
## 当前状态(已确认)
|
||||
* 架构定义中网关应承接 auth/upms/course/question/achievement/recommendation 多域入口。参考 `docs/architecture/logical-view.md (24-41)`。
|
||||
* 现有网关路由仅配置 `auth` 与 `upms` 两条,且目标地址硬编码 localhost。参考 `backend/gateway/src/main/resources/application.yml (1-30)`。
|
||||
* `JwtRelayFilter` 仅做 token 校验并透传 `X-User-Id/X-Username/X-Display-Name/X-Tenant-Id/X-Dept-Id`。参考 `backend/gateway/src/main/java/com/k12study/gateway/filter/JwtRelayFilter.java (1-79)`、`backend/common/common-core/src/main/java/com/k12study/common/core/constants/SecurityConstants.java (1-13)`。
|
||||
* API 设计要求对外统一 `/api/*`,且后续需扩展到 course/question/ai。参考 `docs/architecture/api-design.md (1-82)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `gw-routing`:静态路由基线 + 服务发现路由(后续可接 nacos)。
|
||||
* `gw-authn`:JWT 解析、白名单、令牌有效性检查。
|
||||
* `gw-authz`:基于角色/权限码的接口级访问控制。
|
||||
* `gw-tenant-guard`:租户上下文一致性校验与越权拦截。
|
||||
* `gw-client-policy`:按 `clientType + roleCodes` 执行端侧能力约束(Web 与 Mini 分流,且角色可见能力分层)。
|
||||
### 2) 路由与协议策略
|
||||
* 扩展路由:`/api/course/**`、`/api/question/**`、`/api/ai/**`(以及后续 achievement)。
|
||||
* 统一注入:`traceId`、用户上下文、端侧上下文,确保下游服务具备完整鉴权条件。
|
||||
* 统一错误响应结构:`code/message/data/traceId`,避免当前 401 响应与标准不一致。
|
||||
### 3) 租户隔离与端侧约束
|
||||
* 对路径参数、query、body 中 `tenant_id/class_id/course_id` 做一致性校验(与 token tenant 比对)。
|
||||
* 对小程序令牌执行角色准入:仅 `clientType=MINI` 且含 `STUDENT` 角色可访问;`TEACHER/ORG_ADMIN` 角色直接拒绝 mini 端访问。
|
||||
* 对小程序学生令牌在网关层执行“只允许课堂练习/课后作业相关 API”,屏蔽课件/资料类接口。
|
||||
* 为图检索与向量检索入口统一加租户隔离过滤(至少 tenant_id,必要时 tenant_path + class scope)。
|
||||
## 问题点与风险
|
||||
* 当前仅透传 `tenant_id`,缺 tenant_path/adcode/clientType,难以实现层级隔离与端侧细分授权。
|
||||
* 路由静态且服务少,course/question/ai 接入后若不先做网关收口,跨域鉴权规则会分散在业务服务。
|
||||
* 401 响应未附 traceId,排障链路不完整。
|
||||
* 白名单仅按路径匹配,缺 method 维度与来源限制,存在误开放风险。
|
||||
## 需确认的设计决策
|
||||
* 首期是否在网关做“端侧能力强约束”还是只做鉴权透传(推荐首期即强约束)。
|
||||
* 路由配置是否直接切到配置中心统一管理,还是先保持本地静态配置再迁移。
|
||||
* 租户校验失败返回码与错误语义(401/403/422)统一口径。
|
||||
38
docs/plan/modules/question.md
Normal file
38
docs/plan/modules/question.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# 问题陈述
|
||||
将 `question` 拆分为可演进的习题/作业/批改核心域,并在同一计划中处理错题复习、费曼讲解、推荐闭环与小程序学生端作业可见规则。
|
||||
## 当前状态(已确认)
|
||||
* 架构与 API 已定义 `question` 为核心业务域,覆盖题库、作业、提交、批改、复习。参考 `docs/architecture/api-design.md (42-61)`、`docs/architecture/logical-view.md (58-66)`。
|
||||
* 当前后端尚无 `question` 服务代码,能力主要体现在 `init/pg/question` 表结构。参考 `backend/pom.xml (11-20)`、`init/pg/question/10_create_question_tables.sql (1-1272)`。
|
||||
* SQL 已覆盖题库/作业/批改/错题/复习/讲解评估,并把推荐与画像并入 `question.rc_*`。参考 `init/pg/question/10_create_question_tables.sql (1041-1272)`。
|
||||
* 复习策略已有租户级默认种子(E1-E6)。参考 `init/pg/question/20_init_question_seed.sql (8-56)`。
|
||||
* 功能清单对错题、变式题、费曼评估、复习提醒、推荐闭环都有明确诉求。参考 `docs/AI智能学习系统功能清单.md (11-24)`、`docs/AI智能学习系统功能清单.md (91-108)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `question-bank`:题库、题目、题目知识点关联。
|
||||
* `question-assignment`:试卷、作业、投放对象、提交与答案。
|
||||
* `question-grading`:批改任务、答案评分、错因标签、知识点分析。
|
||||
* `question-review`:错题沉淀、艾宾浩斯计划与执行。
|
||||
* `question-explanation`:费曼讲解提交、评估与维度评分。
|
||||
* `question-recommendation-bridge`:保留 `rc_*` 闭环数据(中期可再独立 recommendation 服务)。
|
||||
### 2) 小程序学生端规则
|
||||
* 小程序仅面向学生,`assignment` 查询必须限制为“学生所在班级 + 已发布 + 节点类型为课堂练习/课后作业”。
|
||||
* 对应教师创建课程中的课件节点,不在学生端作业列表和详情返回。
|
||||
* 通过 `course.cl_node_homework_rel.relation_type(IN_CLASS/AFTER_CLASS)` 与班级成员关系联合过滤。
|
||||
### 3) 数据与契约修正
|
||||
* 强化 `hw_assignment_target.target_ref_id` 的对象完整性(按 `target_type` 校验 class_id/student_id 存在且同租户)。
|
||||
* 补充“变式题生成任务”数据结构(任务、来源错题、生成题、命中策略),连接功能清单中的举一反三链路。
|
||||
* `gd_answer_grade` 继续作为统一批改结果主表,避免客观/主观分表回退。
|
||||
* 推荐闭环暂存于 `question` 时,需定义清晰子包边界,避免与习题核心耦合扩散。
|
||||
### 4) 租户隔离策略
|
||||
* 所有 `hw_* / gd_* / rc_*` 读写统一按 `tenant_id` 强过滤。
|
||||
* 跨表关联(submission->student、assignment->class、recommendation->user)均执行租户一致性断言。
|
||||
* 对 AI 生成、图检索、向量检索调用记录 tenant 维度与来源对象,便于追溯越权风险。
|
||||
## 问题点与风险
|
||||
* `question` 当前“超大域”承载习题+复习+讲解+推荐,若不先做包级拆分,后续维护成本会快速上升。
|
||||
* 目前无运行时代码,尽管 SQL 完整,但缺业务规则执行层,容易出现“表有字段、行为缺失”。
|
||||
* `target_ref_id` 弱关联容易引发错投放与越权读取。
|
||||
* 功能清单的变式题追踪链路在现有表中仍缺专门任务模型。
|
||||
## 需确认的设计决策
|
||||
* 推荐相关 `rc_*` 是短期保留在 `question`,还是本阶段即拆到 `recommendation` 独立服务。
|
||||
* 变式题生成首期是否强依赖 AI 服务,或先以规则模板生成保障可交付。
|
||||
* 费曼评估通过阈值与回流规则(与系统文档口径)是否纳入一期强约束。
|
||||
39
docs/plan/modules/upms.md
Normal file
39
docs/plan/modules/upms.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 问题陈述
|
||||
将 `upms` 从当前“基础演示能力”拆分为可支撑多租户教学业务的基础域模块,承接组织权限、班级关系、文件资源、站内信,并为 `auth/course/question/gateway` 提供统一主体与隔离上下文。
|
||||
## 当前状态(已确认)
|
||||
* 架构文档把 `upms` 定位为租户/组织/用户/角色/菜单的平台能力层,且要求核心表统一保留租户隔离字段。参考 `docs/architecture/logical-view.md (2-13)`、`docs/architecture/logical-view.md (74-77)`。
|
||||
* API 设计中 `upms` 当前冻结接口仅覆盖 routes/currentUser/areas/tenants/departments,文件与消息接口仍为“建议补充”。参考 `docs/architecture/api-design.md (17-29)`。
|
||||
* 代码层 `upms` 仅有查询接口,且服务实现为硬编码返回,未接数据库。参考 `backend/upms/src/main/java/com/k12study/upms/controller/UpmsController.java (1-52)`、`backend/upms/src/main/java/com/k12study/upms/service/impl/UpmsQueryServiceImpl.java (1-132)`、`backend/upms/src/main/resources/application.yml (1-18)`。
|
||||
* `init` 已具备班级主表/成员表/班级课程关系、文件表、消息主表与收件人表等基础结构,可在设计阶段调整。参考 `init/pg/upms/10_create_upms_tables.sql (39-434)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `upms-identity`:租户、组织、用户、角色、菜单、角色授权。
|
||||
* `upms-class`:班级、班级成员、班级与课程关系(作为 class authoritative source)。
|
||||
* `upms-file`:统一文件元数据、上传登记、跨域引用约束。
|
||||
* `upms-message`:站内信投递、已读/点击回执、业务跳转。
|
||||
* `upms-context`:向网关与业务域提供用户上下文(tenant/dept/roleCodes/clientType)。
|
||||
### 2) API 设计增补
|
||||
* 保留现有 `/api/upms/routes|users/current|areas|tenants|departments`,其中 `routes` 仅用于 Web 端动态路由管理。
|
||||
* 新增并冻结:
|
||||
* 班级:`/api/upms/classes`、`/api/upms/classes/{id}/members`、`/api/upms/classes/{id}/courses`
|
||||
* 文件:`POST /api/upms/files/upload`、`GET /api/upms/files/{fileId}`
|
||||
* 消息:`GET /api/upms/messages/inbox`、`POST /api/upms/messages/{messageId}/read`
|
||||
* 小程序端当前不做动态路由管理;仅保留业务可见性相关查询能力(如课堂练习/课后作业可见对象)。
|
||||
### 3) 数据与隔离策略
|
||||
* 统一强制查询键:`tenant_id + (tenant_path/dept_path)`;所有列表与详情接口默认附加租户过滤。
|
||||
* 身份区分以角色体系为准:在 `upms` 侧补齐用户-角色映射(建议新增 `tb_sys_user_role`),以 `role` 作为鉴权与端侧准入主依据;`client_scope` 用于端类型控制。
|
||||
* 在 `tb_sys_user` 增补手机号绑定字段(如 `mobile_phone/mobile_verified_at/mobile_bind_status`);学生手机号在租户内唯一,用于手动登录主凭据。
|
||||
* 小程序端仅开放 `STUDENT` 角色;`TEACHER/ORG_ADMIN` 角色不开放小程序登录授权。
|
||||
* `tb_school_class_course_rel` 增补可见性配置(如 `mini_visible_scope`),用于后续小程序“仅课堂练习+课后作业”过滤联动。
|
||||
* 为消息与文件接口建立“跨租户不可见 + 对象存在性校验”统一拦截器。
|
||||
## 问题点与风险
|
||||
* 现状 `upms` 返回硬编码数据,和 SQL 实体脱节,后续联调会出现“接口有值但数据库无一致性”风险。
|
||||
* 现有上下文仅传 `tenant_id/dept_id`,缺 `tenant_path/adcode/roleCodes/clientType`,不利于层级隔离与端侧差异控制。参考 `backend/common/common-core/src/main/java/com/k12study/common/core/constants/SecurityConstants.java (1-13)`。
|
||||
* 班级实体虽已落表,但缺 API 与领域服务,`question` 当前仍需通过弱关联字段投放对象,存在错投/越权风险。
|
||||
* 站内信与文件在产品链路中为关键公共能力,但目前仅有表结构和种子,缺完整业务闭环。
|
||||
* 若 `tb_sys_user` 缺手机号唯一约束与换绑审计,会放大共享设备场景下的账号冒用与追责困难。
|
||||
## 已确定的实现决策
|
||||
* 班级由 `upms` 完全统一托管,其他业务域仅通过 `class_id` 关联。
|
||||
* `roleCodes/clientType` 放入 JWT claims,同时在 `upms` 角色关系中保留权威数据。
|
||||
* `upms` 仅承担 Web 端路由资源管理;小程序端当前不做动态路由。
|
||||
* 学生手机号换绑不启用“原手机号确认 + 班级归属校验 + 冷静期”三段式流程,采用手机号验证或线下联系老师处理。
|
||||
39
docs/plan/modules/向量知识库.md
Normal file
39
docs/plan/modules/向量知识库.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 问题陈述
|
||||
为“向量知识库”单独建立可实施设计,补齐向量入库、切片、检索、审计与租户隔离能力,并与图谱知识库形成明确分工与协同。
|
||||
## 当前状态(已确认)
|
||||
* 架构文档将 Milvus 设为向量检索主方案。参考 `docs/architecture/base-services.md (13-16)`、`docs/architecture.md (8-13)`。
|
||||
* 现有 AI 表仅包含 `vector_sync_status` 字段与 `target_store=VECTOR` 同步任务,不含向量文档/切片/检索日志实体。参考 `init/pg/ai/10_create_ai_tables.sql (13-15)`、`init/pg/ai/10_create_ai_tables.sql (77-104)`。
|
||||
* 种子数据已演示 GRAPH 与 VECTOR 双任务并存,但仍是占位任务。参考 `init/pg/ai/20_init_ai_seed.sql (46-76)`。
|
||||
* `python-ai` 与 `ai-client` 当前仅有健康检查能力,未实现向量入库与检索接口。参考 `backend/python-ai/app/main.py (1-13)`、`backend/ai-client/src/main/java/com/k12study/aiclient/client/PythonAiClient.java (1-7)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `vector-ingestion`:文档清洗、切片、embedding 生成、重建任务。
|
||||
* `vector-storage`:向量文档、切片元数据、索引状态管理。
|
||||
* `vector-retrieval`:语义检索、召回重排、结果解释。
|
||||
* `vector-governance`:模型版本、数据有效期、删除回收、审计日志。
|
||||
### 2) 入库策略(按你给定口径)
|
||||
* 总部知识库:进入向量 + 图谱。
|
||||
* 教师班级课程/课件:仅图谱,不进入向量。
|
||||
* 在知识文件层配置 `ingest_policy`(BOTH/GRAPH_ONLY),向量任务创建器仅对 `BOTH` 生成向量任务。
|
||||
### 3) 数据模型建议(可改 `init` SQL)
|
||||
* 新增 `ai.tb_ai_vector_document`:文档级元数据(tenant/scope/model_version/index_status)。
|
||||
* 新增 `ai.tb_ai_vector_chunk`:切片文本、chunk_order、token_count、embedding_ref。
|
||||
* 新增 `ai.tb_ai_vector_index_task`:索引构建/重建任务与错误重试。
|
||||
* 新增 `ai.tb_ai_retrieval_log`:查询语句、召回范围、tenant_id、命中文档、耗时、调用端。
|
||||
* 与 `tb_ai_knowledge_file` 建立一对多映射,保留来源追溯。
|
||||
### 4) 租户隔离与端侧约束
|
||||
* 向量检索必须按 `tenant_id + knowledge_scope` 过滤;默认禁止跨租户召回。
|
||||
* 班级场景增加 `class_id/course_id` 过滤,避免跨班级内容泄漏。
|
||||
* 小程序学生端检索结果仅允许返回课堂练习/课后作业关联内容,不返回教师课件全文。
|
||||
### 5) 与图谱协同
|
||||
* 支持“图谱先召回候选 -> 向量精排”或“向量召回 -> 图谱关系扩展”双阶段策略。
|
||||
* 检索响应统一返回来源对象(课程/题目/知识点),交由业务域二次鉴权展示。
|
||||
## 问题点与风险
|
||||
* 当前缺少向量核心表结构,无法稳定支撑入库追踪、检索审计与故障重建。
|
||||
* 未定义 embedding 模型版本与重建策略,后续模型升级会导致历史索引不可比对。
|
||||
* 无检索日志会导致“召回错误/越权返回”难以追溯。
|
||||
* 若不先固化入库策略,HQ/教师内容边界容易在实现时被混用。
|
||||
## 需确认的设计决策
|
||||
* 首期是否先做“单向量模型 + 单索引集合”简化方案,再演进多模型路由。
|
||||
* 向量检索与图检索的融合策略首期采用串行还是并行(推荐串行,便于控制复杂度)。
|
||||
* 检索日志保留周期与脱敏策略(涉及学生查询内容合规)。
|
||||
36
docs/plan/modules/知识图谱.md
Normal file
36
docs/plan/modules/知识图谱.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# 问题陈述
|
||||
按“图谱知识库”独立模块设计知识抽取与图检索链路,明确总部与教师内容入库策略,并把租户隔离作为图检索默认约束。
|
||||
## 当前状态(已确认)
|
||||
* 架构层已定义图数据库主选 NebulaGraph,AI 链路为业务服务 -> ai-client -> python-ai -> 图谱/向量。参考 `docs/architecture/base-services.md (9-16)`、`docs/architecture/logical-view.md (50-72)`。
|
||||
* AI SQL 已有图谱实体、关系、同步任务等基础结构,且同步任务支持 `target_store=GRAPH|VECTOR`。参考 `init/pg/ai/10_create_ai_tables.sql (1-215)`。
|
||||
* 现有 `python-ai` 仅暴露 `/health`,尚无图谱入库与检索 API。参考 `backend/python-ai/app/main.py (1-13)`。
|
||||
* 功能清单强调知识库用于错题关联课程与内容检索,但当前运行时链路未落地。参考 `docs/AI智能学习系统功能清单.md (91-98)`。
|
||||
## 模块拆分与设计细节
|
||||
### 1) 子模块边界
|
||||
* `kg-ingestion`:知识文件到图谱实体/关系抽取、去重、版本管理。
|
||||
* `kg-model`:实体类型体系(知识点/题目/课程/课件)与关系类型体系。
|
||||
* `kg-sync`:图谱同步任务编排、重试、失败补偿。
|
||||
* `kg-retrieval`:图检索 API(按场景返回知识点路径、关联题、关联课程)。
|
||||
* `kg-governance`:内容审核、来源追踪、删除回收策略。
|
||||
### 2) 入库策略(按你给定口径)
|
||||
* 知识库分两类:图谱知识库、向量知识库。
|
||||
* 总部创建知识库:同时进入图谱 + 向量。
|
||||
* 教师班级课程/课件内容:仅进入图谱,不进入向量。
|
||||
* 设计实现:在 `tb_ai_knowledge_file` 增加 `source_owner_type`(HQ/TEACHER)、`knowledge_scope`(GLOBAL/TENANT/CLASS/COURSE)、`ingest_policy`(BOTH/GRAPH_ONLY),同步任务根据策略自动生成。
|
||||
### 3) 图检索与租户隔离
|
||||
* 图检索默认过滤 `tenant_id`,并在班级场景附加 `class_id/course_id` 可见域约束。
|
||||
* 总部全局知识仅在授权租户可见,禁止跨租户回查实体细节。
|
||||
* 返回结果附带 `source_table/source_pk` 以支持业务回查,但回查前再次执行租户一致性校验。
|
||||
### 4) 与业务域联动
|
||||
* `course`:知识点树与课程节点建立双向可追溯引用。
|
||||
* `question`:题目-知识点关系可回写图谱关系,支持错题知识路径解释。
|
||||
* `upms`:复用班级与租户结构进行图谱可见域控制。
|
||||
## 问题点与风险
|
||||
* 目前仅有表结构,图谱入库/检索服务未实现,链路停留在设计层。
|
||||
* 现有 AI 表缺少“来源归属与入库策略”显式字段,无法直接表达 HQ 双入库、教师图谱单入库规则。
|
||||
* 没有图检索访问日志与越权审计,难以定位租户隔离问题。
|
||||
* python-ai 未落地图数据库客户端与查询协议,接口冻结前需先定义查询契约。
|
||||
## 需确认的设计决策
|
||||
* 图检索首期采用“模板化查询 + 场景参数”还是开放式图查询 DSL(推荐模板化)。
|
||||
* 总部知识对分校是否默认可见,或需要租户级授权开关。
|
||||
* 图谱实体冲突(同名知识点跨租户)采用“租户隔离命名空间”还是“全局实体+租户可见边”模型。
|
||||
5
docs/plan/upms.md
Normal file
5
docs/plan/upms.md
Normal file
@@ -0,0 +1,5 @@
|
||||
/plan 实现upms的所有功能, 要支持excel导入导出,使用F:\Project\K12Study\urbanLifeline\urbanLifelineServ\common\common-utils\src\main\java\org\xyzh\common\utils\excel
|
||||
和F:\Project\K12Study\urbanLifeline\urbanLifelineServ\common\common-utils\src\main\java\org\xyzh\common\utils\validation进行参数建议
|
||||
注意实现定时任务的部分和站信
|
||||
注意使用swagger注释
|
||||
注意使用代码注释以及log日志
|
||||
Reference in New Issue
Block a user