提交 87c5d3aa authored 作者: matian's avatar matian

代码提交

上级 c9583aa3
......@@ -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",
......
......@@ -59,3 +59,15 @@ export function deleteStudent(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)
}
......@@ -82,6 +82,7 @@ export default {
}
},
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
......@@ -90,6 +91,7 @@ export default {
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: {
nextStep() {
......
......@@ -40,8 +40,11 @@
</div>
</el-row>
<el-row :span="24" class="btn_next">
<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,51 @@ 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() {
console.log()
if (this.$route.query.isEdit === '2' && JSON.parse(this.$route.query.row)) {
this.getDetail()
}
}
}
......
<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>
<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>
<template v-slot:isVisible="{ row }">
<el-switch v-model="row.isVisible" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</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>
<template v-slot:isRequired="{ row }">
<el-switch v-model="row.isRequired" active-color="#13ce66" inactive-color="#ff4949"> </el-switch>
</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>
<template v-slot:weight="{ row }">
<el-input v-model="row.sort" active-color="#13ce66" inactive-color="#ff4949"> </el-input>
</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>
</app-list>
</el-table-column>
</el-table>
<el-row class="btn_next">
<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: [] // 选择项
}
},
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: [
tableData: [
{
isCheckedInfo: '姓名',
name: '姓名',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '性别',
isEdit: false,
isVisible: false,
isRequired: false,
name: '性别',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '身份证号',
name: '身份证号',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '年龄',
name: '年龄',
ienabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '所学专业',
name: '所学专业',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '所在学校',
name: '所在学校',
enabled_edit: false,
enabled_visible: false,
required: false,
sort: 0
},
{
isCheckedInfo: '邮箱',
name: '邮箱',
enabled_edit: false,
enabled_visible: false,
required: false,
......@@ -93,14 +90,14 @@ export default {
},
{
isCheckedInfo: '学历',
name: '学历',
isEdit: false,
isVisible: false,
isRequired: false,
sort: 0
},
{
isCheckedInfo: '手机号',
name: '手机号',
enabled_edit: false,
enabled_visible: false,
required: false,
......@@ -108,29 +105,71 @@ export default {
}
]
}
},
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]
console.log(info)
this.$emit('getInfo', info)
this.$parent.$parent.nextStep()
},
lastStep() {
this.$parent.$parent.lastStep()
},
getDetail() {
console.log(JSON.parse(this.$route.query.row))
const params = {
id: JSON.parse(this.$route.query.row).exam_id
}
getExamPaperDetail(params).then(res => {
console.log(JSON.parse(res.data.exam_info.config).info)
const list = JSON.parse(res.data.exam_info.config).info
const arr = []
Object.keys(list).forEach(key => {
arr.push(list[key])
})
console.log(arr)
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>
......
......@@ -39,6 +39,16 @@ const routes = [
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: '考试设置' }
}
]
}
......
......@@ -9,7 +9,8 @@
<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="transferStudent">转移考生</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>
......@@ -20,12 +21,36 @@
<template v-slot:table-x="{ row }">
<el-button type="text" @click="handleDetail(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, deleteStudent, downloadExamData } from '../api'
import {
getExamPaperDetail,
deleteStudent,
downloadExamData,
sendMessage,
getTranserList,
transferStudent
} from '../api'
const stuStatus = [
{ id: '1', name: '未开考' },
{ id: '1', name: '已登录' },
......@@ -39,7 +64,10 @@ export default {
data() {
return {
visible: false,
multipleSelection: [] // 选择项
multipleSelection: [], // 选择项
dialogVisible: false,
transferList: [],
transfer_exam_id: ''
}
},
computed: {
......@@ -96,9 +124,21 @@ export default {
},
methods: {
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() {
console.log(this.row, '----')
......@@ -119,11 +159,30 @@ export default {
query: { papers: JSON.stringify(this.row.papers), isEdit: '2', id: this.row.exam_id }
})
},
// 信息采集编辑
editInfo() {
this.$router.push({
path: 'personalInfo',
query: {
row: JSON.stringify(this.row),
isEdit: '2'
}
})
},
// 考试配置编辑
editExamSetting() {
this.$router.push({
path: 'examSetting',
query: {
row: JSON.stringify(this.row),
isEdit: '2'
}
})
},
// 删除考生
delStudent(row) {
delStudent() {
const studentId = this.multipleSelection.map(item => item.student_id).toString()
const studentIds = studentId.toString()
deleteStudent({ id: studentIds }).then(res => {
deleteStudent({ id: studentId }).then(res => {
this.$message.success('删除成功')
})
this.$refs.list.refetch()
......@@ -151,14 +210,40 @@ export default {
}
})
},
// 转移考生
transferStudent() {},
// 发送成绩信息
sendMessage() {},
// 信息采集编辑
editInfo() {},
// 考试配置编辑
editExamSetting() {}
sendMessage() {
this.$confirm('确定发送成绩信息', {
confirmButtonText: '确定'
}).then(() => {
console.log(this.studentIds)
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>
......@@ -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 }
]
}
......
......@@ -14,8 +14,8 @@
@getCheckPaperList="getCheckPaperList"
:isEdit="isEdit"
/>
<personal-info v-if="stepsIndex === 3" @getInfo="getInfo" />
<exam-setting v-if="stepsIndex === 4" @getExamConfig="getExamConfig" />
<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"
......@@ -70,7 +70,7 @@ export default {
},
// 试卷id
getCheckPaper(val) {
// console.log(val)
console.log(val)
this.exam_paper = val
},
// 选择的试卷
......
......@@ -29,7 +29,7 @@ export default defineConfig(({ mode }) => {
rewrite: path => path.replace(/^\/api\/qbs/, '')
},
'/api/exam': {
target: 'http://localhost-exam-admin.ezijing.com',
target: 'https://x-exam-admin-api.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/exam/, '')
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论