|
|
@@ -1,23 +1,22 @@
|
|
|
<template>
|
|
|
<v-container>
|
|
|
- <page-header title="创建考试" :breadcrumb="breadcrumb"> </page-header>
|
|
|
- <!--创建的表格-->
|
|
|
- <v-container class="grey lighten-5 pa-6" v-if="!isExamCreated">
|
|
|
- <v-form ref="form" lazy-validation>
|
|
|
+ <page-header title="创建评测" :breadcrumb="breadcrumb"> </page-header>
|
|
|
+ <v-container class="grey lighten-5 pa-6">
|
|
|
+ <v-form ref="form" v-model="valid">
|
|
|
<v-text-field
|
|
|
v-model="examName"
|
|
|
- :counter="10"
|
|
|
- label="考试名称"
|
|
|
- required
|
|
|
+ :counter="20"
|
|
|
+ label="评测名称"
|
|
|
class="ma-4"
|
|
|
+ :rules="nameRules"
|
|
|
></v-text-field>
|
|
|
|
|
|
<v-text-field
|
|
|
v-model="position"
|
|
|
- :counter="10"
|
|
|
- label="招聘职位"
|
|
|
- required
|
|
|
+ :counter="20"
|
|
|
+ label="职位"
|
|
|
class="ma-4"
|
|
|
+ :rules="nameRules"
|
|
|
></v-text-field>
|
|
|
|
|
|
<v-select
|
|
|
@@ -28,6 +27,8 @@
|
|
|
multiple
|
|
|
outlined
|
|
|
class="ma-4"
|
|
|
+ deletable-chips
|
|
|
+ :rules="arrayRules"
|
|
|
></v-select>
|
|
|
|
|
|
<v-subheader class="ma-2 sm">
|
|
|
@@ -85,6 +86,7 @@
|
|
|
readonly
|
|
|
v-bind="attrs"
|
|
|
v-on="on"
|
|
|
+ :rules="arrayRules"
|
|
|
></v-text-field>
|
|
|
</template>
|
|
|
<v-time-picker
|
|
|
@@ -95,124 +97,68 @@
|
|
|
></v-time-picker>
|
|
|
</v-menu>
|
|
|
</v-row>
|
|
|
-
|
|
|
- <!--结束日期/时间-->
|
|
|
+ <v-slider
|
|
|
+ label="考试时长"
|
|
|
+ :tick-labels="examLengthTicks"
|
|
|
+ class="ma-4"
|
|
|
+ max="5"
|
|
|
+ v-model="examLength"
|
|
|
+ ></v-slider>
|
|
|
<v-row class="ma-4">
|
|
|
- <v-menu
|
|
|
- v-model="menu3"
|
|
|
- :close-on-content-click="false"
|
|
|
- transition="scale-transition"
|
|
|
- offset-y
|
|
|
- max-width="290px"
|
|
|
- min-width="290px"
|
|
|
- >
|
|
|
- <template v-slot:activator="{ on, attrs }">
|
|
|
- <v-text-field
|
|
|
- v-model="endDateFormatted"
|
|
|
- label="结束日期"
|
|
|
- prepend-icon="mdi-calendar"
|
|
|
- readonly
|
|
|
- v-bind="attrs"
|
|
|
- v-on="on"
|
|
|
- ></v-text-field>
|
|
|
- </template>
|
|
|
- <v-date-picker
|
|
|
- v-model="endDate"
|
|
|
- no-title
|
|
|
- @input="menu3 = false"
|
|
|
- ></v-date-picker>
|
|
|
- </v-menu>
|
|
|
-
|
|
|
- <v-menu
|
|
|
- v-model="menu4"
|
|
|
- ref="menu4"
|
|
|
- :close-on-content-click="false"
|
|
|
- :nudge-right="40"
|
|
|
- :return-value.sync="endTime"
|
|
|
- transition="scale-transition"
|
|
|
- offset-y
|
|
|
- max-width="290px"
|
|
|
- min-width="290px"
|
|
|
- >
|
|
|
- <template v-slot:activator="{ on, attrs }">
|
|
|
- <v-text-field
|
|
|
- v-model="endTime"
|
|
|
- label="结束时间"
|
|
|
- prepend-icon="mdi-clock-time-four-outline"
|
|
|
- readonly
|
|
|
- v-bind="attrs"
|
|
|
- v-on="on"
|
|
|
- ></v-text-field>
|
|
|
- </template>
|
|
|
- <v-time-picker
|
|
|
- v-if="menu4"
|
|
|
- v-model="endTime"
|
|
|
- full-width
|
|
|
- @click:minute="$refs.menu4.save(endTime)"
|
|
|
- ></v-time-picker>
|
|
|
- </v-menu>
|
|
|
+ <v-text-field
|
|
|
+ :value="computedEndDate"
|
|
|
+ label="结束日期"
|
|
|
+ prepend-icon="mdi-calendar"
|
|
|
+ disabled
|
|
|
+ ></v-text-field>
|
|
|
+ <v-text-field
|
|
|
+ :value="computedEndTime"
|
|
|
+ label="结束时间"
|
|
|
+ prepend-icon="mdi-clock-time-four-outline"
|
|
|
+ disabled
|
|
|
+ ></v-text-field>
|
|
|
</v-row>
|
|
|
-
|
|
|
+ <v-switch
|
|
|
+ class="ma-4"
|
|
|
+ v-model="antiCheating"
|
|
|
+ :label="`在线监考: ${antiCheating ? '开' : '关'}`"
|
|
|
+ ></v-switch>
|
|
|
<v-text-field
|
|
|
v-model="comment"
|
|
|
label="备注"
|
|
|
class="ma-4 mb-8"
|
|
|
></v-text-field>
|
|
|
- <v-btn color="success" class="ma-4" @click="onCreateExam">
|
|
|
- 提交创建
|
|
|
- </v-btn>
|
|
|
- <v-btn color="primary" class="ma-4" @click="selectQuestion = true">
|
|
|
- 手动选择试题
|
|
|
+ <v-btn
|
|
|
+ color="success"
|
|
|
+ class="ma-4"
|
|
|
+ @click="onCreateExam"
|
|
|
+ :disabled="!valid"
|
|
|
+ >
|
|
|
+ 创建评测
|
|
|
</v-btn>
|
|
|
+ <!-- <v-btn color="primary" class="ma-4" @click="selectQuestion = true">-->
|
|
|
+ <!-- 手动选择试题-->
|
|
|
+ <!-- </v-btn>-->
|
|
|
</v-form>
|
|
|
</v-container>
|
|
|
-
|
|
|
- <!--创建成功后显示-->
|
|
|
- <v-container v-else>
|
|
|
- <v-card class="px-3 mb-5">
|
|
|
- <v-card-title
|
|
|
- >考试「{{ createdExamInfo.examName }}」创建成功</v-card-title
|
|
|
- >
|
|
|
- <v-card-subtitle>考试ID: {{ createdExamInfo.examId }}</v-card-subtitle>
|
|
|
- <v-row no-gutters align-content="start">
|
|
|
- <v-col>
|
|
|
- <v-card-text class="pa-0 pb-3"
|
|
|
- >考试邀请码:{{ createdExamInfo.inviteCode }}</v-card-text
|
|
|
- >
|
|
|
- </v-col>
|
|
|
- <v-col>
|
|
|
- <v-card-text class="pa-0 pb-5"
|
|
|
- >当前难度值:{{ createdExamInfo.difficulty }}</v-card-text
|
|
|
- >
|
|
|
- </v-col>
|
|
|
- </v-row>
|
|
|
- </v-card>
|
|
|
-
|
|
|
- <v-container class="grey lighten-5 pa-6">
|
|
|
- <v-card-title>样卷</v-card-title>
|
|
|
- </v-container>
|
|
|
- </v-container>
|
|
|
-
|
|
|
- <v-container v-if="selectQuestion">
|
|
|
- <v-overlay :value="true" :dark="false" absolute>
|
|
|
- <question-list></question-list>
|
|
|
- </v-overlay>
|
|
|
- </v-container>
|
|
|
+ <v-snackbar>
|
|
|
+ 创建成功
|
|
|
+ </v-snackbar>
|
|
|
</v-container>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
import Vue from 'vue'
|
|
|
import PageHeader from '@/components/PageHeader.vue'
|
|
|
-import QuestionList from '@/views/teacher/components/QuestionList.vue'
|
|
|
import { createExam } from '@/api/exam'
|
|
|
import { ExamSerializer, ID } from '@/api/types'
|
|
|
+import { mapGetters } from 'vuex'
|
|
|
+import dayjs from 'dayjs'
|
|
|
|
|
|
export default Vue.extend({
|
|
|
name: 'ExamCreate',
|
|
|
components: {
|
|
|
- PageHeader,
|
|
|
- QuestionList
|
|
|
+ PageHeader
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
@@ -224,7 +170,7 @@ export default Vue.extend({
|
|
|
href: '/'
|
|
|
},
|
|
|
{
|
|
|
- text: '创建考试',
|
|
|
+ text: '创建评测',
|
|
|
disabled: true,
|
|
|
href: '/'
|
|
|
}
|
|
|
@@ -241,7 +187,7 @@ export default Vue.extend({
|
|
|
'Vue'
|
|
|
],
|
|
|
isExamCreated: false,
|
|
|
- createdExamInfo: {} as ExamSerializer,
|
|
|
+ createdExamInfo: (null as unknown) as ExamSerializer,
|
|
|
menu1: false,
|
|
|
menu2: false,
|
|
|
menu3: false,
|
|
|
@@ -249,7 +195,7 @@ export default Vue.extend({
|
|
|
examName: '',
|
|
|
position: '',
|
|
|
skills: [],
|
|
|
- difficulty: 1,
|
|
|
+ difficulty: 50,
|
|
|
startDate: '',
|
|
|
startDateFormatted: '',
|
|
|
startTime: '',
|
|
|
@@ -259,28 +205,62 @@ export default Vue.extend({
|
|
|
comment: '',
|
|
|
selectedQuestions: [] as Array<ID>,
|
|
|
selectQuestion: false,
|
|
|
- antiCheating: false
|
|
|
+ antiCheating: false,
|
|
|
+ valid: true,
|
|
|
+ nameRules: [
|
|
|
+ (v: string) => !!v || '该项为必填项',
|
|
|
+ (v: string) => v.length < 20 || '字数过多'
|
|
|
+ ],
|
|
|
+ arrayRules: [(v: [] | string) => v.length > 0 || '该项为必填项'],
|
|
|
+ examLengthTicks: [
|
|
|
+ '0.5 小时',
|
|
|
+ '1 小时',
|
|
|
+ '1.5 小时',
|
|
|
+ '2 小时',
|
|
|
+ '2.5 小时',
|
|
|
+ '3 小时'
|
|
|
+ ],
|
|
|
+ examLength: 0,
|
|
|
+ timeFormat: 'YYYY-MM-DD HH:mm:ss'
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
- computedStartDateFormatted(): string {
|
|
|
- return this.formatDate(this.startDate)
|
|
|
+ computedEndDate(): string {
|
|
|
+ if (this.startTime === '') {
|
|
|
+ return this.startDateFormatted
|
|
|
+ }
|
|
|
+ return this.computedExamEndTime.substr(0, 10)
|
|
|
+ },
|
|
|
+ computedEndTime(): string {
|
|
|
+ if (this.startTime === '') {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.computedExamEndTime.substr(11, 5)
|
|
|
},
|
|
|
- computedEndDateFormatted(): string {
|
|
|
- return this.formatDate(this.endDate)
|
|
|
+ computedExamEndTime(): string {
|
|
|
+ const startTime = dayjs(
|
|
|
+ this.startDateFormatted + ' ' + this.startTime + ':00',
|
|
|
+ this.timeFormat
|
|
|
+ )
|
|
|
+
|
|
|
+ const examLength = Number.parseFloat(
|
|
|
+ this.examLengthTicks[this.examLength]
|
|
|
+ )
|
|
|
+ const endTime = startTime.add(examLength, 'h')
|
|
|
+
|
|
|
+ return endTime.format(this.timeFormat)
|
|
|
}
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
startDate(val) {
|
|
|
this.startDateFormatted = this.formatDate(this.startDate)
|
|
|
- },
|
|
|
- endDate(val) {
|
|
|
- this.endDateFormatted = this.formatDate(this.endDate)
|
|
|
}
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
+ ...mapGetters(['getId']),
|
|
|
saveSelectedQuestions(questions: Array<ID>) {
|
|
|
console.log(questions)
|
|
|
this.selectedQuestions = questions
|
|
|
@@ -298,32 +278,39 @@ export default Vue.extend({
|
|
|
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
|
|
|
},
|
|
|
onCreateExam() {
|
|
|
+ // if (!this.$refs.form.validate()) {
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+ console.log(this.valid)
|
|
|
+
|
|
|
const obj = {
|
|
|
- creatorId: 'userId1',
|
|
|
+ creatorId: this.getId(),
|
|
|
examName: this.examName,
|
|
|
position: this.position,
|
|
|
skills: this.skills,
|
|
|
difficulty: this.difficulty,
|
|
|
startTime: this.startDateFormatted + ' ' + this.startTime + ':00',
|
|
|
- endTime: this.endDateFormatted + ' ' + this.endTime + ':00',
|
|
|
+ endTime: this.computedExamEndTime,
|
|
|
comment: this.comment,
|
|
|
antiCheating: this.antiCheating
|
|
|
} as ExamSerializer
|
|
|
- console.log('创建考试', obj)
|
|
|
+ console.log('创建评测', obj)
|
|
|
createExam(obj).then(({ data }) => {
|
|
|
- console.log(data.result)
|
|
|
- this.isExamCreated = data.result ? true : false
|
|
|
- this.createdExamInfo = obj
|
|
|
+ this.isExamCreated = !!data.result
|
|
|
+ const examId = data.result.examId
|
|
|
+ this.$router.push({
|
|
|
+ name: 'edit-exams',
|
|
|
+ params: {
|
|
|
+ examId: examId.toString()
|
|
|
+ }
|
|
|
+ })
|
|
|
})
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
|
- this.startDateFormatted = this.formatDate(
|
|
|
- new Date().toISOString().substr(0, 10)
|
|
|
- )
|
|
|
- this.endDateFormatted = this.formatDate(
|
|
|
- new Date().toISOString().substr(0, 10)
|
|
|
- )
|
|
|
+ this.startDateFormatted = dayjs()
|
|
|
+ .format(this.timeFormat)
|
|
|
+ .substr(0, 10)
|
|
|
}
|
|
|
})
|
|
|
</script>
|