修改问题

This commit is contained in:
xiao12feng 2025-11-28 17:31:13 +08:00
parent 12d943db6c
commit 66773d3577
15 changed files with 679 additions and 221 deletions

View File

@ -549,13 +549,19 @@ public class PsyUserProfileServiceImpl implements IPsyUserProfileService
if (failureNum > 0) if (failureNum > 0)
{ {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); StringBuilder resultMsg = new StringBuilder();
// 如果有成功的数据先显示成功信息
if (successNum > 0) if (successNum > 0)
{ {
failureMsg.append("<br/><br/>").append(successMsg); resultMsg.append(successMsg).append("<br/><br/>");
} }
importProgressManager.finishFailure(progressKey, failureMsg.toString()); // 再显示失败信息
throw new ServiceException(failureMsg.toString()); failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
resultMsg.append(failureMsg);
String finalMsg = resultMsg.toString();
importProgressManager.finishFailure(progressKey, finalMsg);
throw new ServiceException(finalMsg);
} }
if (successNum > 0) if (successNum > 0)

View File

@ -26,6 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" /> <result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="remark" column="remark" /> <result property="remark" column="remark" />
<result property="sourceType" column="source_type" />
</resultMap> </resultMap>
<sql id="selectScaleVo"> <sql id="selectScaleVo">
@ -34,7 +35,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
COALESCE(COUNT(i.item_id), 0) as item_count, COALESCE(COUNT(i.item_id), 0) as item_count,
s.estimated_time, s.target_population, s.estimated_time, s.target_population,
s.author, s.source, s.reference, s.status, s.sort_order, s.create_by, s.create_time, s.author, s.source, s.reference, s.status, s.sort_order, s.create_by, s.create_time,
s.update_by, s.update_time, s.remark s.update_by, s.update_time, s.remark,
'scale' as source_type
from psy_scale s from psy_scale s
left join psy_scale_item i on s.scale_id = i.scale_id left join psy_scale_item i on s.scale_id = i.scale_id
</sql> </sql>

View File

@ -20,6 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time" /> <result property="updateTime" column="update_time" />
<result property="remark" column="remark" /> <result property="remark" column="remark" />
<result property="scaleName" column="scale_name" /> <result property="scaleName" column="scale_name" />
<result property="sourceType" column="source_type" />
<result property="deptName" column="dept_name" /> <result property="deptName" column="dept_name" />
<result property="roleName" column="role_name" /> <result property="roleName" column="role_name" />
<result property="userName" column="user_name" /> <result property="userName" column="user_name" />

View File

@ -182,7 +182,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sentenceEndDate != null">sentence_end_date = #{sentenceEndDate}, </if> <if test="sentenceEndDate != null">sentence_end_date = #{sentenceEndDate}, </if>
<if test="entryDate != null">entry_date = #{entryDate}, </if> <if test="entryDate != null">entry_date = #{entryDate}, </if>
<if test="infoNumber != null">info_number = #{infoNumber}, </if> <if test="infoNumber != null">info_number = #{infoNumber}, </if>
<if test="status != null and status != ''">status = #{status}, </if>
<if test="updateBy != null">update_by = #{updateBy}, </if> <if test="updateBy != null">update_by = #{updateBy}, </if>
<if test="remark != null">remark = #{remark}, </if> <if test="remark != null">remark = #{remark}, </if>
update_time = sysdate() update_time = sysdate()

View File

@ -235,7 +235,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '心理测评管理', title: '心理测评管理',
icon: 'chart', icon: 'chart',
roles: ['admin'] roles: ['admin', 'teacher']
}, },
children: [ children: [
// 量表管理 // 量表管理
@ -246,7 +246,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '量表管理', title: '量表管理',
icon: 'table', icon: 'table',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 题目管理(隐藏菜单,通过量表管理页面进入) // 题目管理(隐藏菜单,通过量表管理页面进入)
@ -257,7 +257,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '题目管理', title: '题目管理',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 因子管理(隐藏菜单,通过量表管理页面进入) // 因子管理(隐藏菜单,通过量表管理页面进入)
@ -268,7 +268,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '因子管理', title: '因子管理',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 测评管理 // 测评管理
@ -279,7 +279,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '测评管理', title: '测评管理',
icon: 'edit', icon: 'edit',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
{ {
@ -289,7 +289,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '全员测评分析', title: '全员测评分析',
icon: 'chart', icon: 'chart',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 开始测评 // 开始测评
@ -300,7 +300,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '开始测评', title: '开始测评',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 测评进行中 // 测评进行中
@ -311,7 +311,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '测评中', title: '测评中',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 测评报告 // 测评报告
@ -322,7 +322,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '测评报告', title: '测评报告',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 报告管理 // 报告管理
@ -333,7 +333,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '报告管理', title: '报告管理',
icon: 'document', icon: 'document',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 报告详情 // 报告详情
@ -344,7 +344,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '报告详情', title: '报告详情',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 综合评估 // 综合评估
@ -355,7 +355,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '综合评估', title: '综合评估',
icon: 'chart', icon: 'chart',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 量表权限管理 // 量表权限管理
@ -366,7 +366,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '量表权限管理', title: '量表权限管理',
icon: 'lock', icon: 'lock',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 用户量表权限分配 // 用户量表权限分配
@ -377,7 +377,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '分配量表权限', title: '分配量表权限',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 解释配置 // 解释配置
@ -388,7 +388,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '解释配置', title: '解释配置',
icon: 'config', icon: 'config',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 用户档案 // 用户档案
@ -399,7 +399,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '用户档案', title: '用户档案',
icon: 'user', icon: 'user',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 自定义问卷 // 自定义问卷
@ -410,7 +410,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '自定义问卷', title: '自定义问卷',
icon: 'edit', icon: 'edit',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 问卷开始答题 // 问卷开始答题
@ -443,7 +443,7 @@ export const dynamicRoutes = [
hidden: true, hidden: true,
meta: { meta: {
title: '问卷题目管理', title: '问卷题目管理',
roles: ['admin'] roles: ['admin', 'teacher']
} }
}, },
// 主观题评分 // 主观题评分
@ -454,7 +454,7 @@ export const dynamicRoutes = [
meta: { meta: {
title: '主观题评分', title: '主观题评分',
icon: 'edit', icon: 'edit',
roles: ['admin'] roles: ['admin', 'teacher']
} }
} }
] ]

View File

@ -100,6 +100,9 @@ service.interceptors.response.use(res => {
}) })
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 403) {
// 403权限不足错误静默处理不显示提示
return Promise.reject('no_permission')
} else if (code === 500) { } else if (code === 500) {
Message({ message: msg, type: 'error' }) Message({ message: msg, type: 'error' })
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg))
@ -116,6 +119,12 @@ service.interceptors.response.use(res => {
async error => { async error => {
console.log('err' + error) console.log('err' + error)
let { message } = error let { message } = error
// 403权限错误静默处理
if (error.response && error.response.status === 403) {
return Promise.reject('no_permission')
}
// 对于blob类型的错误响应尝试解析错误信息 // 对于blob类型的错误响应尝试解析错误信息
if (error.response && error.response.config && if (error.response && error.response.config &&
(error.response.config.responseType === 'blob' || error.response.config.responseType === 'arraybuffer') && (error.response.config.responseType === 'blob' || error.response.config.responseType === 'arraybuffer') &&

View File

@ -41,7 +41,7 @@
icon="el-icon-plus" icon="el-icon-plus"
size="mini" size="mini"
@click="handleStartAssessment" @click="handleStartAssessment"
v-hasPermi="['psychology:assessment:add']" v-hasPermi="['psychology:assessment:start']"
>开始测评</el-button> >开始测评</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
@ -164,7 +164,6 @@
<el-divider content-position="left">答题详情</el-divider> <el-divider content-position="left">答题详情</el-divider>
<el-table :data="answerDetailList" border style="width: 100%"> <el-table :data="answerDetailList" border style="width: 100%">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="题目序号" prop="itemNumber" width="100" align="center" /> <el-table-column label="题目序号" prop="itemNumber" width="100" align="center" />
<el-table-column label="题目内容" prop="itemContent" min-width="200" :show-overflow-tooltip="true" /> <el-table-column label="题目内容" prop="itemContent" min-width="200" :show-overflow-tooltip="true" />
<el-table-column label="题目类型" prop="itemType" width="100" align="center"> <el-table-column label="题目类型" prop="itemType" width="100" align="center">

View File

@ -145,8 +145,9 @@ export default {
const userId = this.$store.getters.id; const userId = this.$store.getters.id;
const roles = this.$store.getters.roles || []; const roles = this.$store.getters.roles || [];
// userId === 1 roles 'admin' // admin
const isAdmin = userId === 1 || (roles && roles.includes('admin')); //
const isAdmin = roles && roles.includes('admin');
// //
if (isAdmin) { if (isAdmin) {

View File

@ -38,10 +38,11 @@
size="small" size="small"
@click="speakText(currentItem.itemContent)" @click="speakText(currentItem.itemContent)"
:disabled="!isTtsSupported" :disabled="!isTtsSupported"
class="tts-btn" :class="['tts-btn', isSpeaking ? 'speaking' : '']"
title="朗读题干" title="朗读题干"
> >
<img :src="voiceIcon" alt="朗读题干" class="tts-icon" /> <i :class="isSpeaking ? 'el-icon-video-pause' : 'el-icon-service'"
style="font-size: 18px; color: #409EFF;"></i>
</el-button> </el-button>
</div> </div>
@ -55,10 +56,11 @@
size="mini" size="mini"
@click="speakText(option.optionContent)" @click="speakText(option.optionContent)"
:disabled="!isTtsSupported" :disabled="!isTtsSupported"
class="option-tts-btn" :class="['option-tts-btn', isSpeaking ? 'speaking' : '']"
title="朗读选项" title="朗读选项"
> >
<img :src="voiceIcon" alt="朗读选项" class="tts-icon" /> <i :class="isSpeaking ? 'el-icon-video-pause' : 'el-icon-service'"
style="font-size: 16px; color: #409EFF;"></i>
</el-button> </el-button>
</div> </div>
</el-radio-group> </el-radio-group>
@ -74,10 +76,11 @@
size="mini" size="mini"
@click="speakText(option.optionContent)" @click="speakText(option.optionContent)"
:disabled="!isTtsSupported" :disabled="!isTtsSupported"
class="option-tts-btn" :class="['option-tts-btn', isSpeaking ? 'speaking' : '']"
title="朗读选项" title="朗读选项"
> >
<img :src="voiceIcon" alt="朗读选项" class="tts-icon" /> <i :class="isSpeaking ? 'el-icon-video-pause' : 'el-icon-service'"
style="font-size: 16px; color: #409EFF;"></i>
</el-button> </el-button>
</div> </div>
</el-checkbox-group> </el-checkbox-group>
@ -134,7 +137,8 @@ export default {
isTtsSupported: false, isTtsSupported: false,
synth: null, synth: null,
currentUtterance: null, currentUtterance: null,
voiceIcon voiceIcon,
isSpeaking: false
}; };
}, },
computed: { computed: {
@ -208,49 +212,62 @@ export default {
/** 朗读文本 */ /** 朗读文本 */
speakText(text) { speakText(text) {
if (!this.isTtsSupported || !text || !text.trim()) { if (!this.isTtsSupported || !text || !text.trim()) {
this.$message.warning('浏览器不支持语音播放功能');
return; return;
} }
//
if (this.isSpeaking) {
this.stopSpeaking();
return;
}
this.stopSpeaking(); this.stopSpeaking();
this.currentUtterance = new SpeechSynthesisUtterance(text.trim()); this.currentUtterance = new SpeechSynthesisUtterance(text.trim());
this.currentUtterance.lang = 'zh-CN'; this.currentUtterance.lang = 'zh-CN';
this.currentUtterance.volume = 1.0; this.currentUtterance.volume = 1.0; //
this.currentUtterance.rate = 1.0; this.currentUtterance.rate = 0.9; //
this.currentUtterance.pitch = 1.0; this.currentUtterance.pitch = 1.0;
//
const voices = this.synth.getVoices(); const voices = this.synth.getVoices();
const chineseVoice = voices.find(voice => voice.lang.includes('zh') || voice.lang.includes('CN')); //
const chineseVoice = voices.find(voice =>
voice.lang.includes('zh') ||
voice.lang.includes('CN') ||
voice.name.includes('中文') ||
voice.name.includes('Chinese')
);
if (chineseVoice) { if (chineseVoice) {
this.currentUtterance.voice = chineseVoice; this.currentUtterance.voice = chineseVoice;
} }
let hasStarted = false;
this.currentUtterance.onstart = () => { this.currentUtterance.onstart = () => {
hasStarted = true; this.isSpeaking = true;
}; };
this.currentUtterance.onend = () => {
this.isSpeaking = false;
};
this.currentUtterance.onerror = (event) => { this.currentUtterance.onerror = (event) => {
this.isSpeaking = false;
const errorType = event.error || ''; const errorType = event.error || '';
// interrupted canceled //
const ignoredErrors = ['interrupted', 'canceled']; const ignoredErrors = ['interrupted', 'canceled'];
if (ignoredErrors.includes(errorType)) { if (ignoredErrors.includes(errorType)) {
console.log('TTS 被中断(正常情况):', errorType);
return; return;
} }
console.error('TTS 错误:', event); console.error('TTS 错误:', event);
if (hasStarted) { //
return;
}
const seriousErrors = ['network-error', 'synthesis-failed', 'synthesis-unavailable', 'not-allowed'];
if (seriousErrors.includes(errorType)) {
this.$message.error('语音朗读失败:' + this.getErrorMessage(errorType));
} else if (errorType === 'text-too-long') {
this.$message.warning('文本过长,无法朗读');
}
}; };
try { try {
//
this.synth.speak(this.currentUtterance); this.synth.speak(this.currentUtterance);
} catch (error) { } catch (error) {
this.isSpeaking = false;
console.error('调用 speak 失败:', error); console.error('调用 speak 失败:', error);
this.$message.error('语音朗读失败:无法启动语音合成');
} }
}, },
/** 停止朗读 */ /** 停止朗读 */
@ -259,6 +276,7 @@ export default {
this.synth.cancel(); this.synth.cancel();
} }
this.currentUtterance = null; this.currentUtterance = null;
this.isSpeaking = false;
}, },
/** 错误信息 */ /** 错误信息 */
getErrorMessage(errorType) { getErrorMessage(errorType) {
@ -446,10 +464,26 @@ export default {
/** 退出 */ /** 退出 */
handleExit() { handleExit() {
this.$modal.confirm('确定要退出测评吗?已答题目将会保存。').then(() => { this.$modal.confirm('确定要退出测评吗?已答题目将会保存。').then(() => {
this.loading = true;
//
setTimeout(() => {
// 退
pauseAssessment(this.assessmentId).then(() => {
this.loading = false;
this.$modal.msgSuccess("测评进度已保存");
// //
const roles = this.$store.getters.roles || []; const roles = this.$store.getters.roles || [];
const isStudent = roles.some(role => role === 'student' || role.includes('学员')); const isStudent = roles.some(role => role === 'student' || role.includes('学员'));
this.$router.push(isStudent ? '/student/tests' : '/psychology/assessment'); this.$router.push(isStudent ? '/student/tests' : '/psychology/assessment');
}).catch(error => {
console.error('保存测评进度失败:', error);
this.loading = false;
// 使退
const roles = this.$store.getters.roles || [];
const isStudent = roles.some(role => role === 'student' || role.includes('学员'));
this.$router.push(isStudent ? '/student/tests' : '/psychology/assessment');
});
}, 500); // 500ms
}); });
}, },
/** 提交测评 */ /** 提交测评 */
@ -794,5 +828,37 @@ export default {
border-radius: 4px; border-radius: 4px;
} }
/* 语音播放时的动画效果 */
.tts-btn.speaking, .option-tts-btn.speaking {
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.tts-btn .el-icon-video-pause,
.option-tts-btn .el-icon-video-pause {
color: #E6A23C !important;
animation: rotate 2s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style> </style>

View File

@ -95,9 +95,10 @@
<span v-else style="color: #909399;">-</span> <span v-else style="color: #909399;">-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="部门名称" align="center" prop="deptName" width="150" /> <!-- 隐藏部门角色班级列 -->
<el-table-column label="角色名称" align="center" prop="roleName" width="150" /> <!-- <el-table-column label="部门名称" align="center" prop="deptName" width="150" /> -->
<el-table-column label="班级名称" align="center" prop="className" width="150" /> <!-- <el-table-column label="角色名称" align="center" prop="roleName" width="150" /> -->
<!-- <el-table-column label="班级名称" align="center" prop="className" width="150" /> -->
<el-table-column label="开始时间" align="center" prop="startTime" width="180"> <el-table-column label="开始时间" align="center" prop="startTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span> <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@ -252,6 +253,8 @@
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleUserQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleUserQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetUserQuery">重置</el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetUserQuery">重置</el-button>
<el-button type="success" icon="el-icon-check" size="mini" @click="handleSelectAllUsers">全选所有用户</el-button>
<el-button type="warning" icon="el-icon-close" size="mini" @click="handleDeselectAllUsers">取消全选</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-table <el-table
@ -745,6 +748,21 @@ export default {
this.updatingSelection = false; this.updatingSelection = false;
}); });
}, },
/** 全选所有用户按钮点击事件 */
handleSelectAllUsers() {
this.selectAllUsersUnderCurrentFilter();
},
/** 取消全选按钮点击事件 */
handleDeselectAllUsers() {
this.selectedUserIds = [];
this.cachedFilteredUsers = [];
this.$nextTick(() => {
if (this.$refs.userTable) {
this.$refs.userTable.clearSelection();
}
});
this.$message.success("已取消所有选择");
},
/** 搜索用户(远程搜索) */ /** 搜索用户(远程搜索) */
searchUsers(keyword) { searchUsers(keyword) {
if (!this.studentRoleId) { if (!this.studentRoleId) {

View File

@ -1,10 +1,10 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
<el-form-item label="用户名称" prop="userName"> <el-form-item label="罪犯姓名" prop="userName">
<el-input <el-input
v-model="queryParams.userName" v-model="queryParams.userName"
placeholder="请输入用户名称" placeholder="请输入罪犯姓名"
clearable clearable
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
@ -488,6 +488,10 @@ export default {
profileList: [], profileList: [],
// ID // ID
studentRoleId: null, studentRoleId: null,
// ID
studentUserIds: null,
//
studentUserTotal: 0,
// //
title: "", title: "",
// //
@ -600,10 +604,8 @@ export default {
this.stopImportProgressPolling() this.stopImportProgressPolling()
}, },
created() { created() {
this.getStudentRoleId().then(() => {
this.getList() this.getList()
this.loadFilterOptions() this.loadFilterOptions()
})
this.getDeptTree() this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => { this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg this.initPassword = response.msg
@ -643,17 +645,83 @@ export default {
}) })
}) })
}, },
/** 加载学员用户ID列表缓存 */
loadStudentUserIds() {
return new Promise((resolve, reject) => {
if (this.studentUserIds !== null) {
//
resolve(this.studentUserIds)
return
}
if (!this.studentRoleId) {
resolve(new Set())
return
}
// ID
const studentUserIds = new Set()
let pageNum = 1
const pageSize = 500 // 500
let total = 0
const fetchPage = () => {
return allocatedUserList({
roleId: this.studentRoleId,
status: '0',
pageNum: pageNum,
pageSize: pageSize
}).then(response => {
const rows = response.rows || []
const responseTotal = response.total || 0
if (total === 0 && responseTotal > 0) {
total = responseTotal
}
rows.forEach(user => {
if (user.userId) {
studentUserIds.add(user.userId)
}
})
//
if (rows.length === pageSize && (total === 0 || studentUserIds.size < total)) {
pageNum++
return fetchPage()
} else {
//
this.studentUserIds = studentUserIds
this.studentUserTotal = studentUserIds.size
resolve(studentUserIds)
}
}).catch(error => {
console.error("获取学员用户列表失败:", error)
// 使Set
this.studentUserIds = new Set()
this.studentUserTotal = 0
reject(error)
})
}
fetchPage()
})
},
/** 查询档案列表 */ /** 查询档案列表 */
getList() { getList() {
this.loading = true this.loading = true
//
// 使
const queryParams = { const queryParams = {
...this.queryParams, ...this.queryParams,
pageNum: 1, pageNum: this.queryParams.pageNum || 1,
pageSize: 10000 // pageSize: this.queryParams.pageSize || 10
} }
//
listProfile(queryParams).then(response => { listProfile(queryParams).then(response => {
const rows = response.rows || [] const rows = response.rows || []
const total = response.total || 0
// //
rows.forEach(row => { rows.forEach(row => {
if (row.status === null || row.status === undefined || row.status === '') { if (row.status === null || row.status === undefined || row.status === '') {
@ -662,16 +730,12 @@ export default {
row.status = String(row.status) // row.status = String(row.status) //
} }
}) })
// ID
if (this.studentRoleId) { // 使
this.filterStudentUsers(rows).then(filteredRows => { //
// this.profileList = rows
const pageNum = this.queryParams.pageNum || 1 this.total = total
const pageSize = this.queryParams.pageSize || 10
const start = (pageNum - 1) * pageSize
const end = start + pageSize
this.profileList = filteredRows.slice(start, end)
this.total = filteredRows.length
this.selectedRows = [] this.selectedRows = []
this.ids = [] this.ids = []
this.single = true this.single = true
@ -682,85 +746,37 @@ export default {
} }
}) })
this.loading = false this.loading = false
}).catch(error => {
console.error("过滤学员用户失败:", error)
//
const pageNum = this.queryParams.pageNum || 1
const pageSize = this.queryParams.pageSize || 10
const start = (pageNum - 1) * pageSize
const end = start + pageSize
this.profileList = rows.slice(start, end)
this.total = rows.length
this.selectedRows = []
this.ids = []
this.single = true
this.multiple = true
this.$nextTick(() => {
if (this.$refs.profileTable) {
this.$refs.profileTable.clearSelection()
}
})
this.loading = false
})
} else {
// ID
this.getStudentRoleId().then(() => {
this.filterStudentUsers(rows).then(filteredRows => {
//
const pageNum = this.queryParams.pageNum || 1
const pageSize = this.queryParams.pageSize || 10
const start = (pageNum - 1) * pageSize
const end = start + pageSize
this.profileList = filteredRows.slice(start, end)
this.total = filteredRows.length
this.selectedRows = []
this.ids = []
this.single = true
this.multiple = true
this.$nextTick(() => {
if (this.$refs.profileTable) {
this.$refs.profileTable.clearSelection()
}
})
this.loading = false
}).catch(error => {
console.error("过滤学员用户失败:", error)
const pageNum = this.queryParams.pageNum || 1
const pageSize = this.queryParams.pageSize || 10
const start = (pageNum - 1) * pageSize
const end = start + pageSize
this.profileList = rows.slice(start, end)
this.total = rows.length
this.selectedRows = []
this.ids = []
this.single = true
this.multiple = true
this.$nextTick(() => {
if (this.$refs.profileTable) {
this.$refs.profileTable.clearSelection()
}
})
this.loading = false
})
})
}
}).catch(error => { }).catch(error => {
console.error("查询档案列表失败:", error) console.error("查询档案列表失败:", error)
this.loading = false this.loading = false
}) })
}, },
/** 加载监狱/监区筛选项 */ /** 加载监狱/监区筛选项(优化:分批加载) */
loadFilterOptions() { loadFilterOptions() {
const params = { // /
pageNum: 1,
pageSize: 10000
}
listProfile(params).then(response => {
const rows = response.rows || []
const handleRows = filteredRows => {
const prisonSet = new Set() const prisonSet = new Set()
const prisonAreaSet = new Set() const prisonAreaSet = new Set()
filteredRows.forEach(row => { let pageNum = 1
const pageSize = 500 // 500
let total = 0
let loadedCount = 0
const loadPage = () => {
return listProfile({
pageNum: pageNum,
pageSize: pageSize
}).then(response => {
const rows = response.rows || []
const responseTotal = response.total || 0
if (total === 0 && responseTotal > 0) {
total = responseTotal
}
loadedCount += rows.length
//
rows.forEach(row => {
if (row && row.prison) { if (row && row.prison) {
prisonSet.add(row.prison) prisonSet.add(row.prison)
} }
@ -768,51 +784,60 @@ export default {
prisonAreaSet.add(row.prisonArea) prisonAreaSet.add(row.prisonArea)
} }
}) })
this.filterPrisonOptions = Array.from(prisonSet)
this.filterPrisonAreaOptions = Array.from(prisonAreaSet) //
} if (rows.length === pageSize && (total === 0 || loadedCount < total)) {
if (this.studentRoleId) { pageNum++
this.filterStudentUsers(rows).then(filteredRows => { return loadPage()
handleRows(filteredRows)
}).catch(() => {
handleRows(rows)
})
} else { } else {
handleRows(rows) //
this.filterPrisonOptions = Array.from(prisonSet).sort()
this.filterPrisonAreaOptions = Array.from(prisonAreaSet).sort()
} }
}).catch(error => { }).catch(error => {
console.error("加载监狱筛选项失败:", error) console.error("加载监狱筛选项失败:", error)
// 使
this.filterPrisonOptions = Array.from(prisonSet).sort()
this.filterPrisonAreaOptions = Array.from(prisonAreaSet).sort()
}) })
}
// ID
//
loadPage()
}, },
/** 过滤学员用户 */ /** 过滤学员用户使用缓存的学员用户ID列表 */
filterStudentUsers(rows) { filterStudentUsers(rows) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!this.studentRoleId || rows.length === 0) { if (rows.length === 0) {
resolve(rows) resolve(rows)
return return
} }
// ID
allocatedUserList({ // ID使
roleId: this.studentRoleId, if (this.studentUserIds && this.studentUserIds.size > 0) {
status: '0',
pageNum: 1,
pageSize: 10000
}).then(response => {
const studentUserIds = new Set()
const studentUsers = response.rows || []
studentUsers.forEach(user => {
if (user.userId) {
studentUserIds.add(user.userId)
}
})
//
const filteredRows = rows.filter(row => { const filteredRows = rows.filter(row => {
return row.userId && studentUserIds.has(row.userId) return row.userId && this.studentUserIds.has(row.userId)
})
resolve(filteredRows)
return
}
//
if (!this.studentRoleId) {
resolve(rows)
return
}
this.loadStudentUserIds().then(() => {
const filteredRows = rows.filter(row => {
return row.userId && this.studentUserIds.has(row.userId)
}) })
resolve(filteredRows) resolve(filteredRows)
}).catch(error => { }).catch(error => {
console.error("获取学员用户列表失败:", error) console.error("过滤学员用户失败:", error)
reject(error) //
resolve(rows)
}) })
}) })
}, },

View File

@ -334,6 +334,13 @@ export default {
}, },
created() { created() {
this.getList() this.getList()
// action: 'edit' questionnaireId
const route = this.$route
if (route.query.action === 'edit' && route.query.questionnaireId) {
this.$nextTick(() => {
this.handleUpdateFromRoute(route.query.questionnaireId)
})
}
}, },
methods: { methods: {
/** 查询问卷列表 */ /** 查询问卷列表 */
@ -395,10 +402,31 @@ export default {
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
const questionnaireId = row.questionnaireId || this.ids[0] const questionnaireId = row.questionnaireId || this.ids[0]
this.handleUpdateFromRoute(questionnaireId)
},
/** 从路由参数或传入的ID打开编辑对话框 */
handleUpdateFromRoute(questionnaireId) {
if (!questionnaireId) {
return
}
this.reset()
getQuestionnaire(questionnaireId).then(response => { getQuestionnaire(questionnaireId).then(response => {
this.form = response.data this.form = response.data
this.open = true this.open = true
this.title = "修改问卷" this.title = "修改问卷"
//
if (this.$route.query.action === 'edit') {
const newQuery = { ...this.$route.query }
delete newQuery.action
delete newQuery.questionnaireId
this.$router.replace({
path: this.$route.path,
query: Object.keys(newQuery).length > 0 ? newQuery : {}
})
}
}).catch(error => {
console.error("获取问卷信息失败:", error)
this.$modal.msgError("获取问卷信息失败")
}) })
}, },
/** 提交按钮 */ /** 提交按钮 */

View File

@ -50,7 +50,7 @@
<el-card class="scale-list" shadow="never" v-loading="loading"> <el-card class="scale-list" shadow="never" v-loading="loading">
<div slot="header"> <div slot="header">
<span>量表列表请勾选需要分析的量表</span> <span>量表/问卷列表请勾选需要分析的量表/问卷</span>
<div class="header-actions"> <div class="header-actions">
<el-button <el-button
type="primary" type="primary"
@ -154,6 +154,7 @@ export default {
generating: false, generating: false,
reportDialogVisible: false, reportDialogVisible: false,
comprehensiveReport: '', comprehensiveReport: '',
// ========== ==========
OLLAMA_URL: 'http://192.168.0.106:11434/api/generate', OLLAMA_URL: 'http://192.168.0.106:11434/api/generate',
MODEL: 'deepseek-r1:32b' MODEL: 'deepseek-r1:32b'
} }
@ -176,6 +177,7 @@ export default {
.then((res) => this.normalizeStudentOptions(res.data || [])) .then((res) => this.normalizeStudentOptions(res.data || []))
.catch(() => []) .catch(() => [])
let profilePromise = Promise.resolve([]) let profilePromise = Promise.resolve([])
//
if (/^\d+$/.test(trimmed)) { if (/^\d+$/.test(trimmed)) {
profilePromise = listProfile({ profilePromise = listProfile({
infoNumber: trimmed, infoNumber: trimmed,
@ -184,10 +186,20 @@ export default {
}) })
.then((res) => this.normalizeProfileOptions(res.rows || [])) .then((res) => this.normalizeProfileOptions(res.rows || []))
.catch(() => []) .catch(() => [])
} else {
//
profilePromise = listProfile({
userName: trimmed,
pageNum: 1,
pageSize: 20
})
.then((res) => this.normalizeProfileOptions(res.rows || []))
.catch(() => [])
} }
return Promise.all([studentPromise, profilePromise]) return Promise.all([studentPromise, profilePromise])
.then(([studentList, profileList]) => { .then(([studentList, profileList]) => {
const merged = this.mergeUserOptions([...studentList, ...profileList]) // 使infoNumber
const merged = this.mergeUserOptions([...profileList, ...studentList])
this.cachedUserOptions = merged this.cachedUserOptions = merged
return merged return merged
}) })
@ -217,16 +229,46 @@ export default {
this.$message.warning('请输入姓名或信息编号') this.$message.warning('请输入姓名或信息编号')
return return
} }
this.fetchUserOptions(keyword).then((list) => {
//
let searchKeyword = keyword
//
const numberMatch = keyword.match(/编号[:]\s*(\d+)/)
if (numberMatch) {
searchKeyword = numberMatch[1]
} else {
//
const nameMatch = keyword.match(/^([^(]+)/)
if (nameMatch) {
searchKeyword = nameMatch[1].trim()
}
}
this.fetchUserOptions(searchKeyword).then((list) => {
if (!list.length) { if (!list.length) {
this.$message.warning('未找到匹配的用户') //
//
return return
} }
if (list.length === 1) { if (list.length === 1) {
//
this.handleUserSelect(list[0]) this.handleUserSelect(list[0])
} else { } else {
//
const exactMatch = list.find(opt => {
const label = this.buildUserLabel(opt)
return label === keyword
})
if (exactMatch) {
//
this.handleUserSelect(exactMatch)
} else {
//
this.$message.info('找到多条记录,请从下拉列表选择具体用户') this.$message.info('找到多条记录,请从下拉列表选择具体用户')
} }
}
}).catch(() => {
//
}) })
}, },
normalizeStudentOptions(list) { normalizeStudentOptions(list) {
@ -263,6 +305,16 @@ export default {
} }
if (!map.has(item.userId)) { if (!map.has(item.userId)) {
map.set(item.userId, item) map.set(item.userId, item)
} else {
// infoNumber
const existing = map.get(item.userId)
if (!existing.infoNumber && item.infoNumber) {
// infoNumber
map.set(item.userId, item)
} else if (existing.infoNumber && !item.infoNumber) {
// infoNumber
//
}
} }
}) })
return Array.from(map.values()) return Array.from(map.values())
@ -512,6 +564,7 @@ ${typeLabel}${index + 1}${report.scaleName}
return `${SYSTEM_PROMPT}\n\n${userInfoText}\n\n${scaleReportsText}` return `${SYSTEM_PROMPT}\n\n${userInfoText}\n\n${scaleReportsText}`
}, },
// OLLAMA API
async callOLLAMA(prompt) { async callOLLAMA(prompt) {
try { try {
const { data } = await axios.post(this.OLLAMA_URL, { const { data } = await axios.post(this.OLLAMA_URL, {
@ -536,13 +589,13 @@ ${typeLabel}${index + 1}${report.scaleName}
.trim() .trim()
if (!response) { if (!response) {
throw new Error('AI分析返回结果为空') throw new Error('本地AI分析返回结果为空')
} }
return response return response
} catch (error) { } catch (error) {
console.error('AI分析失败:', error) console.error('本地AI分析失败:', error)
throw new Error('AI分析失败' + (error.message || '未知错误')) throw new Error('本地AI分析失败' + (error.message || '未知错误'))
} }
}, },
formatReport(aiReport, userInfo, scaleReports) { formatReport(aiReport, userInfo, scaleReports) {
@ -589,7 +642,7 @@ ${typeLabel}${index + 1}${report.scaleName}
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; text-align: right; color: #909399; font-size: 12px;"> <div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; text-align: right; color: #909399; font-size: 12px;">
<div>报告生成时间${parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}')}</div> <div>报告生成时间${parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}')}</div>
<div style="margin-top: 8px;">被评估人____________________</div> <div style="margin-top: 8px;">被评估人<span style="color: #303133; font-weight: bold;">${userInfo.userName || '未知'}</span></div>
</div> </div>
</div> </div>
` `

View File

@ -2,20 +2,38 @@
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
<el-form-item label="量表名称" prop="scaleName"> <el-form-item label="量表名称" prop="scaleName">
<el-input <el-select
v-model="queryParams.scaleName" v-model="queryParams.scaleName"
placeholder="请输入量表名称" placeholder="请选择或输入量表名称"
clearable clearable
@keyup.enter.native="handleQuery" filterable
allow-create
default-first-option
>
<el-option
v-for="name in uniqueScaleNames"
:key="name"
:label="name"
:value="name"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="量表编码" prop="scaleCode"> <el-form-item label="量表编码" prop="scaleCode">
<el-input <el-select
v-model="queryParams.scaleCode" v-model="queryParams.scaleCode"
placeholder="请输入量表编码" placeholder="请选择或输入量表编码"
clearable clearable
@keyup.enter.native="handleQuery" filterable
allow-create
default-first-option
>
<el-option
v-for="code in uniqueScaleCodes"
:key="code"
:label="code"
:value="code"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="量表类型" prop="scaleType"> <el-form-item label="量表类型" prop="scaleType">
<el-select v-model="queryParams.scaleType" placeholder="量表类型" clearable> <el-select v-model="queryParams.scaleType" placeholder="量表类型" clearable>
@ -427,6 +445,95 @@
<p style="margin-top: 20px; color: #606266;">正在生成二维码...</p> <p style="margin-top: 20px; color: #606266;">正在生成二维码...</p>
</div> </div>
</el-dialog> </el-dialog>
<!-- 添加或修改问卷对话框复用问卷管理的对话框 -->
<el-dialog :title="questionnaireTitle" :visible.sync="questionnaireOpen" width="900px" append-to-body>
<el-form ref="questionnaireForm" :model="questionnaireForm" :rules="questionnaireRules" label-width="120px">
<el-row>
<el-col :span="12">
<el-form-item label="问卷编码" prop="questionnaireCode">
<el-input v-model="questionnaireForm.questionnaireCode" placeholder="请输入问卷编码" :disabled="questionnaireForm.questionnaireId != undefined" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="问卷名称" prop="questionnaireName">
<el-input v-model="questionnaireForm.questionnaireName" placeholder="请输入问卷名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="问卷类型" prop="questionnaireType">
<el-select v-model="questionnaireForm.questionnaireType" placeholder="请选择问卷类型">
<el-option label="自定义" value="custom" />
<el-option label="考试" value="exam" />
<el-option label="练习" value="practice" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="组卷方式" prop="paperType">
<el-select v-model="questionnaireForm.paperType" placeholder="请选择组卷方式">
<el-option label="手动" value="manual" />
<el-option label="随机" value="random" />
<el-option label="混合" value="mixed" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="题目数量" prop="itemCount">
<el-input-number v-model="questionnaireForm.itemCount" :min="0" controls-position="right" disabled />
<span style="color: #909399; font-size: 12px; margin-left: 10px;">根据题目自动计算</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="总分" prop="totalScore">
<el-input-number v-model="questionnaireForm.totalScore" :min="0" :precision="2" controls-position="right" disabled />
<span style="color: #909399; font-size: 12px; margin-left: 10px;">根据题目分数自动计算</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="及格分数" prop="passScore">
<el-input-number v-model="questionnaireForm.passScore" :min="0" :precision="2" controls-position="right" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计时间(分)" prop="estimatedTime">
<el-input-number v-model="questionnaireForm.estimatedTime" :min="1" controls-position="right" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="问卷描述" prop="description">
<el-input v-model="questionnaireForm.description" type="textarea" :rows="4" placeholder="请输入问卷描述" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="排序" prop="sortOrder">
<el-input-number v-model="questionnaireForm.sortOrder" :min="0" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="questionnaireForm.status">
<el-radio label="0">正常</el-radio>
<el-radio label="1">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注">
<el-input v-model="questionnaireForm.remark" type="textarea" :rows="2" placeholder="请输入备注" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitQuestionnaireForm"> </el-button>
<el-button @click="cancelQuestionnaire"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
@ -454,6 +561,8 @@ export default {
total: 0, total: 0,
// //
scaleList: [], scaleList: [],
//
allScaleList: [],
// //
title: "", title: "",
// //
@ -474,6 +583,21 @@ export default {
// //
qrcodeOpen: false, qrcodeOpen: false,
qrcodeInfo: null, qrcodeInfo: null,
//
questionnaireOpen: false,
questionnaireTitle: "修改问卷",
questionnaireForm: {},
questionnaireRules: {
questionnaireCode: [
{ required: true, message: "问卷编码不能为空", trigger: "blur" }
],
questionnaireName: [
{ required: true, message: "问卷名称不能为空", trigger: "blur" }
],
questionnaireType: [
{ required: true, message: "问卷类型不能为空", trigger: "change" }
]
},
// //
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
@ -481,7 +605,8 @@ export default {
scaleName: undefined, scaleName: undefined,
scaleCode: undefined, scaleCode: undefined,
scaleType: undefined, scaleType: undefined,
status: undefined status: undefined,
includeQuestionnaire: true //
}, },
// //
form: {}, form: {},
@ -524,10 +649,39 @@ export default {
{ label: "正常", value: "0" }, { label: "正常", value: "0" },
{ label: "停用", value: "1" } { label: "停用", value: "1" }
]; ];
},
/** 去重后的量表名称列表 */
uniqueScaleNames() {
// 使
if (!this.allScaleList || this.allScaleList.length === 0) {
return [];
}
const nameSet = new Set();
this.allScaleList.forEach(scale => {
if (scale.scaleName && scale.scaleName.trim()) {
nameSet.add(scale.scaleName.trim());
}
});
return Array.from(nameSet).sort();
},
/** 去重后的量表编码列表 */
uniqueScaleCodes() {
// 使
if (!this.allScaleList || this.allScaleList.length === 0) {
return [];
}
const codeSet = new Set();
this.allScaleList.forEach(scale => {
if (scale.scaleCode && scale.scaleCode.trim()) {
codeSet.add(scale.scaleCode.trim());
}
});
return Array.from(codeSet).sort();
} }
}, },
created() { created() {
this.getList() this.getAllScaleList() //
this.getList() //
}, },
methods: { methods: {
/** 获取字典标签 */ /** 获取字典标签 */
@ -536,6 +690,21 @@ export default {
const dict = dictList.find(item => item.value === value); const dict = dictList.find(item => item.value === value);
return dict ? dict.label : value; return dict ? dict.label : value;
}, },
/** 获取所有量表列表(不分页,用于下拉框) */
getAllScaleList() {
//
const allParams = {
pageNum: 1,
pageSize: 10000, //
includeQuestionnaire: true //
}
listScale(allParams).then(response => {
this.allScaleList = response.rows || []
}).catch(error => {
console.error('获取所有量表列表失败:', error)
this.allScaleList = []
})
},
/** 查询量表列表 */ /** 查询量表列表 */
getList() { getList() {
this.loading = true this.loading = true
@ -621,12 +790,14 @@ export default {
updateScale(this.form).then(response => { updateScale(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
this.getAllScaleList() //
this.getList() this.getList()
}) })
} else { } else {
addScale(this.form).then(response => { addScale(this.form).then(response => {
this.$modal.msgSuccess("新增成功") this.$modal.msgSuccess("新增成功")
this.open = false this.open = false
this.getAllScaleList() //
this.getList() this.getList()
}) })
} }
@ -639,6 +810,7 @@ export default {
this.$modal.confirm('是否确认删除量表编号为"' + scaleIds + '"的数据项?').then(function() { this.$modal.confirm('是否确认删除量表编号为"' + scaleIds + '"的数据项?').then(function() {
return delScale(scaleIds) return delScale(scaleIds)
}).then(() => { }).then(() => {
this.getAllScaleList() //
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
}).catch(() => {}) }).catch(() => {})
@ -790,6 +962,7 @@ export default {
this.$modal.msgSuccess(response.msg || "导入成功") this.$modal.msgSuccess(response.msg || "导入成功")
this.importOpen = false this.importOpen = false
this.importJsonText = "" this.importJsonText = ""
this.getAllScaleList() //
this.getList() this.getList()
}).catch(error => { }).catch(error => {
this.$modal.msgError(error.msg || "导入失败") this.$modal.msgError(error.msg || "导入失败")
@ -826,6 +999,7 @@ export default {
this.upload.fileContent = null this.upload.fileContent = null
this.$refs.upload.clearFiles() this.$refs.upload.clearFiles()
this.upload.isUploading = false this.upload.isUploading = false
this.getAllScaleList() //
this.getList() this.getList()
}).catch(error => { }).catch(error => {
this.$modal.msgError(error.msg || "导入失败") this.$modal.msgError(error.msg || "导入失败")
@ -858,6 +1032,7 @@ export default {
this.upload.fileContent = null this.upload.fileContent = null
this.$refs.upload.clearFiles() this.$refs.upload.clearFiles()
this.upload.isUploading = false this.upload.isUploading = false
this.getAllScaleList() //
this.getList() this.getList()
}).catch(error => { }).catch(error => {
this.$modal.msgError(error.msg || "导入失败") this.$modal.msgError(error.msg || "导入失败")
@ -927,8 +1102,62 @@ export default {
/** 问卷修改按钮操作 */ /** 问卷修改按钮操作 */
handleQuestionnaireUpdate(row) { handleQuestionnaireUpdate(row) {
const questionnaireId = row.originalId || Math.abs(row.scaleId) const questionnaireId = row.originalId || Math.abs(row.scaleId)
// this.resetQuestionnaireForm()
this.$router.push({ path: '/psychology/questionnaire', query: { questionnaireId: questionnaireId, action: 'edit' } }) getQuestionnaire(questionnaireId).then(response => {
this.questionnaireForm = response.data
this.questionnaireOpen = true
this.questionnaireTitle = "修改问卷"
}).catch(error => {
console.error("获取问卷信息失败:", error)
this.$modal.msgError("获取问卷信息失败")
})
},
/** 提交问卷表单 */
submitQuestionnaireForm() {
this.$refs["questionnaireForm"].validate(valid => {
if (valid) {
if (this.questionnaireForm.questionnaireId != undefined) {
updateQuestionnaire(this.questionnaireForm).then(response => {
this.$modal.msgSuccess("修改成功")
this.questionnaireOpen = false
this.resetQuestionnaireForm()
//
this.getAllScaleList() //
this.getList()
}).catch(error => {
console.error("修改问卷失败:", error)
})
}
}
})
},
/** 取消问卷编辑 */
cancelQuestionnaire() {
this.questionnaireOpen = false
this.resetQuestionnaireForm()
},
/** 重置问卷表单 */
resetQuestionnaireForm() {
this.questionnaireForm = {
questionnaireId: undefined,
questionnaireCode: undefined,
questionnaireName: undefined,
questionnaireType: "custom",
paperType: "manual",
itemCount: 0,
totalScore: undefined,
passScore: undefined,
estimatedTime: undefined,
description: undefined,
status: "0",
sortOrder: 0,
remark: undefined
}
this.$nextTick(() => {
if (this.$refs.questionnaireForm) {
this.$refs.questionnaireForm.clearValidate()
}
})
}, },
/** 问卷删除按钮操作 */ /** 问卷删除按钮操作 */
handleQuestionnaireDelete(row) { handleQuestionnaireDelete(row) {
@ -937,6 +1166,7 @@ export default {
this.$modal.confirm('是否确认删除问卷"' + questionnaireName + '"的数据项?').then(() => { this.$modal.confirm('是否确认删除问卷"' + questionnaireName + '"的数据项?').then(() => {
return delQuestionnaire(questionnaireId) return delQuestionnaire(questionnaireId)
}).then(() => { }).then(() => {
this.getAllScaleList() //
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
}).catch(() => {}) }).catch(() => {})

View File

@ -191,7 +191,23 @@ export default {
const pausedRecord = this.getPausedRecord(test.scaleId) const pausedRecord = this.getPausedRecord(test.scaleId)
if (pausedRecord) { if (pausedRecord) {
//
this.$confirm('检测到您有该量表的暂停测评,是否继续?', '提示', {
confirmButtonText: '继续测评',
cancelButtonText: '重新开始',
type: 'warning'
}).then(() => {
this.continueAssessment(pausedRecord) this.continueAssessment(pausedRecord)
}).catch(() => {
//
this.$confirm('重新开始将清空之前的答题记录,确定要重新开始吗?', '警告', {
confirmButtonText: '确定重新开始',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.createNewAssessment(test)
})
})
return return
} }
@ -209,6 +225,11 @@ export default {
this.createAssessment(test) this.createAssessment(test)
}, },
//
createNewAssessment(test) {
this.createAssessment(test)
},
// //
createAssessment(test) { createAssessment(test) {
this.loading = true this.loading = true