399 lines
12 KiB
Markdown
399 lines
12 KiB
Markdown
# 心理测评问题修复说明
|
||
|
||
## 修复日期
|
||
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: 每次选择答案后都会立即自动保存到数据库,不需要手动保存。
|