Files
td_official/src/views/safety/questionsConfig/index.vue
2025-09-08 20:00:59 +08:00

221 lines
7.3 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="container p-4 md:p-6">
<el-card shadow="hover" class="config-card transition-all duration-300 hover:shadow-lg">
<div class="card-header mb-4">
<h2 class="text-xl font-semibold text-gray-800">题库配置</h2>
<p class="text-gray-500 text-sm">设置各类题型数量分值及考试参数</p>
</div>
<el-form :model="form" label-width="120px" ref="formRef" class="config-form">
<el-row :gutter="20">
<!-- 单选题设置 -->
<el-col :span="12" class="form-item-col">
<el-form-item label="单选题(道)" :rules="[{ required: true, message: '单选题数量不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.singleChoice" min="0" class="transition-all" placeholder="请输入数量" />
</el-form-item>
</el-col>
<el-col :span="12" class="form-item-col">
<el-form-item label="单选分数" :rules="[{ required: true, message: '单选分数不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.singleScore" min="0" class="transition-all" placeholder="每题分数" />
</el-form-item>
</el-col>
<!-- 多选题设置 -->
<el-col :span="12" class="form-item-col">
<el-form-item label="多选题(道)" :rules="[{ required: true, message: '多选题数量不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.multipleChoice" min="0" class="transition-all" placeholder="请输入数量" />
</el-form-item>
</el-col>
<el-col :span="12" class="form-item-col">
<el-form-item label="多选分数" :rules="[{ required: true, message: '多选分数不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.multipleScore" min="0" class="transition-all" placeholder="每题分数" />
</el-form-item>
</el-col>
<!-- 判断题设置 -->
<el-col :span="12" class="form-item-col">
<el-form-item label="判断题(道)" :rules="[{ required: true, message: '判断题数量不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.estimate" min="0" class="transition-all" placeholder="请输入数量" />
</el-form-item>
</el-col>
<el-col :span="12" class="form-item-col">
<el-form-item label="判断分数" :rules="[{ required: true, message: '判断分数不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.estimateScore" min="0" class="transition-all" placeholder="每题分数" />
</el-form-item>
</el-col>
<!-- 分数设置 -->
<el-col :span="12" class="form-item-col">
<el-form-item label="及格分数" :rules="[{ required: true, message: '及格分数不能为空', trigger: 'blur' }]">
<el-input
type="number"
v-model="form.passingScore"
min="0"
:max="form.fullMark"
@change="handlePassingScoreChange"
class="transition-all"
placeholder="请输入及格分数"
/>
</el-form-item>
</el-col>
<el-col :span="12" class="form-item-col">
<el-form-item label="满分">
<el-input type="number" v-model="form.fullMark" disabled class="bg-gray-50" />
</el-form-item>
</el-col>
<!-- 时间设置 -->
<el-col :span="12" class="form-item-col">
<el-form-item label="答题时间(分钟)" :rules="[{ required: true, message: '答题时间不能为空', trigger: 'blur' }]">
<el-input type="number" v-model="form.answerTime" min="0" class="transition-all" placeholder="请输入时间" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="form-actions flex justify-center mt-6">
<el-button type="primary" @click="onSubmit" :loading="buttonLoading" class="px-8 transition-all hover:scale-105"> 保存配置 </el-button>
</div>
</el-card>
</div>
</template>
<script setup name="QuestionsConfig" lang="ts">
import { ref, reactive, computed, onMounted, getCurrentInstance } from 'vue';
import { ElFormInstance, ComponentInternalInstance } from 'element-plus';
import { getQuestionsConfig, updateQuestionsConfig } from '@/api/safety/questionsConfig';
import { QuestionsConfigForm} from '@/api/safety/questionsConfig/types';
import { useUserStoreHook } from '@/store/modules/user';
// 获取用户信息
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
// 表单相关
const formRef = ref<ElFormInstance>();
const buttonLoading = ref(false);
const form = reactive<QuestionsConfigForm>({
id: undefined,
projectId: currentProject.value?.id,
singleChoice: 0,
singleScore: 0,
multipleChoice: 0,
multipleScore: 0,
estimate: 0,
estimateScore: 0,
fullMark: 0,
passScore: 0,
answerTime: 0,
passingScore: 0
});
// 计算满分
const calculateFullMark = () => {
form.fullMark =
(form.singleChoice || 0) * (form.singleScore || 0) +
(form.multipleChoice || 0) * (form.multipleScore || 0) +
(form.estimate || 0) * (form.estimateScore || 0);
// 确保及格分不超过满分
if (form.passingScore > form.fullMark) {
form.passingScore = form.fullMark;
}
};
// 监听分数变化,自动计算满分
['singleChoice', 'singleScore', 'multipleChoice', 'multipleScore', 'estimate', 'estimateScore'].forEach((field) => {
watch(() => form[field], calculateFullMark);
});
// 处理及格分变化
const handlePassingScoreChange = (val: number) => {
if (val >= form.fullMark) {
form.passingScore = form.fullMark;
}
};
// 获取配置详情
const getDetail = () => {
getQuestionsConfig(1).then((res: any) => {
if (res.code == 200 && res.data) {
Object.assign(form, res.data);
calculateFullMark(); // 确保满分计算正确
}
});
};
// 提交表单
const onSubmit = () => {
formRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
try {
await updateQuestionsConfig(form);
// 显示成功消息假设使用element-plus的message组件
ElMessage.success('配置保存成功');
getDetail(); // 重新获取最新配置
} catch (error) {
ElMessage.error('保存失败,请重试');
} finally {
buttonLoading.value = false;
}
}
});
};
// 页面加载时获取数据
onMounted(() => {
getDetail();
});
</script>
<style lang="scss" scoped>
.container {
max-width: 800px;
margin: 0 auto;
padding-top: 20px;
}
.config-card {
border-radius: 12px;
overflow: hidden;
}
.card-header {
border-bottom: 1px solid #f0f0f0;
padding-bottom: 12px;
}
.form-item-col {
margin-bottom: 16px;
}
.form-actions {
padding: 16px;
border-top: 1px solid #f0f0f0;
margin-top: 20px;
}
// 输入框聚焦效果
::v-deep .el-input__wrapper:focus-within {
box-shadow: 0 0 0 2px rgba(48, 163, 255, 0.2);
}
// 响应式调整
@media (max-width: 768px) {
.el-col {
&:span-12 {
width: 100% !important;
}
}
.card-header {
text-align: center;
}
}
</style>