【修改】出题知识点可选择,数据时效性,MYSQL判分语句增加默认权值
【增加】试卷任务参数,在已有的试卷抽卷
This commit is contained in:
@@ -1,6 +1,18 @@
|
||||
<template>
|
||||
<div class="edit-dialog">
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="85%" top="10vh" class="custom-dialog">
|
||||
|
||||
<el-dialog v-model="dialogVisiblePoints" title="选择知识点" width="30%">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:data="deptList"
|
||||
node-key="id"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</el-dialog>
|
||||
<el-scrollbar>
|
||||
<div class="main">
|
||||
<el-form
|
||||
@@ -16,11 +28,13 @@
|
||||
<el-input v-model="formData.specialtyName" placeholder="请输入专业" disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="知识点" prop="pointNames">
|
||||
<el-input v-model="formData.pointNames" placeholder="请输入知识点" disabled/>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="章节名称" prop="chapteridDictText">
|
||||
<el-input v-model="formData.chapteridDictTextVo" placeholder="请输入章节名称" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
@@ -29,21 +43,22 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<!-- <el-form-item label="题型难度" prop="quLevel">
|
||||
<el-input v-model="formData.quLevel" placeholder="请输入题型难度" />
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item label="题型难度" prop="quLevel">
|
||||
<el-select
|
||||
v-model="formData.quLevel"
|
||||
placeholder="请选择题型难度"
|
||||
clearable
|
||||
>
|
||||
<el-option label="简单" :value="'0'" />
|
||||
<el-option label="一般" :value="'1'" />
|
||||
<el-option label="困难" :value="'2'" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="题型难度" prop="quLevel">
|
||||
<el-select
|
||||
v-model="formData.quLevel"
|
||||
placeholder="请选择题型难度"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.EXAM_QUE_DIFF)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
</el-col>
|
||||
@@ -58,10 +73,17 @@
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="章节名称" prop="chapteridDictText">
|
||||
<el-input v-model="formData.chapteridDictText" placeholder="请输入章节名称" disabled />
|
||||
<el-form-item label="知识点" prop="pointNames">
|
||||
<el-input
|
||||
v-model="formData.pointNamesVo"
|
||||
placeholder="请选择知识点"
|
||||
readonly
|
||||
@click="openPoints()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
@@ -234,18 +256,16 @@
|
||||
width="60%"
|
||||
:close-on-click-modal="false"
|
||||
class="custom-dialog"
|
||||
draggable
|
||||
>
|
||||
<!-- 可滚动容器 -->
|
||||
<div style="height: 400px; overflow-y: auto;">
|
||||
<el-table
|
||||
:data="kaodianList"
|
||||
:data="kaodiaRefList"
|
||||
style="width: 100%;"
|
||||
row-key="answerId"
|
||||
:default-expand-all="false"
|
||||
|
||||
|
||||
>
|
||||
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
|
||||
<el-table-column label="文件/文件夹名(带后缀)" width="260">
|
||||
@@ -254,6 +274,8 @@
|
||||
v-model="scope.row.content"
|
||||
size="small"
|
||||
type="input"
|
||||
|
||||
@click="openFileTree(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -263,6 +285,7 @@
|
||||
v-model="scope.row.scoreRate"
|
||||
size="small"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -322,20 +345,6 @@
|
||||
<template #label>
|
||||
<div class="custom-tabs-label">
|
||||
<p>试题附件</p>
|
||||
<!-- <el-dropdown>
|
||||
<span class="el-dropdown-link" @click.stop="false">
|
||||
<div class="setting_icon"></div>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>导入单文件</el-dropdown-item>
|
||||
<el-dropdown-item>导入多文件</el-dropdown-item>
|
||||
<el-dropdown-item>导出</el-dropdown-item>
|
||||
<el-dropdown-item>删除</el-dropdown-item>
|
||||
<el-dropdown-item>帮助</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown> -->
|
||||
</div>
|
||||
</template>
|
||||
<!-- 提示 -->
|
||||
@@ -418,6 +427,22 @@
|
||||
</div>
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<FileForm ref="FileRef" @success="handleUploadSuccess"/>
|
||||
<el-dialog
|
||||
v-model="fileTreeDialogVisible"
|
||||
title="选择文件"
|
||||
width="40%"
|
||||
:close-on-click-modal="false"
|
||||
draggable
|
||||
>
|
||||
<el-tree
|
||||
:data="fileTreeData"
|
||||
node-key="id"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
@node-click="handleFileNodeClick"
|
||||
default-expand-all
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
@@ -426,8 +451,11 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { FormRules } from 'element-plus'
|
||||
import * as QuestionApi from '@/api/paper/question'
|
||||
import FileForm from './components/FileForm.vue';
|
||||
import { defaultProps, handleTree } from '@/utils/tree'
|
||||
import * as SpecialtyApi from '@/api/points'
|
||||
defineOptions({ name: 'ChoiceForm' })
|
||||
|
||||
// 定义一个缓存对象
|
||||
const nodeListCache: Record<number, any> = {};
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
@@ -435,7 +463,16 @@ const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
|
||||
const fileTreeDialogVisible = ref(false);
|
||||
const fileTreeData = ref<Tree[]>([]);
|
||||
const currentEditingRow = ref<any>(null); // 当前点击的行
|
||||
|
||||
|
||||
|
||||
const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '<p>---------------------------------------------------------------------</p><p> 请在打开的窗口中,进行下列操作,完成所有操作后,请关闭窗口。</p><p>---------------------------------------------------------------------</p><p>',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
@@ -443,7 +480,7 @@ const formData = ref({
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
subjectName: '',
|
||||
status: ' ',
|
||||
@@ -453,13 +490,13 @@ const formData = ref({
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '1',
|
||||
fileName: ''
|
||||
fileName: '原始'
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '2',
|
||||
fileName: ''
|
||||
fileName: '结果'
|
||||
}]
|
||||
})
|
||||
|
||||
@@ -471,18 +508,94 @@ function fileTypeFormatter(row, column, cellValue) {
|
||||
|
||||
|
||||
//考点
|
||||
|
||||
|
||||
|
||||
const openFileTree = (row: any) => {
|
||||
|
||||
console.log("111")
|
||||
const quId = kaodianData.value.quId;
|
||||
const cached = nodeListCache[quId];
|
||||
if (!cached) {
|
||||
ElMessage.warning('暂无缓存的文件结构');
|
||||
return;
|
||||
}
|
||||
|
||||
fileTreeData.value.push(...handleTree(cached))
|
||||
currentEditingRow.value = row;
|
||||
fileTreeDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const handleFileNodeClick = (data) => {
|
||||
const pathArray = findFilePathById(fileTreeData.value, data.id)
|
||||
if (!pathArray) return
|
||||
|
||||
const fullPath = pathArray.join('\\')
|
||||
if (currentEditingRow.value) {
|
||||
currentEditingRow.value.content = fullPath
|
||||
}
|
||||
fileTreeDialogVisible.value = false
|
||||
}
|
||||
const findFilePathById = (
|
||||
tree: any[],
|
||||
targetId: number,
|
||||
path: string[] = []
|
||||
): string[] | null => {
|
||||
for (const node of tree) {
|
||||
const currentPath = [...path, node.name]
|
||||
if (node.id === targetId) {
|
||||
return currentPath
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
const result = findFilePathById(node.children, targetId, currentPath)
|
||||
if (result) return result
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
const kaoDialogVisible = ref(false)
|
||||
const kaodianData = ref({
|
||||
quId: '', // 你打开编辑弹窗时会赋值
|
||||
})
|
||||
|
||||
const kaodianList = ref<any[]>([])
|
||||
const kaodiaRefList = ref<any[]>([])
|
||||
|
||||
|
||||
function setKao() {
|
||||
kaodiaRefList.value = JSON.parse(JSON.stringify(kaodianList.value))
|
||||
kaoDialogVisible.value = true
|
||||
}
|
||||
const kaodianList = ref<any[]>([])
|
||||
function confirmKao() {
|
||||
async function confirmKao() {
|
||||
|
||||
const contentSet = new Set<string>();
|
||||
|
||||
for (const [index, item] of kaodiaRefList.value.entries()) {
|
||||
if (!item.content || item.content.trim() === '') {
|
||||
ElMessage.warning(`第 ${index + 1} 行「文件名」不能为空`)
|
||||
return
|
||||
}
|
||||
if (contentSet.has(item.content.trim())) {
|
||||
ElMessage.warning(`第 ${index + 1} 行「文件名」不能重复`)
|
||||
return
|
||||
}
|
||||
contentSet.add(item.content.trim())
|
||||
|
||||
if (item.scoreRate === null || item.scoreRate === '' || item.scoreRate < 0) {
|
||||
ElMessage.warning(`第 ${index + 1} 行「权值」不能为空且不能小于 0`)
|
||||
return
|
||||
}
|
||||
if (!item.contentIn || item.contentIn.trim() === '') {
|
||||
ElMessage.warning(`第 ${index + 1} 行「考察类型」不能为空`)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 构建 questionAnswerList
|
||||
const questionAnswerList = kaodianList.value.map(item => ({
|
||||
const questionAnswerList = kaodiaRefList.value.map(item => ({
|
||||
answerId: item.answerId,
|
||||
content: item.content,
|
||||
quId:kaodianData.value.quId,
|
||||
@@ -497,13 +610,17 @@ function confirmKao() {
|
||||
|
||||
console.log('确认后的结果:', payload)
|
||||
|
||||
QuestionApi.setBrowserPoint(payload)
|
||||
await QuestionApi.setBrowserPoint(payload)
|
||||
|
||||
const res = await QuestionApi.getListByQuId(kaodianData.value.quId);
|
||||
kaodianList.value = res;
|
||||
kaoDialogVisible.value= false;
|
||||
|
||||
}
|
||||
|
||||
// 增加行
|
||||
function addKaodianRow() {
|
||||
kaodianList.value.push({
|
||||
kaodiaRefList.value.push({
|
||||
answerId: '', // 用你项目里生成 ID 的方法
|
||||
content: '',
|
||||
quId:kaodianData.value.quId,
|
||||
@@ -513,7 +630,7 @@ function addKaodianRow() {
|
||||
}
|
||||
// 删除行
|
||||
function removeKaodian(index: number) {
|
||||
kaodianList.value.splice(index, 1)
|
||||
kaodiaRefList.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const setKaodianRow =async () => {
|
||||
@@ -529,15 +646,20 @@ const setKaodianRow =async () => {
|
||||
|
||||
console.log('导入考点的文件地址为:', fileUrl1, fileUrl2);
|
||||
const params = {
|
||||
answerPath: fileUrl1,
|
||||
shucaiPath: fileUrl2 // 如果不传可以是空字符串,也可以删除这个字段(根据后端是否必填)
|
||||
shucaiPath: fileUrl1,
|
||||
answerPath : fileUrl2 // 如果不传可以是空字符串,也可以删除这个字段(根据后端是否必填)
|
||||
};
|
||||
|
||||
const res = await QuestionApi.getFilePoint(params);
|
||||
|
||||
kaodianList.value=res;
|
||||
// 示例:调用后端接口进行导入
|
||||
// importKaodianFromFiles(fileUrl1, fileUrl2);
|
||||
kaodiaRefList.value=res.examQuestionAnswerList;
|
||||
|
||||
// 缓存 nodeList,键为当前 quId
|
||||
const quId = kaodianData.value.quId;
|
||||
if (quId) {
|
||||
nodeListCache[quId] = res.nodeList;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -754,13 +876,17 @@ keywordList.value = res.keywords
|
||||
}
|
||||
} else {
|
||||
resetForm()
|
||||
console.log(queryParams.pointNamesVo+"queryParams")
|
||||
console.log(queryParams.chapteridDictTextVo+"queryParams")
|
||||
console.log(queryParams.pointNames+"queryParams")
|
||||
console.log(queryParams.chapteridDictText+"queryParams")
|
||||
formData.value.specialtyName = queryParams.specialtyName
|
||||
formData.value.courseName = queryParams.courseName
|
||||
formData.value.subjectName = queryParams.subjectName
|
||||
formData.value.pointNames=queryParams.pointNames
|
||||
formData.value.chapteridDictText=queryParams.chapteridDictText
|
||||
|
||||
|
||||
formData.value.pointNames=queryParams.pointNamesVo
|
||||
formData.value.pointNamesVo=queryParams.pointNames
|
||||
formData.value.chapteridDictText=queryParams.chapteridDictTextVo
|
||||
formData.value.chapteridDictTextVo=queryParams.chapteridDictText
|
||||
}
|
||||
|
||||
}
|
||||
@@ -822,7 +948,7 @@ const resetForm = () => {
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '0',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
subjectName: '',
|
||||
status: '0',
|
||||
@@ -832,19 +958,76 @@ const resetForm = () => {
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '1',
|
||||
fileName: ''
|
||||
fileName: '原始'
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '2',
|
||||
fileName: ''
|
||||
fileName: '结果'
|
||||
}]
|
||||
}
|
||||
keywordList.value=[],
|
||||
formRef.value?.resetFields()
|
||||
|
||||
}
|
||||
|
||||
|
||||
const selectedPointName = ref('')
|
||||
const selectedchapterText = ref('')
|
||||
const dialogVisiblePoints = ref(false)
|
||||
|
||||
// 添加层级信息
|
||||
const handleTreeWithLevel = (list, level = 1) => {
|
||||
return list.map(item => {
|
||||
const node = { ...item, level }
|
||||
if (item.children && item.children.length > 0) {
|
||||
node.children = handleTreeWithLevel(item.children, level + 1)
|
||||
}
|
||||
return node
|
||||
})
|
||||
}
|
||||
|
||||
// 只允许点击第三级节点
|
||||
const treeRef = ref() // 引用 el-tree
|
||||
const handleNodeClick = (data, node) => {
|
||||
if (data.level === 3) {
|
||||
formData.value.pointNames = data.id
|
||||
formData.value.pointNamesVo = data.name
|
||||
|
||||
// 获取父节点(章节名称)
|
||||
const currentNode = treeRef.value.getNode(data)
|
||||
const parentNode = currentNode.parent
|
||||
if (parentNode && parentNode.data) {
|
||||
formData.value.chapteridDictTextVo = parentNode.data.name
|
||||
formData.value.chapteridDictText = parentNode.data.id
|
||||
} else {
|
||||
formData.value.chapteridDictText = ''
|
||||
}
|
||||
|
||||
dialogVisiblePoints.value = false
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const deptList = ref<Tree[]>([]) // 树形结构
|
||||
/** 获得部门树 */
|
||||
const getTree = async () => {
|
||||
const res = await SpecialtyApi.listPoints()
|
||||
const tree = handleTree(res)
|
||||
deptList.value = []
|
||||
deptList.value = handleTreeWithLevel(tree)
|
||||
|
||||
|
||||
}
|
||||
const openPoints = async () => {
|
||||
await getTree();
|
||||
dialogVisiblePoints.value = true;
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.edit-dialog {
|
||||
|
Reference in New Issue
Block a user