提交 dd13280e authored 作者: lihuihui's avatar lihuihui
......@@ -10,6 +10,7 @@
"@tinymce/tinymce-vue": "^3.2.8",
"axios": "^0.25.0",
"blueimp-md5": "^2.19.0",
"clipboard": "^2.0.8",
"element-ui": "^2.15.6",
"query-string": "^7.1.1",
"vue": "^2.6.14",
......@@ -1316,6 +1317,17 @@
"fsevents": "~2.3.2"
}
},
"node_modules/clipboard": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
"integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
"license": "MIT",
"dependencies": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"dev": true,
......@@ -1519,6 +1531,11 @@
"node": ">= 6"
}
},
"node_modules/delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"node_modules/depd": {
"version": "1.1.2",
"dev": true,
......@@ -2638,6 +2655,14 @@
"node": ">=4"
}
},
"node_modules/good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"dependencies": {
"delegate": "^3.1.2"
}
},
"node_modules/graceful-fs": {
"version": "4.2.6",
"dev": true,
......@@ -3941,6 +3966,11 @@
"get-ready": "~1.0.0"
}
},
"node_modules/select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
},
"node_modules/semver": {
"version": "6.3.0",
"dev": true,
......@@ -4224,6 +4254,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"node_modules/tiny-invariant": {
"version": "1.2.0",
"dev": true,
......@@ -5657,6 +5692,16 @@
"readdirp": "~3.6.0"
}
},
"clipboard": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
"integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
"requires": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"color-convert": {
"version": "2.0.1",
"dev": true,
......@@ -5777,6 +5822,11 @@
"esprima": "^4.0.0"
}
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"depd": {
"version": "1.1.2",
"dev": true
......@@ -6500,6 +6550,14 @@
"version": "11.12.0",
"dev": true
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
"requires": {
"delegate": "^3.1.2"
}
},
"graceful-fs": {
"version": "4.2.6",
"dev": true
......@@ -7301,6 +7359,11 @@
"get-ready": "~1.0.0"
}
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
},
"semver": {
"version": "6.3.0",
"dev": true
......@@ -7475,6 +7538,11 @@
"version": "2.3.8",
"dev": true
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"tiny-invariant": {
"version": "1.2.0",
"dev": true
......
......@@ -13,6 +13,7 @@
"@tinymce/tinymce-vue": "^3.2.8",
"axios": "^0.25.0",
"blueimp-md5": "^2.19.0",
"clipboard": "^2.0.8",
"element-ui": "^2.15.6",
"query-string": "^7.1.1",
"vue": "^2.6.14",
......
......@@ -32,3 +32,10 @@ export function uploadFile(data) {
export function getAllProjects() {
return httpRequest.get('/api/qbs/admin/v1/projects')
}
/**
* 获取试卷分类
*/
export function getQuestionCategory(params) {
return httpRequest.get(`/api/qbs/admin/v1/question-category/tree/${params.project_prefix}`, { params })
}
......@@ -163,7 +163,7 @@ export default {
.then(res => {
const { data = {} } = res || {}
this.page.total = parseInt(data.total || 0)
this.dataList = callback ? callback(data) : data.list
this.dataList = callback ? callback(data) : data.list || data.data
})
.catch(() => {
this.page.total = 0
......
<template>
<el-cascader
clearable
:options="options"
:props="defaultProps"
v-on="$listeners"
@change="handleChange"
></el-cascader>
</template>
<script>
import { getQuestionCategory } from '@/api/base.js'
export default {
data() {
return {
options: [],
defaultProps: {
label: 'category_name',
value: 'id',
checkStrictly: true
}
}
},
computed: {
activeProject() {
return this.$store.state.activeProject || {}
}
},
beforeMount() {
this.getQuestionCategory()
},
methods: {
getQuestionCategory() {
getQuestionCategory({ project_prefix: this.activeProject.tag }).then(res => {
// 移除空数组
const options = JSON.parse(JSON.stringify(res.data).replaceAll(',"children":[]', ''))
this.options = options
})
},
handleChange(value = []) {
const lastValue = value[value.length - 1]
this.$emit('input', lastValue)
}
}
}
</script>
<style></style>
......@@ -38,7 +38,7 @@ export default {
name: '试卷中心',
path: '/paper',
icon: 'el-icon-toilet-paper',
children: [{ name: '我的试卷库', path: '/paper/list' }]
children: [{ name: '我的试卷库', path: '/paper' }]
},
{
name: '考试中心',
......
......@@ -28,3 +28,46 @@ export function delExamPaper(data) {
export function getExamPaperDetail(params) {
return httpRequest.get('/api/exam/v1/exam/view', { params })
}
/**
* 添加考生
*/
export function addStudent(data) {
return httpRequest.post('/api/exam/v1/exam/add-student', data)
}
/**
* 更新考试
*/
export function updateExam(data) {
return httpRequest.post('/api/exam/v1/exam/update', data)
}
/**
* 考试数据下载
*/
export function downloadExamData(params) {
return httpRequest.get('/api/exam/v1/exam/download-details', { params, responseType: 'blob' })
}
/**
* 删除考生
*/
export function deleteStudent(data) {
return httpRequest.post('/api/exam/v1/student/delete', data)
}
/**
* 发送成绩信息
*/
export function sendMessage(data) {
return httpRequest.post('/api/exam/v1/exam/send-msg', data)
}
/**
* 发送成绩信息
*/
export function getTranserList(params) {
return httpRequest.get('/api/exam/v1/exam/transfer-student', { params })
}
/**
* 发送成绩信息
*/
export function transferStudent(data) {
return httpRequest.post('/api/exam/v1/exam/transfer-student', data)
}
......@@ -36,21 +36,29 @@
<v-editor v-model="config.welcome_message" class="editor"></v-editor>
</el-row>
<el-row :span="24" class="btn_next row_margin">
<el-button type="primary" disabled>上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
<el-button type="primary" v-if="$route.query.isEdit === '2'" @click="saveExamInfo">保存</el-button>
<div v-if="isEdit === '1'">
<el-button type="primary" disabled>上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
</div>
</el-row>
</el-card>
</template>
<script>
// import { createExamList } from '../api'
import { updateExam } from '../api'
import VEditor from '@/components/tinymce/Index.vue'
export default {
components: { VEditor },
props: {
isEdit: {
type: String,
default: ''
}
},
data() {
return {
exam_time: [],
labelPosition: 'left',
name: '',
config: {
enabled_before: false,
......@@ -68,6 +76,21 @@ export default {
},
end_time() {
return this.exam_time[1]
},
row() {
return JSON.parse(this.$route.query.row)
}
},
mounted() {
if (this.$route.query.isEdit === '2' && this.row) {
this.exam_time = [this.row.start_time, this.row.end_time]
this.name = this.row.name
this.config.enabled_before = this.row.config.enabled_before
this.config.enabled_after = this.row.config.enabled_after
this.config.before_login = this.row.config.before_login
this.config.after_login = this.row.config.after_login
this.config.welcome_message = this.row.config.welcome_message
this.config.waiting_message = this.row.config.waiting_message
}
},
methods: {
......@@ -92,9 +115,33 @@ export default {
this.$message.warning('请选择考试时间')
return
}
// console.log(params)
this.$emit('getBaseInfo', params)
this.$parent.$parent.nextStep()
},
saveExamInfo() {
const params = {
id: this.row.exam_id,
type: 'basic',
name: this.name,
start_time: this.start_time,
end_time: this.end_time,
config: {
enabled_before: this.config.enabled_before,
enabled_after: this.config.enabled_after,
before_login: this.config.before_login,
after_login: this.config.after_login,
welcome_message: this.config.welcome_message,
waiting_message: this.config.waiting_message
}
}
if (params.name === '') {
this.$message.warning('请输入考试名称')
} else if (params.start_time === '' || params.end_time === '') {
this.$message.warning('请选择考试时间')
}
updateExam(params).then(res => {
history.go(-1)
})
}
}
}
......
......@@ -13,17 +13,21 @@
<div class="paper_desc">考试开始两个小时前,可以对试卷进行替换</div>
</el-row>
<el-row class="btn_next">
<el-button type="primary" @click="lastStep">上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
<el-button type="primary" v-if="$route.query.isEdit === '2'" @click="saveExamInfo">保存</el-button>
<div v-if="isEdit === '1'">
<el-button type="primary" @click="lastStep">上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
</div>
</el-row>
</el-card>
</template>
<script>
import { getExamPaperList } from '../api'
import { getExamPaperList, updateExam } from '../api'
export default {
data() {
return {
row: {},
ExamParerList: [],
q: [],
filterMethod(query, item) {
......@@ -32,17 +36,22 @@ export default {
checkedArrs: []
}
},
props: {
isEdit: {
type: String,
default: ''
}
},
methods: {
getExamParerList() {
const params = { q: '' }
getExamPaperList(params).then(res => {
// this.ExamParerList = res.data.list
// console.log(res.data.list)
this.ExamParerList = res.data.list.reduce((a, b) => {
this.ExamParerList.push({ label: b.paper_title, key: b.id })
return this.ExamParerList
}, [])
this.getCheckedExam()
})
},
lastStep() {
......@@ -54,21 +63,37 @@ export default {
return
}
this.$parent.$parent.nextStep()
console.log(this.q)
for (let i = 0; i < this.q.length; i++) {
const listArray = []
for (let j = 0; j < this.ExamParerList.length; j++) {
if (this.q[i] === this.ExamParerList[j].key) {
console.log(this.ExamParerList[j])
listArray.push(this.ExamParerList[j])
}
}
this.checkedArrs = listArray
}
// console.log(this.checkedArrs)
const qs = this.q.toString()
this.$emit('getCheckPaper', qs)
this.$emit('getCheckPaperList', this.checkedArrs)
},
saveExamInfo() {
const params = { id: this.$route.query.id, type: 'paper', exam_paper: this.q.toString() }
updateExam(params).then(res => {
history.go(-1)
})
},
getCheckedExam() {
if (this.$route.query.papers) {
const papers = JSON.parse(this.$route.query.papers)
const arr = []
papers.forEach(element => {
const findItem = this.ExamParerList.find(item => {
return item.label === element
}).key
findItem && arr.push(findItem)
})
this.q = arr
}
}
},
mounted() {
......
......@@ -40,8 +40,11 @@
</div>
</el-row>
<el-row :span="24" class="btn_next">
<el-button type="primary" @click="lastStep">上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
<el-button type="primary" v-if="$route.query.isEdit === '2'" @click="saveExamInfo">保存</el-button>
<div v-if="isEdit === '1'">
<el-button type="primary" @click="lastStep">上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
</div>
</el-row>
</el-card>
</div>
......@@ -49,8 +52,16 @@
<script>
import VEditor from '@/components/tinymce/Index.vue'
import { getExamPaperDetail, updateExam } from '../api'
export default {
components: { VEditor },
props: {
isEdit: {
type: String,
default: ''
}
},
data() {
return {
config: {
......@@ -67,6 +78,11 @@ export default {
}
}
},
computed: {
row() {
return JSON.parse(this.$route.query.row)
}
},
methods: {
lastStep() {
this.$parent.$parent.lastStep()
......@@ -74,6 +90,50 @@ export default {
nextStep() {
this.$parent.$parent.nextStep()
this.$emit('getExamConfig', this.config)
},
saveExamInfo() {
const params = {
id: JSON.parse(this.$route.query.row).exam_id,
type: 'config',
config: {
enabled_ip_limit: this.config.enabled_ip_limit,
ip_limits: this.config.ip_limits,
enabled_promise: this.config.enabled_promise,
enabled_lock: this.config.enabled_lock,
max_login_times: this.config.max_login_times,
enabled_web_login: this.config.enabled_web_login,
leave_interval: this.config.leave_interval,
max_leave_times: this.config.max_leave_times,
enabled_watermark: this.config.enabled_watermark,
promise_message: this.config.promise_message
}
}
updateExam(params).then(res => {
history.go(-1)
})
},
getDetail() {
const params = {
id: JSON.parse(this.$route.query.row).exam_id
}
getExamPaperDetail(params).then(res => {
const config = JSON.parse(res.data.exam_info.config)
this.config.enabled_ip_limit = config.enabled_ip_limit
this.config.ip_limits = config.ip_limits
this.config.enabled_promise = config.enabled_promise
this.config.enabled_lock = config.enabled_lock
this.config.max_login_times = config.max_login_times
this.config.enabled_web_login = config.enabled_web_login
this.config.leave_interval = config.leave_interval
this.config.max_leave_times = config.max_leave_times
this.config.enabled_watermark = config.enabled_watermark
this.config.promise_message = config.promise_message
})
}
},
mounted() {
if (this.$route.query.isEdit === '2' && JSON.parse(this.$route.query.row)) {
this.getDetail()
}
}
}
......
......@@ -43,9 +43,7 @@ export default {
return a
}
},
mounted() {
console.log(this.params, 'params')
},
methods: {
lastStep() {
this.$parent.$parent.lastStep()
......
<template>
<app-card>
<app-list v-bind="tableOptions" ref="list">
<template v-slot:isEdit="{ row }">
<el-switch v-model="row.isEdit" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</template>
<template v-slot:isVisible="{ row }">
<el-switch v-model="row.isVisible" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</template>
<template v-slot:isRequired="{ row }">
<el-switch v-model="row.isRequired" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</template>
<template v-slot:weight="{ row }">
<el-input v-model="row.sort" active-color="#13ce66" inactive-color="#ff4949"> </el-input>
</template>
</app-list>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="已选信息" width="180"> </el-table-column>
<el-table-column prop="enabled_edit" label="允许编辑" width="180">
<template slot-scope="scope">
<el-switch v-model="scope.row.enabled_edit" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</template>
</el-table-column>
<el-table-column prop="enabled_visible" label="考生可见">
<template slot-scope="scope">
<el-switch v-model="scope.row.enabled_visible" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</template>
</el-table-column>
<el-table-column prop="required" label="必填">
<template slot-scope="scope">
<el-switch v-model="scope.row.required" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</template>
</el-table-column>
<el-table-column prop="sort" label="权重">
<template slot-scope="scope">
<el-input v-model="scope.row.sort" active-color="#13ce66" inactive-color="#ff4949"> </el-input>
</template>
</el-table-column>
</el-table>
<el-row class="btn_next">
<el-button type="primary" @click="lastStep">上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
<el-button type="primary" v-if="$route.query.isEdit === '2'" @click="saveExamInfo">保存</el-button>
<div v-if="isEdit === '1'">
<el-button type="primary" @click="lastStep">上一步</el-button>
<el-button type="primary" @click="nextStep">下一步</el-button>
</div>
</el-row>
</app-card>
</template>
<script>
import { getExamPaperDetail, updateExam } from '../api'
export default {
data() {
return {
visible: false,
multipleSelection: [] // 选择项
tableData: [
{
name: '姓名',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '性别',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '身份证号',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '年龄',
ienabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '所学专业',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '所在学校',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '邮箱',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
name: '学历',
isEdit: false,
isVisible: false,
isRequired: false,
sort: 0
},
{
name: '手机号',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
}
]
}
},
computed: {
tableOptions() {
return {
// remote: { httpRequest: getAppList },
columns: [
{ label: '已选信息', prop: 'isCheckedInfo' },
{ label: '允许编辑', prop: 'enabled_edit', slots: 'isEdit' },
{ label: '考生可见', prop: 'enabled_visible', slots: 'isVisible' },
{ label: '必填', prop: 'required', slots: 'isRequired' },
{ label: '权重', prop: 'sort', slots: 'weight' }
],
data: [
{
isCheckedInfo: '姓名',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '性别',
isEdit: false,
isVisible: false,
isRequired: false,
sort: 0
},
{
isCheckedInfo: '身份证号',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '年龄',
ienabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '所学专业',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '所在学校',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '邮箱',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '学历',
isEdit: false,
isVisible: false,
isRequired: false,
sort: 0
},
{
isCheckedInfo: '手机号',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
}
]
}
props: {
isEdit: {
type: String,
default: ''
}
},
methods: {
nextStep() {
const info = {}
info.name = this.tableData[0]
info.gender = this.tableData[1]
info.id_number = this.tableData[2]
info.age = this.tableData[3]
info.major = this.tableData[4]
info.school = this.tableData[5]
info.email = this.tableData[6]
info.educational_background = this.tableData[7]
info.mobile = this.tableData[8]
this.$emit('getInfo', info)
this.$parent.$parent.nextStep()
},
lastStep() {
this.$parent.$parent.lastStep()
},
getDetail() {
const params = {
id: JSON.parse(this.$route.query.row).exam_id
}
getExamPaperDetail(params).then(res => {
const list = JSON.parse(res.data.exam_info.config).info
const arr = []
Object.keys(list).forEach(key => {
arr.push(list[key])
})
this.tableData = arr
})
},
saveExamInfo() {
const params = {
id: JSON.parse(this.$route.query.row).exam_id,
type: 'student',
config: {
enabled_before: this.config.enabled_before,
enabled_after: this.config.enabled_after,
before_login: this.config.before_login,
after_login: this.config.after_login,
welcome_message: this.config.welcome_message,
waiting_message: this.config.waiting_message
}
}
updateExam(params).then(res => {
history.go(-1)
})
}
},
mounted() {
console.log(this.tableOptions.data)
const info = {}
info.name = this.tableOptions.data[0]
info.gender = this.tableOptions.data[1]
info.id_number = this.tableOptions.data[2]
info.age = this.tableOptions.data[3]
info.major = this.tableOptions.data[4]
info.school = this.tableOptions.data[5]
info.email = this.tableOptions.data[6]
info.educational_background = this.tableOptions.data[7]
info.mobile = this.tableOptions.data[8]
this.$emit('getInfo', info)
if (this.$route.query.isEdit === '2') {
this.getDetail()
}
}
}
</script>
......
......@@ -24,6 +24,31 @@ const routes = [
path: 'examDetail',
component: () => import('./views/Detail.vue'),
meta: { title: '考试详情' }
},
{
path: 'createStudent',
component: () => import('./views/CreateStudent.vue'),
meta: { title: '添加考生' }
},
{
path: 'baseInfo',
component: () => import('../exam/components/BaseInfo.vue'),
meta: { title: '编辑考试' }
},
{
path: 'checkPaper',
component: () => import('../exam/components/CheckPaper.vue'),
meta: { title: '选择考试' }
},
{
path: 'personalInfo',
component: () => import('./components/PersonalInfo.vue'),
meta: { title: '个人信息' }
},
{
path: 'examSetting',
component: () => import('./components/ExamSetting.vue'),
meta: { title: '考试设置' }
}
]
}
......
<template>
<el-form ref="form" :model="form" label-width="80px" :label-position="labelPosition" :rules="rules">
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="身份证号" prop="id_number">
<el-input v-model="form.id_number" placeholder="请输入身份证号" />
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-select v-model="form.gender">
<el-option label="男" :value="1"></el-option>
<el-option label="女" :value="2"></el-option>
</el-select>
<!-- <el-input v-model="form.gender" placeholder="请输入性别" /> -->
</el-form-item>
<el-form-item label="学校" prop="school">
<el-input v-model="form.school" placeholder="请输入学校" />
</el-form-item>
<el-form-item label="电话" prop="mobile">
<el-input v-model="form.mobile" placeholder="请输入电话" />
</el-form-item>
<el-form-item prop="examinee_number">
<el-checkbox label="自定义准考证号" v-model="isChecked"></el-checkbox>
<el-input v-model="form.examinee_number" placeholder="不超过20个字母必填" v-if="isChecked === true" />
</el-form-item>
<el-form-item>
<el-row style="margin-top: 30px">
<el-button type="primary" @click="handleSubmit">保存</el-button>
</el-row>
</el-form-item>
</el-form>
</template>
<script>
import { addStudent } from '../api'
export default {
data() {
return {
isChecked: false,
labelPosition: 'left',
btnDisabled: false,
paper_category: [
{ label: '测试', value: 1 },
{ label: '考试', value: 2 },
{ label: '模拟', value: 3 }
],
form: {
name: '',
id_number: '',
gender: '',
school: '',
mobile: '',
examinee_number: ''
},
rules: {
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
id_number: [{ required: true, message: '请输入身份证号', trigger: 'blur' }]
}
}
},
computed: {
id() {
return this.$route.query.id
}
},
methods: {
handleSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
// 调用接口
addStudent(Object.assign({ exam_id: this.id }, this.form)).then(res => {})
}
history.go(-1)
})
}
}
}
</script>
<style lang="scss" scoped>
:v-deep .el-input-number .el-input-number__decrease {
display: none;
}
:v-deep .el-input-number .el-input-number__increase {
display: none;
}
::v-deep .el-input-number .el-input__inner {
padding-left: 15px;
text-align: left;
}
</style>
......@@ -2,32 +2,72 @@
<app-card>
<app-list v-bind="tableOptions" ref="list" @selection-change="handleSelectionChange">
<div style="margin-bottom: 30px">
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">考试信息编辑</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">考试试卷编辑</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">信息采集编辑</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">考试配置编辑</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">复制考试地址</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">转移考生</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">导出明细</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">删除考生</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">添加考生</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">发送成绩信息</el-button>
<el-dropdown split-button size="small" style="margin-left: 10px; margin-right: 10px; float: right">
操作
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="editExamInfo">考试信息编辑</el-dropdown-item>
<el-dropdown-item @click.native="editExam">考试试卷编辑</el-dropdown-item>
<el-dropdown-item @click.native="editInfo">信息采集编辑</el-dropdown-item>
<el-dropdown-item @click.native="editExamSetting">考试配置编辑</el-dropdown-item>
<el-dropdown-item @click.native="copyExamUrl">复制考试地址</el-dropdown-item>
<el-dropdown-item @click.native="dialogVisible = true">转移考生</el-dropdown-item>
<el-dropdown-item @click.native="exportDetail">导出明细</el-dropdown-item>
<el-dropdown-item @click.native="delStudent">删除考生</el-dropdown-item>
<el-dropdown-item @click.native="handleAddStudent">添加考生</el-dropdown-item>
<el-dropdown-item @click.native="sendMessage">发送成绩信息</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleDetail(row)">查看详情</el-button>
<el-button type="text" @click="handleDelete(row)">删除</el-button>
</template>
<el-dialog title="转移考生" :visible.sync="dialogVisible" width="40%">
<div>
将这些人转移至
<el-select v-model="transfer_exam_id" placeholder="请选择">
<el-option v-for="(item, exam_id) in transferList" :key="exam_id" :label="item.name" :value="item.exam_id">
</el-option>
</el-select>
</div>
<p>*转移至的考试中,采集信息和考试配置应与本场次一致,否则将导致某些考生数据丢失。</p>
<p>*转移后的考试地址会变更,请在新场次中再次通知考生参加考试。</p>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="transferStudent">确 定</el-button>
</span>
</el-dialog>
</app-list>
<input tyoe="text" style="opacity: 0" id="copyInput" />
</app-card>
</template>
<script>
import { getExamPaperDetail } from '../api'
import {
getExamPaperDetail,
deleteStudent,
downloadExamData,
sendMessage,
getTranserList,
transferStudent
} from '../api'
const stuStatus = [
{ id: '1', name: '未开考' },
{ id: '1', name: '已登录' },
{ id: '1', name: '考试中' },
{ id: '1', name: '已中断' },
{ id: '1', name: '已提交' },
{ id: '1', name: '已完成' },
{ id: '1', name: '待批阅' }
]
export default {
data() {
return {
visible: false,
multipleSelection: [] // 选择项
multipleSelection: [], // 选择项
dialogVisible: false,
transferList: [],
transfer_exam_id: ''
}
},
computed: {
......@@ -36,30 +76,27 @@ export default {
remote: {
httpRequest: getExamPaperDetail,
params: {
id: this.row.exam_id,
school: '',
relation_status: '',
name: ''
id: this.row.exam_id
}
},
filters: [
{
type: 'input',
prop: 'paperName',
placeholder: '请输入考试名称',
prop: 'name',
placeholder: '请输入考生姓名',
label: '姓名'
},
{
type: 'input',
prop: 'paperLabel',
prop: 'school',
label: '学校'
},
{
type: 'select',
prop: 'paperType',
placeholder: '请选择考试班级',
options: this.natureList,
prop: 'relation_status',
placeholder: '请选择考生状态',
options: stuStatus,
labelKey: 'name',
valueKey: 'id',
label: '考生状态'
......@@ -67,7 +104,7 @@ export default {
],
columns: [
{ type: 'selection', minWidth: '50px', fixed: 'left' },
{ label: '考生状态', prop: 'name' },
{ label: '考生状态', prop: 'relation_status' },
{ label: '准考证号', prop: 'examinee_number' },
{ label: '身份证号', prop: 'id_number' },
{ label: '电话', prop: 'mobile' },
......@@ -75,57 +112,134 @@ export default {
{ label: '学校', prop: 'school' },
{ label: '参考时间', prop: 'exam_begin_time' },
{ label: '考中异常', prop: 'exam_error' },
{ label: '成绩', prop: 'sheet.score' }
],
data: [
{
stu_name: '里斯',
stu_school: '清华',
stu_status: ''
}
{ label: '成绩', prop: 'sheet.score' },
{ label: '操作', slots: 'table-x', align: 'right', width: 150 }
]
}
},
row() {
return this.$route.query.row
return JSON.parse(this.$route.query.row)
}
},
methods: {
// 新建试卷
handleCreatePaper() {
handleDetail() {},
// 获取选中项
handleSelectionChange(val) {
this.multipleSelection = val
},
// 复制考试地址
copyExamUrl() {
const copyDom = document.querySelector('#copyInput')
copyDom.value = window.location.origin + '/login/' + this.row.exam_id
copyDom.select() // 选择对象
document.execCommand('Copy')
this.$message({
message: '复制成功!',
type: 'success'
})
},
// 添加考生
handleAddStudent() {
this.$router.push({
path: 'newExam'
path: 'createStudent',
query: { id: this.row.exam_id }
})
},
// 编辑试卷
handleDdit(row) {
console.log(row)
// 考试信息编辑
editExamInfo() {
this.$router.push({ path: 'baseInfo', query: { row: JSON.stringify(this.row), isEdit: '2' } })
},
// 考试试卷编辑
editExam() {
console.log(this.row)
this.$router.push({
path: 'newPapers',
path: 'checkPaper',
query: { papers: JSON.stringify(this.row.papers), isEdit: '2', id: this.row.exam_id }
})
},
// 信息采集编辑
editInfo() {
this.$router.push({
path: 'personalInfo',
query: {
paperDetail: row,
isEdit: true
row: JSON.stringify(this.row),
isEdit: '2'
}
})
},
handleSelectionChange(val) {
this.multipleSelection = val
console.log(val)
// 考试配置编辑
editExamSetting() {
this.$router.push({
path: 'examSetting',
query: {
row: JSON.stringify(this.row),
isEdit: '2'
}
})
},
// 批量删除
batchDelete() {
console.log('111')
// 删除考生
delStudent() {
const studentId = this.multipleSelection.map(item => item.student_id).toString()
deleteStudent({ id: studentId }).then(res => {
this.$message.success('删除成功')
})
this.$refs.list.refetch()
},
// 查看详情
handleDetail(row) {
this.$router.push({
path: 'examDetail'
// 导出明细
exportDetail() {
const params = {
id: this.row.exam_id,
name: '',
relation_status: '',
school: ''
}
downloadExamData(params).then(r => {
const blob = new Blob([r], { type: 'application/vnd.ms-excel' })
if ('download' in document.createElement('a')) {
const elink = document.createElement('a')
elink.download = '学员数据.xlsx'
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href)
document.body.removeChild(elink)
}
})
},
// 单个删除
handleDelete(row) {
// this.$refs.list.refetch()
// 发送成绩信息
sendMessage() {
this.$confirm('确定发送成绩信息', {
confirmButtonText: '确定'
}).then(() => {
const studentId = this.multipleSelection.map(item => item.student_id).toString()
const params = { exam_id: this.row.exam_id, students_id: studentId }
sendMessage(params).then(res => {
this.$message.success('信息发送成功')
})
})
},
// 获取转移考生列表
getTransferList() {
getTranserList({ exam_id: this.row.exam_id }).then(res => {
this.transferList = res.data.list
})
},
// 转移考生
transferStudent() {
const params = {
transfer_exam_id: this.transfer_exam_id,
exam_id: this.row.exam_id,
student_ids: this.multipleSelection.map(item => item.student_id).toString()
}
transferStudent(params).then(res => {
this.$message.success('考生转移成功')
this.dialogVisible = false
})
}
},
mounted() {
this.getTransferList()
}
}
</script>
<template>
<app-card>
<app-list v-bind="tableOptions" ref="list" @selection-change="handleSelectionChange">
<app-list v-bind="tableOptions" ref="list">
<template #header-aside>
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">新建试卷</el-button>
</template>
......@@ -14,6 +14,12 @@
<script>
import { getExamList, delExamPaper } from '../api'
const status = [
{ value: '0', label: '未开始' },
{ value: '1', label: '进行中' },
{ value: '2', label: '已结束' },
{ value: '3', label: '待批阅' }
]
export default {
data() {
return {
......@@ -40,10 +46,13 @@ export default {
},
{
type: 'input',
prop: 'papers',
placeholder: '请输入考试试卷',
label: '考试试卷'
type: 'select',
prop: 'status',
placeholder: '请输入考试状态',
label: '考试状态',
options: status,
labelKey: 'label',
valueKey: 'value'
}
],
columns: [
......@@ -60,7 +69,10 @@ export default {
{ label: '应考人数', prop: 'exam_all' },
{ label: '完成人数', prop: 'exam_complete' },
{ label: '在线人数', prop: 'exam_online' },
{ label: '考试状态', prop: 'status_text' },
{
label: '考试状态',
prop: 'status_text'
},
{ label: '操作', slots: 'table-x', align: 'right', width: 150 }
]
}
......@@ -70,41 +82,24 @@ export default {
// 新建试卷
handleCreatePaper() {
this.$router.push({
path: 'newExam'
})
},
// 编辑试卷
handleDdit(row) {
console.log(row)
this.$router.push({
path: 'newPapers',
path: 'newExam',
query: {
paperDetail: row,
isEdit: true
isEdit: '1'
}
})
},
handleSelectionChange(val) {
this.multipleSelection = val
console.log(val)
},
// 批量删除
batchDelete() {
console.log('111')
},
// 查看详情
// 查看详情
handleDetail(row) {
this.$router.push({
path: 'examDetail',
query: {
row: row
row: JSON.stringify(row)
}
})
},
// 单个删除
handleDelete(row) {
console.log(row)
const params = { id: row.exam_id }
delExamPaper(params).then(res => {
this.$message.success('删除考试成功')
......
......@@ -7,10 +7,15 @@
<el-step title="考试配置"></el-step>
<el-step title="考试配置"></el-step>
</el-steps>
<base-info v-if="stepsIndex === 1" @getBaseInfo="getBaseInfo" />
<check-paper v-if="stepsIndex === 2" @getCheckPaper="getCheckPaper" @getCheckPaperList="getCheckPaperList" />
<personal-info v-if="stepsIndex === 3" @getInfo="getInfo" />
<exam-setting v-if="stepsIndex === 4" @getExamConfig="getExamConfig" />
<base-info data="" v-if="stepsIndex === 1" @getBaseInfo="getBaseInfo" :isEdit="isEdit" />
<check-paper
v-if="stepsIndex === 2"
@getCheckPaper="getCheckPaper"
@getCheckPaperList="getCheckPaperList"
:isEdit="isEdit"
/>
<personal-info v-if="stepsIndex === 3" @getInfo="getInfo" :isEdit="isEdit" />
<exam-setting v-if="stepsIndex === 4" @getExamConfig="getExamConfig" :isEdit="isEdit" />
<finished
v-if="stepsIndex === 5"
:params="params"
......@@ -38,6 +43,9 @@ export default {
},
data() {
return {
data: {
BaseInfo: {}
},
stepsIndex: 1,
config: {
info: {}
......@@ -48,27 +56,28 @@ export default {
checkedPaper: []
}
},
computed: {
isEdit() {
return this.$route.query.isEdit
}
},
methods: {
// 获取子组件传过来的页面基本信息
getBaseInfo(val) {
this.params = val
console.log(val, '123')
},
// 试卷id
getCheckPaper(val) {
// console.log(val)
this.exam_paper = val
},
// 选择的试卷
getCheckPaperList(val) {
console.log(val)
this.checkedPaper = val
},
// @ts-nocheck个人信息
getInfo(val) {
this.config.info = val
// console.log(this.config.info)
},
// 考试配置
getExamConfig(val) {
......
......@@ -10,17 +10,33 @@ export function getKnowledge(params) {
* 获取试卷列表
*/
export function getPaperList(params) {
return httpRequest.get('/api/qbs/admin/v1/question-papers/x1', { params })
return httpRequest.get(`/api/qbs/admin/v1/question-papers/${params.project_prefix}`, { params })
}
/**
* 新建试卷
*/
export function createNewPaper(data) {
export function createPaper(data) {
return httpRequest.post('/api/qbs/admin/v1/question-paper', data)
}
/**
* 更新试卷
*/
export function updatePaper(data) {
return httpRequest.put(`/api/qbs/admin/v1/question-paper/${data.id}`, data)
}
/**
* 获取试卷详情
*/
export function getPaper(params) {
return httpRequest.get(`/api/qbs/admin/v1/question-paper/${params.id}`, { params })
}
/**
* 获取试卷分类
*/
export function getPaperCategory(params) {
return httpRequest.get(`/api/qbs/admin/v1/question-category/tree/${params}`, { params })
return httpRequest.get(`/api/qbs/admin/v1/question-category/tree/${params.project_prefix}`, { params })
}
......@@ -3,8 +3,8 @@
<el-row :gutter="20">
<!-- 试题列表 -->
<el-col :span="18">
<el-card id="questionMain"
><div slot="header" class="clearfix">
<el-card id="questionMain">
<div slot="header" class="clearfix">
<span class="clearfix_tit"> 试题列表</span>
<el-button class="clearfix_del" type="primary" @click="delCheckedQuestion" v-if="questionList.length > 0"
>删除所选试题</el-button
......
<template>
<el-dialog title="添加试卷试题" v-bind="$attrs" v-on="$listeners"></el-dialog>
</template>
<script>
export default {
props: { data: { type: Object, default: () => ({}) } },
data() {
return {}
}
}
</script>
<style></style>
......@@ -5,33 +5,32 @@ const routes = [
path: '/paper',
component: AppLayout,
meta: { title: '试卷中心' },
redirect: '/paper/list',
children: [
{
path: '',
redirect: '/paper/list'
},
{
path: 'list',
component: () => import('./views/List.vue'),
meta: { title: '我的试卷库' }
},
{
path: 'newPaper',
name: 'newPaper',
name: 'createPaper',
path: 'create',
component: () => import('./views/NewPaper.vue'),
meta: { title: '新建试卷' }
},
{
path: 'newPapers',
name: 'newPaper',
name: 'editPaper',
path: 'update/:id',
component: () => import('./views/NewPaper.vue'),
meta: { title: '编辑试卷' }
meta: { title: '编辑试卷' },
props: true
},
{
path: 'detail',
name: 'detail',
name: 'viewPaper',
path: 'detail/:id',
component: () => import('./views/Detail.vue'),
meta: { title: '试卷详情' }
meta: { title: '试卷详情' },
props: true
}
]
}
......
<template>
<div>
<!-- 试卷描述 -->
<el-card>
<app-card title="试卷信息">
<template #header-aside>
<el-button type="primary" size="mini" @click="handleUpdate">编辑试卷</el-button>
</template>
<el-descriptions :column="2" class="descriptionsCon">
<template slot="extra">
<el-button type="primary" @click="editPaper">编辑试卷</el-button>
</template>
<el-descriptions-item label="试卷名称">{{ paperDetail.paperName }}</el-descriptions-item>
<el-descriptions-item label="标签">1111</el-descriptions-item>
<el-descriptions-item label="试卷分类">{{ paperDetail.paperType }}</el-descriptions-item>
<el-descriptions-item label="组卷模式">{{ paperDetail.paperMode }}</el-descriptions-item>
<el-descriptions-item label="试卷总分">{{ paperDetail.paperTotalScore }}</el-descriptions-item>
<el-descriptions-item label="及格分数">{{ paperDetail.paperPassScore }}</el-descriptions-item>
<el-descriptions-item label="考试时长">40分钟</el-descriptions-item>
<el-descriptions-item label="最短交卷时长">20分钟</el-descriptions-item>
<el-descriptions-item label="试题顺序">固定</el-descriptions-item>
<el-descriptions-item label="多次考试"></el-descriptions-item>
<el-descriptions-item label="多次考试成绩计算规则">平均计算法 </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_category }}</el-descriptions-item>
<el-descriptions-item label="组卷模式">{{ detail.paper_type }}</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.paper_times }}分钟</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.is_multiple_exams }}</el-descriptions-item>
<el-descriptions-item label="多次考试成绩计算规则">{{ detail.multiple_test_score_rule }}</el-descriptions-item>
</el-descriptions>
</el-card>
</app-card>
<!-- 试卷列表 -->
<QuestionList :paperMode="paperDetail.paperMode" :paperTotalScore="paperDetail.paperTotalScore" />
<QuestionList :paperMode="detail.paperMode" :paperTotalScore="detail.paperTotalScore" />
</div>
</template>
<script>
import QuestionList from '../components/QuestionList.vue'
import { getPaper } from '../api.js'
export default {
props: { id: { type: String } },
components: { QuestionList },
computed: {
paperDetail() {
return JSON.parse(this.$route.query.paperDetail)
data() {
return {
detail: {}
}
},
// watch: {
// paperDetail: {
// paperDetail: {
// immediate: true,
// handler(data) {
// this.form = Object.assign({}, this.form, data)
// }
// }
// }
// },
computed: {},
beforeMount() {
this.getDetail()
},
methods: {
// 编辑试卷
editPaper() {
this.$router.push({
path: 'newPaper',
query: {
paperDetail: this.paperDetail,
isEdit: true
}
// 获取试卷详情
getDetail() {
getPaper({ id: this.id }).then(res => {
this.detail = Object.assign({}, this.detail, res.data)
})
},
// 编辑试卷
handleUpdate() {
this.$router.push({ name: 'editPaper', params: { id: this.detail.id } })
}
}
}
......
......@@ -2,12 +2,15 @@
<app-card>
<app-list v-bind="tableOptions" ref="list" @selection-change="handleSelectionChange">
<div class="btn_operate">
<el-button type="primary" icon="el-icon-plus" @click="handleCreatePaper">新建试卷</el-button>
<el-button type="primary" icon="el-icon-plus" @click="batchDelete">批量删除</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleCreate">新建试卷</el-button>
<el-button type="primary" icon="el-icon-delete" @click="batchDelete">批量删除</el-button>
</div>
<template v-slot:filter-category="{ params }">
<question-type-cascader v-model="params.paper_category"></question-type-cascader>
</template>
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleDdit(row)">编辑</el-button>
<el-button type="text" @click="handleDetail(row)">查看详情</el-button>
<el-button type="text" @click="handleUpdate(row)">编辑</el-button>
<el-button type="text" @click="handleView(row)">查看详情</el-button>
<el-button type="text" @click="handleDelete(row)">删除</el-button>
</template>
</app-list>
......@@ -15,12 +18,16 @@
</template>
<script>
import { getPaperList, getPaperCategory } from '../api'
import { getPaperList } from '../api'
import QuestionTypeCascader from '@/components/base/QuestionTypeCascader.vue'
const paperType = [
{ label: '选题组卷', value: 0 },
{ label: '自动组卷', value: 1 }
{ label: '选题组卷', value: 1 },
{ label: '自动组卷', value: 2 }
]
export default {
components: { QuestionTypeCascader },
data() {
return {
visible: false,
......@@ -29,11 +36,15 @@ export default {
}
},
computed: {
activeProject() {
return this.$store.state.activeProject || {}
},
tableOptions() {
return {
remote: {
httpRequest: getPaperList,
params: {
project_prefix: this.activeProject.tag,
id: '',
paper_title: '',
paper_type: '',
......@@ -67,85 +78,45 @@ export default {
{
type: 'select',
prop: 'paperType',
placeholder: '请选择试卷分类',
options: this.initTree,
labelKey: 'category_name',
valueKey: 'id',
label: '试卷分类:'
label: '试卷分类:',
slots: 'filter-category'
}
],
columns: [
{ type: 'selection', minWidth: '50px', fixed: 'left' },
{ type: 'selection', width: '50px', fixed: 'left' },
{ type: 'index', label: '序号', minWidth: '50px', fixed: 'left' },
{ label: '组卷模式', prop: 'paper_type' },
{ label: '试卷分类', prop: 'paper_category' },
{ label: '试卷名称', prop: 'paper_title' },
{ label: '总分', prop: 'paper_total_score' },
{ label: '及格分数', prop: 'paperPassScore' },
{ label: '更新人', prop: 'operator.username' },
{ label: '及格分数', prop: 'pass_score' },
{ label: '更新人', prop: 'operator.realname' },
{ label: '更新时间', prop: 'updated_at' },
{ label: '操作', slots: 'table-x', align: 'right', width: 150 }
]
// data: [
// {
// paperMode: '选题组卷',
// paperType: '测试',
// paperName: '期中考试',
// paperTotalScore: 100,
// paperPassScore: 60,
// update_name: '张三',
// update_time: '2022-02-18'
// }
// ]
}
}
},
mounted() {
// 获取试卷分类
this.getPaperCategory()
},
methods: {
getPaperCategory() {
getPaperCategory('x1').then(res => {
this.paperCategoryList = res.data
})
},
// 新建试卷
handleCreatePaper() {
this.$router.push({
path: 'newPaper',
query: { isEdit: false }
})
handleCreate() {
this.$router.push({ name: 'createPaper' })
},
// 编辑试卷
handleDdit(row) {
console.log(row)
this.$router.push({
path: 'newPapers',
query: {
rowDetail: row,
isEdit: true
}
})
handleUpdate(row) {
this.$router.push({ name: 'editPaper', params: { id: row.id } })
},
// 查看详情
handleView(row) {
this.$router.push({ name: 'viewPaper', params: { id: row.id } })
},
handleSelectionChange(val) {
this.multipleSelection = val
console.log(val)
},
// 批量删除
batchDelete() {
console.log('111')
},
// 查看详情
handleDetail(row) {
this.$router.push({
path: 'detail',
query: {
paperDetail: JSON.stringify(row)
}
})
},
// 单个删除
handleDelete(row) {
// this.$refs.list.refetch()
......
<template>
<el-form ref="form" :model="form" label-width="160px" :label-position="labelPosition">
<el-row>
<el-col :span="12">
<el-form-item
label="试卷名称"
prop="paper_title"
:rules="[{ message: '请输入试卷名称', required: true, trigger: 'blur' }]"
>
<el-input v-model="form.paper_title" placeholder="请输入试卷名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="18">
<app-card>
<el-form ref="form" :model="form" :rules="rules" label-width="160px" label-position="right">
<el-row>
<el-col :span="12">
<el-form-item label="试卷名称" prop="paper_title">
<el-input v-model="form.paper_title" placeholder="请输入试卷名称" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-form-item label="试卷用途" prop="paper_uses">
<el-radio-group v-model="form.paper_uses">
<el-radio :label="1">考试</el-radio>
......@@ -20,257 +16,245 @@
<el-radio :label="3">课程测试</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="标签" prop="paper_labels">
<el-input v-model="form.paper_labels" placeholder="请输入试卷标签" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="试卷分类" prop="paper_category">
<el-select v-model="form.paper_category" placeholder="请选择试卷分类" style="width: 100%">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="组卷模式" prop="paper_type">
<el-select v-model="form.paper_type" placeholder="请选择组卷模式" style="width: 100%">
<el-option label="自动组卷" :value="0"> </el-option>
<el-option label="选题组卷" :value="1"> </el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item
label="试题顺序"
:rules="[{ message: '请选择试题顺序', required: true, trigger: 'change' }]"
style="padding-left: 20px"
v-if="form.paper_type === 1"
>
<el-radio-group v-model="form.paper_question_order">
<el-radio :label="1">固定</el-radio>
<el-radio :label="2">随机</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item
label="试卷总分"
prop="paper_total_score"
:rules="[{ message: '请输入试卷总分', required: true, trigger: 'blur' }]"
>
<el-input-number
:controls="false"
:step="1"
v-model="form.paper_total_score"
:min="0"
:max="200"
placeholder="请输入试卷总分"
style="width: 100%"
:precision="0"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item
label="及格分数"
prop="pass_score"
:rules="[{ message: '请输入及格分数', required: true, trigger: 'blur' }]"
style="padding-left: 20px"
>
<el-input-number
:controls="false"
:step="1"
v-model="form.pass_score"
:min="0"
:max="200"
placeholder="请输入及格分数"
style="width: 100%"
:precision="0"
></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item
label="考试时长"
prop="paper_times"
:rules="[{ message: '请输入考试时长', required: true, trigger: 'blur' }]"
>
<el-input-number
v-model="form.paper_times"
:controls="false"
:min="1"
:max="150"
placeholder="请输入考试时长"
style="width: 90%"
:precision="0"
></el-input-number
>&nbsp;分钟
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="最短交卷时长"
prop="minimum_paper_handing_time"
:rules="[{ message: '请输入考试时长', required: true, trigger: 'blur' }]"
style="padding-left: 20px"
>
<el-input-number
v-model="form.minimum_paper_handing_time"
:controls="false"
:min="1"
:max="150"
placeholder="请输入考试时长"
style="width: 90%"
:precision="0"
></el-input-number
>&nbsp;分钟
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="多次考试" :rules="[{ required: true, trigger: 'blur' }]">
<el-radio-group v-model="form.is_multiple_exams">
<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="多次考试成绩计算规则" style="padding-left: 20px" v-if="form.moreExam === '1'">
<el-radio-group v-model="form.multiple_test_score_rule">
<el-radio :label="1">平均计算法</el-radio>
<el-radio :label="2">最高得分法</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-row style="margin-top: 30px">
<el-button @click="handleCancel" style="margin-left: 100px">取消</el-button>
<el-button type="primary" @click="handleSubmit">提交</el-button>
<el-button type="primary" @click="handleSubmitSelect">保存并选择试题</el-button>
</el-row>
</el-form-item>
</el-form>
<el-row>
<el-col :span="12">
<el-form-item label="标签" prop="paper_labels">
<el-input v-model="form.paper_labels" placeholder="请输入试卷标签" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="试卷分类" prop="paper_category">
<question-type-cascader v-model="form.paper_category"></question-type-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="组卷模式" prop="paper_type">
<el-select v-model="form.paper_type" placeholder="请选择组卷模式" style="width: 100%">
<el-option label="选题组卷" :value="1"></el-option>
<el-option label="自动组卷" :value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="试题顺序" prop="paper_question_order" v-if="form.paper_type === 1">
<el-radio-group v-model="form.paper_question_order">
<el-radio :label="1">固定</el-radio>
<el-radio :label="2">随机</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="试卷总分" prop="paper_total_score">
<el-input-number
:controls="false"
:step="1"
v-model="form.paper_total_score"
:min="0"
:max="200"
placeholder="请输入试卷总分"
style="width: 100%"
:precision="0"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="及格分数" prop="pass_score">
<el-input-number
:controls="false"
:step="1"
v-model="form.pass_score"
:min="0"
:max="200"
placeholder="请输入及格分数"
style="width: 100%"
:precision="0"
></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="考试时长" prop="paper_times">
<el-input-number
v-model="form.paper_times"
:controls="false"
:min="1"
:max="150"
placeholder="请输入考试时长"
:precision="0"
></el-input-number
>&nbsp;分钟
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最短交卷时长" prop="minimum_paper_handing_time">
<el-input-number
v-model="form.minimum_paper_handing_time"
:controls="false"
:min="1"
:max="150"
placeholder="请输入考试时长"
:precision="0"
></el-input-number
>&nbsp;分钟
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="多次考试" prop="is_multiple_exams">
<el-radio-group v-model="form.is_multiple_exams">
<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="多次考试成绩计算规则" v-if="form.is_multiple_exams === 1">
<el-radio-group v-model="form.multiple_test_score_rule">
<el-radio :label="1">平均计算法</el-radio>
<el-radio :label="2">最高得分法</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<div style="padding: 30px; text-align: center">
<el-button @click="handleCancel" style="margin-left: 100px">取消</el-button>
<el-button type="primary" @click="handleSubmit">保存</el-button>
<el-button type="primary" @click="handleSubmitSelect" v-if="hasSelectQuestionButton">保存并选择试题</el-button>
</div>
</el-form>
<question-select :visible.sync="questionSelectVisible"></question-select>
</app-card>
</template>
<script>
import { createNewPaper } from '../api'
import { getPaper, createPaper, updatePaper } from '../api'
import QuestionTypeCascader from '@/components/base/QuestionTypeCascader.vue'
export default {
props: { id: { type: String } },
components: { QuestionTypeCascader, QuestionSelect: () => import('../components/QuestionSelect.vue') },
data() {
return {
labelPosition: 'left',
btnDisabled: false,
paper_category: [
{ label: '测试', value: 1 },
{ label: '考试', value: 2 },
{ label: '模拟', value: 3 }
],
form: {
paper_title: '', // 试卷名称
paper_uses: 1, // 试卷用途
paper_labels: '', // 标签
paper_category: 1, // 试卷分类
paper_type: 1, // 组卷模式
paper_question_order: 0, // 试题顺序
paper_total_score: undefined, // 试卷总分
paperPassScore: undefined, // 及格分数
paper_times: undefined, // 考试时长
minimum_paper_handing_time: undefined, // 最短交卷时长
is_multiple_exams: 1, // 多次考试
paper_category: undefined, // 试卷分类
paper_type: undefined, // 组卷模式
paper_question_order: 1, // 试题顺序
paper_total_score: 100, // 试卷总分
pass_score: 60, // 及格分数
paper_times: 90, // 考试时长
minimum_paper_handing_time: 15, // 最短交卷时长
is_multiple_exams: 0, // 多次考试
multiple_test_score_rule: 1 // 多次考试成绩计算规则
}
}
},
computed: {
paperDetail() {
return this.$route.query.paperDetail
},
isEdit() {
return this.$route.query.isEdit
},
rules: {
paper_title: [{ message: '请输入试卷名称', required: true, trigger: 'blur' }],
paper_uses: [{ message: '请选择试卷用途', required: true, trigger: 'change' }],
paper_category: [{ message: '请选择试卷分类', required: true, trigger: 'change' }],
paper_type: [{ message: '请选择组卷模式', required: true, trigger: 'change' }],
paper_total_score: [{ message: '请输入试卷总分', required: true, trigger: 'blur' }],
paper_question_order: [{ message: '请选择试题顺序', required: true, trigger: 'change' }],
pass_score: [{ message: '请输入及格分数', required: true, trigger: 'blur' }],
paper_times: [{ message: '请输入考试时长', required: true, trigger: 'blur' }],
minimum_paper_handing_time: [{ message: '请输入考试时长', required: true, trigger: 'blur' }],
is_multiple_exams: [{ message: '请选择是否多次考试', required: true, trigger: 'change' }]
},
questionSelectVisible: false
}
},
watch: {
rowDetail: {
'$route.query.select': {
immediate: true,
handler(data) {
this.form = Object.assign({}, this.form, data)
handler(value) {
value && this.showSelectQuestion()
}
}
},
computed: {
isEdit() {
return !!this.id
},
paperDetail: {
immediate: true,
handler(data) {
this.form = Object.assign({}, this.form, data)
}
hasSelectQuestionButton() {
return !this.isEdit || this.$route.query.select
}
},
beforeMount() {
this.isEdit && this.getDetail()
},
methods: {
// 取消
handleCancel() {
history.go(-1)
this.$router.replace('/paper/list')
},
// 保存
handleSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
this.$confirm('保存成功!', {
confirmButtonText: '确定'
}).then(() => {
history.go(-1)
createNewPaper(Object.assign(this.form, { project_prefix: 'x1' })).then(res => {
this.$message.sucess('新建试卷成功')
})
})
} else {
setTimeout(() => {
// 表单校验不通过聚焦至第一个不通过的输入框
const isError = document.getElementsByClassName('is-error')
isError[0].querySelector('input').focus()
}, 100)
return false
}
this.$refs.form.validate().then(() => {
// 保存成功回到列表
this.createPaper().then(res => {
this.$router.replace('/paper/list')
})
})
},
// 保存并选择试题
handleSubmitSelect() {
this.$refs.form.validate(valid => {
if (valid) {
this.$confirm('保存成功!', {
confirmButtonText: '确定'
}).then(() => {
// 调用接口
this.$router.push({
path: 'detail',
form: this.form
})
this.$refs.form.validate().then(async () => {
if (this.isEdit) {
this.updatePaper(() => {
this.showSelectQuestion()
})
} else {
setTimeout(() => {
// 表单校验不通过聚焦至第一个不通过的输入框
const isError = document.getElementsByClassName('is-error')
isError[0].querySelector('input').focus()
}, 100)
return false
this.createPaper(res => {
this.$router.replace({ path: '/paper/update/' + res.data.id, query: { select: true } })
})
}
})
},
// 显示选题
showSelectQuestion() {
if (this.isEdit) {
this.visible = true
} else {
this.$router.replace('/paper/update')
}
this.questionSelectVisible = true
},
// 创建试卷
createPaper(callback) {
return createPaper(this.form).then(res => {
this.$message.success('保存成功')
callback && callback(res)
return res
})
},
// 更新试卷
updatePaper(callback) {
return updatePaper(this.form).then(res => {
this.$message.success('保存成功')
callback && callback(res)
return res
})
},
// 获取试卷详情
getDetail() {
getPaper({ id: this.id }).then(res => {
this.form = Object.assign({}, this.form, res.data)
})
}
}
}
</script>
<style lang="scss" scoped>
:v-deep .el-input-number .el-input-number__decrease {
display: none;
......
......@@ -49,8 +49,9 @@ httpRequest.interceptors.request.use(
httpRequest.interceptors.response.use(
function (response) {
const { data } = response
console.log(response)
// 正常返回
if (data.code === 0) {
if (data.code === 0 || data.type === 'application/vnd.ms-excel') {
return data
}
// 未登录
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论