【修改】试题审核出题页面
This commit is contained in:
@@ -16,48 +16,103 @@
|
||||
<el-input v-model="formData.specialtyName" placeholder="请输入专业" disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="试题名称" prop="quBankName">
|
||||
<el-input v-model="formData.quBankName" placeholder="请试题名称" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
<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">
|
||||
<el-form-item label="题库" prop="required">
|
||||
<el-input v-model="formData.required" placeholder="请选择题库" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="课程" prop="courseName">
|
||||
<el-input v-model="formData.courseName" placeholder="请输入课程" disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="题型难度" prop="quLevel">
|
||||
<el-input v-model="formData.quLevel" placeholder="请输入题型难度" disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="章节名称" prop="chapteridDictText">
|
||||
<el-input v-model="formData.chapteridDictText" placeholder="请输入章节名称" disabled />
|
||||
<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>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="知识点" prop="pointNames">
|
||||
<el-input v-model="formData.pointNames" placeholder="请输入知识点" disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="题型" prop="subjectName">
|
||||
<el-input v-model="formData.subjectName" placeholder="请输入题型" disabled/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<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-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-input v-model="formData.audit" placeholder="请输入审核状态" />
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
<el-row>
|
||||
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="启用状态" prop="status">
|
||||
<el-form-item label="启用状态" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio :label="'0'">启用</el-radio>
|
||||
<el-radio :label="'1'">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- <el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="来源" prop="resourceValue">
|
||||
<el-input v-model="formData.resourceValue" placeholder="请输入来源" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row> -->
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
<div class="edit-left bottom-common">
|
||||
@@ -256,7 +311,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'
|
||||
defineOptions({ name: 'ChoiceForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
@@ -267,6 +323,8 @@ const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
@@ -274,7 +332,7 @@ const formData = ref({
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
@@ -349,12 +407,9 @@ const open = async (queryParams: any ,type: string, id?: number) => {
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
console.log(id+"idid")
|
||||
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
|
||||
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await QuestionApi.getQuestionnotId(id)
|
||||
@@ -422,10 +477,8 @@ const submitForm = async () => {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown
|
||||
|
||||
await QuestionApi.editQuestionNoAudit(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
|
||||
await QuestionApi.editQuestionNoAudit(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
@@ -444,21 +497,66 @@ const resetForm = () => {
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
status: '',
|
||||
resourceValue: '',
|
||||
|
||||
resourceValue: ''
|
||||
}
|
||||
radio.value = 'A',
|
||||
// 清空 optionsContent 的属性
|
||||
Object.keys(optionsContent).forEach(key => {
|
||||
delete optionsContent[key]
|
||||
})
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
|
||||
const dialogVisiblePoints = ref(false)
|
||||
const openPoints = async () => {
|
||||
await getTree();
|
||||
dialogVisiblePoints.value = true;
|
||||
}
|
||||
// 只允许点击第三级节点
|
||||
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 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
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.edit-dialog {
|
||||
|
@@ -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,9 +419,9 @@ const formData = ref({
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
|
||||
subjectName: '',
|
||||
status: ' ',
|
||||
keywords: '',
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -577,14 +541,12 @@ function addKaodian(row: any) {
|
||||
|
||||
|
||||
function confirmKao() {
|
||||
if (!kaodianList.value.length) {
|
||||
ElMessage.warning("没有考点数据");
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建 questionAnswerList
|
||||
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,
|
||||
@@ -632,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: [] // 默认空关键词列表
|
||||
}));
|
||||
|
||||
@@ -663,7 +626,7 @@ const beforeUpload = (file: File) => {
|
||||
|
||||
function removeKeyword(parentRow: any, keywordIndex: number) {
|
||||
parentRow.examMysqlKeywordList.splice(keywordIndex, 1);
|
||||
updateScore(parentRow); // 删除后更新score
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -880,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
|
||||
|
||||
|
||||
}
|
||||
@@ -917,12 +882,8 @@ const submitForm = async () => {
|
||||
data.fileUploads = data.fileUploads?.filter(file => file.url && file.url.trim() !== '');
|
||||
|
||||
console.log(data, "提交的数据");
|
||||
|
||||
|
||||
await QuestionApi.editQuestionNoAudit(data);
|
||||
message.success(t('common.updateSuccess'));
|
||||
|
||||
|
||||
await QuestionApi.editQuestionNoAudit(data);
|
||||
message.success(t('common.updateSuccess'));
|
||||
dialogVisible.value = false;
|
||||
emit('success');
|
||||
} finally {
|
||||
@@ -935,23 +896,15 @@ const submitForm = async () => {
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
content: `---------------------------------------------------------------------------
|
||||
注意事项:
|
||||
请利用图形化管理界面或者MySQL命令行工具,在指定的试题数据库中进行答题。
|
||||
MySQL连接地址为localhost
|
||||
MySQL登录用户名为root
|
||||
MySQL端口号为6033或3306
|
||||
MySQL密码为空
|
||||
---------------------------------------------------------------------------`,
|
||||
content: `<p style="text-align: left;"><span style="font-family: 宋体;">--------------------------------------------------------------------------- </span></p><p style="text-align: left;"><span style="font-family: 宋体;">注意事项:</span></p><p style="text-align: left;"><span style="font-family: 宋体;">请利用图形化管理界面或者MySQL命令行工具,在指定的试题数据库中进行答题。 </span></p><p style="text-align: left;"><span style="font-family: 宋体;">MySQL连接地址为localhost</span></p><p style="text-align: left;"><span style="font-family: 宋体;">MySQL登录用户名为root</span></p><p style="text-align: left;"><span style="font-family: 宋体;">MySQL端口号为3306或者6033</span></p><p style="text-align: left;"><span style="font-family: 宋体;">MySQL密码为空</span></p><p style="text-align: left;"><span style="font-family: 宋体;">---------------------------------------------------------------------------</span>`,
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
quBankName: '',
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '0',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
status: '0',
|
||||
keywords: '',
|
||||
@@ -961,13 +914,13 @@ MySQL密码为空
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '1',
|
||||
fileName: ''
|
||||
fileName: '原始'
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '2',
|
||||
fileName: ''
|
||||
fileName: '结果'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -977,6 +930,62 @@ MySQL密码为空
|
||||
|
||||
}
|
||||
|
||||
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(() => {
|
||||
|
@@ -17,8 +17,12 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="知识点" prop="pointNames">
|
||||
<el-input v-model="formData.pointNames" placeholder="请输入知识点" disabled />
|
||||
<el-form-item label="章节名称" prop="chapteridDictText">
|
||||
<el-input
|
||||
v-model="formData.chapteridDictTextVo"
|
||||
placeholder="请输入章节名称"
|
||||
disabled
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -30,10 +34,17 @@
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<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
|
||||
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>
|
||||
@@ -45,29 +56,49 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="章节名称" prop="chapteridDictText">
|
||||
<el-form-item label="知识点" prop="pointNames">
|
||||
<el-input
|
||||
v-model="formData.chapteridDictText"
|
||||
placeholder="请输入章节名称"
|
||||
disabled
|
||||
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>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="启用状态" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYS_STATUS)"
|
||||
:key="dict.value"
|
||||
:value="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
<el-radio :label="'0'">启用</el-radio>
|
||||
<el-radio :label="'1'">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -87,8 +118,24 @@
|
||||
<Editor v-model="formData.analysis" height="150px" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="试题考点" name="answer">
|
||||
<el-button @click="addPptxInfo">新增</el-button>
|
||||
<el-tab-pane name="answer">
|
||||
<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-button @click="addPptxInfo">添加</el-button>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<!-- <el-button type="danger">删除</el-button> -->
|
||||
<div class="block">
|
||||
<el-table
|
||||
@@ -97,8 +144,15 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<!-- <el-table-column type="selection" width="55" /> -->
|
||||
<el-table-column label="考点" align="center" prop="contentIn" />
|
||||
<el-table-column label="权值" align="center" prop="scoreRate" />
|
||||
<el-table-column label="考点" align="center" prop="contentIn" width="360px"/>
|
||||
<el-table-column label="权值" align="center" prop="scoreRate" width="100px"/>
|
||||
<el-table-column label="操作" align="center" width="100px">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="handleDelete(scope.row)">
|
||||
<Icon icon="ep:delete" />删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@@ -186,9 +240,29 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" plain @click="openForm(scope.row.fileType)">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm(scope.row.fileType)"
|
||||
size="small"
|
||||
>
|
||||
<Icon icon="ep:upload" class="mr-5px" /> 上传
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="downloadFile(scope.row.url)"
|
||||
size="small"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 下载
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="deleteUrl(scope.$index)"
|
||||
size="small"
|
||||
><Icon icon="ep:download" class="mr-5px" />删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -232,7 +306,7 @@
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
||||
import { FormRules } from 'element-plus'
|
||||
import * as QuestionApi from '@/api/paper/question'
|
||||
import * as WordApi from '@/api/wps/word'
|
||||
@@ -240,7 +314,7 @@ import * as PptxApi from '@/api/wps/pptx'
|
||||
import FileForm from './components/FileForm.vue'
|
||||
import { defaultProps, handleTree } from '@/utils/tree'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
import * as SpecialtyApi from '@/api/points'
|
||||
defineOptions({ name: 'WpsPptxFrom' })
|
||||
const pptxPointsList = ref<Tree[]>([]) // 树形结构
|
||||
const pptxPointsInfoList = ref<Tree[]>([]) // 树形结构
|
||||
@@ -254,6 +328,8 @@ const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
@@ -261,7 +337,7 @@ const formData = ref({
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
@@ -311,6 +387,14 @@ const pptxPoints = ref({
|
||||
})
|
||||
let pptxPointsInfosList: (typeof pptxPoints)[] = []
|
||||
|
||||
const handleDelete = (row) => {
|
||||
for (let i = 0; i < list.value.length; i++) {
|
||||
if (row.content == list.value[i].content) {
|
||||
list.value.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fileTypeFormatter(row, column, cellValue) {
|
||||
if (cellValue === '0') return '素材文件(上传ZIP)'
|
||||
if (cellValue === '1') return '考试文件'
|
||||
@@ -368,13 +452,21 @@ const handleCheckChange = (data: Tree, checked: boolean, indeterminate: boolean)
|
||||
}
|
||||
|
||||
const addPptxInfo = async () => {
|
||||
var filePath = ''
|
||||
for (var i = 0; i < documentList.value.length; i++) {
|
||||
if (documentList.value[i].fileType == '2') {
|
||||
filePath = documentList.value[i].url
|
||||
}
|
||||
}
|
||||
// http://115.120.213.238:9000/exam/9f7d8f5d7c68cc2bfd03a23c19045efe7ba13a4bebeb833abece146908bcd0c6.docx documentList.value[1].url
|
||||
if (documentList.value[2].url == '' || documentList.value[2].url == null) {
|
||||
if (filePath == '' || filePath == null) {
|
||||
return
|
||||
}
|
||||
const res = await PptxApi.getPptxInfo(documentList.value[2].url)
|
||||
pptxPointsList.value = []
|
||||
pptxPointsList.value.push(...handleTree(res))
|
||||
if (pptxPointsList.value.length <= 0) {
|
||||
const res = await PptxApi.getPptxInfo(filePath)
|
||||
pptxPointsList.value = []
|
||||
pptxPointsList.value.push(...handleTree(res))
|
||||
}
|
||||
dialogFormVisiblePptxInfo.value = true
|
||||
}
|
||||
const queryParams = reactive({
|
||||
@@ -405,11 +497,21 @@ const submitPptxPoints = async () => {
|
||||
const res = await PptxApi.getPptxListInfos(pptxPointsInfosList)
|
||||
pptxPointsInfosList = []
|
||||
console.log(list.value)
|
||||
var indexFlag = false
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
list.value.push(res[i])
|
||||
for (let x = 0; x < list.value.length; x++) {
|
||||
if (res[i].content == list.value[x].content) {
|
||||
// 如果存在相同的数据话 不进入
|
||||
indexFlag = true
|
||||
}
|
||||
}
|
||||
if (!indexFlag) {
|
||||
list.value.push(res[i])
|
||||
}
|
||||
}
|
||||
dialogFormVisiblePptxInfo.value = false
|
||||
dialogFormVisiblePptxInfos.value = false
|
||||
pptxPointsList.value = []
|
||||
}
|
||||
const formRules = reactive<FormRules>({
|
||||
status: [{ required: true, message: '启用状态必填', trigger: 'blur' }]
|
||||
@@ -462,7 +564,7 @@ const open = async (queryParams: any, type: string, id?: number) => {
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const res = await QuestionApi.getQuestion(id)
|
||||
const res = await QuestionApi.getQuestionnotId(id)
|
||||
formData.value = res
|
||||
list.value = formData.value.answerList
|
||||
documentList.value = res.fileUploads
|
||||
@@ -492,13 +594,8 @@ const submitForm = async () => {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown
|
||||
if (formType.value === 'create') {
|
||||
await QuestionApi.addQuestion(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await QuestionApi.editQuestion(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
await QuestionApi.editQuestionNoAudit(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
@@ -506,7 +603,42 @@ const submitForm = async () => {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
const downloadFile = async (url: string) => {
|
||||
if (!url) {
|
||||
ElMessage.warning('暂无可下载的文件地址')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url)
|
||||
if (!response.ok) {
|
||||
throw new Error('下载失败')
|
||||
}
|
||||
|
||||
const blob = await response.blob()
|
||||
const blobUrl = window.URL.createObjectURL(blob)
|
||||
|
||||
// 提取文件名
|
||||
const filename = url.substring(url.lastIndexOf('/') + 1).split('?')[0]
|
||||
|
||||
// 创建 a 标签并下载
|
||||
const a = document.createElement('a')
|
||||
a.href = blobUrl
|
||||
a.download = filename
|
||||
a.style.display = 'none'
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
a.remove()
|
||||
|
||||
window.URL.revokeObjectURL(blobUrl)
|
||||
} catch (err: any) {
|
||||
ElMessage.error(`下载失败:${err.message}`)
|
||||
}
|
||||
}
|
||||
const deleteUrl = (index: number) => {
|
||||
formData.value.fileUploads[index].url = ''
|
||||
formData.value.fileUploads[index].fileName = ''
|
||||
}
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
@@ -517,11 +649,11 @@ const resetForm = () => {
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
status: '',
|
||||
status: '0',
|
||||
resourceValue: '',
|
||||
answerList: [
|
||||
{
|
||||
@@ -572,8 +704,59 @@ const resetForm = () => {
|
||||
fileName: ''
|
||||
}
|
||||
]
|
||||
list.value = []
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
const dialogVisiblePoints = ref(false)
|
||||
const openPoints = async () => {
|
||||
await getTree();
|
||||
dialogVisiblePoints.value = true;
|
||||
}
|
||||
// 只允许点击第三级节点
|
||||
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 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
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.edit-dialog {
|
||||
|
@@ -16,11 +16,18 @@
|
||||
<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-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,13 +36,21 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<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>
|
||||
@@ -45,29 +60,50 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="章节名称" prop="chapteridDictText">
|
||||
<el-form-item label="知识点" prop="pointNames">
|
||||
<el-input
|
||||
v-model="formData.chapteridDictText"
|
||||
placeholder="请输入章节名称"
|
||||
disabled
|
||||
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>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="启用状态" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYS_STATUS)"
|
||||
:key="dict.value"
|
||||
:value="dict.value"
|
||||
>
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
<el-radio :label="'0'">启用</el-radio>
|
||||
<el-radio :label="'1'">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="审核状态" prop="audit">
|
||||
<el-select v-model="formData.audit" placeholder="请选择审核状态">
|
||||
<el-option
|
||||
v-for="dict in getStrDictOptions(DICT_TYPE.QUESTION_AUDIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="edit-bottom">
|
||||
@@ -87,8 +123,24 @@
|
||||
<Editor v-model="formData.analysis" height="150px" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="试题考点" name="answer">
|
||||
<el-button @click="addWordInfo">新增</el-button>
|
||||
<el-tab-pane name="answer">
|
||||
<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-button @click="addWordInfo">添加</el-button>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
<!-- <el-button type="danger">删除</el-button> -->
|
||||
<div class="block">
|
||||
<el-table
|
||||
@@ -97,8 +149,15 @@
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<!-- <el-table-column type="selection" width="55" /> -->
|
||||
<el-table-column label="考点" align="center" prop="contentIn" />
|
||||
<el-table-column label="权值" align="center" prop="scoreRate" />
|
||||
<el-table-column label="考点" align="center" prop="contentIn" width="360px" />
|
||||
<el-table-column label="权值" align="center" prop="scoreRate" width="100px" />
|
||||
<el-table-column label="操作" align="center" width="100px">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="handleDelete(scope.row)">
|
||||
<Icon icon="ep:delete" />删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@@ -186,9 +245,29 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" plain @click="openForm(scope.row.fileType)">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm(scope.row.fileType)"
|
||||
size="small"
|
||||
>
|
||||
<Icon icon="ep:upload" class="mr-5px" /> 上传
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="downloadFile(scope.row.url)"
|
||||
size="small"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 下载
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="deleteUrl(scope.$index)"
|
||||
size="small"
|
||||
><Icon icon="ep:download" class="mr-5px" />删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -208,6 +287,7 @@
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<FileForm ref="FileRef" @success="handleUploadSuccess" />
|
||||
<el-dialog v-model="dialogFormVisibleWordInfo" title="考点设置" width="400px">
|
||||
<el-skeleton :rows="5" animated v-if="wordPointsList.length < 0 && isLoading" />
|
||||
<el-tree
|
||||
style="max-width: 600px"
|
||||
:data="wordPointsList"
|
||||
@@ -232,7 +312,7 @@
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
||||
import { FormRules } from 'element-plus'
|
||||
import * as QuestionApi from '@/api/paper/question'
|
||||
import * as WordApi from '@/api/wps/word'
|
||||
@@ -241,7 +321,7 @@ import WordInfo from './components/WordInfo.vue'
|
||||
import WordInfos from './components/WordInfos.vue'
|
||||
import { defaultProps, handleTree } from '@/utils/tree'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
import * as SpecialtyApi from '@/api/points'
|
||||
defineOptions({ name: 'WpsWordFrom' })
|
||||
const wordPointsList = ref<Tree[]>([]) // 树形结构
|
||||
const wordPointsInfoList = ref<Tree[]>([]) // 树形结构
|
||||
@@ -251,10 +331,13 @@ const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const loading = ref(false) // 列表的加载中
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const isLoading = ref(false)
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
pointNamesVo:'',
|
||||
chapteridDictTextVo:'',
|
||||
content: '',
|
||||
specialtyName: '',
|
||||
courseName: '',
|
||||
@@ -262,7 +345,7 @@ const formData = ref({
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
@@ -270,10 +353,10 @@ const formData = ref({
|
||||
resourceValue: '',
|
||||
answerList: [
|
||||
{
|
||||
image: "",
|
||||
content: "",
|
||||
contentIn: "",
|
||||
scoreRate: "",
|
||||
image: '',
|
||||
content: '',
|
||||
contentIn: '',
|
||||
scoreRate: ''
|
||||
}
|
||||
],
|
||||
fileUploads: [
|
||||
@@ -302,17 +385,13 @@ const wordPointsFun = ref({
|
||||
function: ''
|
||||
})
|
||||
const wordPoints = ref({
|
||||
id: '',
|
||||
chineseName: '',
|
||||
name: '',
|
||||
englishName: '',
|
||||
filePath: '',
|
||||
type: '',
|
||||
belongTo: '',
|
||||
parameter: '',
|
||||
function: [] as {
|
||||
chineseName: string
|
||||
function: string
|
||||
}[]
|
||||
isboo: '',
|
||||
function: ''
|
||||
})
|
||||
let wordPointsInfosList: (typeof wordPoints)[] = []
|
||||
|
||||
@@ -359,74 +438,154 @@ const wordData = reactive({
|
||||
})
|
||||
|
||||
const handleCheckChange = (data: Tree, checked: boolean, indeterminate: boolean) => {
|
||||
if (checked || indeterminate) {
|
||||
// if (checked || indeterminate) {
|
||||
// wordPoints.value.belongTo = data.belongTo
|
||||
// wordPoints.value.parameter = data.isboo
|
||||
// wordPoints.value.type = data.type
|
||||
// wordPointsFun.value = {
|
||||
// chineseName: '',
|
||||
// function: ''
|
||||
// }
|
||||
// wordPointsFun.value.chineseName = data.toChinese
|
||||
// wordPointsFun.value.function = data.nodeFunction
|
||||
// wordPoints.value.function.push(cloneDeep(wordPointsFun.value))
|
||||
// console.log(wordPoints)
|
||||
// }
|
||||
if (data.titleType == '2') {
|
||||
wordPoints.value.name = chineseName.value + data.toChinese
|
||||
wordPoints.value.filePath = filePath.value
|
||||
wordPoints.value.function = englishNames.value + data.nodeFunction
|
||||
wordPoints.value.englishName = englishNames.value
|
||||
wordPoints.value.belongTo = data.belongTo
|
||||
wordPoints.value.parameter = data.isboo
|
||||
wordPoints.value.isboo = data.isboo
|
||||
wordPoints.value.type = data.type
|
||||
wordPointsFun.value = {
|
||||
chineseName: '',
|
||||
function: ''
|
||||
}
|
||||
wordPointsFun.value.chineseName = data.name
|
||||
wordPointsFun.value.function = data.nodeFunction
|
||||
wordPoints.value.function.push(cloneDeep(wordPointsFun.value))
|
||||
console.log(wordPoints)
|
||||
wordPointsInfosList.push(cloneDeep(wordPoints.value))
|
||||
}
|
||||
console.log(data, checked, indeterminate)
|
||||
}
|
||||
const dialogVisiblePoints = ref(false)
|
||||
const openPoints = async () => {
|
||||
await getTree();
|
||||
dialogVisiblePoints.value = true;
|
||||
}
|
||||
// 只允许点击第三级节点
|
||||
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 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 addWordInfo = async () => {
|
||||
var filePath = ''
|
||||
for (var i = 0; i < documentList.value.length; i++) {
|
||||
if (documentList.value[i].fileType == '2') {
|
||||
filePath = documentList.value[i].url
|
||||
}
|
||||
}
|
||||
// http://115.120.213.238:9000/exam/9f7d8f5d7c68cc2bfd03a23c19045efe7ba13a4bebeb833abece146908bcd0c6.docx documentList.value[1].url
|
||||
if (documentList.value[2].url == '' || documentList.value[2].url == null) {
|
||||
if (filePath == '' || filePath == null) {
|
||||
return
|
||||
}
|
||||
const res = await WordApi.getWordInfo(documentList.value[2].url)
|
||||
wordPointsList.value = []
|
||||
wordPointsList.value.push(...handleTree(res))
|
||||
dialogFormVisibleWordInfo.value = true
|
||||
isLoading.value = true
|
||||
if (wordPointsList.value.length <= 0) {
|
||||
const res = await WordApi.getWordInfo(filePath)
|
||||
isLoading.value = false
|
||||
wordPointsList.value = []
|
||||
wordPointsList.value.push(...handleTree(res))
|
||||
}
|
||||
}
|
||||
const queryParams = reactive({
|
||||
nodeFunction: undefined
|
||||
})
|
||||
const handleSpecialtyNodeClick = async (row: any) => {
|
||||
titles.value = row.name
|
||||
englishName.value = row.englishName
|
||||
filePath.value = row.filePath
|
||||
nodeFunction.value = row.selectName
|
||||
dialogFormVisibleWordInfos.value = true
|
||||
}
|
||||
|
||||
const chineseName = ref('')
|
||||
const nodeFunctions = ref('')
|
||||
const englishNames = ref('')
|
||||
const handleNodelClick = async (row: any) => {
|
||||
console.log(row)
|
||||
queryParams.nodeFunction = row.selectName
|
||||
wordPoints.value.chineseName = row.name.split(':')[0]
|
||||
wordPoints.value.englishName = row.englishName
|
||||
wordPoints.value.filePath = row.filePath
|
||||
wordPoints.value.id = row.id
|
||||
chineseName.value = '【' + row.name + '】'
|
||||
filePath.value = row.filePath
|
||||
nodeFunctions.value = row.selectName
|
||||
englishNames.value = row.englishName
|
||||
const res = await WordApi.getWordInfos(queryParams)
|
||||
wordPointsInfoList.value = []
|
||||
wordPointsInfoList.value.push(...handleTree(res))
|
||||
dialogFormVisibleWordInfos.value = true
|
||||
}
|
||||
const handleDelete = (row) => {
|
||||
console.log(row)
|
||||
for (let i = 0; i < list.value.length; i++) {
|
||||
if (row.content == list.value[i].content) {
|
||||
list.value.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const submitWordPoints = async () => {
|
||||
wordPointsInfosList.push(wordPoints.value)
|
||||
const res = await WordApi.getWordListInfos(wordPointsInfosList)
|
||||
wordPoints.value = {
|
||||
id: '',
|
||||
chineseName: '',
|
||||
name: '',
|
||||
englishName: '',
|
||||
filePath: '',
|
||||
type: '',
|
||||
belongTo: '',
|
||||
parameter: '',
|
||||
function: []
|
||||
isboo: '',
|
||||
function: ''
|
||||
}
|
||||
wordPointsInfosList = []
|
||||
console.log(list.value)
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
list.value.push(res[i])
|
||||
var indexFlag = false
|
||||
for (let x = 0; x < list.value.length; x++) {
|
||||
if (res[i].content == list.value[x].content) {
|
||||
// 如果存在相同的数据话 不进入
|
||||
indexFlag = true
|
||||
}
|
||||
}
|
||||
if (!indexFlag) {
|
||||
list.value.push(res[i])
|
||||
}
|
||||
}
|
||||
dialogFormVisibleWordInfo.value = false
|
||||
dialogFormVisibleWordInfos.value = false
|
||||
wordPointsList.value = []
|
||||
}
|
||||
const formRules = reactive<FormRules>({
|
||||
status: [{ required: true, message: '启用状态必填', trigger: 'blur' }]
|
||||
@@ -455,7 +614,42 @@ const FileRef = ref()
|
||||
const openForm = (type: string) => {
|
||||
FileRef.value.open(type)
|
||||
}
|
||||
const downloadFile = async (url: string) => {
|
||||
if (!url) {
|
||||
ElMessage.warning('暂无可下载的文件地址')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url)
|
||||
if (!response.ok) {
|
||||
throw new Error('下载失败')
|
||||
}
|
||||
|
||||
const blob = await response.blob()
|
||||
const blobUrl = window.URL.createObjectURL(blob)
|
||||
|
||||
// 提取文件名
|
||||
const filename = url.substring(url.lastIndexOf('/') + 1).split('?')[0]
|
||||
|
||||
// 创建 a 标签并下载
|
||||
const a = document.createElement('a')
|
||||
a.href = blobUrl
|
||||
a.download = filename
|
||||
a.style.display = 'none'
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
a.remove()
|
||||
|
||||
window.URL.revokeObjectURL(blobUrl)
|
||||
} catch (err: any) {
|
||||
ElMessage.error(`下载失败:${err.message}`)
|
||||
}
|
||||
}
|
||||
const deleteUrl = (index: number) => {
|
||||
formData.value.fileUploads[index].url = ''
|
||||
formData.value.fileUploads[index].fileName = ''
|
||||
}
|
||||
// 媒体文件
|
||||
const mediumList = ref([] as any)
|
||||
const multipleMediumSelection = ref([] as any)
|
||||
@@ -484,7 +678,7 @@ const open = async (queryParams: any, type: string, id?: number) => {
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const res = await QuestionApi.getQuestion(id)
|
||||
const res = await QuestionApi.getQuestionnotId(id)
|
||||
formData.value = res
|
||||
console.log(formData.value)
|
||||
list.value = formData.value.answerList
|
||||
@@ -497,8 +691,10 @@ const open = async (queryParams: any, type: string, id?: number) => {
|
||||
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
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
@@ -527,13 +723,8 @@ const submitForm = async () => {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown
|
||||
if (formType.value === 'create') {
|
||||
await QuestionApi.addQuestion(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await QuestionApi.editQuestion(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
await QuestionApi.editQuestionNoAudit(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
@@ -552,40 +743,40 @@ const resetForm = () => {
|
||||
required: '',
|
||||
chapteridDictText: '',
|
||||
analysis: '',
|
||||
quLevel: '',
|
||||
quLevel: 0,
|
||||
pointNames: '',
|
||||
audit: '',
|
||||
subjectName: '',
|
||||
status: '',
|
||||
status: '0',
|
||||
resourceValue: '',
|
||||
answerList: [
|
||||
{
|
||||
image: "",
|
||||
content: "",
|
||||
contentIn: "",
|
||||
scoreRate: "",
|
||||
}
|
||||
],
|
||||
fileUploads: [
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '0',
|
||||
fileName: ''
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '1',
|
||||
fileName: ''
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '2',
|
||||
fileName: ''
|
||||
}
|
||||
]
|
||||
{
|
||||
image: '',
|
||||
content: '',
|
||||
contentIn: '',
|
||||
scoreRate: ''
|
||||
}
|
||||
],
|
||||
fileUploads: [
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '0',
|
||||
fileName: ''
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '1',
|
||||
fileName: ''
|
||||
},
|
||||
{
|
||||
quId: '',
|
||||
url: '',
|
||||
fileType: '2',
|
||||
fileName: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
documentList.value = [
|
||||
{
|
||||
@@ -607,6 +798,7 @@ const resetForm = () => {
|
||||
fileName: ''
|
||||
}
|
||||
]
|
||||
list.value = []
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
@@ -179,7 +179,7 @@
|
||||
<el-table-column
|
||||
label="知识点"
|
||||
align="center"
|
||||
prop="pointNames"
|
||||
prop="pointNamesVo"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column
|
||||
|
Reference in New Issue
Block a user