pangu-user-platform/docs/会员教育信息重构方案.md

819 lines
23 KiB
Markdown
Raw Normal View History

# 会员教育信息重构方案
> 作者pangu
> 创建时间2026-02-03
> 状态:**已审核通过**
---
## 一、需求变更说明
### 1.1 变更内容
1. **去掉身份类型**:会员不再区分"家长"和"教师"
2. **重构会员信息表**:会员与教育信息变为**一对多**关系,一个会员可以有多个教育身份
3. **pg_member 表移除字段**
- `region_id` - 区域ID
- `school_id` - 学校ID
- `school_grade_id` - 年级ID
- `school_class_id` - 班级ID
- `identity_type` - 身份类型
- ~~`union_id`~~ - **保留**(微信多应用打通需要)
### 1.2 变更原因
- 业务场景:一个用户可能同时是多个学校/班级的教师
- 简化会员模型:会员表只存储基础信息,教育信息独立管理
---
## 二、当前架构分析
### 2.1 现有数据结构
**pg_member 表**(部分字段):
| 字段 | 类型 | 说明 | 变更 |
|------|------|------|------|
| member_id | bigint | 主键 | 保留 |
| member_code | varchar(32) | 会员编号 | 保留 |
| phone | varchar(20) | 手机号 | 保留 |
| password | varchar(100) | 密码 | 保留 |
| nickname | varchar(50) | 昵称 | 保留 |
| avatar | varchar(500) | 头像 | 保留 |
| gender | char(1) | 性别 | 保留 |
| birthday | date | 生日 | 保留 |
| **identity_type** | char(1) | 身份类型 | **删除** |
| open_id | varchar(100) | 微信OpenID | 保留 |
| union_id | varchar(100) | 微信UnionID | 保留 |
| **region_id** | bigint | 区域ID | **删除** |
| **school_id** | bigint | 学校ID | **删除** |
| **school_grade_id** | bigint | 年级ID | **删除** |
| **school_class_id** | bigint | 班级ID | **删除** |
| register_source | char(1) | 注册来源 | 保留 |
| register_time | datetime | 注册时间 | 保留 |
| status | char(1) | 状态 | 保留 |
### 2.2 现有关联关系
```
pg_member会员
├── 一对一:教育信息(存在会员表中) ← 需要改为一对多
└── 一对多pg_student学生 ← 已改为多对多
```
---
## 三、目标架构设计
### 3.1 新数据结构
```
pg_member会员- 只存基础信息
├── 一对多pg_education会员教育信息 ← 新建
└── 多对多pg_member_student ↔ pg_student ← 已重构(支持多会员绑定同一学生)
```
### 3.2 新建表pg_member_education
**设计理念**:一个教育身份 = 一个班级的教学关系
```
张老师教3个班 → 3条教育身份记录
教育身份1: 二中 - 高二 - 1班 - 数学
教育身份2: 二中 - 高二 - 2班 - 数学
教育身份3: 二中 - 高二 - 3班 - 数学
```
```sql
CREATE TABLE pg_member_education (
education_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '教育身份ID',
member_id BIGINT NOT NULL COMMENT '会员ID',
region_id BIGINT COMMENT '区域ID',
school_id BIGINT NOT NULL COMMENT '学校ID',
school_grade_id BIGINT NOT NULL COMMENT '年级IDschool_grade关联ID',
school_class_id BIGINT NOT NULL COMMENT '班级IDschool_class关联ID',
subject_id BIGINT COMMENT '学科ID',
is_default CHAR(1) DEFAULT '0' COMMENT '是否默认身份0否 1是',
status CHAR(1) DEFAULT '0' COMMENT '状态0正常 1停用',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
del_flag CHAR(1) DEFAULT '0' COMMENT '删除标志',
KEY idx_member_id (member_id),
KEY idx_school_id (school_id),
KEY idx_class_id (school_class_id)
) COMMENT '会员教育信息表';
```
### 3.3 最终关系图
```
pg_member会员基础信息
├── 一对多 → pg_member_education教育身份每班一条
└── 一对多 → pg_student学生/孩子)
```
---
## 四、影响范围分析
### 4.1 数据库层
| 操作 | 对象 | 说明 |
|------|------|------|
| 修改 | pg_member | 删除5个字段 |
| 新建 | pg_member_education | 会员教育信息表(含班级字段) |
| 迁移 | 现有教育数据 | 迁移到新表 |
### 4.2 后端层
| 文件 | 改动类型 | 说明 |
|------|----------|------|
| `PgMember.java` | 修改 | 删除5个字段保留unionId |
| `PgMemberEducation.java` | 新建 | 教育身份实体 |
| `PgMemberEducationMapper.java` | 新建 | Mapper |
| `H5MemberServiceImpl.java` | 重构 | 教育相关逻辑 |
| `H5EducationDto.java` | 修改 | 添加educationId |
| `H5EducationVo.java` | 修改 | 添加educationId等字段 |
| `H5MemberController.java` | 修改 | 接口调整 |
| `H5MemberInfoVo.java` | 修改 | 删除identityType |
| `PgMemberController.java` | 修改 | 删除身份类型相关 |
| `PgMemberServiceImpl.java` | 修改 | 删除教育信息处理 |
### 4.3 管理后台前端
| 文件 | 改动类型 | 说明 |
|------|----------|------|
| `business/member/index.vue` | 修改 | 删除身份类型筛选和列 |
| `business/member/components/MemberDialog.vue` | 重构 | 删除身份类型和教师信息区块 |
| `business/member/components/EducationTab.vue` | **新建** | 教育身份管理Tab |
| `business/member/components/MemberDetail.vue` | **新建** | 会员详情页含教育身份Tab |
| `api/pangu/member.js` | 修改 | 删除/新增接口 |
| `api/pangu/memberEducation.js` | **新建** | 教育身份接口 |
### 4.4 H5前端
| 文件 | 改动类型 | 说明 |
|------|----------|------|
| `stores/user.ts` | 修改 | 删除 identityType |
| `views/userCenter/index.vue` | 修改 | 教育身份列表支持多个 |
| `components/TeacherIdentityForm.vue` | 修改 | 新增/编辑某个教育身份 |
| `api/user.js` | 修改 | 接口调整 |
---
## 五、接口变更
### 5.1 H5接口变更
#### 5.1.1 获取会员信息(修改)
**接口**`GET /h5/member/info`
**响应变更**
```json
// 修改前
{
"code": 200,
"data": {
"consumerId": 1,
"phone": "138****0000",
"nickname": "测试用户",
"identityType": "2", // ← 删除
"education": { ... }, // 单个
"students": [...]
}
}
// 修改后
{
"code": 200,
"data": {
"consumerId": 1,
"phone": "138****0000",
"nickname": "测试用户",
"educations": [...], // 多个教育身份
"students": [...]
}
}
```
#### 5.1.2 教育身份列表(修改)
**接口**`GET /h5/member/educations`
**响应**
```json
{
"code": 200,
"data": [
{
"educationId": 1,
"schoolId": 1,
"schoolName": "武汉市第二中学",
"schoolGradeId": 5,
"gradeName": "高二",
"schoolClassId": 104,
"className": "1班",
"subjectId": 1,
"subjectName": "数学",
"isDefault": "1"
},
{
"educationId": 2,
"schoolId": 1,
"schoolName": "武汉市第二中学",
"schoolGradeId": 5,
"gradeName": "高二",
"schoolClassId": 105,
"className": "2班",
"subjectId": 1,
"subjectName": "数学",
"isDefault": "0"
}
]
}
```
#### 5.1.3 新增教育身份
**接口**`POST /h5/member/educations`
**请求参数**
```json
{
"schoolId": 1,
"schoolGradeId": 5,
"schoolClassId": 104,
"subjectId": 1
}
```
#### 5.1.4 编辑教育身份
**接口**`PUT /h5/member/educations/{educationId}`
**请求参数**
```json
{
"schoolId": 1,
"schoolGradeId": 5,
"schoolClassId": 104,
"subjectId": 1
}
```
#### 5.1.5 删除教育身份
**接口**`DELETE /h5/member/educations/{educationId}`
#### 5.1.6 设置默认教育身份
**接口**`PUT /h5/member/educations/{educationId}/default`
### 5.2 管理后台接口变更
#### 5.2.1 会员列表(修改)
- 删除 `identityType` 筛选参数
- 响应中删除 `identityType` 字段
#### 5.2.2 会员详情(修改)
- 删除教育信息字段
- 新增 `educations` 列表
#### 5.2.3 新增/编辑会员(修改)
- 删除 `identityType`、`regionId`、`schoolId`、`schoolGradeId`、`schoolClassId` 参数
#### 5.2.4 会员教育身份管理(新增)
| 接口 | 方法 | 说明 |
|------|------|------|
| `/business/member/{memberId}/educations` | GET | 获取会员教育身份列表 |
| `/business/member/{memberId}/education` | POST | 添加教育身份 |
| `/business/member/{memberId}/education/{educationId}` | PUT | 修改教育身份 |
| `/business/member/{memberId}/education/{educationId}` | DELETE | 删除教育身份 |
---
## 六、详细技术方案
### 6.1 数据库改造
#### 6.1.1 DDL脚本
```sql
-- 新建会员教育信息表(一个教育身份 = 一个班级的教学关系)
CREATE TABLE pg_member_education (
education_id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '教育身份ID',
member_id BIGINT NOT NULL COMMENT '会员ID',
region_id BIGINT COMMENT '区域ID',
school_id BIGINT NOT NULL COMMENT '学校ID',
school_grade_id BIGINT NOT NULL COMMENT '年级ID',
school_class_id BIGINT NOT NULL COMMENT '班级ID',
subject_id BIGINT COMMENT '学科ID',
is_default CHAR(1) DEFAULT '0' COMMENT '是否默认身份0否 1是',
status CHAR(1) DEFAULT '0' COMMENT '状态0正常 1停用',
tenant_id VARCHAR(20) DEFAULT '000000' COMMENT '租户编号',
create_dept BIGINT COMMENT '创建部门',
create_by BIGINT COMMENT '创建者',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by BIGINT COMMENT '更新者',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
del_flag CHAR(1) DEFAULT '0' COMMENT '删除标志',
KEY idx_member_id (member_id),
KEY idx_school_id (school_id),
KEY idx_class_id (school_class_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='会员教育信息表';
```
#### 6.1.2 数据迁移脚本
```sql
-- 迁移现有教育数据identity_type = '2' 的教师数据)
INSERT INTO pg_member_education (
member_id, region_id, school_id, school_grade_id, school_class_id, subject_id, is_default, status, tenant_id, create_time
)
SELECT
member_id, region_id, school_id, school_grade_id, school_class_id, NULL, '1', '0', tenant_id, NOW()
FROM pg_member
WHERE identity_type = '2'
AND school_id IS NOT NULL
AND school_class_id IS NOT NULL
AND del_flag = '0';
```
#### 6.1.3 删除字段(迁移完成后执行)
```sql
-- 删除 pg_member 表中的字段(建议先备份)
-- 注意union_id 保留,不删除
ALTER TABLE pg_member
DROP COLUMN identity_type,
DROP COLUMN region_id,
DROP COLUMN school_id,
DROP COLUMN school_grade_id,
DROP COLUMN school_class_id;
```
### 6.2 后端改造
#### 6.2.1 新建实体类
**PgMemberEducation.java**
```java
package org.dromara.pangu.member.domain;
@Data
@TableName("pg_member_education")
public class PgMemberEducation extends BaseEntity {
@TableId(type = IdType.AUTO)
private Long educationId;
private Long memberId;
private Long regionId;
private Long schoolId;
private Long schoolGradeId;
private Long schoolClassId;
private Long subjectId;
private String isDefault;
private String status;
private String tenantId;
@TableLogic
private String delFlag;
// 非数据库字段用于VO展示
@TableField(exist = false)
private String schoolName;
@TableField(exist = false)
private String gradeName;
@TableField(exist = false)
private String className;
@TableField(exist = false)
private String subjectName;
}
```
#### 6.2.2 修改 PgMember.java
删除以下字段:
- identityType
- regionId
- regionIds@TableField(exist = false)
- schoolId
- schoolGradeId
- schoolClassId
**保留字段**
- unionId微信多应用打通需要
#### 6.2.3 新建 Mapper
- PgMemberEducationMapper.java
#### 6.2.4 修改 H5 Service
**H5MemberServiceImpl.java 主要改动**
1. `getEducation()``getEducations()` 返回列表
2. `saveEducation()` 支持新增/编辑
3. `deleteEducation(Long educationId)` 按ID删除
4. 新增 `setDefaultEducation(Long educationId)` 设置默认
### 6.3 管理后台前端改造
#### 6.3.1 会员列表页index.vue
**删除内容**
```vue
<!-- 删除:身份类型筛选 -->
<el-form-item label="身份类型">
<el-select v-model="queryParams.identityType" ... />
</el-form-item>
<!-- 删除:身份类型列 -->
<el-table-column prop="identityType" label="身份类型" ... />
```
#### 6.3.2 会员编辑弹窗MemberDialog.vue
**删除内容**
```vue
<!-- 删除:身份类型选择 -->
<el-form-item label="身份类型" prop="identityType">
<el-radio-group v-model="form.identityType" ... />
</el-form-item>
<!-- 删除:教师信息区块 -->
<template v-if="form.identityType === '2'">
<el-divider>学校信息(教师必填)</el-divider>
<!-- 区域、学校、年级、班级选择 -->
</template>
```
#### 6.3.3 新建会员详情页
**MemberDetail.vue**(新建)
```vue
<template>
<el-dialog v-model="visible" title="会员详情" width="900px">
<el-tabs v-model="activeTab">
<el-tab-pane label="基本信息" name="basic">
<!-- 会员基本信息展示 -->
</el-tab-pane>
<el-tab-pane label="教育身份" name="education">
<EducationTab :member-id="memberId" />
</el-tab-pane>
<el-tab-pane label="绑定学生" name="students">
<!-- 学生列表 -->
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
```
#### 6.3.4 新建教育身份Tab
**EducationTab.vue**(新建)
```vue
<template>
<div>
<el-button type="primary" @click="handleAdd">添加教育身份</el-button>
<el-table :data="educationList">
<el-table-column prop="schoolName" label="学校" />
<el-table-column prop="gradeName" label="年级" />
<el-table-column label="班级">
<template #default="{ row }">
{{ row.classNames?.join('、') }}
</template>
</el-table-column>
<el-table-column prop="subjectName" label="学科" />
<el-table-column prop="isDefault" label="默认" width="80">
<template #default="{ row }">
<el-tag v-if="row.isDefault === '1'" type="success"></el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button link @click="handleEdit(row)">编辑</el-button>
<el-button link @click="handleSetDefault(row)">设为默认</el-button>
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 编辑弹窗 -->
<EducationDialog ref="dialogRef" @success="loadData" />
</div>
</template>
```
### 6.4 H5前端改造
#### 6.4.1 user.ts 修改
```typescript
// 删除
identityType: string
// 修改
education: any // 单个 →
educations: any[] // 多个
```
#### 6.4.2 userCenter/index.vue 修改
支持展示多个教育身份,而不是只展示一个。
#### 6.4.3 TeacherIdentityForm.vue 修改
新增 `educationId` 字段用于编辑。
---
## 七、文件改动清单
### 7.1 数据库
| 文件/操作 | 类型 |
|-----------|------|
| DDL: pg_member_education | 新建表(含 school_class_id |
| DML: 数据迁移脚本 | 执行 |
| DDL: pg_member 删除字段 | 修改表 |
### 7.2 后端(共 12+ 文件)
| 文件 | 类型 | 说明 |
|------|------|------|
| `member/domain/PgMember.java` | 修改 | 删除5个字段保留unionId |
| `member/domain/PgMemberEducation.java` | 新建 | |
| `member/mapper/PgMemberEducationMapper.java` | 新建 | |
| `member/service/PgMemberEducationService.java` | 新建 | |
| `member/service/impl/PgMemberEducationServiceImpl.java` | 新建 | |
| `member/controller/PgMemberController.java` | 修改 | 删除身份类型相关 |
| `member/service/impl/PgMemberServiceImpl.java` | 修改 | |
| `h5/domain/dto/H5EducationDto.java` | 修改 | 添加educationId |
| `h5/domain/vo/H5EducationVo.java` | 修改 | |
| `h5/domain/vo/H5MemberInfoVo.java` | 修改 | 删除identityType |
| `h5/controller/H5MemberController.java` | 修改 | 接口调整 |
| `h5/service/impl/H5MemberServiceImpl.java` | 重构 | 教育相关逻辑 |
### 7.3 管理后台前端(共 8+ 文件)
| 文件 | 类型 | 说明 |
|------|------|------|
| `views/business/member/index.vue` | 修改 | 删除身份类型 |
| `views/business/member/components/MemberDialog.vue` | 重构 | 删除教师信息 |
| `views/business/member/components/MemberDetail.vue` | 新建 | 会员详情 |
| `views/business/member/components/EducationTab.vue` | 新建 | 教育身份Tab |
| `views/business/member/components/EducationDialog.vue` | 新建 | 教育身份编辑 |
| `api/pangu/member.js` | 修改 | |
| `api/pangu/memberEducation.js` | 新建 | |
### 7.4 H5前端共 5+ 文件)
| 文件 | 类型 | 说明 |
|------|------|------|
| `stores/user.ts` | 修改 | 删除identityType |
| `views/userCenter/index.vue` | 修改 | 支持多教育身份 |
| `components/TeacherIdentityForm.vue` | 修改 | 添加educationId |
| `api/user.js` | 修改 | 接口调整 |
| `views/register/index.vue` | 可能修改 | 如有身份类型相关 |
---
## 八、测试要点
| 场景 | 测试内容 |
|------|----------|
| 数据迁移 | 现有教师数据正确迁移到新表 |
| H5-新增教育身份 | 首次添加、多次添加(每班一条记录) |
| H5-编辑教育身份 | 修改学校/年级/班级/学科 |
| H5-删除教育身份 | 删除非默认、删除默认 |
| H5-设置默认 | 切换默认身份 |
| H5-多教育身份 | 一个老师添加多条教育身份(教多个班) |
| 管理后台-会员列表 | 不显示身份类型 |
| 管理后台-会员详情 | 查看多个教育身份 |
| 管理后台-教育身份管理 | 增删改查 |
---
## 九、上线计划
| 步骤 | 内容 | 说明 |
|------|------|------|
| 1 | 备份数据库 | 全量备份 pg_member |
| 2 | 执行建表DDL | 创建新表 |
| 3 | 执行数据迁移 | 迁移现有教育数据 |
| 4 | 部署后端 | 新代码 |
| 5 | 部署管理后台前端 | 新代码 |
| 6 | 部署H5前端 | 新代码 |
| 7 | 验证测试 | 回归测试 |
| 8 | 执行删除字段DDL | 确认无问题后 |
---
## 十、回滚方案
1. 后端代码回滚
2. 前端代码回滚
3. 数据库:
- 从新表恢复数据到 pg_member
- 删除新建的两张表
---
## 十一、风险评估
| 风险 | 等级 | 应对措施 |
|------|------|----------|
| 数据迁移丢失 | 高 | 完整备份,测试环境验证 |
| 接口不兼容 | 高 | 前后端同步上线 |
| 性能问题 | 低 | 新表已加索引 |
| 业务中断 | 中 | 选择低峰期上线 |
---
## 附录A现有数据统计上线前执行
```sql
-- 统计需要迁移的教育数据
SELECT COUNT(*) FROM pg_member
WHERE identity_type = '2' AND school_id IS NOT NULL AND del_flag = '0';
-- 统计有班级信息的数据
SELECT COUNT(*) FROM pg_member
WHERE identity_type = '2' AND school_class_id IS NOT NULL AND del_flag = '0';
```
---
## 附录B学生多会员绑定重构2026-02-03
### B.1 需求说明
**原设计**:一个学生只能被一个会员绑定(`pg_student.member_id` 单值字段)
**新设计**:一个学生可以被多个会员绑定(如爸爸和妈妈都能绑定同一个孩子)
### B.2 数据库变更
#### 新建关联表 `pg_member_student`
```sql
CREATE TABLE pg_member_student (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
member_id BIGINT NOT NULL COMMENT '会员ID',
student_id BIGINT NOT NULL COMMENT '学生ID',
relation VARCHAR(20) COMMENT '关系(父亲/母亲/其他)',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_member_student (member_id, student_id),
KEY idx_member_id (member_id),
KEY idx_student_id (student_id)
) COMMENT='会员学生关联表';
```
#### 数据迁移
```sql
-- 迁移现有绑定关系
INSERT IGNORE INTO pg_member_student (member_id, student_id)
SELECT member_id, student_id FROM pg_student WHERE member_id IS NOT NULL;
-- 移除 pg_student.member_id 字段
ALTER TABLE pg_student DROP COLUMN member_id;
```
### B.3 后端变更
| 文件 | 变更 |
|------|------|
| PgMemberStudent.java | 新建关联实体 |
| PgMemberStudentMapper.java | 新建 Mapper |
| PgStudent.java | 删除 memberId 字段 |
| StudentVo.java | memberCount + List<MemberSimpleVo> members |
| PgStudentServiceImpl.java | 绑定/解绑/查询改用关联表 |
| H5MemberServiceImpl.java | 绑定/解绑/查询改用关联表 |
| H5StudentVo.java | 新增 relation 字段 |
| H5StudentBindDto.java | 新增 relation 字段 |
### B.4 前端变更
| 文件 | 变更 |
|------|------|
| MemberDialog.vue | 解绑接口路径调整 |
| StudentSelectDialog.vue | 绑定状态显示多会员数量 |
### B.5 关系模型
```
变更前:会员 --1:N--> 学生(通过 pg_student.member_id
变更后:会员 --N:M--> 学生(通过 pg_member_student 关联表)
```
---
## 附录CH5 前端同步变更
> 完成时间2026-02-03
> 项目user_authentication_center_front
### C.1 变更概述
H5 前端同步适配后端「会员教育信息重构」和「学生多会员绑定」变更。
### C.2 注册流程简化
删除注册页面的身份类型选择步骤:
| 变更前 | 变更后 |
|--------|--------|
| 步骤1: 基本信息 → 步骤2: 身份选择 → 步骤3: 详细信息 | 仅基本信息,注册后跳转用户中心 |
**涉及文件**
- `views/register/index.vue` - 删除身份选择和详细信息步骤
### C.3 教育身份改为数组
| 文件 | 变更 |
|------|------|
| `stores/user.ts` | 删除 `identityType``education: any` → `educations: any[]` |
| `api/user.js` | 接口路径 `/h5/member/education``/h5/member/educations` |
| `views/userCenter/index.vue` | 列表展示多教育身份,支持删除指定 ID |
**接口变更**
```javascript
// 变更前
POST /h5/member/education // 新增(覆盖式)
GET /h5/member/education // 获取单个
DELETE /h5/member/education // 删除
// 变更后
POST /h5/member/educations // 新增
PUT /h5/member/educations/{id} // 修改
GET /h5/member/educations // 获取列表
DELETE /h5/member/educations/{id} // 删除指定
PUT /h5/member/educations/{id}/default // 设为默认
```
### C.4 基础数据前端缓存
新建 `stores/baseData.ts` 实现区域和学科数据的前端缓存:
```typescript
// 缓存结构
{
regionTree: [], // 区域树
subjects: [], // 学科列表
expire: timestamp, // 过期时间24小时
}
// 存储位置
localStorage.setItem('h5:baseData', JSON.stringify(data))
```
**数据流**
```
用户登录成功
强制刷新基础数据fetchRegionTree(true), fetchSubjects(true)
存入 Pinia Store + localStorage
后续页面从 Store 读取,秒加载
```
**涉及文件**
| 文件 | 变更 |
|------|------|
| `stores/baseData.ts` | **新建** - 基础数据 Store |
| `views/login/index.vue` | 登录成功后调用 `fetchRegionTree(true)``fetchSubjects(true)` |
| `components/TeacherIdentityForm.vue` | 区域和学科使用 Store 缓存 |
| `components/ParentChildrenForm.vue` | 区域使用 Store 缓存 |
### C.5 缓存策略说明
| 数据 | 是否缓存 | 原因 |
|------|----------|------|
| 区域树 `/h5/base/regions` | ✅ 缓存 | 数据量大且变化少 |
| 学科列表 `/h5/base/subjects` | ✅ 缓存 | 基础数据,变化少 |
| 学校列表 `/h5/base/schools` | ❌ 不缓存 | 依赖区域动态查询 |
| 年级列表 `/h5/base/grades` | ❌ 不缓存 | 依赖学校动态查询 |
| 班级列表 `/h5/base/classes` | ❌ 不缓存 | 依赖学校+年级动态查询 |