|
|
@@ -2,7 +2,6 @@
|
|
|
<el-row id="manage-page-body">
|
|
|
<el-col :span="3">
|
|
|
<el-card style="position: fixed;">
|
|
|
-<<<<<<< HEAD
|
|
|
<el-menu default-active="1" @select="handleSelect">
|
|
|
<el-menu-item index="0">
|
|
|
<el-icon>
|
|
|
@@ -29,34 +28,6 @@
|
|
|
<span style="padding-left: 20px">全部题目</span>
|
|
|
</el-menu-item>
|
|
|
</el-menu>
|
|
|
-=======
|
|
|
- <el-menu default-active="1" @select="handleSelect">
|
|
|
- <el-menu-item index="0">
|
|
|
- <el-icon>
|
|
|
- <Back/>
|
|
|
- </el-icon>
|
|
|
- <span style="padding-left: 20px">返回首页</span>
|
|
|
- </el-menu-item>
|
|
|
- <el-menu-item index="1">
|
|
|
- <el-icon>
|
|
|
- <Document/>
|
|
|
- </el-icon>
|
|
|
- <span style="padding-left: 20px">全部课程</span>
|
|
|
- </el-menu-item>
|
|
|
- <el-menu-item index="2">
|
|
|
- <el-icon>
|
|
|
- <DocumentChecked/>
|
|
|
- </el-icon>
|
|
|
- <span style="padding-left: 20px">全部测试</span>
|
|
|
- </el-menu-item>
|
|
|
- <el-menu-item index="3">
|
|
|
- <el-icon>
|
|
|
- <DocumentChecked/>
|
|
|
- </el-icon>
|
|
|
- <span style="padding-left: 20px">全部题目</span>
|
|
|
- </el-menu-item>
|
|
|
- </el-menu>
|
|
|
->>>>>>> efe3831aac9edd6d113ed30d273ebeb3776bb381
|
|
|
</el-card>
|
|
|
</el-col>
|
|
|
<el-col :span="1"/>
|
|
|
@@ -70,10 +41,10 @@
|
|
|
<div class="course-type-selector">
|
|
|
<el-select v-model="courseType" class="m-2" placeholder="课程类型">
|
|
|
<el-option
|
|
|
- v-for="item in courseTypeOptions"
|
|
|
- :key="item.value"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
+ v-for="item in courseTypeOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
/>
|
|
|
</el-select>
|
|
|
<el-button class="ml-16" plain type="primary"
|
|
|
@@ -182,9 +153,9 @@
|
|
|
<el-table-column label="操作" width="200">
|
|
|
<template #default="scope">
|
|
|
<el-button
|
|
|
- type="primary"
|
|
|
- size="mini"
|
|
|
- @click="checkDetails(scope.row.id)"
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ @click="checkDetails(scope.row.id)"
|
|
|
>
|
|
|
详情
|
|
|
</el-button>
|
|
|
@@ -192,12 +163,12 @@
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
<el-pagination
|
|
|
- background
|
|
|
- layout="prev, pager, next"
|
|
|
- :current-page="problemPageInfo.page"
|
|
|
- :page-size="problemPageInfo.limit"
|
|
|
- :total="problemPageInfo.total"
|
|
|
- @current-change="changePage"
|
|
|
+ background
|
|
|
+ layout="prev, pager, next"
|
|
|
+ :current-page="problemPageInfo.page"
|
|
|
+ :page-size="problemPageInfo.limit"
|
|
|
+ :total="problemPageInfo.total"
|
|
|
+ @current-change="changePage"
|
|
|
/>
|
|
|
</el-card>
|
|
|
</el-col>
|
|
|
@@ -253,16 +224,16 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="课程图片">
|
|
|
<el-upload
|
|
|
- :before-upload="beforeUpload"
|
|
|
- :file-list="form.fileList"
|
|
|
- :http-request="httpRequest"
|
|
|
- :limit="1"
|
|
|
- :on-change="handleChange"
|
|
|
- :on-exceed="handleExceed"
|
|
|
- :on-remove="handleChange"
|
|
|
- action=""
|
|
|
- class="upload-demo"
|
|
|
- list-type="picture">
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ :file-list="form.fileList"
|
|
|
+ :http-request="httpRequest"
|
|
|
+ :limit="1"
|
|
|
+ :on-change="handleChange"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-remove="handleChange"
|
|
|
+ action=""
|
|
|
+ class="upload-demo"
|
|
|
+ list-type="picture">
|
|
|
<el-button plain size="small" type="primary">点击上传</el-button>
|
|
|
</el-upload>
|
|
|
</el-form-item>
|
|
|
@@ -286,20 +257,20 @@
|
|
|
<el-form-item label="测试种类" prop="type">
|
|
|
<el-select v-model="examForm.examType" class="m-2" placeholder="请选择种类">
|
|
|
<el-option
|
|
|
- v-for="item in examCategoryOptions"
|
|
|
- :key="item.value"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
+ v-for="item in examCategoryOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
/>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item v-if="isCoder" label="所属课程" prop="course">
|
|
|
<el-select v-model="examForm.course" class="m-2" placeholder="请选择课程">
|
|
|
<el-option
|
|
|
- v-for="item in courseOptions"
|
|
|
- :key="item.value"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
+ v-for="item in courseOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
/>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
@@ -325,9 +296,9 @@
|
|
|
<el-form-item v-if="$store.state.problem.cart.length">
|
|
|
<el-collapse accordion>
|
|
|
<el-collapse-item
|
|
|
- v-for="problem in $store.state.problem.cart"
|
|
|
- :key="problem.id"
|
|
|
- :name="problem.id"
|
|
|
+ v-for="problem in $store.state.problem.cart"
|
|
|
+ :key="problem.id"
|
|
|
+ :name="problem.id"
|
|
|
>
|
|
|
<template #title>
|
|
|
<span>{{ problem.name }}</span>
|
|
|
@@ -337,9 +308,9 @@
|
|
|
<span class="problem-description">{{ problem.description }}</span>
|
|
|
<div class="remove-button">
|
|
|
<el-button
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- @click="$store.commit('removeProblem', problem)"
|
|
|
+ type="danger"
|
|
|
+ size="mini"
|
|
|
+ @click="$store.commit('removeProblem', problem)"
|
|
|
>移除该题
|
|
|
</el-button
|
|
|
>
|
|
|
@@ -386,25 +357,25 @@
|
|
|
<el-table-column label="操作" width="200">
|
|
|
<template #default="scope">
|
|
|
<el-button
|
|
|
- type="primary"
|
|
|
- size="mini"
|
|
|
- @click="checkDetails"
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ @click="checkDetails"
|
|
|
>详情
|
|
|
</el-button
|
|
|
>
|
|
|
<el-button
|
|
|
- v-if="removeEnable(scope.row)"
|
|
|
- type="danger"
|
|
|
- size="mini"
|
|
|
- @click="$store.commit('removeProblem', scope.row)"
|
|
|
+ v-if="removeEnable(scope.row)"
|
|
|
+ type="danger"
|
|
|
+ size="mini"
|
|
|
+ @click="$store.commit('removeProblem', scope.row)"
|
|
|
>移出试题清单
|
|
|
</el-button
|
|
|
>
|
|
|
<el-button
|
|
|
- v-else-if="addEnable(scope.row)"
|
|
|
- type="success"
|
|
|
- size="mini"
|
|
|
- @click="$store.commit('addProblem', scope.row)"
|
|
|
+ v-else-if="addEnable(scope.row)"
|
|
|
+ type="success"
|
|
|
+ size="mini"
|
|
|
+ @click="$store.commit('addProblem', scope.row)"
|
|
|
>加入试题清单
|
|
|
</el-button
|
|
|
>
|
|
|
@@ -412,20 +383,20 @@
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
<el-pagination
|
|
|
- background
|
|
|
- layout="prev, pager, next"
|
|
|
- :total="problemPageInfo.total"
|
|
|
- @current-change="changePage"
|
|
|
+ background
|
|
|
+ layout="prev, pager, next"
|
|
|
+ :total="problemPageInfo.total"
|
|
|
+ @current-change="changePage"
|
|
|
/>
|
|
|
</el-dialog>
|
|
|
|
|
|
<el-dialog v-model="uploadFileDialog" :width="1000">
|
|
|
<el-form
|
|
|
- ref="form"
|
|
|
- :model="uploadFileForm"
|
|
|
- label-width="80px"
|
|
|
- :rules="uploadFileRules"
|
|
|
- class="fill-card"
|
|
|
+ ref="form"
|
|
|
+ :model="uploadFileForm"
|
|
|
+ label-width="80px"
|
|
|
+ :rules="uploadFileRules"
|
|
|
+ class="fill-card"
|
|
|
>
|
|
|
<el-form-item label="题目名称" prop="name">
|
|
|
<el-input v-model="uploadFileForm.name"></el-input>
|
|
|
@@ -433,29 +404,29 @@
|
|
|
<el-form-item label="题目类型" prop="type">
|
|
|
<el-select v-model="uploadFileForm.type" placeholder="请选择" value="">
|
|
|
<el-option
|
|
|
- v-for="item in problemTypeOptions"
|
|
|
- :key="item.value"
|
|
|
- :label="item.label"
|
|
|
- :value="item.value"
|
|
|
+ v-for="item in problemTypeOptions"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
></el-option>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="题目描述" prop="description">
|
|
|
<el-input
|
|
|
- v-model="uploadFileForm.description"
|
|
|
- type="textarea"
|
|
|
- :rows="3"
|
|
|
+ v-model="uploadFileForm.description"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
></el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="题目文件" prop="file">
|
|
|
<el-upload
|
|
|
- ref="file"
|
|
|
- action=""
|
|
|
- :auto-upload="false"
|
|
|
- :limit="1"
|
|
|
- accept=".zip"
|
|
|
- :on-change="onFileChange"
|
|
|
- :on-remove="onFileChange"
|
|
|
+ ref="file"
|
|
|
+ action=""
|
|
|
+ :auto-upload="false"
|
|
|
+ :limit="1"
|
|
|
+ accept=".zip"
|
|
|
+ :on-change="onFileChange"
|
|
|
+ :on-remove="onFileChange"
|
|
|
>
|
|
|
<el-button size="small" type="primary">选取</el-button>
|
|
|
</el-upload>
|
|
|
@@ -464,10 +435,10 @@
|
|
|
<div class="form-button">
|
|
|
<el-button type="danger" plain @click="resetForm">重置</el-button>
|
|
|
<el-button
|
|
|
- type="primary"
|
|
|
- :loading="loading"
|
|
|
- :disabled="!uploadFiles.length"
|
|
|
- @click="submitProblem"
|
|
|
+ type="primary"
|
|
|
+ :loading="loading"
|
|
|
+ :disabled="!uploadFiles.length"
|
|
|
+ @click="submitProblem"
|
|
|
>上传
|
|
|
</el-button
|
|
|
>
|
|
|
@@ -480,568 +451,568 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
- import CourseCard from "@/components/CourseCard";
|
|
|
- import {ElMessage, ElMessageBox} from "element-plus";
|
|
|
- import {Back, Document} from "@element-plus/icons-vue";
|
|
|
- import TestCard from "@/components/TestCard";
|
|
|
- import {debounce} from "@/utils/debounce";
|
|
|
- import {formatTimestamp, problemTypeOptions, problemTypeToTagContent} from "@/utils/coder-utils";
|
|
|
- import PageHeader from "@/components/PageHeader";
|
|
|
+import CourseCard from "@/components/CourseCard";
|
|
|
+import {ElMessage, ElMessageBox} from "element-plus";
|
|
|
+import {Back, Document} from "@element-plus/icons-vue";
|
|
|
+import TestCard from "@/components/TestCard";
|
|
|
+import {debounce} from "@/utils/debounce";
|
|
|
+import {formatTimestamp, problemTypeOptions, problemTypeToTagContent} from "@/utils/coder-utils";
|
|
|
+import PageHeader from "@/components/PageHeader";
|
|
|
|
|
|
- export default {
|
|
|
- name: "ManagePage",
|
|
|
- components: {
|
|
|
- PageHeader,
|
|
|
- TestCard,
|
|
|
- Document,
|
|
|
- Back,
|
|
|
- CourseCard,
|
|
|
- },
|
|
|
- data() {
|
|
|
- const validateName = async (rule, value, callback) => {
|
|
|
- const res = await this.$apis.checkCourseNameUnique(this.form.id === null ? -1 : this.form.id, value);
|
|
|
- const isNameUnique = res.data.data;
|
|
|
- if (value === "") {
|
|
|
- callback(new Error("请输入课程名称"));
|
|
|
- } else if (!isNameUnique) {
|
|
|
- callback(new Error("课程名称重复"));
|
|
|
- } else {
|
|
|
- callback();
|
|
|
- }
|
|
|
- };
|
|
|
- const validateTime = (rule, value, callback) => {
|
|
|
- if (this.form.courseTime[0] === null || this.form.courseTime[1] === null) {
|
|
|
- callback(new Error("请选择课程始末时间"));
|
|
|
- } else {
|
|
|
- callback();
|
|
|
- }
|
|
|
- };
|
|
|
- const validateCode = async (rule, value, callback) => {
|
|
|
- const res = await this.$apis.checkCourseCodeUnique(this.form.id === null ? -1 : this.form.id, value);
|
|
|
- const isCodeUnique = res.data.data;
|
|
|
- if (value === "") {
|
|
|
- callback(new Error("请输入课程邀请码"));
|
|
|
- } else if (!isCodeUnique) {
|
|
|
- callback(new Error("课程邀请码重复"));
|
|
|
- } else {
|
|
|
- callback();
|
|
|
- }
|
|
|
- };
|
|
|
- const validatePrice = (rule, value, callback) => {
|
|
|
- let regs = /^(\d+)(\.\d+)?$/;
|
|
|
- if (regs.test(value)) {
|
|
|
- callback();
|
|
|
- } else {
|
|
|
- callback(new Error("请正确输入课程价格"));
|
|
|
- }
|
|
|
- };
|
|
|
- return {
|
|
|
- activeIndex: "1",
|
|
|
- activeTestPaneName: "eval",
|
|
|
- dialogVisible: false,
|
|
|
- dialogExamVisible: false,
|
|
|
- dialogTitle: "新增课程",
|
|
|
- dialogExamTitle: "新增测试",
|
|
|
- form: {
|
|
|
- id: null,
|
|
|
- name: "",
|
|
|
- year: "",
|
|
|
- season: "",
|
|
|
- description: "",
|
|
|
- courseTime: [
|
|
|
- null,
|
|
|
- null,
|
|
|
- ],
|
|
|
- invitationCode: "",
|
|
|
- price: "0",//input均会将Number类型转化成为字符串类型
|
|
|
- moocUrl: null,
|
|
|
- fileList: [],
|
|
|
- imageUrl: null,
|
|
|
- coderLink: false,
|
|
|
- evalLink: false,
|
|
|
+export default {
|
|
|
+ name: "ManagePage",
|
|
|
+ components: {
|
|
|
+ PageHeader,
|
|
|
+ TestCard,
|
|
|
+ Document,
|
|
|
+ Back,
|
|
|
+ CourseCard,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ const validateName = async (rule, value, callback) => {
|
|
|
+ const res = await this.$apis.checkCourseNameUnique(this.form.id === null ? -1 : this.form.id, value);
|
|
|
+ const isNameUnique = res.data.data;
|
|
|
+ if (value === "") {
|
|
|
+ callback(new Error("请输入课程名称"));
|
|
|
+ } else if (!isNameUnique) {
|
|
|
+ callback(new Error("课程名称重复"));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const validateTime = (rule, value, callback) => {
|
|
|
+ if (this.form.courseTime[0] === null || this.form.courseTime[1] === null) {
|
|
|
+ callback(new Error("请选择课程始末时间"));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const validateCode = async (rule, value, callback) => {
|
|
|
+ const res = await this.$apis.checkCourseCodeUnique(this.form.id === null ? -1 : this.form.id, value);
|
|
|
+ const isCodeUnique = res.data.data;
|
|
|
+ if (value === "") {
|
|
|
+ callback(new Error("请输入课程邀请码"));
|
|
|
+ } else if (!isCodeUnique) {
|
|
|
+ callback(new Error("课程邀请码重复"));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const validatePrice = (rule, value, callback) => {
|
|
|
+ let regs = /^(\d+)(\.\d+)?$/;
|
|
|
+ if (regs.test(value)) {
|
|
|
+ callback();
|
|
|
+ } else {
|
|
|
+ callback(new Error("请正确输入课程价格"));
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return {
|
|
|
+ activeIndex: "1",
|
|
|
+ activeTestPaneName: "eval",
|
|
|
+ dialogVisible: false,
|
|
|
+ dialogExamVisible: false,
|
|
|
+ dialogTitle: "新增课程",
|
|
|
+ dialogExamTitle: "新增测试",
|
|
|
+ form: {
|
|
|
+ id: null,
|
|
|
+ name: "",
|
|
|
+ year: "",
|
|
|
+ season: "",
|
|
|
+ description: "",
|
|
|
+ courseTime: [
|
|
|
+ null,
|
|
|
+ null,
|
|
|
+ ],
|
|
|
+ invitationCode: "",
|
|
|
+ price: "0",//input均会将Number类型转化成为字符串类型
|
|
|
+ moocUrl: null,
|
|
|
+ fileList: [],
|
|
|
+ imageUrl: null,
|
|
|
+ coderLink: false,
|
|
|
+ evalLink: false,
|
|
|
+ },
|
|
|
+ examForm: {
|
|
|
+ examType: "coder",
|
|
|
+ course: "",
|
|
|
+ name: "",
|
|
|
+ range: [],
|
|
|
+ isCodeAnalysisNeeded: false,
|
|
|
+ isConsoleOutputShownForStu: false
|
|
|
+ },
|
|
|
+ formRules: {
|
|
|
+ name: {
|
|
|
+ required: true, validator: validateName, trigger: "blur",
|
|
|
},
|
|
|
- examForm: {
|
|
|
- examType: "coder",
|
|
|
- course: "",
|
|
|
- name: "",
|
|
|
- range: [],
|
|
|
- isCodeAnalysisNeeded: false,
|
|
|
- isConsoleOutputShownForStu: false
|
|
|
+ year: {
|
|
|
+ required: true, message: "请选择年份", trigger: "blur",
|
|
|
},
|
|
|
- formRules: {
|
|
|
- name: {
|
|
|
- required: true, validator: validateName, trigger: "blur",
|
|
|
- },
|
|
|
- year: {
|
|
|
- required: true, message: "请选择年份", trigger: "blur",
|
|
|
- },
|
|
|
- season: {
|
|
|
- required: true, message: "请选择季节", trigger: "blur",
|
|
|
- },
|
|
|
- description: {
|
|
|
- required: true, message: "请输入课程简介", trigger: "blur",
|
|
|
- },
|
|
|
- time: {
|
|
|
- required: true, validator: validateTime, trigger: "blur",
|
|
|
- },
|
|
|
- invitationCode: {
|
|
|
- required: true, validator: validateCode, trigger: "blur",
|
|
|
- },
|
|
|
- price: {
|
|
|
- required: true, validator: validatePrice, trigger: "blur",
|
|
|
- },
|
|
|
+ season: {
|
|
|
+ required: true, message: "请选择季节", trigger: "blur",
|
|
|
},
|
|
|
- examFormRules: {
|
|
|
- // type: {
|
|
|
- // required: true, message: "请选择测试种类",
|
|
|
- // },
|
|
|
- name: {
|
|
|
- required: true, message: "请输入测试名称", trigger: "blur",
|
|
|
- },
|
|
|
- course: {
|
|
|
- required: true, message: "请选择测试名称",
|
|
|
- },
|
|
|
- range: {
|
|
|
- required: true, message: "请选择测试时间段", trigger: "blur",
|
|
|
- }
|
|
|
+ description: {
|
|
|
+ required: true, message: "请输入课程简介", trigger: "blur",
|
|
|
},
|
|
|
- coderCourses: [],
|
|
|
- courseOptions: [],
|
|
|
-
|
|
|
- switchDisabled: false,
|
|
|
- switchExamDisabled: false,
|
|
|
- //
|
|
|
- myCourseList: [],
|
|
|
- courseType: "all",
|
|
|
- courseTypeOptions: [
|
|
|
- {value: "all", label: "全部课程"},
|
|
|
- {value: "pending", label: "未开始"},
|
|
|
- {value: "start", label: "正在进行"},
|
|
|
- {value: "end", label: "已结束"},
|
|
|
- ],
|
|
|
- evalExamList: [],
|
|
|
- coderExamList: [],
|
|
|
- examType: "all",
|
|
|
- examTypeOptions: [
|
|
|
- {value: "all", label: "全部测试"},
|
|
|
- {value: "pending", label: "未开始"},
|
|
|
- {value: "start", label: "正在进行"},
|
|
|
- {value: "end", label: "已结束"},
|
|
|
- ],
|
|
|
- examCategoryOptions: [
|
|
|
- {value: "eval", label: "评测题"},
|
|
|
- {value: "coder", label: "代码题"},
|
|
|
- ],
|
|
|
- dialogProblemVisible: false,
|
|
|
- dialogProblemPage: 1,
|
|
|
- dialogProblemLimit: 10,
|
|
|
- dialogProblemTypeStr: "",
|
|
|
- dialogProblemName: "",
|
|
|
- problemList: [],
|
|
|
- problemPageInfo: {},
|
|
|
-
|
|
|
- //上传Coder代码题
|
|
|
- uploadFileDialog: false,
|
|
|
- uploadFileForm: {
|
|
|
- name: "",
|
|
|
- type: "",
|
|
|
- description: ""
|
|
|
+ time: {
|
|
|
+ required: true, validator: validateTime, trigger: "blur",
|
|
|
},
|
|
|
- uploadFileRules: {
|
|
|
- name: [{required: true, message: "请输入题目名称", trigger: "blur"}],
|
|
|
- type: [{required: true, message: "请选择题目类型", trigger: "blur"}],
|
|
|
- description: [
|
|
|
- {required: true, message: "请输入题目描述", trigger: "blur"}
|
|
|
- ]
|
|
|
+ invitationCode: {
|
|
|
+ required: true, validator: validateCode, trigger: "blur",
|
|
|
+ },
|
|
|
+ price: {
|
|
|
+ required: true, validator: validatePrice, trigger: "blur",
|
|
|
},
|
|
|
- uploadFiles: [],
|
|
|
- loading: false,
|
|
|
- };
|
|
|
- },
|
|
|
- computed: {
|
|
|
- filterCourses: function () {
|
|
|
- if (this.courseType === "all") return this.myCourseList;
|
|
|
- if (this.courseType === "pending") return this.myCourseList.filter(i => this.state(i) === "NOT_STARTED");
|
|
|
- if (this.courseType === "start") return this.myCourseList.filter(i => this.state(i) === "RUNNING");
|
|
|
- if (this.courseType === "end") return this.myCourseList.filter(i => this.state(i) === "FINISHED");
|
|
|
- else return this.myCourseList;
|
|
|
},
|
|
|
- isCoder() {
|
|
|
- return this.examForm.examType === "coder";
|
|
|
+ examFormRules: {
|
|
|
+ // type: {
|
|
|
+ // required: true, message: "请选择测试种类",
|
|
|
+ // },
|
|
|
+ name: {
|
|
|
+ required: true, message: "请输入测试名称", trigger: "blur",
|
|
|
+ },
|
|
|
+ course: {
|
|
|
+ required: true, message: "请选择测试名称",
|
|
|
+ },
|
|
|
+ range: {
|
|
|
+ required: true, message: "请选择测试时间段", trigger: "blur",
|
|
|
+ }
|
|
|
},
|
|
|
- problemTypeOptions() {
|
|
|
- return problemTypeOptions(true);
|
|
|
- }
|
|
|
+ coderCourses: [],
|
|
|
+ courseOptions: [],
|
|
|
+
|
|
|
+ switchDisabled: false,
|
|
|
+ switchExamDisabled: false,
|
|
|
+ //
|
|
|
+ myCourseList: [],
|
|
|
+ courseType: "all",
|
|
|
+ courseTypeOptions: [
|
|
|
+ {value: "all", label: "全部课程"},
|
|
|
+ {value: "pending", label: "未开始"},
|
|
|
+ {value: "start", label: "正在进行"},
|
|
|
+ {value: "end", label: "已结束"},
|
|
|
+ ],
|
|
|
+ evalExamList: [],
|
|
|
+ coderExamList: [],
|
|
|
+ examType: "all",
|
|
|
+ examTypeOptions: [
|
|
|
+ {value: "all", label: "全部测试"},
|
|
|
+ {value: "pending", label: "未开始"},
|
|
|
+ {value: "start", label: "正在进行"},
|
|
|
+ {value: "end", label: "已结束"},
|
|
|
+ ],
|
|
|
+ examCategoryOptions: [
|
|
|
+ {value: "eval", label: "评测题"},
|
|
|
+ {value: "coder", label: "代码题"},
|
|
|
+ ],
|
|
|
+ dialogProblemVisible: false,
|
|
|
+ dialogProblemPage: 1,
|
|
|
+ dialogProblemLimit: 10,
|
|
|
+ dialogProblemTypeStr: "",
|
|
|
+ dialogProblemName: "",
|
|
|
+ problemList: [],
|
|
|
+ problemPageInfo: {},
|
|
|
+
|
|
|
+ //上传Coder代码题
|
|
|
+ uploadFileDialog: false,
|
|
|
+ uploadFileForm: {
|
|
|
+ name: "",
|
|
|
+ type: "",
|
|
|
+ description: ""
|
|
|
+ },
|
|
|
+ uploadFileRules: {
|
|
|
+ name: [{required: true, message: "请输入题目名称", trigger: "blur"}],
|
|
|
+ type: [{required: true, message: "请选择题目类型", trigger: "blur"}],
|
|
|
+ description: [
|
|
|
+ {required: true, message: "请输入题目描述", trigger: "blur"}
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ uploadFiles: [],
|
|
|
+ loading: false,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ filterCourses: function () {
|
|
|
+ if (this.courseType === "all") return this.myCourseList;
|
|
|
+ if (this.courseType === "pending") return this.myCourseList.filter(i => this.state(i) === "NOT_STARTED");
|
|
|
+ if (this.courseType === "start") return this.myCourseList.filter(i => this.state(i) === "RUNNING");
|
|
|
+ if (this.courseType === "end") return this.myCourseList.filter(i => this.state(i) === "FINISHED");
|
|
|
+ else return this.myCourseList;
|
|
|
},
|
|
|
- mounted() {
|
|
|
- this.$apis.getTeacherCourses().then(res => {
|
|
|
- this.myCourseList = res.data.data;
|
|
|
- });
|
|
|
- this.$apis.getTeacherEvalExamsGroupByCourse().then(res => {
|
|
|
- this.evalExamList = res.data.data;
|
|
|
- });
|
|
|
- this.$apis.getTeacherCoderExamsGroupByCourse().then(res => {
|
|
|
- this.coderExamList = res.data.data;
|
|
|
- });
|
|
|
- this.fetchProblemData();
|
|
|
+ isCoder() {
|
|
|
+ return this.examForm.examType === "coder";
|
|
|
},
|
|
|
- watch: {
|
|
|
- //TODO 防抖!
|
|
|
- dialogProblemName() {
|
|
|
- debounce(this.fetchProblemData, 500);
|
|
|
+ problemTypeOptions() {
|
|
|
+ return problemTypeOptions(true);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.$apis.getTeacherCourses().then(res => {
|
|
|
+ this.myCourseList = res.data.data;
|
|
|
+ });
|
|
|
+ this.$apis.getTeacherEvalExamsGroupByCourse().then(res => {
|
|
|
+ this.evalExamList = res.data.data;
|
|
|
+ });
|
|
|
+ this.$apis.getTeacherCoderExamsGroupByCourse().then(res => {
|
|
|
+ this.coderExamList = res.data.data;
|
|
|
+ });
|
|
|
+ this.fetchProblemData();
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ //TODO 防抖!
|
|
|
+ dialogProblemName() {
|
|
|
+ debounce(this.fetchProblemData, 500);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ formatTimestamp,
|
|
|
+ problemTypeToTagContent,
|
|
|
+ state(courseVO) {
|
|
|
+ const now = new Date();
|
|
|
+ if (new Date(courseVO.endTime) < now) {
|
|
|
+ return "FINISHED";
|
|
|
+ } else if (new Date(courseVO.startTime) > now) {
|
|
|
+ return "NOT_STARTED";
|
|
|
+ } else {
|
|
|
+ return "RUNNING";
|
|
|
}
|
|
|
},
|
|
|
- methods: {
|
|
|
- formatTimestamp,
|
|
|
- problemTypeToTagContent,
|
|
|
- state(courseVO) {
|
|
|
- const now = new Date();
|
|
|
- if (new Date(courseVO.endTime) < now) {
|
|
|
- return "FINISHED";
|
|
|
- } else if (new Date(courseVO.startTime) > now) {
|
|
|
- return "NOT_STARTED";
|
|
|
- } else {
|
|
|
- return "RUNNING";
|
|
|
- }
|
|
|
- },
|
|
|
- handleSelect(index) {
|
|
|
- if (index === "0") {
|
|
|
- this.$router.push("portal");
|
|
|
- }
|
|
|
- if (index === "1") {
|
|
|
- document.getElementById("app").scrollIntoView({behavior: "smooth"});
|
|
|
- }
|
|
|
- if (index === "2") {
|
|
|
- document.querySelector("#manage-page-divider").scrollIntoView({behavior: "smooth"});
|
|
|
- }
|
|
|
- if (index === "3") {
|
|
|
- document.querySelector("#manage-page-divider-3").scrollIntoView({behavior: "smooth"});
|
|
|
- }
|
|
|
- this.activeIndex = index;
|
|
|
- },
|
|
|
- handleFormConfirm() {
|
|
|
- const _this = this;
|
|
|
- _this.$refs.formRef.validate((valid) => {
|
|
|
- if (valid) {
|
|
|
- if (_this.form.id === null) {
|
|
|
- // 首先创建课程
|
|
|
- // 之后上传课程图片
|
|
|
- _this.$apis.createCourse({
|
|
|
- name: _this.form.name,
|
|
|
- teacher: {
|
|
|
- id: _this.$store.state.user.id,
|
|
|
- },
|
|
|
- semester: _this.form.year + _this.form.season,
|
|
|
- imageUrl: null,
|
|
|
- description: _this.form.description,
|
|
|
- startTime: _this.form.courseTime[0],
|
|
|
- endTime: _this.form.courseTime[1],
|
|
|
- invitationCode: _this.form.invitationCode,
|
|
|
- moocUrl: _this.form.moocUrl,
|
|
|
- createdTime: new Date(),
|
|
|
- price: Number(_this.form.price),
|
|
|
- coderId: _this.form.coderLink ? -1 : null,
|
|
|
- evalId: _this.form.evalLink ? -1 : null,
|
|
|
- }).then(async (res) => {
|
|
|
- const createdCourse = res.data.data;
|
|
|
- if (createdCourse) {
|
|
|
- if (_this.form.fileList.length !== 0 && this.form.fileList[0].raw) {
|
|
|
- const imageUrl = (await _this.$apis.uploadCourseImage(createdCourse.name, this.form.fileList[0].raw)).data.data;
|
|
|
- if (imageUrl) {
|
|
|
- createdCourse.imageUrl = imageUrl;
|
|
|
- }
|
|
|
+ handleSelect(index) {
|
|
|
+ if (index === "0") {
|
|
|
+ this.$router.push("portal");
|
|
|
+ }
|
|
|
+ if (index === "1") {
|
|
|
+ document.getElementById("app").scrollIntoView({behavior: "smooth"});
|
|
|
+ }
|
|
|
+ if (index === "2") {
|
|
|
+ document.querySelector("#manage-page-divider").scrollIntoView({behavior: "smooth"});
|
|
|
+ }
|
|
|
+ if (index === "3") {
|
|
|
+ document.querySelector("#manage-page-divider-3").scrollIntoView({behavior: "smooth"});
|
|
|
+ }
|
|
|
+ this.activeIndex = index;
|
|
|
+ },
|
|
|
+ handleFormConfirm() {
|
|
|
+ const _this = this;
|
|
|
+ _this.$refs.formRef.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ if (_this.form.id === null) {
|
|
|
+ // 首先创建课程
|
|
|
+ // 之后上传课程图片
|
|
|
+ _this.$apis.createCourse({
|
|
|
+ name: _this.form.name,
|
|
|
+ teacher: {
|
|
|
+ id: _this.$store.state.user.id,
|
|
|
+ },
|
|
|
+ semester: _this.form.year + _this.form.season,
|
|
|
+ imageUrl: null,
|
|
|
+ description: _this.form.description,
|
|
|
+ startTime: _this.form.courseTime[0],
|
|
|
+ endTime: _this.form.courseTime[1],
|
|
|
+ invitationCode: _this.form.invitationCode,
|
|
|
+ moocUrl: _this.form.moocUrl,
|
|
|
+ createdTime: new Date(),
|
|
|
+ price: Number(_this.form.price),
|
|
|
+ coderId: _this.form.coderLink ? -1 : null,
|
|
|
+ evalId: _this.form.evalLink ? -1 : null,
|
|
|
+ }).then(async (res) => {
|
|
|
+ const createdCourse = res.data.data;
|
|
|
+ if (createdCourse) {
|
|
|
+ if (_this.form.fileList.length !== 0 && this.form.fileList[0].raw) {
|
|
|
+ const imageUrl = (await _this.$apis.uploadCourseImage(createdCourse.name, this.form.fileList[0].raw)).data.data;
|
|
|
+ if (imageUrl) {
|
|
|
+ createdCourse.imageUrl = imageUrl;
|
|
|
}
|
|
|
- _this.myCourseList.push(createdCourse);
|
|
|
- _this.dialogVisible = false;
|
|
|
- _this.clearForm();
|
|
|
- ElMessage.success("新建课程成功");
|
|
|
- } else {
|
|
|
- console.log(res);
|
|
|
}
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 首先更新课程
|
|
|
- // 之后更新课程图片
|
|
|
- _this.$apis.updateCourse({
|
|
|
- id: _this.form.id,
|
|
|
- name: _this.form.name,
|
|
|
- semester: _this.form.year + _this.form.season,
|
|
|
- imageUrl: _this.form.imageUrl,
|
|
|
- description: _this.form.description,
|
|
|
- startTime: _this.form.courseTime[0],
|
|
|
- endTime: _this.form.courseTime[1],
|
|
|
- invitationCode: _this.form.invitationCode,
|
|
|
- moocUrl: _this.form.moocUrl,
|
|
|
- price: Number(_this.form.price),
|
|
|
- }).then(async (res) => {
|
|
|
- const updatedCourse = res.data.data;
|
|
|
- if (updatedCourse) {
|
|
|
- if (_this.form.fileList.length !== 0 && this.form.fileList[0].raw) {
|
|
|
- const imageUrl = (await _this.$apis.uploadCourseImage(updatedCourse.name, this.form.fileList[0].raw)).data.data;
|
|
|
- if (imageUrl) {
|
|
|
- updatedCourse.imageUrl = imageUrl;
|
|
|
- }
|
|
|
+ _this.myCourseList.push(createdCourse);
|
|
|
+ _this.dialogVisible = false;
|
|
|
+ _this.clearForm();
|
|
|
+ ElMessage.success("新建课程成功");
|
|
|
+ } else {
|
|
|
+ console.log(res);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 首先更新课程
|
|
|
+ // 之后更新课程图片
|
|
|
+ _this.$apis.updateCourse({
|
|
|
+ id: _this.form.id,
|
|
|
+ name: _this.form.name,
|
|
|
+ semester: _this.form.year + _this.form.season,
|
|
|
+ imageUrl: _this.form.imageUrl,
|
|
|
+ description: _this.form.description,
|
|
|
+ startTime: _this.form.courseTime[0],
|
|
|
+ endTime: _this.form.courseTime[1],
|
|
|
+ invitationCode: _this.form.invitationCode,
|
|
|
+ moocUrl: _this.form.moocUrl,
|
|
|
+ price: Number(_this.form.price),
|
|
|
+ }).then(async (res) => {
|
|
|
+ const updatedCourse = res.data.data;
|
|
|
+ if (updatedCourse) {
|
|
|
+ if (_this.form.fileList.length !== 0 && this.form.fileList[0].raw) {
|
|
|
+ const imageUrl = (await _this.$apis.uploadCourseImage(updatedCourse.name, this.form.fileList[0].raw)).data.data;
|
|
|
+ if (imageUrl) {
|
|
|
+ updatedCourse.imageUrl = imageUrl;
|
|
|
}
|
|
|
- for (let i = 0; i < _this.myCourseList.length; i++) {
|
|
|
- if (_this.myCourseList[i].id === _this.form.id) {
|
|
|
- _this.myCourseList[i] = updatedCourse;
|
|
|
- }
|
|
|
+ }
|
|
|
+ for (let i = 0; i < _this.myCourseList.length; i++) {
|
|
|
+ if (_this.myCourseList[i].id === _this.form.id) {
|
|
|
+ _this.myCourseList[i] = updatedCourse;
|
|
|
}
|
|
|
- _this.$refs["courseCard" + _this.form.id][0].$props.courseVO = updatedCourse;
|
|
|
- _this.dialogVisible = false;
|
|
|
- _this.clearForm();
|
|
|
- ElMessage.success("更新课程成功");
|
|
|
}
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- handleFormCancel(done) {
|
|
|
- ElMessageBox.confirm("是否确认退出?退出后将不保存表格信息。", "提示", {
|
|
|
- confirmButtonText: "确认退出",
|
|
|
- cancelButtonText: "我再想想",
|
|
|
- type: "warning",
|
|
|
- center: true,
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- this.dialogVisible = false;
|
|
|
- this.clearForm();
|
|
|
- // Zhurui修改,关闭dialog
|
|
|
- done();
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.log(err);
|
|
|
- });
|
|
|
- },
|
|
|
- handleExamCreate() {
|
|
|
- const form = this.$refs.examFormRef;
|
|
|
- form.validate((valid) => {
|
|
|
- if (valid) {
|
|
|
- console.log("validate 成功");
|
|
|
- this.createCoderExam();
|
|
|
- } else {
|
|
|
- console.log("validate 失败了");
|
|
|
- return false;
|
|
|
+ _this.$refs["courseCard" + _this.form.id][0].$props.courseVO = updatedCourse;
|
|
|
+ _this.dialogVisible = false;
|
|
|
+ _this.clearForm();
|
|
|
+ ElMessage.success("更新课程成功");
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
- });
|
|
|
- },
|
|
|
- createCoderExam() {
|
|
|
- //创建Coder考试
|
|
|
- this.$apis.createCoderExam({
|
|
|
- course: this.examForm.course,
|
|
|
- name: this.examForm.name,
|
|
|
- startAt: this.examForm.range[0].getTime() / 1000,
|
|
|
- endAt: this.examForm.range[1].getTime() / 1000,
|
|
|
- problems: this.$store.state.problem.cart.map((item) => item.id),
|
|
|
- isConsoleOutputShownForStu: this.examForm.isConsoleOutputShownForStu
|
|
|
- }).then(_res => {
|
|
|
- this.$store.commit("clearProblem");
|
|
|
- ElMessage.success("创建测试成功!");
|
|
|
- this.dialogExamVisible = false;
|
|
|
- }).catch(_err => {
|
|
|
- console.log(_err);
|
|
|
- ElMessage.warning("创建测试失败!");
|
|
|
- });
|
|
|
- },
|
|
|
- handleExamFormCancel(done) {
|
|
|
- //关闭dialog的提示
|
|
|
- ElMessageBox.confirm("是否确认退出?退出后将不保存表格信息。", "提示", {
|
|
|
- confirmButtonText: "确认退出",
|
|
|
- cancelButtonText: "我再想想",
|
|
|
- type: "warning",
|
|
|
- center: true,
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- this.dialogExamVisible = false;
|
|
|
- // this.clearForm();
|
|
|
- //TODO 清除表格信息
|
|
|
- done();
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- console.log(err);
|
|
|
- });
|
|
|
- },
|
|
|
- showProblemDialog() { //打开弹框,获取初始数据
|
|
|
- this.fetchProblemData();
|
|
|
- this.dialogProblemVisible = true;
|
|
|
- },
|
|
|
- // handleProblemChange(){
|
|
|
- // debounce(fetchProblemData,1000);
|
|
|
- // },
|
|
|
- checkDetails(problemId) {
|
|
|
- this.$router.push(`/problem/${problemId}`);
|
|
|
- },
|
|
|
- fetchProblemData(page = 1) { // 按需获得Coder题目
|
|
|
- this.$apis.retrievePageProblem(page, this.dialogProblemLimit, this.dialogProblemTypeStr, this.dialogProblemName)
|
|
|
- .then(_res => {
|
|
|
- this.problemPageInfo = _res.data.page;
|
|
|
- this.problemList = _res.data.res;
|
|
|
- }).catch(err => {
|
|
|
- console.log(err);
|
|
|
- });
|
|
|
- },
|
|
|
- removeEnable(problem) { //是否可以移除题目
|
|
|
- return this.$store.state.problem.cart.length && this.$store.state.problem.cart
|
|
|
- .map((item) => item.id)
|
|
|
- .includes(problem.id);
|
|
|
- },
|
|
|
- addEnable(problem) { //是否可以添加题目
|
|
|
- return this.$store.getters.isTeacher && problem.modifiedAt;
|
|
|
- },
|
|
|
- changePage(val) {
|
|
|
- this.fetchProblemData(val);
|
|
|
- },
|
|
|
- clearForm() {
|
|
|
- this.form = {
|
|
|
- id: null,
|
|
|
- name: "",
|
|
|
- year: "",
|
|
|
- season: "",
|
|
|
- description: "",
|
|
|
- courseTime: [null, null],
|
|
|
- invitationCode: "",
|
|
|
- price: "0",//input均会将Number类型转化成为字符串类型
|
|
|
- moocUrl: null,
|
|
|
- fileList: [],
|
|
|
- imageUrl: null,
|
|
|
- coderLink: false,
|
|
|
- evalLink: false,
|
|
|
- };
|
|
|
- },
|
|
|
- // el-upload相关的方法
|
|
|
- handleChange(file, fileList) {
|
|
|
- this.form.fileList = fileList;
|
|
|
- },
|
|
|
- handleExceed(files, fileList) {
|
|
|
- ElMessage.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
|
|
|
- },
|
|
|
- httpRequest(event) {
|
|
|
- },
|
|
|
- beforeUpload(file) {
|
|
|
- const isJPG = file.type === "image/jpeg";
|
|
|
- const isLt10M = file.size / 1024 / 1024 < 3;
|
|
|
- const isPNG = file.type === "image/png";
|
|
|
- if (!(isJPG || isPNG)) {
|
|
|
- ElMessage.error("上传头像图片只能是 JPG/PNG 格式!");
|
|
|
- }
|
|
|
- if (!isLt10M) {
|
|
|
- ElMessage.error("上传图片大小不能超过 3MB!");
|
|
|
}
|
|
|
- return (isJPG || isPNG) && isLt10M;
|
|
|
- },
|
|
|
- // update & delete
|
|
|
- beforeUpdateCourse(item) {
|
|
|
- this.form.id = item.id;
|
|
|
- this.form.name = item.name;
|
|
|
- this.form.year = Number(item.semester.substring(0, 4));
|
|
|
- this.form.season = item.semester[4];
|
|
|
- this.form.description = item.description;
|
|
|
- this.form.courseTime[0] = new Date(item.startTime);
|
|
|
- this.form.courseTime[1] = new Date(item.endTime);
|
|
|
- this.form.invitationCode = item.invitationCode;
|
|
|
- this.form.price = String(item.price);
|
|
|
- this.form.moocUrl = item.moocUrl;
|
|
|
- this.form.fileList = item.imageUrl === null ? [] : [{
|
|
|
- name: item.name + "-image.jpg",
|
|
|
- url: item.imageUrl
|
|
|
- }];
|
|
|
- this.form.imageUrl = item.imageUrl;
|
|
|
- this.form.coderLink = item.coderId !== null;
|
|
|
- this.form.evalLink = item.evalId !== null;
|
|
|
- this.dialogTitle = "修改课程";
|
|
|
- this.switchDisabled = true;
|
|
|
- this.dialogVisible = true;
|
|
|
- },
|
|
|
- deleteCourse(item) {
|
|
|
- if (item.state === "EXAMPLE") {
|
|
|
- ElMessage.error("无法删除示例课程");
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleFormCancel(done) {
|
|
|
+ ElMessageBox.confirm("是否确认退出?退出后将不保存表格信息。", "提示", {
|
|
|
+ confirmButtonText: "确认退出",
|
|
|
+ cancelButtonText: "我再想想",
|
|
|
+ type: "warning",
|
|
|
+ center: true,
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ this.dialogVisible = false;
|
|
|
+ this.clearForm();
|
|
|
+ // Zhurui修改,关闭dialog
|
|
|
+ done();
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleExamCreate() {
|
|
|
+ const form = this.$refs.examFormRef;
|
|
|
+ form.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ console.log("validate 成功");
|
|
|
+ this.createCoderExam();
|
|
|
} else {
|
|
|
- ElMessageBox.confirm(
|
|
|
- "确定删除课程",
|
|
|
- "Warning",
|
|
|
- {
|
|
|
- confirmButtonText: "立即删除",
|
|
|
- cancelButtonText: "让我想想",
|
|
|
- type: "warning",
|
|
|
- center: true,
|
|
|
- }
|
|
|
- )
|
|
|
- .then(() => {
|
|
|
- this.$apis.deleteCourse(item.id)
|
|
|
- .then(res => {
|
|
|
- for (let i = 0; i < this.myCourseList.length; i++) {
|
|
|
- if (this.myCourseList[i].id === item.id) {
|
|
|
- this.myCourseList.splice(i, 1);
|
|
|
- }
|
|
|
- }
|
|
|
- ElMessage.success(res.data.data);
|
|
|
- });
|
|
|
- })
|
|
|
- .catch(() => {
|
|
|
- ElMessage({
|
|
|
- type: "info",
|
|
|
- message: "取消删除",
|
|
|
- });
|
|
|
- });
|
|
|
+ console.log("validate 失败了");
|
|
|
+ return false;
|
|
|
}
|
|
|
- },
|
|
|
- handleProblemCreate() {
|
|
|
- alert("创建Coder题目");
|
|
|
- },
|
|
|
- uploadFile() {
|
|
|
- this.uploadFileDialog = true;
|
|
|
- },
|
|
|
- onFileChange(fileList) {
|
|
|
- console.log(fileList);
|
|
|
- this.uploadFiles.push(fileList);
|
|
|
- },
|
|
|
- resetForm() {
|
|
|
- const form = this.$refs.form;
|
|
|
- form.resetFields();
|
|
|
- const file = this.$refs.file;
|
|
|
- file.clearFiles();
|
|
|
- this.uploadFiles = [];
|
|
|
- },
|
|
|
- submitProblem() {
|
|
|
- const form = this.$refs.form;
|
|
|
- form.validate((valid) => {
|
|
|
- if (valid) {
|
|
|
- this.uploadProblem();
|
|
|
- } else {
|
|
|
- return false;
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- uploadProblem() {
|
|
|
- this.loading = true;
|
|
|
- const body = new FormData();
|
|
|
- const meta = new Blob([JSON.stringify(this.uploadFileForm)], {
|
|
|
- type: "application/json",
|
|
|
- });
|
|
|
- body.append("meta", meta);
|
|
|
- body.append("data", this.uploadFiles[0].raw);
|
|
|
- this.$apis.createCoderProblem(body)
|
|
|
- .then((data) => {
|
|
|
- ElMessage.success("创建Coder代码题成功");
|
|
|
- this.loading = false;
|
|
|
- this.uploadFileDialog = false;
|
|
|
- // this.problemList.push()
|
|
|
- // this.$nuxt.$router.push("/problem/" + data.res?.id);
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- this.$message.error({
|
|
|
- message: errorMessage(err),
|
|
|
- center: true
|
|
|
+ });
|
|
|
+ },
|
|
|
+ createCoderExam() {
|
|
|
+ //创建Coder考试
|
|
|
+ this.$apis.createCoderExam({
|
|
|
+ course: this.examForm.course,
|
|
|
+ name: this.examForm.name,
|
|
|
+ startAt: this.examForm.range[0].getTime() / 1000,
|
|
|
+ endAt: this.examForm.range[1].getTime() / 1000,
|
|
|
+ problems: this.$store.state.problem.cart.map((item) => item.id),
|
|
|
+ isConsoleOutputShownForStu: this.examForm.isConsoleOutputShownForStu
|
|
|
+ }).then(_res => {
|
|
|
+ this.$store.commit("clearProblem");
|
|
|
+ ElMessage.success("创建测试成功!");
|
|
|
+ this.dialogExamVisible = false;
|
|
|
+ }).catch(_err => {
|
|
|
+ console.log(_err);
|
|
|
+ ElMessage.warning("创建测试失败!");
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleExamFormCancel(done) {
|
|
|
+ //关闭dialog的提示
|
|
|
+ ElMessageBox.confirm("是否确认退出?退出后将不保存表格信息。", "提示", {
|
|
|
+ confirmButtonText: "确认退出",
|
|
|
+ cancelButtonText: "我再想想",
|
|
|
+ type: "warning",
|
|
|
+ center: true,
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ this.dialogExamVisible = false;
|
|
|
+ // this.clearForm();
|
|
|
+ //TODO 清除表格信息
|
|
|
+ done();
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ showProblemDialog() { //打开弹框,获取初始数据
|
|
|
+ this.fetchProblemData();
|
|
|
+ this.dialogProblemVisible = true;
|
|
|
+ },
|
|
|
+ // handleProblemChange(){
|
|
|
+ // debounce(fetchProblemData,1000);
|
|
|
+ // },
|
|
|
+ checkDetails(problemId) {
|
|
|
+ this.$router.push(`/problem/${problemId}`);
|
|
|
+ },
|
|
|
+ fetchProblemData(page = 1) { // 按需获得Coder题目
|
|
|
+ this.$apis.retrievePageProblem(page, this.dialogProblemLimit, this.dialogProblemTypeStr, this.dialogProblemName)
|
|
|
+ .then(_res => {
|
|
|
+ this.problemPageInfo = _res.data.page;
|
|
|
+ this.problemList = _res.data.res;
|
|
|
+ }).catch(err => {
|
|
|
+ console.log(err);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ removeEnable(problem) { //是否可以移除题目
|
|
|
+ return this.$store.state.problem.cart.length && this.$store.state.problem.cart
|
|
|
+ .map((item) => item.id)
|
|
|
+ .includes(problem.id);
|
|
|
+ },
|
|
|
+ addEnable(problem) { //是否可以添加题目
|
|
|
+ return this.$store.getters.isTeacher && problem.modifiedAt;
|
|
|
+ },
|
|
|
+ changePage(val) {
|
|
|
+ this.fetchProblemData(val);
|
|
|
+ },
|
|
|
+ clearForm() {
|
|
|
+ this.form = {
|
|
|
+ id: null,
|
|
|
+ name: "",
|
|
|
+ year: "",
|
|
|
+ season: "",
|
|
|
+ description: "",
|
|
|
+ courseTime: [null, null],
|
|
|
+ invitationCode: "",
|
|
|
+ price: "0",//input均会将Number类型转化成为字符串类型
|
|
|
+ moocUrl: null,
|
|
|
+ fileList: [],
|
|
|
+ imageUrl: null,
|
|
|
+ coderLink: false,
|
|
|
+ evalLink: false,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ // el-upload相关的方法
|
|
|
+ handleChange(file, fileList) {
|
|
|
+ this.form.fileList = fileList;
|
|
|
+ },
|
|
|
+ handleExceed(files, fileList) {
|
|
|
+ ElMessage.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
|
|
|
+ },
|
|
|
+ httpRequest(event) {
|
|
|
+ },
|
|
|
+ beforeUpload(file) {
|
|
|
+ const isJPG = file.type === "image/jpeg";
|
|
|
+ const isLt10M = file.size / 1024 / 1024 < 3;
|
|
|
+ const isPNG = file.type === "image/png";
|
|
|
+ if (!(isJPG || isPNG)) {
|
|
|
+ ElMessage.error("上传头像图片只能是 JPG/PNG 格式!");
|
|
|
+ }
|
|
|
+ if (!isLt10M) {
|
|
|
+ ElMessage.error("上传图片大小不能超过 3MB!");
|
|
|
+ }
|
|
|
+ return (isJPG || isPNG) && isLt10M;
|
|
|
+ },
|
|
|
+ // update & delete
|
|
|
+ beforeUpdateCourse(item) {
|
|
|
+ this.form.id = item.id;
|
|
|
+ this.form.name = item.name;
|
|
|
+ this.form.year = Number(item.semester.substring(0, 4));
|
|
|
+ this.form.season = item.semester[4];
|
|
|
+ this.form.description = item.description;
|
|
|
+ this.form.courseTime[0] = new Date(item.startTime);
|
|
|
+ this.form.courseTime[1] = new Date(item.endTime);
|
|
|
+ this.form.invitationCode = item.invitationCode;
|
|
|
+ this.form.price = String(item.price);
|
|
|
+ this.form.moocUrl = item.moocUrl;
|
|
|
+ this.form.fileList = item.imageUrl === null ? [] : [{
|
|
|
+ name: item.name + "-image.jpg",
|
|
|
+ url: item.imageUrl
|
|
|
+ }];
|
|
|
+ this.form.imageUrl = item.imageUrl;
|
|
|
+ this.form.coderLink = item.coderId !== null;
|
|
|
+ this.form.evalLink = item.evalId !== null;
|
|
|
+ this.dialogTitle = "修改课程";
|
|
|
+ this.switchDisabled = true;
|
|
|
+ this.dialogVisible = true;
|
|
|
+ },
|
|
|
+ deleteCourse(item) {
|
|
|
+ if (item.state === "EXAMPLE") {
|
|
|
+ ElMessage.error("无法删除示例课程");
|
|
|
+ } else {
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ "确定删除课程",
|
|
|
+ "Warning",
|
|
|
+ {
|
|
|
+ confirmButtonText: "立即删除",
|
|
|
+ cancelButtonText: "让我想想",
|
|
|
+ type: "warning",
|
|
|
+ center: true,
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ this.$apis.deleteCourse(item.id)
|
|
|
+ .then(res => {
|
|
|
+ for (let i = 0; i < this.myCourseList.length; i++) {
|
|
|
+ if (this.myCourseList[i].id === item.id) {
|
|
|
+ this.myCourseList.splice(i, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ElMessage.success(res.data.data);
|
|
|
});
|
|
|
- this.loading = false;
|
|
|
- });
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ ElMessage({
|
|
|
+ type: "info",
|
|
|
+ message: "取消删除",
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
},
|
|
|
+ handleProblemCreate() {
|
|
|
+ alert("创建Coder题目");
|
|
|
+ },
|
|
|
+ uploadFile() {
|
|
|
+ this.uploadFileDialog = true;
|
|
|
+ },
|
|
|
+ onFileChange(fileList) {
|
|
|
+ console.log(fileList);
|
|
|
+ this.uploadFiles.push(fileList);
|
|
|
+ },
|
|
|
+ resetForm() {
|
|
|
+ const form = this.$refs.form;
|
|
|
+ form.resetFields();
|
|
|
+ const file = this.$refs.file;
|
|
|
+ file.clearFiles();
|
|
|
+ this.uploadFiles = [];
|
|
|
+ },
|
|
|
+ submitProblem() {
|
|
|
+ const form = this.$refs.form;
|
|
|
+ form.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ this.uploadProblem();
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ uploadProblem() {
|
|
|
+ this.loading = true;
|
|
|
+ const body = new FormData();
|
|
|
+ const meta = new Blob([JSON.stringify(this.uploadFileForm)], {
|
|
|
+ type: "application/json",
|
|
|
+ });
|
|
|
+ body.append("meta", meta);
|
|
|
+ body.append("data", this.uploadFiles[0].raw);
|
|
|
+ this.$apis.createCoderProblem(body)
|
|
|
+ .then((data) => {
|
|
|
+ ElMessage.success("创建Coder代码题成功");
|
|
|
+ this.loading = false;
|
|
|
+ this.uploadFileDialog = false;
|
|
|
+ // this.problemList.push()
|
|
|
+ // this.$nuxt.$router.push("/problem/" + data.res?.id);
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ this.$message.error({
|
|
|
+ message: errorMessage(err),
|
|
|
+ center: true
|
|
|
+ });
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- };
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
- @import "managePage.css";
|
|
|
+@import "managePage.css";
|
|
|
</style>
|