提交 e527f099 authored 作者: 王鹏飞's avatar 王鹏飞

updates

上级 15bafdeb
$--color-primary: #c01c40; $--color-primary: #c01c40;
$--color-info: #3c4043; $--color-info: #3c4043;
// border // border
$--border-radius-small: 8px !default; $--border-radius-small: 8px !default;
// checkbox
$--checkbox-border-radius: 2px !default;
// dialog // dialog
$--message-close-size: 20px !default; $--message-close-size: 20px !default;
......
...@@ -143,7 +143,7 @@ export default { ...@@ -143,7 +143,7 @@ export default {
return return
} }
// 参数设置 // 参数设置
let params = this.params let params = { ...this.params }
// 翻页参数设置 // 翻页参数设置
if (this.hasPagination) { if (this.hasPagination) {
params.page = this.page.currentPage.toString() params.page = this.page.currentPage.toString()
......
...@@ -13,17 +13,20 @@ import { getQuestionCategory } from '@/api/base.js' ...@@ -13,17 +13,20 @@ import { getQuestionCategory } from '@/api/base.js'
export default { export default {
data() { data() {
return { return {
options: [], options: []
defaultProps: {
label: 'category_name',
value: 'id',
checkStrictly: true
}
} }
}, },
computed: { computed: {
activeProject() { activeProject() {
return this.$store.state.activeProject || {} return this.$store.state.activeProject || {}
},
defaultProps() {
return {
label: 'category_name',
value: 'id',
checkStrictly: true,
multiple: this.$attrs.multiple || false
}
} }
}, },
beforeMount() { beforeMount() {
......
...@@ -57,16 +57,22 @@ export function updatePaperRules(data) { ...@@ -57,16 +57,22 @@ export function updatePaperRules(data) {
return httpRequest.post(`/api/qbs/admin/v1/question-paper/rules/${data.id}`, data) return httpRequest.post(`/api/qbs/admin/v1/question-paper/rules/${data.id}`, data)
} }
/**
* 搜索试题数量--自动组卷
*/
export function getQuestionCount(params) {
return httpRequest.get('/api/qbs/admin/v1/question/search/count', { params })
}
/** /**
* 获取试卷分类 * 获取试卷分类
*/ */
export function getPaperCategory(params) { export function getPaperCategory(params) {
return httpRequest.get(`/api/qbs/admin/v1/question-category/tree/${params.project_prefix}`, { params }) return httpRequest.get(`/api/qbs/admin/v1/question-category/tree/${params.project_prefix}`, { params })
} }
/** /**
* 获取知识点/标签 * 获取知识点/标签
*/ */
export function getKnowledge(params) { export function getKnowledge(params) {
return httpRequest.get('/admin/v1/knowledge-point/search/x1', { params }) return httpRequest.get('/api/admin/v1/knowledge-point/search/x1', { params })
} }
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
<div style="margin: 0 20px"> <div style="margin: 0 20px">
<!-- 选题组卷添加试卷第一步 --> <!-- 选题组卷添加试卷第一步 -->
<div v-show="step === 1"> <div v-show="step === 1">
<app-list v-bind="tableOptions" ref="list" @selection-change="handleSelectionChange"></app-list> <question-select @selection-change="handleSelectionChange"></question-select>
<el-button type="primary" class="nextStep" @click="nextStep">下一步</el-button> <div class="buttons">
<el-button type="primary" @click="nextStep">下一步</el-button>
</div>
</div> </div>
<!-- 选题组卷添加试卷第二步 --> <!-- 选题组卷添加试卷第二步 -->
<div v-show="step === 2"> <div v-show="step === 2">
...@@ -19,136 +21,65 @@ ...@@ -19,136 +21,65 @@
<el-form-item label="此次试卷总分:">{{ data.paper_total_score }}</el-form-item> <el-form-item label="此次试卷总分:">{{ data.paper_total_score }}</el-form-item>
<el-form-item label="已设置试题总分:">{{ addedQuestionsScore }}</el-form-item> <el-form-item label="已设置试题总分:">{{ addedQuestionsScore }}</el-form-item>
<el-divider></el-divider> <el-divider></el-divider>
<el-form-item <template v-if="setMethod === 1">
:label="item.question_type_name + ':'" <el-form-item
v-for="(item, index) in questionTypeGroups" :label="item.question_type_name + ':'"
:key="index" :key="index"
> v-for="(item, index) in questionTypeGroups"
<span>数量:{{ item.total }}</span>
<span style="margin-left: 20px"
>分值: <el-input v-model="item.score" style="width: 100px"></el-input>{{ item.score }}</span
> >
<!-- <template v-if="canBatchSetting(item.question_type)"> <ul>
<el-button type="primary" class="settingScore" @click="batchSetting">批量设置分数</el-button> <li>数量:{{ item.total }}</li>
</template> <li>分值: {{ item.score }}</li>
<template v-else> <li>
<span class="settingScore">此题型只能在试卷详情页面逐一设置</span> <template v-if="canBatchSetting(item.question_type)">
</template> --> <el-button type="primary" class="settingScore" @click="showBatchSetting(item)"
</el-form-item> >批量设置分数</el-button
<el-button type="primary" @click="prevStep">上一步</el-button> >
<el-button type="primary" style="margin-left: 20px" @click="handleSubmit">保存</el-button> </template>
<template v-else>
<span class="settingScore">此题型只能在试卷详情页面逐一设置</span>
</template>
</li>
</ul>
</el-form-item>
</template>
</el-form> </el-form>
<div class="buttons">
<el-button type="primary" @click="prevStep">上一步</el-button>
<el-button type="primary" style="margin-left: 20px" @click="handleSave">保存</el-button>
</div>
</div> </div>
<BatchSetting :visible.sync="visible" /> <BatchSetting
:visible.sync="visible"
:data="questionTypeGroups[batchSettingQuestionType]"
@update="handleUpdateScore"
v-if="visible"
/>
</div> </div>
</el-drawer> </el-drawer>
</template> </template>
<script> <script>
import QuestionSelect from './QuestionSelect.vue'
import BatchSetting from './BatchSetting.vue' import BatchSetting from './BatchSetting.vue'
import { getQuestionList, batchGetQuestionList, updatePaperRules } from '../api.js' import { batchGetQuestionList, updatePaperRules } from '../api.js'
export default { export default {
props: { props: {
data: { type: Object, default: () => ({}) } data: { type: Object, default: () => ({}) }
}, },
components: { BatchSetting }, components: { QuestionSelect, BatchSetting },
data() { data() {
return { return {
visible: false, multipleSelection: [], // 选择的试题,不包含子题
multipleSelection: [], // 选择项
setMethod: 1, // 设置方式 setMethod: 1, // 设置方式
step: 1, step: 1,
questions: [], // 试题列表 questions: [], // 选择的完整试题列表
questionTypeGroups: {} // 试题类型组 questionTypeGroups: {}, // 试题类型组
visible: false,
batchSettingQuestionType: null // 批量设置试题类型
} }
}, },
computed: { computed: {
tableOptions() {
return {
remote: {
httpRequest: getQuestionList,
params: { question_type: '', question_title: '', question_difficulty: '', question_category: '' }
},
filters: [
{
type: 'select',
prop: 'question_type',
placeholder: '请选择题目类型',
options: [
{ label: '单选题', value: '1' },
{ label: '多选题', value: '2' },
{ label: '问答题', value: '3' },
{ label: '案例题', value: '5' },
{ label: '判断题', value: '6' },
{ label: '实操题', value: '7' },
{ label: '情景题', value: '8' }
],
label: '题目类型'
},
{
type: 'select',
prop: 'question_difficulty',
placeholder: '请选择题目难度等级',
options: [
{ label: '易', value: '1' },
{ label: '中', value: '2' },
{ label: '难', value: '3' }
],
label: '难度等级'
},
{
type: 'input',
prop: 'question_category',
placeholder: '请选择试题分类',
options: this.staffList,
label: '试题分类'
},
{
type: 'input',
prop: 'question_title',
label: '题目标题',
placeholder: '请输入题目标题'
},
{
type: 'input',
prop: 'name4',
label: '题干内容',
placeholder: '请输入题干内容'
},
{
type: 'input',
prop: 'name5',
label: '知识点',
placeholder: '请输入知识点'
}
],
columns: [
{ type: 'selection' },
{ type: 'index', label: '序号' },
{
label: '题目类型',
prop: 'question_type',
computed: ({ row }) => {
const map = { 1: '单选题', 2: '多选题', 3: '问答题', 5: '案例题', 6: '判断题', 7: '实操题', 8: '情景题' }
return map[row.question_type] || row.question_type
}
},
{ label: '试卷分类', prop: 'question_category.category_name' },
{ label: '题目标题', prop: 'question_title' },
{ label: '知识点', prop: 'knowledge_point.title' },
{
label: '难度等级',
prop: 'question_difficulty',
computed: ({ row }) => {
const map = { 1: '易', 2: '中', 3: '难' }
return map[row.question_difficulty] || row.question_difficulty
}
},
{ label: '更新人', prop: 'operator.realname' }
]
}
},
// 已添加的试题 // 已添加的试题
addedQuestions() { addedQuestions() {
return this.data.questions || [] return this.data.questions || []
...@@ -161,8 +92,8 @@ export default { ...@@ -161,8 +92,8 @@ export default {
} }
}, },
methods: { methods: {
handleSelectionChange(val) { handleSelectionChange(value) {
this.multipleSelection = val this.multipleSelection = value
}, },
// 下一步 // 下一步
nextStep() { nextStep() {
...@@ -193,7 +124,7 @@ export default { ...@@ -193,7 +124,7 @@ export default {
total: 1, total: 1,
question_type: item.question_type, question_type: item.question_type,
question_type_name: map[item.question_type], question_type_name: map[item.question_type],
score: '', score: '0',
questions: [item] questions: [item]
} }
} }
...@@ -205,18 +136,44 @@ export default { ...@@ -205,18 +136,44 @@ export default {
canBatchSetting(value) { canBatchSetting(value) {
return [1, 2, 6].includes(value) return [1, 2, 6].includes(value)
}, },
batchSetting() { // 批量设置分数
showBatchSetting(data) {
this.visible = true this.visible = true
this.batchSettingQuestionType = data.question_type
},
handleUpdateScore(data) {
const { question_type: questionType, score } = data
this.questionTypeGroups[questionType].score = score
}, },
// 保存 // 保存
handleSave() {
// 批量设置分数
if (this.setMethod === 1) {
this.questions = this.questions.map(item => {
return { ...item, score: this.questionTypeGroups[item.question_type].score }
})
}
// 合并已添加和选择的试题,新的替换旧的
const questionList = this.addedQuestions.reduce((result, item) => {
if (!result.find(item2 => item2.id === item.id)) {
result.unshift(item)
}
return result
}, this.questions)
// 更新详情页的试题
this.$emit('update', questionList)
// 关闭弹框
this.$emit('update:visible', false)
},
// 保存,更新试卷规则
handleSubmit() { handleSubmit() {
const rules = [] const rules = []
Object.values(this.questionTypeGroups).forEach(item => { Object.values(this.questionTypeGroups).forEach(item => {
item.questions.forEach(question => { item.questions.forEach(question => {
rules.push({ id: question.id, score: item.score || 0 }) rules.push({ id: question.id, score: item.score })
if (item.children && item.children.length) { if (item.children && item.children.length) {
item.children.forEach(question => { item.children.forEach(question => {
rules.push({ id: question.id, score: item.score || 0 }) rules.push({ id: question.id, score: item.score })
}) })
} }
}) })
...@@ -232,13 +189,20 @@ export default { ...@@ -232,13 +189,20 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.nextStep { .buttons {
position: absolute; position: absolute;
left: 50%; left: 50%;
bottom: 10px; bottom: 30px;
transform: translateX(-50%); transform: translateX(-50%);
text-align: center;
} }
.settingScore { ul {
margin-left: 120px; display: flex;
li {
margin-right: 20px;
min-width: 140px;
line-height: 32px;
color: #606266;
}
} }
</style> </style>
<template> <template>
<el-drawer size="80%" v-bind="$attrs" v-on="$listeners"> <el-drawer title="试卷列表" size="80%" v-bind="$attrs" v-on="$listeners">
<div slot="header" class="clearfix"> <div style="margin: 0 20px">
<span>试卷列表</span> <el-form :model="form">
</div> <!-- 组卷题库 -->
<el-form :model="form" style="padding-left: 30px"> <el-form-item label="组卷题库:">
<!-- 组卷题库 --> <el-radio-group v-model="form.permission">
<el-form-item label="组卷题库:"> <el-radio label="1">我的题库</el-radio>
<el-radio-group v-model="form.paperType"> <el-radio label="2">公共题库</el-radio>
<el-radio label="0">我的题库</el-radio> </el-radio-group>
<el-radio label="1">公共题库</el-radio> </el-form-item>
</el-radio-group> <!-- 自动组卷规则 -->
</el-form-item> <el-form-item label="自动组卷规则:">
<!-- 自动组卷规则 --> <el-table ref="mytable" :data="questionList" style="width: 100%">
<el-form-item label="自动组卷规则:"> <el-table-column align="center" label="题目类型">
<el-table ref="mytable" :data="table_data" style="width: 100%" class="paperRule"> <template slot-scope="{ row, $index }">
<el-table-column <el-select v-model="row.question_type" @change="getQuestionMaxCount($index, row)">
align="center" <el-option
v-for="(item, index, key) in table_columns" v-for="item in questionTypeMap"
:item="item" :key="item.value"
:key="key" :label="item.label"
:index="index" :value="item.value"
:label="item.label" ></el-option>
> </el-select>
<template slot-scope="scope"> </template>
<!-- 多选 --> </el-table-column>
<el-select v-model="scope.row[item.prop]" v-if="scope.row.edit && item.type === 'select'">
{{ scope.row[item.prop] }}
<el-option v-for="(el, index) in item.options" :key="index" :label="el.label" :value="el.value">
</el-option>
</el-select>
<!-- 数量 -->
<el-input-number
v-if="scope.row.edit && item.type === 'input' && item.prop === 'question_num'"
size="small"
v-model="scope.row[item.prop]"
:placeholder="'请输入' + item.label"
:min="1"
:max="20"
></el-input-number>
<!-- 分值 --> <el-table-column align="center" label="难度">
<el-input-number <template slot-scope="{ row, $index }">
v-if="scope.row.edit && item.type === 'input' && item.prop === 'question_score'" <el-select v-model="row.question_difficulty" @change="getQuestionMaxCount($index, row)">
size="small" <el-option
v-model="scope.row[item.prop]" v-for="item in questionDifficultyMap"
:placeholder="'请输入' + item.label" :key="item.value"
:min="1" :label="item.label"
:max="30" :value="item.value"
> ></el-option>
</el-input-number> </el-select>
<span v-if="!scope.row.edit && item.prop === 'questionType'">{{ </template>
subOptionType[scope.row[item.prop]] </el-table-column>
}}</span>
<span v-if="!scope.row.edit && item.prop === 'difficulty'">{{
difficultyOptionType[scope.row[item.prop]]
}}</span>
<span v-if="!scope.row.edit && item.prop === 'question_num'">{{ scope.row[item.prop] }}</span>
<span v-if="!scope.row.edit && item.prop === 'question_score'">{{ scope.row[item.prop] }}</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<!-- 编辑 -->
<el-button
type="primary"
icon="el-icon-edit"
circle
size="mini"
v-if="!scope.row.edit"
@click="handleEdit(scope.$index, scope.row)"
></el-button>
<!-- 保存 -->
<el-button
circle
size="mini"
type="success"
:plain="true"
icon="el-icon-check"
v-if="scope.row.edit"
@click="handleSave(scope.$index, scope.row)"
></el-button>
<el-button <el-table-column align="center" label="题目类别">
style="margin-left: 10px" <template slot-scope="{ row, $index }">
circle <question-type-cascader
icon="el-icon-minus" v-model="row.question_categories"
size="mini" @change="getQuestionMaxCount($index, row)"
:plain="true" ></question-type-cascader>
type="danger" </template>
@click="handleDelete(scope.$index, scope.row)" </el-table-column>
></el-button>
</template>
</el-table-column>
</el-table>
<!-- editData -->
<el-table :data="editData" :show-header="false">
<el-table-column
align="center"
v-for="(item, index, key) in add_columns"
:item="item"
:key="key"
:index="index"
:label="item.label"
>
<template slot-scope="scope">
<!-- 多选 -->
<el-select v-model="scope.row[item.prop]" v-if="item.type === 'select'">
<el-option v-for="(el, index) in item.options" :key="index" :label="el.label" :value="el.value">
</el-option>
</el-select>
<!-- 数量 -->
<el-input-number
v-if="item.type === 'input' && item.prop === 'question_num_add'"
size="small"
v-model="scope.row[item.prop]"
:placeholder="'请输入' + item.label"
:min="1"
:max="20"
></el-input-number>
<!-- 分值 --> <el-table-column align="center" label="数量">
<el-input-number <template slot-scope="{ row }">
v-if="item.type === 'input' && item.prop === 'question_score_add'" <el-input-number
size="small" v-model="row.question_num"
v-model="scope.row[item.prop]" :min="0"
:placeholder="'请输入' + item.label" :max="row.max_question_num"
:min="1" :step-strictly="true"
:max="30" ></el-input-number>
> </template>
</el-input-number> </el-table-column>
</template>
</el-table-column> <el-table-column align="center" label="每题分值">
<el-table-column> <template slot-scope="{ row }">
<template slot-scope="scope"> <el-input-number v-model="row.question_score" :min="0" :step-strictly="true"></el-input-number>
<el-button </template>
type="primary" </el-table-column>
icon="el-icon-plus"
circle <el-table-column align="center" label="操作">
slot="reference"
@click="saveEdit(scope.row)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<!-- 您计划自动组卷的试题情况: -->
<el-form-item label="您计划自动组卷的试题情况:">
<!-- 您计划自动组卷的试题情况 -->
<div class="automatic">
<div class="automatic_questionNum">试题数量总数:{{ getTotalQuestionNum }}</div>
<div class="automatic_totalScore">试卷总分:XXX</div>
</div>
<div>
<el-table ref="mytable" :data="getSituationData" style="width: 100%">
<el-table-column
align="center"
v-for="(item, index, key) in situation_columns"
:item="item"
:key="key"
:index="index"
:label="item.label"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="item.prop === 'questionType'">{{ subOptionType[scope.row.questionType] }}</span> <el-button
<span v-if="item.prop === 'questionDesc'"> style="margin-left: 10px"
难 / {{ scope.row.newItem.items[0].num }} / {{ scope.row.newItem.items[0].score }} 易 / circle
{{ scope.row.newItem.items[1].num }} / {{ scope.row.newItem.items[1].score }} 中 / icon="el-icon-plus"
{{ scope.row.newItem.items[2].num }} / {{ scope.row.newItem.items[2].score }} size="mini"
</span> :plain="true"
<span v-if="item.prop === 'questionTotal'" type="danger"
>{{ scope.row.newItem.tNum }} / {{ scope.row.newItem.tScore }}</span @click="handleAdd(scope.$index, scope.row)"
> ></el-button>
<el-button
style="margin-left: 10px"
circle
icon="el-icon-minus"
size="mini"
:plain="true"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
v-if="questionList.length > 1"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<!-- 您计划自动组卷的试题情况: -->
<el-form-item label="您计划自动组卷的试题情况:">
<!-- 您计划自动组卷的试题情况 -->
<div class="automatic">
<div class="automatic_questionNum">试题数量总数:{{ questionTotalNum }}</div>
<div class="automatic_totalScore">试卷总分:{{ questionTotalScore }}</div>
</div>
<el-table ref="mytable" :data="totalQuestionList" style="width: 100%">
<el-table-column align="center" label="题目类型" prop="question_type_name"></el-table-column>
<el-table-column align="center" label="难度 / 数量 / 分值">
<template slot-scope="{ row }">
<div v-for="(item, index) in row.children" :key="index">
{{ item.question_difficulty_name }} / {{ item.question_num }} / {{ item.question_score }}
</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="小计(数量 / 分值)">
<template slot-scope="{ row }"> {{ row.question_num }} / {{ row.question_score }} </template>
</el-table-column>
</el-table> </el-table>
</el-form-item>
<div style="text-align: center">
<el-button type="primary" @click="handleSubmit">自动组卷</el-button>
</div> </div>
</el-form-item> </el-form>
<el-form-item> </div>
<el-button type="primary" class="autoClick" @click="autoClick" :disabled="table_data.length < 1"
>自动组卷</el-button
>
</el-form-item>
</el-form>
</el-drawer> </el-drawer>
</template> </template>
<script> <script>
import QuestionTypeCascader from '@/components/base/QuestionTypeCascader.vue'
import { getQuestionCount, updatePaperRules } from '../api.js'
export default { export default {
props: {
data: { type: Object, default: () => ({}) }
},
components: { QuestionTypeCascader },
data() { data() {
const questionTypeMap = [
{ value: '1', label: '单选题' },
{ value: '2', label: '多选题' },
{ value: '3', label: '问答题' },
{ value: '5', label: '案例题' },
{ value: '6', label: '判断题' },
{ value: '7', label: '实操题' },
{ value: '8', label: '情景题' }
]
const questionDifficultyMap = [
{ value: '1', label: '易' },
{ value: '2', label: '中' },
{ value: '3', label: '难' }
]
const defaultItem = {
question_type: '',
question_difficulty: '',
question_num: '',
question_score: '',
question_categories: '',
edit: true,
max_question_num: 0
}
return { return {
questionTypeMap,
questionDifficultyMap,
defaultItem,
// 组卷题库 // 组卷题库
form: { form: { permission: '1' },
paperType: '0' questionList: [{ ...defaultItem }]
},
// 组卷规则默认输入框值
editData: [
{
questionType_add: '',
difficulty_add: '',
question_num_add: 1,
question_score_add: 1,
question_category_add: '',
edit: false
}
],
is_delete: true, // 是否可删除
// 自动组卷规则:
table_columns: [
{
prop: 'questionType',
label: '题目类型',
type: 'select',
options: [
{
value: '0',
label: '单选题'
},
{
value: '1',
label: '多选题'
},
{
value: '2',
label: '判断题'
},
{
value: '3',
label: '问答题'
},
{
value: '4',
label: '情景题'
},
{
value: '5',
label: '案例题'
}
]
},
{
prop: 'difficulty',
label: '难度',
type: 'select',
options: [
{
value: '0',
label: '难'
},
{
value: '1',
label: '易'
},
{
value: '2',
label: '中'
}
]
},
{
prop: 'question_num',
label: '数量',
type: 'input'
},
{
prop: 'question_score',
label: '分值',
type: 'input'
},
{
prop: 'question_category',
label: '题目类别',
type: 'select',
options: [
{
value: '0',
label: '难'
},
{
value: '0',
label: '易'
},
{
value: '0',
label: '高'
}
]
}
],
// 自动组卷规则编辑框属性
add_columns: [
{
prop: 'questionType_add',
label: '题目类型',
type: 'select',
options: [
{
value: '0',
label: '单选题'
},
{
value: '1',
label: '多选题'
},
{
value: '2',
label: '判断题'
},
{
value: '3',
label: '问答题'
},
{
value: '4',
label: '情景题'
},
{
value: '5',
label: '案例题'
}
]
},
{
prop: 'difficulty_add',
label: '难度',
type: 'select',
options: [
{
value: '0',
label: '难'
},
{
value: '1',
label: '易'
},
{
value: '2',
label: '中'
}
]
},
{
prop: 'question_num_add',
label: '数量',
type: 'input'
},
{
prop: 'question_score_add',
label: '分值',
type: 'input'
},
{
prop: 'question_category_add',
label: '题目类别',
type: 'select',
options: [
{
value: '0',
label: '难'
},
{
value: '1',
label: '易'
},
{
value: '2',
label: '高'
}
]
}
],
// 计划组卷试题情况
situation_columns: [
{
prop: 'questionType',
label: '题目类型'
},
{
prop: 'questionDesc',
label: '难度 / 数量 / 分值'
},
{
prop: 'questionTotal',
label: '小计 (数量 / 分值)'
}
],
// 表格数据
table_data: [],
// select之后回显数据
subOptionType: {
0: '单选题',
1: '多选题',
2: '判断题',
3: '问答题',
4: '情景题',
5: '案例题'
},
// 题难度回显
difficultyOptionType: {
0: '难',
1: '易',
2: '中'
}
} }
}, },
computed: { computed: {
// 试题数量总数 // 试题数量总数
getTotalQuestionNum() { questionTotalNum() {
const totalNum = this.table_data.map(item => item.question_num) return this.getQuestionTotalNumberByProp('question_num')
const r = totalNum.reduce((pre, item) => (pre += item), 0) // 计算数组总和 },
return r // 试题总分
questionTotalScore() {
return this.questionList.reduce((result, item) => {
return result + parseInt(item.question_score) * parseInt(item.question_num)
}, 0)
}, },
// 试题情况 // 试题情况
getSituationData() { totalQuestionList() {
// 对每次天加的数据进行计算分值和数量 const result = []
const getNumsAndScores = (diffValue, type) => { this.questionList.forEach(item => {
const data = this.table_data if (
if (type === 'num') { item.question_type &&
// 数量 item.question_num &&
const numArray = data?.filter(item => item.difficulty === diffValue).map(val => val.question_num) !result.find(item2 => item2.question_type === item.question_type)
const init = 0 ) {
const totalNum = numArray.reduce((prev, cur) => prev + cur, init) // 当前类型的试题列表
return totalNum const currentTypeQuestionList = this.questionList.filter(item2 => item2.question_type === item.question_type)
} else if (type === 'score') {
// 分值 // 难度列表
const numArray = data?.filter(item => item.difficulty === diffValue).map(val => val.question_score) const questionDifficultyList = this.questionDifficultyMap.map(item => {
const init = 0 // 当前难度的试题列表
const totalScore = numArray.reduce((prev, cur) => prev + cur, init) const currentDifficultyQuestionList = currentTypeQuestionList.filter(
return totalScore item2 => item2.question_difficulty === item.value
} )
} return {
const getLastData = () => { question_difficulty: item.value,
const newItem = { question_difficulty_name: item.label,
items: [ question_num: this.getQuestionTotalNumberByProp('question_num', currentDifficultyQuestionList),
{ question_score: this.getQuestionTotalNumberByProp('question_score', currentDifficultyQuestionList)
type: '难',
num: getNumsAndScores('0', 'num'),
score: getNumsAndScores('0', 'score')
},
{
type: '易',
num: getNumsAndScores('1', 'num'),
score: getNumsAndScores('1', 'score')
},
{
type: '中',
num: getNumsAndScores('2', 'num'),
score: getNumsAndScores('2', 'score')
} }
], })
tNum: getNumsAndScores('0', 'num') + getNumsAndScores('1', 'num') + getNumsAndScores('2', 'num'), const temp = {
tScore: getNumsAndScores('0', 'score') + getNumsAndScores('1', 'score') + getNumsAndScores('2', 'score') question_type: item.question_type,
question_type_name: this.questionTypeMap.find(type => type.value === item.question_type)?.label,
question_num: this.getQuestionTotalNumberByProp('question_num', currentTypeQuestionList),
question_score: this.getQuestionTotalNumberByProp('question_score', currentTypeQuestionList),
children: questionDifficultyList.filter(item => item.question_num) // 难度列表
}
result.push(temp)
} }
this.table_data.forEach(item => { })
item.newItem = newItem return result
}) // 每次添加的数据进行加上newItem选项
return this.deteleObjectItem(this.table_data) // 去重,添加每个题型会累加,需要根据题的类型去重
}
const data = getLastData() // 赋值
return data
} }
}, },
methods: { methods: {
// 去重方法 ---根据题的类型去重 getQuestionTotalNumberByProp(prop, list = this.questionList) {
deteleObjectItem(obj) { return list.reduce((result, item) => {
const newArr = [] return result + parseInt(item[prop])
const newIndex = [] }, 0)
obj.forEach(item => {
if (newIndex.indexOf(item.questionType) === -1) {
newIndex.push(item.questionType)
newArr.push(item)
}
})
return newArr
}, },
// 新增
autoClick() {}, handleAdd(index, row) {
// 新增列表项 if (!row.question_categories || !row.question_difficulty || !row.question_type) {
saveEdit(row) {
console.log(row)
const newData = {
questionType: row.questionType_add,
difficulty: row.difficulty_add,
question_num: row.question_num_add,
question_score: row.question_score_add,
question_category: row.question_category_add,
edit: false
}
if (newData?.questionType && newData?.difficulty && newData?.question_num >= 1 && newData?.question_score >= 1) {
this.table_data.push(newData)
const addData = [
{
questionType_add: null,
difficulty_add: null,
question_num_add: 1,
question_score_add: 1,
question_category_add: null,
edit: false
}
]
this.editData = addData // 重置
} else {
this.$message({ this.$message({
message: '试题规则不能为空!', message: '试题规则不能为空!',
type: 'warning' type: 'warning'
}) })
} else {
this.questionList.push({ ...this.defaultItem })
} }
}, },
// 编辑
handleEdit(index, row) {
console.log(row, '----')
row.edit = true
},
// 删除 // 删除
handleDelete(index, row) { handleDelete(index) {
console.log(index, row) this.questionList.splice(index, 1) // 前端删除
this.table_data.splice(index, 1) // 前端删除
// 下面掉接口删除-------
this.$message({
message: '删除成功!',
type: 'success'
})
}, },
// 保存 // 保存
handleSave(index, row) { handleSave(index, row) {
console.log(index, row)
row.edit = false row.edit = false
delete this.table_data[index].add },
this.$message({ // 自动组卷
message: '保存成功!', handleSubmit() {
type: 'success' const rules = []
this.questionList.forEach(question => {
rules.push(Object.assign({}, question, { question_categories: [question.question_categories] }))
})
const parmas = { id: this.data.id, permission: this.form.permission, rules }
updatePaperRules(parmas).then(res => {
this.$message.success('保存成功')
this.$emit('update')
this.$emit('update:visible', false)
})
},
// 获取试题最大数量
getQuestionMaxCount(index, row) {
const params = Object.assign({}, this.form, row)
if (!row.question_categories || !row.question_difficulty || !row.question_type) {
return
}
params.question_categories = [row.question_categories]
getQuestionCount(params).then(res => {
row.max_question_num = res.data.count
if (row.question_num > row.max_question_num) {
row.question_num = row.max_question_num
}
}) })
} }
} }
...@@ -536,33 +266,13 @@ export default { ...@@ -536,33 +266,13 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.autoClick {
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.editList {
// padding-left: 100px;
display: flex;
justify-content: space-around;
align-items: center;
}
.automatic { .automatic {
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
margin-top: 100px; justify-content: center;
margin-bottom: 50px; margin: 50px 0 50px;
color: #909399; div {
font-size: 16px; margin: 0 20px;
.automatic_questionNum {
margin-right: 50px;
} }
} }
::v-deep .paperRule .el-table__empty-text {
display: none;
}
::v-deep .paperRule .el-table__empty-block {
min-height: 0;
}
</style> </style>
<template> <template>
<el-dialog title="批量设置分数" v-bind="$attrs" v-on="$listeners" append-to-body width="400px"> <el-dialog
<el-form> title="批量设置分数"
<el-form-item>单选题</el-form-item> v-bind="$attrs"
<el-form-item>数量:8</el-form-item> v-on="$listeners"
<el-form-item label="每道试题分值"> <el-input></el-input></el-form-item> append-to-body
:close-on-click-modal="false"
width="400px"
>
<el-form :model="form" :rules="rules" ref="form">
<el-form-item label="单选题"></el-form-item>
<el-form-item label="数量">8</el-form-item>
<el-form-item label="每道试题分值" prop="score"><el-input v-model="form.score"></el-input></el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="saveSetting">保存</el-button> <el-button type="primary" @click="handleSubmit">保存</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-dialog> </el-dialog>
...@@ -13,12 +20,24 @@ ...@@ -13,12 +20,24 @@
<script> <script>
export default { export default {
props: {
data: { type: Object, default: () => ({}) }
},
data() {
return {
form: { score: '0' },
rules: {
score: [{ required: true, message: '请输入试题分值', trigger: 'blur' }]
}
}
},
methods: { methods: {
saveSetting() { handleSubmit() {
this.$emit('update:visible', false) this.$refs.form.validate().then(() => {
this.$emit('update', Object.assign({}, this.data, this.form))
this.$emit('update:visible', false)
})
} }
} }
} }
</script> </script>
<style></style>
...@@ -5,20 +5,27 @@ ...@@ -5,20 +5,27 @@
<el-col :span="18"> <el-col :span="18">
<app-card title="试题列表"> <app-card title="试题列表">
<template #header-aside> <template #header-aside>
<el-button type="primary" @click="handleAdd">添加试题</el-button> <template v-if="data.paper_type === 1">
<el-button type="primary" @click="handleRemove">删除选中试题</el-button> <el-button type="primary" @click="showSelectQuestion">添加试题</el-button>
<el-button type="primary" :disabled="!multipleSelection.length" @click="handleRemove"
>删除选中试题</el-button
>
</template>
<template v-if="data.paper_type === 2">
<el-button type="primary" @click="showSelectQuestion">自动组卷</el-button>
</template>
</template> </template>
<question-list :list="questions"> <question-list :list="questions" :disableScore="data.paper_type === 2" style="margin-top: 20px">
<template v-slot:selection="item"> <template v-slot:selection="item" v-if="data.paper_type === 1">
<el-checkbox @change="handleSelectionChange(arguments[0], item)"></el-checkbox> <el-checkbox @change="handleSelectionChange(arguments[0], item)"></el-checkbox>
</template> </template>
</question-list> </question-list>
</app-card> </app-card>
</el-col> </el-col>
<!-- 试题序号 --> <!-- 试题序号 -->
<el-col :span="6"> <el-col :span="6" ref="questionNumWrapper">
<question-num :list="questions"> <question-num :list="questions" ref="questionNum" :style="`position:relative;top:${top}px`">
<template #footer> <template #footer v-if="data.paper_type === 1">
<el-button type="primary" @click="handleSubmit">保存试卷</el-button> <el-button type="primary" @click="handleSubmit">保存试卷</el-button>
</template> </template>
</question-num> </question-num>
...@@ -26,11 +33,11 @@ ...@@ -26,11 +33,11 @@
</el-row> </el-row>
<!-- 选题组卷 --> <!-- 选题组卷 -->
<template v-if="data.paper_type === 1"> <template v-if="data.paper_type === 1">
<addPaper :visible.sync="visible" :data="data" @update="handelUpdate" v-if="visible" /> <addPaper :visible.sync="visible" :data="data" @update="handleUpdate" v-if="visible" />
</template> </template>
<!-- 自动组卷 --> <!-- 自动组卷 -->
<template v-if="data.paper_type === 2"> <template v-if="data.paper_type === 2">
<AutomaticPaper :visible.sync="visible" :data="data" @update="handelUpdate" v-if="visible" /> <AutomaticPaper :visible.sync="visible" :data="data" @update="$emit('update')" v-if="visible" />
</template> </template>
</div> </div>
</template> </template>
...@@ -50,7 +57,8 @@ export default { ...@@ -50,7 +57,8 @@ export default {
return { return {
visible: false, visible: false,
questions: [], questions: [],
multipleSelection: [] // 选择项 multipleSelection: [], // 选择项
top: 0
} }
}, },
watch: { watch: {
...@@ -59,12 +67,29 @@ export default { ...@@ -59,12 +67,29 @@ export default {
handler(data) { handler(data) {
this.questions = data.questions || [] this.questions = data.questions || []
} }
},
'$route.query.select': {
immediate: true,
handler(value) {
value && this.showSelectQuestion()
}
} }
}, },
computed: {}, mounted() {
const questionNumWrapper = this.$refs.questionNumWrapper.$el
const parentTop = questionNumWrapper.getBoundingClientRect().top
document.addEventListener('scroll', () => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
if (scrollTop > parentTop) {
this.top = scrollTop - parentTop + 84
} else {
this.top = 0
}
})
},
methods: { methods: {
// 增加试题 // 增加试题
handleAdd() { showSelectQuestion() {
this.visible = true this.visible = true
}, },
handleSelectionChange(checked, data) { handleSelectionChange(checked, data) {
...@@ -95,9 +120,19 @@ export default { ...@@ -95,9 +120,19 @@ export default {
}) })
}, },
// 更新详情数据 // 更新详情数据
handelUpdate() { handleUpdate(list) {
this.$emit('update') this.questions = list
// this.$emit('update')
} }
} }
} }
</script> </script>
<style lang="scss" scoped>
.fixed {
position: relative;
top: 64px;
right: 0;
z-index: 100;
}
</style>
<template> <template>
<div class="question-list"> <div class="question-list">
<template v-for="(item, index) in list"> <template v-for="(item, index) in list">
<question-list-item :data="item" :index="index + 1" :key="item.id" v-on="$listeners"> <question-list-item :data="item" :index="index + 1" :key="item.id" v-bind="$attrs" v-on="$listeners">
<template v-if="item.children && item.children.length"> <template v-if="item.children && item.children.length">
<question-list :list="item.children" :key="item.id" v-on="$listeners"> <question-list :list="item.children" :key="item.id" v-bind="$attrs" v-on="$listeners">
<template #selection> <template #selection>
<slot name="selection" v-bind="item"></slot> <slot name="selection" v-bind="item"></slot>
</template> </template>
......
<template> <template>
<el-card style="margin-bottom: 20px" shadow="hover"> <el-card style="margin-bottom: 20px" shadow="hover">
<div class="question-item"> <div class="question-item">
<div class="question-item-hd"> <div class="question-item-selection">
<div class="question-item-hd-top"> <slot name="selection"></slot>
<slot name="selection"></slot> </div>
<div class="question-index">{{ index }}</div> <div class="question-item-main">
<div class="question-type">{{ questionTypeText }}</div> <div class="question-item-hd">
<div class="question-score"> <div class="question-item-hd-top">
<p>分数:</p> <div class="question-index">{{ index }}</div>
<el-input v-model="data.score" style="width: 100px"></el-input> <div class="question-type">{{ questionTypeText }}</div>
<div class="question-score">
<p>分数:</p>
<el-input v-model="data.score" :disabled="disableScore" style="width: 100px"></el-input>
</div>
</div> </div>
<!-- 题干 -->
<div class="question-title" v-html="data.question_content"></div>
</div> </div>
<!-- 题干 --> <slot>
<div class="question-title" v-html="data.question_content"></div> <div class="question-item-bd">
<!-- 单选题 -->
<template v-if="questionType === 1">
<el-radio-group :disabled="disabled" :value="data.question_answer">
<div class="question-item-option" v-for="item in data.question_options" :key="item.id">
<el-radio :label="item.id">{{ item.option }}</el-radio>
</div>
</el-radio-group>
</template>
<!-- 多选题 -->
<template v-if="questionType === 2">
<el-checkbox-group :disabled="disabled" :value="data.question_answer">
<div class="question-item-option" v-for="item in data.question_options" :key="item.id">
<el-checkbox :label="item.id"> {{ item.option }} </el-checkbox>
</div>
</el-checkbox-group>
</template>
<!-- 问答题 -->
<template v-if="questionType === 3">
<v-editor></v-editor>
</template>
<!-- 判断题 -->
<template v-if="questionType === 6">
<el-radio-group :disabled="disabled" :value="data.question_answer">
<div class="question-item-option" v-for="item in data.question_options" :key="item.id">
<el-radio :label="item.id">{{ item.option }}</el-radio>
</div>
</el-radio-group>
</template>
</div>
</slot>
<div class="question-item-ft"></div>
</div> </div>
<slot>
<div class="question-item-bd">
<!-- 单选题 -->
<template v-if="questionType === 1">
<el-radio-group :disabled="disabled" :value="data.question_answer[0]">
<div class="question-item-option" v-for="item in data.question_options" :key="item.id">
<el-radio :label="item.id">{{ item.option }}</el-radio>
</div>
</el-radio-group>
</template>
<!-- 多选题 -->
<template v-if="questionType === 2">
<el-checkbox-group :disabled="disabled" :value="data.question_answer">
<div class="question-item-option" v-for="item in data.question_options" :key="item.id">
<el-checkbox :label="item.id"> {{ item.option }} </el-checkbox>
</div>
</el-checkbox-group>
</template>
<!-- 问答题 -->
<template v-if="questionType === 3">
<v-editor></v-editor>
</template>
<!-- 判断题 -->
<template v-if="questionType === 6">
<el-radio-group :disabled="disabled" :value="data.question_answer">
<div class="question-item-option" v-for="item in data.question_options" :key="item.id">
<el-radio :label="item.id">{{ item.option }}</el-radio>
</div>
</el-radio-group>
</template>
</div>
</slot>
<div class="question-item-ft"></div>
</div> </div>
</el-card> </el-card>
</template> </template>
...@@ -57,7 +61,8 @@ export default { ...@@ -57,7 +61,8 @@ export default {
props: { props: {
index: { type: Number, default: 1 }, index: { type: Number, default: 1 },
disabled: { type: Boolean, default: false }, disabled: { type: Boolean, default: false },
data: { type: Object, default: () => ({}) } data: { type: Object, default: () => ({}) },
disableScore: { type: Boolean, default: false }
}, },
components: { VEditor }, components: { VEditor },
data() { data() {
...@@ -69,7 +74,7 @@ export default { ...@@ -69,7 +74,7 @@ export default {
data: { data: {
immediate: true, immediate: true,
handler(data) { handler(data) {
this.question = this.genQuestion(data) // this.question = this.genQuestion(data)
} }
} }
}, },
...@@ -100,10 +105,23 @@ export default { ...@@ -100,10 +105,23 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.question-item {
display: flex;
}
.question-item-selection {
margin-right: 10px;
padding-top: 3px;
}
.question-item-selection:empty {
margin: 0;
}
.question-item-main {
flex: 1;
}
.question-item-hd-top { .question-item-hd-top {
display: flex; display: flex;
align-items: center;
.question-index { .question-index {
margin-left: 10px;
color: #c01c40; color: #c01c40;
} }
.question-type { .question-type {
......
<template> <template>
<app-card class="fixed"> <app-card>
<div class="question-num"> <div class="question-num">
<div class="question-num-bd"> <div class="question-num-bd">
<ul> <ul>
...@@ -43,10 +43,6 @@ export default { ...@@ -43,10 +43,6 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.fixed {
position: sticky;
top: 0;
}
.question-num { .question-num {
ul { ul {
display: flex; display: flex;
......
<template> <template>
<app-list v-bind="tableOptions" ref="list" style="padding-left: 30px"> </app-list> <app-list v-bind="tableOptions" ref="list" v-on="$listeners">
<template v-slot:filter-permission="{ params }">
<el-radio-group v-model="params.permission" @change="refetchList">
<el-radio label="1">我的题库</el-radio>
<el-radio label="2">公共题库</el-radio>
</el-radio-group>
</template>
<template v-slot:filter-category="{ params }">
<question-type-cascader v-model="params.question_category" @change="refetchList"></question-type-cascader>
</template>
</app-list>
</template> </template>
<script> <script>
import { getQuestionList } from '../api.js'
import QuestionTypeCascader from '@/components/base/QuestionTypeCascader.vue'
export default { export default {
props: { data: { type: Object, default: () => ({}) } }, props: { data: { type: Object, default: () => ({}) } },
components: { QuestionTypeCascader },
data() { data() {
return {} return {}
},
computed: {
tableOptions() {
return {
limit: 10,
remote: {
httpRequest: getQuestionList,
params: {
permission: '1',
question_type: '',
question_title: '',
question_difficulty: '',
question_category: ''
}
},
filters: [
{
prop: 'permission',
label: '题库范围',
slots: 'filter-permission'
},
{
type: 'select',
prop: 'question_type',
placeholder: '请选择题目类型',
options: [
{ label: '单选题', value: '1' },
{ label: '多选题', value: '2' },
{ label: '问答题', value: '3' },
{ label: '案例题', value: '5' },
{ label: '判断题', value: '6' },
{ label: '实操题', value: '7' },
{ label: '情景题', value: '8' }
],
label: '题目类型'
},
{
type: 'select',
prop: 'question_difficulty',
placeholder: '请选择题目难度等级',
options: [
{ label: '易', value: '1' },
{ label: '中', value: '2' },
{ label: '难', value: '3' }
],
label: '难度等级'
},
{
prop: 'question_category',
label: '试题分类',
slots: 'filter-category'
},
{
type: 'input',
prop: 'question_title',
label: '题目标题',
placeholder: '请输入题目标题'
},
{
type: 'input',
prop: 'name4',
label: '题干内容',
placeholder: '请输入题干内容'
},
{
type: 'input',
prop: 'name5',
label: '知识点',
placeholder: '请输入知识点'
}
],
columns: [
{ type: 'selection' },
{ type: 'index', label: '序号' },
{
label: '题目类型',
prop: 'question_type',
computed: ({ row }) => {
const map = { 1: '单选题', 2: '多选题', 3: '问答题', 5: '案例题', 6: '判断题', 7: '实操题', 8: '情景题' }
return map[row.question_type] || row.question_type
}
},
{ label: '试卷分类', prop: 'question_category.category_name' },
{ label: '题目标题', prop: 'question_title' },
{ label: '知识点', prop: 'knowledge_point.title' },
{
label: '难度等级',
prop: 'question_difficulty',
computed: ({ row }) => {
const map = { 1: '易', 2: '中', 3: '难' }
return map[row.question_difficulty] || row.question_difficulty
}
},
{ label: '更新人', prop: 'operator.realname' }
]
}
}
},
methods: {
// 刷新列表
refetchList() {
// 刷新列表
this.$refs.list.refetch()
}
} }
} }
</script> </script>
<style></style>
...@@ -15,13 +15,13 @@ const routes = [ ...@@ -15,13 +15,13 @@ const routes = [
{ {
name: 'createPaper', name: 'createPaper',
path: 'create', path: 'create',
component: () => import('./views/NewPaper.vue'), component: () => import('./views/Update.vue'),
meta: { title: '新建试卷' } meta: { title: '新建试卷' }
}, },
{ {
name: 'editPaper', name: 'editPaper',
path: 'update/:id', path: 'update/:id',
component: () => import('./views/NewPaper.vue'), component: () => import('./views/Update.vue'),
meta: { title: '编辑试卷' }, meta: { title: '编辑试卷' },
props: true props: true
}, },
......
<template> <template>
<div> <div v-loading="loading">
<!-- 试卷描述 --> <!-- 试卷描述 -->
<app-card title="试卷信息"> <app-card title="试卷信息">
<template #header-aside> <template #header-aside>
...@@ -9,23 +9,24 @@ ...@@ -9,23 +9,24 @@
<el-descriptions-item label="试卷名称">{{ detail.paper_title }}</el-descriptions-item> <el-descriptions-item label="试卷名称">{{ detail.paper_title }}</el-descriptions-item>
<el-descriptions-item label="标签">{{ detail.paper_labels }}</el-descriptions-item> <el-descriptions-item label="标签">{{ detail.paper_labels }}</el-descriptions-item>
<el-descriptions-item label="试卷分类">{{ detail.paper_category.category_name }}</el-descriptions-item> <el-descriptions-item label="试卷分类">{{ detail.paper_category.category_name }}</el-descriptions-item>
<el-descriptions-item label="组卷模式">{{ detail.paper_type }}</el-descriptions-item> <el-descriptions-item label="组卷模式">{{ detail.paper_type_name }}</el-descriptions-item>
<el-descriptions-item label="试卷总分">{{ detail.paper_total_score }}</el-descriptions-item> <el-descriptions-item label="试卷总分">{{ detail.paper_total_score }}</el-descriptions-item>
<el-descriptions-item label="及格分数">{{ detail.pass_score }}</el-descriptions-item> <el-descriptions-item label="及格分数">{{ detail.pass_score }}</el-descriptions-item>
<el-descriptions-item label="考试时长">{{ detail.paper_times }}分钟</el-descriptions-item> <el-descriptions-item label="考试时长">{{ detail.paper_times }}分钟</el-descriptions-item>
<el-descriptions-item label="最短交卷时长">{{ detail.minimum_paper_handing_time }}分钟</el-descriptions-item> <el-descriptions-item label="最短交卷时长">{{ detail.minimum_paper_handing_time }}分钟</el-descriptions-item>
<el-descriptions-item label="试题顺序">{{ detail.paper_question_order }}</el-descriptions-item> <el-descriptions-item label="试题顺序">{{ detail.paper_question_order_name }}</el-descriptions-item>
<el-descriptions-item label="多次考试">{{ detail.is_multiple_exams }}</el-descriptions-item> <el-descriptions-item label="多次考试">{{ detail.is_multiple_exams_name }}</el-descriptions-item>
<el-descriptions-item label="多次考试成绩计算规则">{{ detail.multiple_test_score_rule }}</el-descriptions-item> <el-descriptions-item label="多次考试成绩计算规则">{{
detail.multiple_test_score_rule_name
}}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</app-card> </app-card>
<!-- 试卷列表 --> <!-- 试卷列表 -->
<paper-questions :data="detail" :list="detail.questions" @update="getDetail"></paper-questions> <paper-questions :data="detail" @update="getDetail"></paper-questions>
</div> </div>
</template> </template>
<script> <script>
// import QuestionList from '../components/QuestionList.vue'
import PaperQuestions from '../components/PaperQuestions.vue' import PaperQuestions from '../components/PaperQuestions.vue'
import { getPaper } from '../api.js' import { getPaper } from '../api.js'
export default { export default {
...@@ -33,554 +34,39 @@ export default { ...@@ -33,554 +34,39 @@ export default {
components: { PaperQuestions }, components: { PaperQuestions },
data() { data() {
return { return {
loading: true,
detail: { paper_category: {}, questions: [] } detail: { paper_category: {}, questions: [] }
// detail: {
// id: '355310262572814336',
// project_prefix: 'x1',
// paper_uses: 1,
// paper_title: '测试试卷',
// paper_labels: '',
// paper_type: 1,
// paper_contents: [
// {
// id: '355016409588379649',
// score: 20
// },
// {
// id: '355014384641318913',
// score: 20
// },
// {
// id: '355666309116432384',
// score: 10
// },
// {
// id: '355666267181780992',
// score: 10
// },
// {
// id: '355666228921339905',
// score: 10
// },
// {
// id: '354948368938758145',
// score: 10
// },
// {
// id: '355016685372256256',
// score: 20
// },
// {
// id: '355016686743793664',
// score: 10
// },
// {
// id: '355016685909127168',
// score: 10
// }
// ],
// paper_category: '7223',
// paper_times: 10,
// paper_total_score: 100,
// pass_score: 60,
// paper_question_order: 1,
// minimum_paper_handing_time: 1,
// is_multiple_exams: 0,
// multiple_test_score_rule: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-24 11:16:07',
// updated_at: '2022-02-25 10:57:08',
// deleted_at: null,
// questions: [
// {
// id: '354948368938758145',
// project_prefix: 'x1',
// permission: 2,
// question_type: 3,
// question_title: '问答题测试题1',
// question_content: '问答题测试题1',
// common_content: '',
// question_options: [],
// question_category: {},
// question_answer: {},
// question_analysis: '',
// question_difficulty: 3,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '0',
// question_order: 0,
// question_tag: 'test',
// is_parent: 1,
// child_question_type: 0,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-23 11:18:05',
// updated_at: '2022-02-23 11:18:05',
// score: 10,
// children: []
// },
// {
// id: '355016409588379649',
// project_prefix: 'x1',
// permission: 2,
// question_type: 1,
// question_title: '单选题测试题1',
// question_content: '单选题测试题1',
// common_content: '',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902157182012227584'
// },
// {
// option: '错误',
// checked: false,
// id: '6902157182012227585'
// }
// ],
// question_category: {},
// question_answer: ['6902157182012227584'],
// question_analysis: '',
// question_difficulty: 3,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '0',
// question_order: 0,
// question_tag: 'test',
// is_parent: 1,
// child_question_type: 0,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-23 15:48:27',
// updated_at: '2022-02-23 15:48:27',
// score: 20,
// children: []
// },
// {
// id: '355014384641318913',
// project_prefix: 'x1',
// permission: 2,
// question_type: 1,
// question_title: '单选题测试题1',
// question_content: '单选题测试题1',
// common_content: '',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902155157220360192'
// },
// {
// option: '错误',
// checked: false,
// id: '6902155157220360193'
// }
// ],
// question_category: {},
// question_answer: ['6902155157220360192'],
// question_analysis: '',
// question_difficulty: 3,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '0',
// question_order: 0,
// question_tag: 'test',
// is_parent: 1,
// child_question_type: 0,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-23 15:40:25',
// updated_at: '2022-02-23 15:40:25',
// score: 20,
// children: []
// },
// {
// id: '355666309116432384',
// project_prefix: 'x1',
// permission: 2,
// question_type: 2,
// question_title: '多选题测试题3',
// question_content: '多选题测试题3',
// common_content: '',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902807082072801280'
// },
// {
// option: '错误',
// checked: false,
// id: '6902807082072801281'
// }
// ],
// question_category: {
// id: '7223',
// category_name: '测试使用的分类',
// name: '题目分类/测试使用的分类'
// },
// question_answer: ['6902807082072801280'],
// question_analysis: '',
// question_difficulty: 3,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '0',
// question_order: 0,
// question_tag: 'test',
// is_parent: 1,
// child_question_type: 0,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-25 10:50:56',
// updated_at: '2022-02-25 10:50:56',
// score: 10,
// children: []
// },
// {
// id: '355666267181780992',
// project_prefix: 'x1',
// permission: 2,
// question_type: 2,
// question_title: '多选题测试题2',
// question_content: '多选题测试题2',
// common_content: '',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902807040146538496'
// },
// {
// option: '错误',
// checked: false,
// id: '6902807040146538497'
// }
// ],
// question_category: {
// id: '7223',
// category_name: '测试使用的分类',
// name: '题目分类/测试使用的分类'
// },
// question_answer: ['6902807040146538496'],
// question_analysis: '',
// question_difficulty: 3,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '0',
// question_order: 0,
// question_tag: 'test',
// is_parent: 1,
// child_question_type: 0,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-25 10:50:46',
// updated_at: '2022-02-25 10:50:46',
// score: 10,
// children: []
// },
// {
// id: '355666228921339905',
// project_prefix: 'x1',
// permission: 2,
// question_type: 2,
// question_title: '多选题测试题1',
// question_content: '多选题测试题1',
// common_content: '',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902807001823182848'
// },
// {
// option: '错误',
// checked: false,
// id: '6902807001823182849'
// }
// ],
// question_category: {
// id: '7223',
// category_name: '测试使用的分类',
// name: '题目分类/测试使用的分类'
// },
// question_answer: ['6902807001823182848'],
// question_analysis: '',
// question_difficulty: 3,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '0',
// question_order: 0,
// question_tag: 'test',
// is_parent: 1,
// child_question_type: 0,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-25 10:50:36',
// updated_at: '2022-02-25 10:50:36',
// score: 10,
// children: []
// },
// {
// id: '355016685372256256',
// project_prefix: 'x1',
// permission: 1,
// question_type: 5,
// question_title: '案例题测试2',
// question_content: '',
// common_content: '案例题测试2',
// question_options: [],
// question_category: {},
// question_answer: {},
// question_analysis: {},
// question_difficulty: 1,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '6902157457808687104',
// question_order: 0,
// question_tag: 'test2',
// is_parent: 1,
// child_question_type: 0,
// created_by: {},
// created_at: '2022-02-23 15:49:33',
// updated_at: '2022-02-23 15:49:33',
// score: 20,
// children: [
// {
// id: '355016686743793664',
// project_prefix: 'x1',
// permission: 1,
// question_type: 5,
// question_title: '案例-单选题测试题1',
// question_content: '案例-单选题测试题1',
// common_content: '案例题测试2',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902157458941149184'
// },
// {
// option: '错误',
// checked: false,
// id: '6902157458941149185'
// }
// ],
// question_category: {},
// question_answer: ['6902157458941149184'],
// question_analysis: '',
// question_difficulty: 1,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '6902157457808687104',
// question_order: 3,
// question_tag: 'test2',
// is_parent: 0,
// child_question_type: 1,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-23 15:49:34',
// updated_at: '2022-02-23 15:49:34',
// score: 10
// },
// {
// id: '355016685909127168',
// project_prefix: 'x1',
// permission: 1,
// question_type: 5,
// question_title: '案例-判断题测试题1',
// question_content: '案例-判断题测试题1',
// common_content: '案例题测试2',
// question_options: [
// {
// option: '正确',
// checked: true,
// id: '6902157458161008640'
// },
// {
// option: '错误',
// checked: false,
// id: '6902157458161008641'
// }
// ],
// question_category: {},
// question_answer: '6902157458161008640',
// question_analysis: '',
// question_difficulty: 1,
// status: 1,
// operator: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// group_id: '6902157457808687104',
// question_order: 1,
// question_tag: 'test2',
// is_parent: 0,
// child_question_type: 6,
// created_by: {
// id: '6653195831513972736',
// username: '王诒正',
// nickname: '王诒正',
// realname: '王诒正',
// email: 'wangyizheng@ezijing.com',
// mobile: '18435134258',
// country_code: '86'
// },
// created_at: '2022-02-23 15:49:33',
// updated_at: '2022-02-23 15:49:33',
// score: 10
// }
// ]
// }
// ]
// }
} }
}, },
computed: {},
beforeMount() { beforeMount() {
this.getDetail() this.getDetail()
}, },
methods: { methods: {
// 获取试卷详情 // 获取试卷详情
getDetail() { getDetail() {
getPaper({ id: this.id }).then(res => { this.loading = true
this.detail = Object.assign({}, this.detail, res.data) getPaper({ id: this.id })
}) .then(res => {
const data = res.data
const temp = {}
// 组卷模式
const paperTypeMap = { 1: '选题组卷', 2: '自动组卷' }
temp.paper_type_name = paperTypeMap[data.paper_type] || data.paper_type
// 试题顺序
const questionOrderMap = { 1: '固定', 2: '随机' }
temp.paper_question_order_name = questionOrderMap[data.paper_question_order] || data.paper_question_order
// 是否多次考试
const isMultipleExamsMap = { 1: '是', 0: '否' }
temp.is_multiple_exams_name = isMultipleExamsMap[data.is_multiple_exams] || data.is_multiple_exams
// 多次考试成绩计算规则
const multipleTestScoreRuleMap = { 1: '平均计算法', 2: '最高得分法' }
temp.multiple_test_score_rule_name =
multipleTestScoreRuleMap[data.multiple_test_score_rule] || data.multiple_test_score_rule
this.detail = Object.assign({}, this.detail, res.data, temp)
})
.finally(() => {
this.loading = false
})
}, },
// 编辑试卷 // 编辑试卷
handleUpdate() { handleUpdate() {
...@@ -589,5 +75,3 @@ export default { ...@@ -589,5 +75,3 @@ export default {
} }
} }
</script> </script>
<style lang="scss" scoped></style>
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
> >
</div> </div>
<template v-slot:filter-category="{ params }"> <template v-slot:filter-category="{ params }">
<question-type-cascader v-model="params.paper_category"></question-type-cascader> <question-type-cascader v-model="params.paper_category" @change="refetchList"></question-type-cascader>
</template> </template>
<template v-slot:table-x="{ row }"> <template v-slot:table-x="{ row }">
<el-button type="text" @click="handleUpdate(row)">编辑</el-button> <el-button type="text" @click="handleUpdate(row)">编辑</el-button>
...@@ -74,10 +74,8 @@ export default { ...@@ -74,10 +74,8 @@ export default {
placeholder: '请输入试卷标签', placeholder: '请输入试卷标签',
label: '标签:' label: '标签:'
}, },
{ {
type: 'select', prop: 'paper_category',
prop: 'paperType',
label: '试卷分类:', label: '试卷分类:',
slots: 'filter-category' slots: 'filter-category'
} }
...@@ -146,8 +144,13 @@ export default { ...@@ -146,8 +144,13 @@ export default {
batchDeletePaper(ids) { batchDeletePaper(ids) {
batchDeletePaper({ ids }).then(res => { batchDeletePaper({ ids }).then(res => {
// 刷新列表 // 刷新列表
this.$refs.list.refetch() this.refetchList()
}) })
},
// 刷新列表
refetchList() {
// 刷新列表
this.$refs.list.refetch()
} }
} }
} }
......
...@@ -172,14 +172,6 @@ export default { ...@@ -172,14 +172,6 @@ export default {
questionSelectVisible: false questionSelectVisible: false
} }
}, },
watch: {
'$route.query.select': {
immediate: true,
handler(value) {
value && this.showSelectQuestion()
}
}
},
computed: { computed: {
isEdit() { isEdit() {
return !!this.id return !!this.id
...@@ -194,15 +186,21 @@ export default { ...@@ -194,15 +186,21 @@ export default {
methods: { methods: {
// 取消 // 取消
handleCancel() { handleCancel() {
this.$router.replace('/paper/list') this.$router.back()
}, },
// 保存 // 保存
handleSubmit() { handleSubmit() {
this.$refs.form.validate().then(() => { this.$refs.form.validate().then(() => {
// 保存成功回到列表 // 保存成功回到列表
this.createPaper().then(res => { if (this.isEdit) {
this.$router.replace('/paper/list') this.updatePaper().then(res => {
}) this.$router.back()
})
} else {
this.createPaper().then(res => {
this.$router.replace('/paper/list')
})
}
}) })
}, },
// 保存并选择试题 // 保存并选择试题
...@@ -214,7 +212,7 @@ export default { ...@@ -214,7 +212,7 @@ export default {
}) })
} else { } else {
this.createPaper(res => { this.createPaper(res => {
this.$router.replace({ path: '/paper/update/' + res.data.id, query: { select: true } }) this.$router.replace({ path: '/paper/detail/' + res.data.id, query: { select: true } })
}) })
} }
}) })
...@@ -247,7 +245,8 @@ export default { ...@@ -247,7 +245,8 @@ export default {
// 获取试卷详情 // 获取试卷详情
getDetail() { getDetail() {
getPaper({ id: this.id }).then(res => { getPaper({ id: this.id }).then(res => {
this.form = Object.assign({}, this.form, res.data) const data = res.data
this.form = Object.assign({}, this.form, data, { paper_category: data.paper_category.id })
}) })
} }
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论