【修改】出题知识点可选择,数据时效性,MYSQL判分语句增加默认权值

【增加】试卷任务参数,在已有的试卷抽卷
This commit is contained in:
YOHO\20373
2025-06-09 10:31:14 +08:00
parent ee776e7961
commit 41e5324bb9
49 changed files with 3727 additions and 2186 deletions

View File

@@ -16,9 +16,10 @@
<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>
@@ -33,19 +34,20 @@
<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>
</el-row>
<el-row>
@@ -58,10 +60,27 @@
</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-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-row>
<el-row>
@@ -173,7 +192,7 @@
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="score" label="权值" width="60" />
<el-table-column prop="scoreRate" label="权值" width="60" />
<el-table-column prop="content" label="考点语句" width="800" />
</el-table>
</div>
@@ -185,21 +204,30 @@
width="60%"
:close-on-click-modal="false"
class="custom-dialog"
draggable
>
<!-- 可滚动容器 -->
<div style="height: 400px; overflow-y: auto;">
<div style="height: 400px; overflow-y: auto;width:100%;">
<el-table
:data="kaodianList"
style="width: 100%;"
style="width: 100%; "
row-key="answerId"
:default-expand-all="false"
@row-contextmenu="(row, column, event) => handleTextRightClick(event, row)"
>
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="score" label="权值" width="60" />
<el-table-column prop="content" label="考点语句" width="600" />
<el-table-column type="index" label="序号" />
<el-table-column label="权值" width="80">
<template #default="{ row }">
<el-input
v-model="row.scoreRate"
size="small"
placeholder="请输入"
style="width: 100%;"
/>
</template>
</el-table-column>
<el-table-column prop="content" label="考点语句" />
<!-- 展开行 -->
<el-table-column type="expand">
@@ -218,7 +246,8 @@
v-model="scope.row.scoreRate"
size="small"
style="width: 70px;"
@input="updateScore(props.row)"
min="0"
/>
</template>
</el-table-column>
@@ -272,67 +301,12 @@
</el-tab-pane>
<!-- <el-tab-pane name="medium">
<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-upload
v-model:file-list="fileList"
class="upload-demo"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
>
<el-button>导入</el-button>
</el-upload>
</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>
<div class="block">
<el-table
:data="mediumList"
style="width: 100%"
@selection-change="handleMediumSelectionChange"
>
<el-table-column type="index" width="50" />
<el-table-column type="selection" width="55" />
<el-table-column prop="type" label="媒体类型" width="80" />
<el-table-column prop="title" label="标题" />
<el-table-column prop="displayIndex" label="显示序号" />
<el-table-column prop="size" label="大小" />
</el-table>
</div>
</el-tab-pane> -->
<el-tab-pane name="annex">
<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>
<!-- 提示 -->
@@ -422,6 +396,8 @@
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { FormRules } from 'element-plus'
import * as QuestionApi from '@/api/paper/question'
import * as SpecialtyApi from '@/api/points'
import { defaultProps, handleTree } from '@/utils/tree'
import FileForm from './components/FileForm.vue';
defineOptions({ name: 'ChoiceForm' })
import type { TabPaneName } from 'element-plus'
@@ -434,6 +410,8 @@ const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
pointNamesVo:'',
chapteridDictTextVo:'',
content: '',
specialtyName: '',
courseName: '',
@@ -441,7 +419,7 @@ const formData = ref({
required: '',
chapteridDictText: '',
analysis: '',
quLevel: '',
quLevel: 0,
pointNames: '',
subjectName: '',
@@ -452,13 +430,13 @@ const formData = ref({
quId: '',
url: '',
fileType: '1',
fileName: ''
fileName: '原始'
},
{
quId: '',
url: '',
fileType: '2',
fileName: ''
fileName: '结果'
}]
})
@@ -490,24 +468,10 @@ const rightHandleClick = (tab, e) => {
// 发起考点请求
QuestionApi.getListByQuId(kaodianData.value.quId).then(res => {
// res 是接口返回的数据数组
kaodianList.value = res.map(item => {
const totalScore = item.examMysqlKeywordList?.reduce((sum, kw) => {
return sum + Number(kw.scoreRate || 0);
}, 0);
return {
...item,
score: isNaN(totalScore) ? 0 : totalScore, // 如果是 NaN 则显示为 0
};
});
kaodianList.value = res;
});
}
};
function updateScore(parentRow: any) {
parentRow.score = (parentRow.examMysqlKeywordList || []).reduce((sum, kw) => {
const rate = parseFloat(kw.scoreRate);
return sum + (isNaN(rate) ? 0 : rate);
}, 0);
}
@@ -582,6 +546,7 @@ function confirmKao() {
const questionAnswerList = kaodianList.value.map(item => ({
answerId: item.answerId,
content: item.content,
scoreRate:item.scoreRate,
examMysqlKeywordList: (item.examMysqlKeywordList || []).map(kw => ({
keywordId: kw.keywordId,
answerId: kw.answerId,
@@ -629,9 +594,10 @@ const fetchKaodianByUrl = async (url: string) => {
// 将 SQL 字符串数组转换为 kaodianList 所需结构
kaodianList.value = sqlList.map((sql, index) => ({
answerId: index + 1, // 可自定义唯一ID生成逻辑
answerId: index + 1, // 可自定义唯一ID生成逻辑
quId: kaodianData.value.quId, // 如果有题目ID可以在这里设置
content: sql,
scoreRate:1,
examMysqlKeywordList: [] // 默认空关键词列表
}));
@@ -660,7 +626,7 @@ const beforeUpload = (file: File) => {
function removeKeyword(parentRow: any, keywordIndex: number) {
parentRow.examMysqlKeywordList.splice(keywordIndex, 1);
updateScore(parentRow); // 删除后更新score
}
@@ -877,8 +843,10 @@ keywordList.value = res.keywords
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
}
@@ -942,7 +910,7 @@ const resetForm = () => {
required: '',
chapteridDictText: '',
analysis: '',
quLevel: '0',
quLevel: 0,
pointNames: '',
subjectName: '',
status: '0',
@@ -953,13 +921,13 @@ const resetForm = () => {
quId: '',
url: '',
fileType: '1',
fileName: ''
fileName: '原始'
},
{
quId: '',
url: '',
fileType: '2',
fileName: ''
fileName: '结果'
}
]
}
@@ -969,6 +937,62 @@ const resetForm = () => {
}
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;
}
onMounted(() => {