xinli/心理测评问题修复说明.md

399 lines
12 KiB
Markdown
Raw Normal View History

2025-12-02 15:12:55 +08:00
# 心理测评问题修复说明
## 修复日期
2025年12月1日
## 问题清单
### 问题1用户档案与量表权限管理用户数量不一致 ✅
**问题描述**:
- 用户档案显示 3014 个用户
- 量表权限管理显示 3016 个用户
- 数据不一致导致分配权限时出现困惑
**根本原因**:
两个页面使用了不同的API接口
- **用户档案页面**:使用 `listStudentProfile` 接口(`/psychology/profile/student/list`
- 只查询拥有**学员角色**的用户 → 3014个
- **量表权限管理**:使用 `listProfile` 接口(`/psychology/profile/list`
- 查询**所有用户档案** → 3016个包括非学员用户
**修复方案**:
修改量表权限管理的用户查询逻辑,统一使用 `listStudentProfile` 接口,只查询学员用户,与用户档案页面保持一致。
**修改文件**:
- `xinli-ui/src/views/psychology/permission/index.vue`
**修改内容**:
1. **导入接口更改** (第300行)
```javascript
// 修改前
import { listProfile } from "@/api/psychology/profile";
// 修改后
import { listStudentProfile } from "@/api/psychology/profile";
```
2. **加载监区选项** (第556行)
```javascript
// 修改前
listProfile({ pageNum: 1, pageSize: 10000, status: undefined }).then(response => {
// 修改后
listStudentProfile({ pageNum: 1, pageSize: 10000 }).then(response => {
```
3. **获取用户选择列表** (第599行)
```javascript
// 修改前
return listProfile(query).then(response => {
// 修改后
return listStudentProfile(query).then(response => {
```
4. **批量获取所有用户** (第675行)
```javascript
// 修改前
const response = await listProfile({
// 修改后
const response = await listStudentProfile({
```
5. **保留查询参数配置** (第346-353行)
```javascript
userQueryParams: {
pageNum: 1,
pageSize: 10,
infoNumber: undefined,
userName: undefined,
prisonArea: undefined,
status: undefined // 不限制状态
}
```
**修复效果**:
- ✅ 量表权限管理和用户档案显示相同数量的用户都是3014
- ✅ 只显示学员角色的用户,数据更准确
- ✅ 数据统计保持一致性
---
### 问题2测评状态显示和管理 ✅
**问题描述**:
1. 用户退出测评后,状态显示为"进行中"而不是"已暂停"
2. 希望区分"进行中"(正在答题)、"已暂停"(退出或暂停)、"已完成"(提交完成)
3. 暂停和退出都要保留用户填写的内容
**状态定义**:
```
status = '0' - 进行中(正在答题,未退出)
status = '1' - 已完成(已提交)
status = '2' - 已作废(删除或作废)
status = '3' - 已暂停(用户暂停或退出)
```
**现有逻辑验证**:
#### ✅ 暂停功能
**前端** (`xinli-ui/src/views/psychology/assessment/taking.vue` 第494-503行):
```javascript
handlePause() {
this.$modal.confirm('确定要暂停测评吗?您可以稍后继续完成。').then(() => {
pauseAssessment(this.assessmentId).then(() => {
this.$modal.msgSuccess("测评已暂停");
// 跳转回列表页
this.$router.push(isStudent ? '/student/tests' : '/psychology/assessment');
});
});
}
```
**后端** (`PsyAssessmentMapper.xml` 第142-152行):
```xml
<update id="pauseAssessment">
update psy_assessment
<set>
pause_time = sysdate(),
pause_count = pause_count + 1,
status = '3', <!-- 设置为已暂停 -->
update_time = sysdate()
</set>
where assessment_id = #{assessmentId}
</update>
```
#### ✅ 退出功能
**前端** (`xinli-ui/src/views/psychology/assessment/taking.vue` 第506-528行):
```javascript
handleExit() {
this.$modal.confirm('确定要退出测评吗?已答题目将会保存。').then(() => {
this.loading = true;
// 先等待一小段时间,确保最后的答案保存请求发出
setTimeout(() => {
// 退出前先暂停测评,保存进度
pauseAssessment(this.assessmentId).then(() => { // ✅ 调用暂停接口
this.loading = false;
this.$modal.msgSuccess("测评进度已保存");
// 跳转回列表页
this.$router.push(isStudent ? '/student/tests' : '/psychology/assessment');
});
}, 500); // 等待500ms确保答案保存请求已发送
});
}
```
**说明**: 退出功能也调用 `pauseAssessment`,会将状态设为 `'3'`(已暂停)
#### ✅ 提交功能
**前端** (`xinli-ui/src/views/psychology/assessment/taking.vue` 第531-560行):
```javascript
handleSubmit() {
if (!this.isComplete) {
const remaining = this.itemList.length - this.answeredCount;
this.$modal.msgError(`还有 ${remaining} 道题未作答,请完成后再提交`);
return;
}
this.$modal.confirm('确定要提交测评吗?提交后将不能修改。').then(() => {
this.loading = true;
submitAssessment(this.assessmentId).then(response => {
this.loading = false;
this.$modal.msgSuccess("测评已提交,报告正在生成中...");
// 跳转到报告页面
});
});
}
```
**后端** (`PsyAssessmentController.java` 第436-445行):
```java
// 更新测评状态为已完成
assessment.setStatus("1"); // ✅ 设置为已完成
assessment.setSubmitTime(new Date());
if (assessment.getStartTime() != null) {
long completeSeconds = (System.currentTimeMillis() - assessment.getStartTime().getTime()) / 1000;
assessment.setCompleteTime((int) completeSeconds);
}
assessmentService.updateAssessment(assessment);
```
#### ✅ 继续答题功能
**前端** (`xinli-ui/src/views/psychology/assessment/index.vue` 第103-106行):
```vue
<el-button
@click="handleContinue(scope.row)"
v-if="scope.row.status === '0' || scope.row.status === '3'"
>继续答题</el-button>
```
**说明**: 只有"进行中"(`status='0'`)或"已暂停"(`status='3'`)状态才显示"继续答题"按钮
#### ✅ 恢复测评
**后端** (`PsyAssessmentMapper.xml` 第154-163行):
```xml
<update id="resumeAssessment">
update psy_assessment
<set>
resume_time = sysdate(),
status = '0', <!-- 恢复为进行中 -->
update_time = sysdate()
</set>
where assessment_id = #{assessmentId}
</update>
```
**说明**: 点击"继续答题"时会调用 `resumeAssessment`,将状态从 `'3'` 改为 `'0'`
#### ✅ 答案自动保存
**前端** (`xinli-ui/src/views/psychology/assessment/taking.vue`):
```javascript
// 每次选择答案时自动保存
handleAnswerChange() {
// ... 保存逻辑
this.saveCurrentAnswer();
}
```
**说明**:
- 用户每选择一个答案都会自动保存到数据库
- 退出或暂停时不会丢失已答题目
- 继续答题时可以从上次位置继续
### 测评状态流转图
```
开始测评 ──> status='0'(进行中)
├──> 点击"暂停" ──> status='3'(已暂停)──> 点击"继续答题" ──> status='0'
├──> 点击"退出" ──> status='3'(已暂停)──> 点击"继续答题" ──> status='0'
└──> 点击"提交" ──> status='1'(已完成)
```
### 测评管理列表显示
**文件**: `xinli-ui/src/views/psychology/assessment/index.vue`
**状态显示** (第81-87行):
```vue
<el-table-column label="状态" align="center" prop="status" width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === '0'" type="info">进行中</el-tag>
<el-tag v-else-if="scope.row.status === '1'" type="success">已完成</el-tag>
<el-tag v-else-if="scope.row.status === '2'" type="danger">已作废</el-tag>
<el-tag v-else-if="scope.row.status === '3'" type="warning">已暂停</el-tag>
</template>
</el-table-column>
```
**状态筛选** (第22-28行):
```vue
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable>
<el-option label="进行中" value="0" />
<el-option label="已完成" value="1" />
<el-option label="已作废" value="2" />
<el-option label="已暂停" value="3" />
</el-select>
</el-form-item>
```
## 修复验证
### 验证步骤
#### 问题1验证
1. 登录系统
2. 进入"心理 → 用户档案",查看总数 → 应显示 **3014**(学员用户)
3. 进入"心理 → 量表权限管理",点击"分配用户"
4. 不添加任何筛选条件,查看用户列表总数 → 应显示 **3014**(与用户档案一致)
5. ✅ 数量一致,都显示学员角色用户
**说明**: 修改后两个页面都只显示拥有学员角色的用户3014个不再显示其他角色的用户如管理员等2个用户
#### 问题2验证
**测试场景1暂停测评**
1. 开始一个测评
2. 答几道题
3. 点击"暂停"按钮
4. 返回测评管理列表
5. ✅ 该测评显示为"已暂停"状态(黄色标签)
6. 点击"继续答题"
7. ✅ 之前答的题目答案都保留
**测试场景2退出测评**
1. 开始一个测评
2. 答几道题
3. 点击"退出"按钮
4. 返回测评管理列表
5. ✅ 该测评显示为"已暂停"状态(黄色标签)
6. 点击"继续答题"
7. ✅ 之前答的题目答案都保留
**测试场景3完成测评**
1. 开始一个测评
2. 答完所有题目
3. 点击"提交测评"
4. 返回测评管理列表
5. ✅ 该测评显示为"已完成"状态(绿色标签)
6. ✅ 不再显示"继续答题"按钮
7. ✅ 显示"查看答题"和"查看报告"按钮
## 技术说明
### 数据库表结构
```sql
-- psy_assessment 测评表
CREATE TABLE psy_assessment (
assessment_id BIGINT PRIMARY KEY,
scale_id BIGINT,
assessee_name VARCHAR(100),
status CHAR(1), -- 0:进行中 1:已完成 2:已作废 3:已暂停
start_time DATETIME,
pause_time DATETIME,
resume_time DATETIME,
submit_time DATETIME,
pause_count INT DEFAULT 0,
complete_time INT,
total_score DECIMAL(10,2),
-- ... 其他字段
);
```
### API接口
- `POST /psychology/assessment/pause/{assessmentId}` - 暂停测评
- `POST /psychology/assessment/resume/{assessmentId}` - 恢复测评
- `POST /psychology/assessment/submit/{assessmentId}` - 提交测评
- `POST /psychology/assessment/answer/save` - 保存答案
## 总结
### 问题1用户数量不一致 ✅
**修复方式**: 统一使用学员档案接口(`listStudentProfile`),只查询学员角色用户
**影响范围**: 量表权限管理的用户选择对话框
**预期效果**:
- 用户档案和量表权限管理显示相同数量的用户都是3014
- 只显示学员用户,不包括其他角色的用户
- 数据来源统一,避免混淆
### 问题2测评状态管理 ✅
**验证结果**: 现有逻辑已正确实现
**核心功能**:
1. ✅ 退出测评会设置 status='3'(已暂停)
2. ✅ 暂停测评会设置 status='3'(已暂停)
3. ✅ 提交测评会设置 status='1'(已完成)
4. ✅ 继续答题会恢复 status='0'(进行中)
5. ✅ 所有答案都会自动保存,不会丢失
6. ✅ 测评列表正确显示各种状态
**如果用户仍然遇到"退出显示进行中"的问题,请检查**:
1. 浏览器缓存是否清除
2. 后端服务是否重启
3. 数据库中 psy_assessment 表的 status 字段值
4. 网络请求是否成功F12查看Network
5. 是否有其他地方修改了状态
## 部署说明
1. **前端部署**:
- 修改文件: `xinli-ui/src/views/psychology/permission/index.vue`
- 重新编译: `npm run build`
- 部署到服务器
2. **无需后端修改**:
- 后端逻辑已经正确实现
- 无需重新部署
3. **验证步骤**:
- 清除浏览器缓存
- 刷新页面
- 按照验证步骤测试
## 附录:常见问题
**Q: 为什么要查询所有状态的用户?**
A: 因为即使用户被停用或删除,其历史测评记录和权限仍然存在,需要能够管理和查看。
**Q: 状态'0'和'3'有什么区别?**
A:
- status='0'(进行中): 用户正在答题页面答题
- status='3'(已暂停): 用户点击了暂停或退出按钮,离开了答题页面
**Q: 如何区分正在答题和已退出?**
A:
- 在测评列表中status='0'和'3'都显示"继续答题"按钮
- 区别在于status='0'可能是打开了答题页面但没有答题status='3'是明确点击了暂停/退出
**Q: 答案什么时候保存?**
A: 每次选择答案后都会立即自动保存到数据库,不需要手动保存。