xinli/ruoyi-ui/src/views/psychology/scale/item.vue
2025-11-12 15:25:47 +08:00

485 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<!-- 量表选择界面当没有scaleId时显示 -->
<el-card v-if="!queryParams.scaleId" class="box-card">
<div slot="header" class="clearfix">
<span>请选择量表</span>
</div>
<el-form :inline="true" :model="scaleQuery" class="demo-form-inline">
<el-form-item label="量表名称">
<el-input v-model="scaleQuery.scaleName" placeholder="请输入量表名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleScaleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetScaleQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="scaleLoading" :data="scaleList" @row-click="handleScaleSelect">
<el-table-column label="量表名称" prop="scaleName" />
<el-table-column label="量表编码" prop="scaleCode" width="150" />
<el-table-column label="题目数量" prop="itemCount" width="100" align="center" />
<el-table-column label="操作" width="100" align="center">
<template slot-scope="scope">
<el-button type="text" size="mini" @click.stop="handleScaleSelect(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 题目管理界面当有scaleId时显示 -->
<div v-else>
<el-row :gutter="10" class="mb8">
<el-col :span="21.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['psychology:item:add']"
>新增题目</el-button>
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['psychology:item:remove']"
>批量删除</el-button>
</el-col>
<el-col :span="2.5">
<el-button
type="info"
plain
icon="el-icon-back"
size="mini"
@click="handleBack"
>返回</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="itemList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" prop="itemNumber" width="80" />
<el-table-column
label="题目内容"
align="left"
prop="itemContent"
:show-overflow-tooltip="true"
/>
<el-table-column label="题型" align="center" prop="itemType" width="100">
<template slot-scope="scope">
{{ getItemTypeName(scope.row.itemType) }}
</template>
</el-table-column>
<el-table-column label="必填" align="center" prop="required" width="80">
<template slot-scope="scope">
{{ scope.row.required === '1' ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="反向计分" align="center" prop="reverseScore" width="100">
<template slot-scope="scope">
{{ scope.row.reverseScore === '1' ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['psychology:item:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-setting"
@click="handleManageOptions(scope.row)"
v-hasPermi="['psychology:option:list']"
>选项</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['psychology:item:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 添加或修改题目对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="题目序号" prop="itemNumber">
<el-input-number v-model="form.itemNumber" :min="1" :max="1000" placeholder="请输入题目序号" />
</el-form-item>
<el-form-item label="题目类型" prop="itemType">
<el-select v-model="form.itemType" placeholder="请选择题目类型">
<el-option label="单选题" value="single" />
<el-option label="多选题" value="multiple" />
<el-option label="矩阵题" value="matrix" />
</el-select>
</el-form-item>
<el-form-item label="题目内容" prop="itemContent">
<el-input v-model="form.itemContent" type="textarea" :rows="4" placeholder="请输入题目内容" />
</el-form-item>
<el-form-item label="是否必填">
<el-radio-group v-model="form.required">
<el-radio label="1">是</el-radio>
<el-radio label="0">否</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否反向计分">
<el-radio-group v-model="form.reverseScore">
<el-radio label="1">是</el-radio>
<el-radio label="0">否</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序">
<el-input-number v-model="form.sortOrder" :min="0" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- 选项管理对话框 -->
<el-dialog title="选项管理" :visible.sync="optionOpen" width="900px" append-to-body>
<el-row :gutter="10" class="mb8">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAddOption"
>新增选项</el-button>
</el-row>
<el-table :data="optionList" border>
<el-table-column label="选项编码" align="center" prop="optionCode" width="100" />
<el-table-column label="选项内容" align="left" prop="optionContent" />
<el-table-column label="分值" align="center" prop="optionScore" width="100" />
<el-table-column label="排序" align="center" prop="sortOrder" width="80" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdateOption(scope.row, scope.$index)"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDeleteOption(scope.$index)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitOptions">保 存</el-button>
<el-button @click="optionOpen = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listItem, getItem, delItem, addItem, updateItem } from "@/api/psychology/item";
import { listOption, saveOptions } from "@/api/psychology/option";
export default {
name: "ScaleItem",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 题目表格数据
itemList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 选项弹出层
optionOpen: false,
// 选项列表
optionList: [],
// 当前编辑的题目ID
currentItemId: null,
// 当前编辑的题目行
currentItemRow: null,
// 查询参数
queryParams: {
scaleId: undefined
},
// 量表选择相关
scaleLoading: false,
scaleList: [],
scaleQuery: {
scaleName: undefined
},
currentScaleName: '',
// 表单参数
form: {},
// 表单校验
rules: {
itemNumber: [
{ required: true, message: "题目序号不能为空", trigger: "blur" }
],
itemType: [
{ required: true, message: "题目类型不能为空", trigger: "change" }
],
itemContent: [
{ required: true, message: "题目内容不能为空", trigger: "blur" }
]
}
};
},
created() {
const scaleId = this.$route.query.scaleId;
const scaleName = this.$route.query.scaleName;
if (scaleId) {
this.queryParams.scaleId = scaleId;
this.currentScaleName = scaleName || '';
this.getList();
} else {
// 如果没有scaleId加载量表列表供选择
this.loadScales();
}
// 更新页面标题
if (scaleName) {
document.title = scaleName + " - 题目管理";
} else {
document.title = "题目管理";
}
},
methods: {
/** 加载量表列表 */
loadScales() {
this.scaleLoading = true;
listScale(this.scaleQuery).then(response => {
this.scaleList = response.rows || [];
this.scaleLoading = false;
}).catch(() => {
this.scaleLoading = false;
});
},
/** 搜索量表 */
handleScaleQuery() {
this.loadScales();
},
/** 重置量表搜索 */
resetScaleQuery() {
this.scaleQuery = {
scaleName: undefined
};
this.loadScales();
},
/** 选择量表 */
handleScaleSelect(row) {
this.queryParams.scaleId = row.scaleId;
this.currentScaleName = row.scaleName;
document.title = row.scaleName + " - 题目管理";
this.getList();
},
/** 查询题目列表 */
getList() {
if (!this.queryParams.scaleId) {
this.$modal.msgError("请先选择量表");
return;
}
this.loading = true;
listItem(this.queryParams.scaleId).then(response => {
this.itemList = response.data || [];
this.loading = false;
}).catch(error => {
console.error("查询题目列表失败:", error);
this.$modal.msgError("查询题目列表失败:" + (error.message || "未知错误"));
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
itemId: undefined,
scaleId: this.queryParams.scaleId,
itemNumber: undefined,
itemContent: undefined,
itemType: "single",
required: "1",
reverseScore: "0",
sortOrder: 0
};
this.resetForm("form");
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.itemId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加题目";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const itemId = row.itemId;
getItem(itemId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改题目";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.itemId != undefined) {
updateItem(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addItem(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const itemIds = row.itemId ? [row.itemId] : this.ids;
this.$modal.confirm('是否确认删除选中的题目?').then(() => {
return delItem(itemIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 返回按钮操作 */
handleBack() {
if (this.queryParams.scaleId) {
// 如果有scaleId清除它并显示量表选择界面
this.queryParams.scaleId = undefined;
this.currentScaleName = '';
this.itemList = [];
this.loadScales();
document.title = "题目管理";
} else {
// 如果没有scaleId返回量表管理页面
this.$router.push('/psychology/scale');
}
},
/** 题型名称 */
getItemTypeName(type) {
const types = {
single: '单选题',
multiple: '多选题',
matrix: '矩阵题'
};
return types[type] || type;
},
/** 选项管理按钮操作 */
handleManageOptions(row) {
this.currentItemId = row.itemId;
this.currentItemRow = row;
this.optionList = [];
this.optionOpen = true;
// 加载已有选项
listOption(row.itemId).then(response => {
this.optionList = response.data || [];
});
},
/** 新增选项 */
handleAddOption() {
const newOption = {
optionId: undefined,
optionCode: '',
optionContent: '',
optionScore: 0,
sortOrder: this.optionList.length
};
this.optionList.push(newOption);
},
/** 修改选项 */
handleUpdateOption(row, index) {
// 编辑模式,显示输入框
this.$prompt('请输入新内容', '修改选项', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: row.optionContent,
inputPlaceholder: '请输入选项内容'
}).then(({ value }) => {
this.optionList[index].optionContent = value;
});
},
/** 删除选项 */
handleDeleteOption(index) {
this.optionList.splice(index, 1);
// 更新排序
this.optionList.forEach((item, idx) => {
item.sortOrder = idx;
});
},
/** 保存选项 */
submitOptions() {
// 验证必填项
for (let i = 0; i < this.optionList.length; i++) {
const option = this.optionList[i];
if (!option.optionContent || !option.optionContent.trim()) {
this.$modal.msgError('第' + (i + 1) + '个选项内容不能为空');
return;
}
}
// 自动生成选项编码
const optionCodes = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
this.optionList.forEach((option, index) => {
if (!option.optionCode) {
option.optionCode = optionCodes[index] || (index + 1).toString();
}
});
saveOptions(this.currentItemId, this.optionList).then(response => {
this.$modal.msgSuccess("保存成功");
this.optionOpen = false;
});
}
}
};
</script>
<style scoped>
.app-container {
padding: 20px;
}
</style>