Bladeren bron

[修改]文档作业和代码作业重复代码抽出

Johnson 7 jaren geleden
bovenliggende
commit
165610baee

+ 24 - 22
mock/modules/assignment/index.js

@@ -11,7 +11,7 @@ const groupSerializer = require("../../serializers/course/GroupSerializer");
 //新建代码作业
 router.route("/course/:courseId/code").post((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: CodeSerializer()
   });
 });
@@ -21,14 +21,14 @@ router
   //更新代码作业信息
   .put((req, res) => {
     res.send({
-      err: 0,
+      code: 0,
       data: CodeSerializer()
     });
   })
   //删除代码作业
   .delete((req, res) => {
     res.send({
-      err: 0,
+      code: 0,
       data: {}
     });
   });
@@ -36,7 +36,7 @@ router
 //老师查看代码作业列表
 router.route("/teacher/course/:courseId/code").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [CodeSerializer(), CodeSerializer()]
   });
 });
@@ -44,7 +44,7 @@ router.route("/teacher/course/:courseId/code").get((req, res) => {
 //学生查看代码作业列表
 router.route("/student/course/:courseId/code").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [CodeSerializer(), CodeSerializer()]
   });
 });
@@ -52,7 +52,7 @@ router.route("/student/course/:courseId/code").get((req, res) => {
 //学生查看单个代码作业
 router.route("/student/code/:codeId").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: CodeSerializer()
   });
 });
@@ -60,7 +60,7 @@ router.route("/student/code/:codeId").get((req, res) => {
 //学生查看单个代码作业下的项目信息列表
 router.route("/student/code/:codeId/project").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [ProjectSerializer(), ProjectSerializer()]
   });
 });
@@ -68,7 +68,7 @@ router.route("/student/code/:codeId/project").get((req, res) => {
 //老师查看单个代码作业下所有已提交组的过程统计信息
 router.route("/teacher/code/:codeId/submitted/procedure").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [codeProcedureSerializer(), codeProcedureSerializer()]
   });
 });
@@ -76,7 +76,7 @@ router.route("/teacher/code/:codeId/submitted/procedure").get((req, res) => {
 //老师查看单个代码作业下所有未提交组的信息
 router.route("/teacher/code/:codeId/unsubmitted/groups").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [groupSerializer(), groupSerializer()]
   });
 });
@@ -84,7 +84,7 @@ router.route("/teacher/code/:codeId/unsubmitted/groups").get((req, res) => {
 //老师查看单个代码作业的成绩列表(所有组的)
 router.route("/teacher/code/:codeId/result").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [CodeResultSerializer, CodeResultSerializer]
   });
 });
@@ -92,7 +92,7 @@ router.route("/teacher/code/:codeId/result").get((req, res) => {
 //学生查看单个代码作业的成绩
 router.route("/student/code/:codeId/result").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: CodeResultSerializer
   });
 });
@@ -101,7 +101,7 @@ router.route("/student/code/:codeId/result").get((req, res) => {
 //新建文档作业
 router.route("/course/:courseId/document").post((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: DocumentSerializer()
   });
 });
@@ -111,14 +111,14 @@ router
   //更新文档作业信息
   .put((req, res) => {
     res.send({
-      err: 0,
+      code: 0,
       data: DocumentSerializer()
     });
   })
   //删除文档作业
   .delete((req, res) => {
     res.send({
-      err: 0,
+      code: 0,
       data: {}
     });
   });
@@ -126,7 +126,7 @@ router
 //老师查看文档作业列表
 router.route("/teacher/course/:courseId/document").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [DocumentSerializer(), DocumentSerializer()]
   });
 });
@@ -134,7 +134,7 @@ router.route("/teacher/course/:courseId/document").get((req, res) => {
 //学生查看文档作业列表
 router.route("/student/course/:courseId/document").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: [DocumentSerializer(), DocumentSerializer()]
   });
 });
@@ -142,7 +142,7 @@ router.route("/student/course/:courseId/document").get((req, res) => {
 //学生查看单个文档作业信息
 router.route("/student/document/:documentId").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: DocumentSerializer()
   });
 });
@@ -152,9 +152,11 @@ router
   .route("/teacher/document/:documentId/submitted/result")
   .get((req, res) => {
     res.send({
-      err: 0,
-      status: "正在互评",
-      data: [DocumentResultSerializer(), DocumentResultSerializer()]
+      code: 0,
+      data: {
+        status: "正在互评",
+        result: [DocumentResultSerializer(), DocumentResultSerializer()]
+      }
     });
   });
 
@@ -163,7 +165,7 @@ router
   .route("/teacher/document/:documentId/unsubmitted/groups")
   .get((req, res) => {
     res.send({
-      err: 0,
+      code: 0,
       data: [groupSerializer(), groupSerializer()]
     });
   });
@@ -171,7 +173,7 @@ router
 //学生查看文档作业的成绩
 router.route("/student/document/:documentId/result").get((req, res) => {
   res.send({
-    err: 0,
+    code: 0,
     data: DocumentResultSerializer()
   });
 });

+ 1 - 1
src/api/assignment.js

@@ -240,7 +240,7 @@ export const getDocResultById = documentId => {
 /**
  * 老师查看文档作业的成绩列表(已提交小组)
  * @param documentId
- * @returns {Promise<{data:DocumentResultSerializerType}>}
+ * @returns {Promise<{data:DocumentResultSerializerType[]}>}
  */
 export const getSubmittedDocResultListByDocId = documentId => {
   return request(

+ 8 - 7
src/views/teacher/Code/index.vue

@@ -5,7 +5,7 @@
         代码作业列表
       </template>
       <template slot="content">
-        共有{{ codeData.length }}份作业
+        共有 {{ codeData.length }} 份作业
       </template>
       <template slot="action">
         <b-field>
@@ -87,6 +87,7 @@
                 :value="searchContent"
                 v-model="$v.params.problem.$model"
                 expanded
+                @keyup.enter.native="search(searchContent)"
               >
               </b-input>
               <p class="control">
@@ -273,7 +274,7 @@ export default {
         onConfirm: () => {
           delCodeAssignment(id).then(res => {
             console.log(res);
-            if (res.err === 0) {
+            if (res.code === 0) {
               //删除成功
               for (let item of this.codeData) {
                 if (item.id === id) {
@@ -284,7 +285,7 @@ export default {
             } else {
               this.$dialog.alert({
                 title: "删除失败",
-                message: res.msg,
+                message: res.message,
                 type: "is-danger",
                 hasIcon: true,
                 icon: "times-circle",
@@ -337,7 +338,7 @@ export default {
           this.params["type"] = "DOCUMENT";
           postCodeAssignment(this.params, this.course.id).then(res => {
             console.log(res);
-            if (res.err === 0) {
+            if (res.code === 0) {
               //创建成功
               this.codeData.push(res.data);
               this.$router.push({
@@ -347,7 +348,7 @@ export default {
               //创建失败
               this.$dialog.alert({
                 title: "创建失败",
-                message: res.msg,
+                message: res.message,
                 type: "is-danger",
                 hasIcon: true,
                 icon: "times-circle",
@@ -358,7 +359,7 @@ export default {
         } else {
           // 确认修改作业
           putCodeAssignment(this.params, codeId).then(res => {
-            if (res.err === 0) {
+            if (res.code === 0) {
               let id = res.data.id;
               for (let item of this.codeData) {
                 if (item.id === id) {
@@ -370,7 +371,7 @@ export default {
             } else {
               this.$dialog.alert({
                 title: "修改失败",
-                message: res.msg,
+                message: res.message,
                 type: "is-danger",
                 hasIcon: true,
                 icon: "times-circle",

+ 340 - 0
src/views/teacher/Document/components/CreateAssignment/index.vue

@@ -0,0 +1,340 @@
+<template>
+  <div>
+    <a class="button is-link" @click="startCreation()">新建文档作业</a>
+
+    <!--新建文档作业模态框-->
+    <b-modal :active.sync="isCreateModalActive" :width="640" scroll="keep">
+      <div class="card">
+        <div class="title">新建文档作业</div>
+        <div class="content">
+          <b-field label="题目名称">
+            <b-input v-model="problemName"></b-input>
+          </b-field>
+          <b-field
+            label="作业名称"
+            :type="$v.params.name.$error ? 'is-danger' : ''"
+            :message="$v.params.name.$error ? '请填写作业名称' : ''"
+          >
+            <b-input
+              placeholder="请填写作业名称"
+              v-model="$v.params.name.$model"
+            ></b-input>
+          </b-field>
+          <b-field
+            label="作业描述"
+            :type="$v.params.description.$error ? 'is-danger' : ''"
+            :message="$v.params.description.$error ? '请填写作业描述' : ''"
+          >
+            <b-input
+              type="textarea"
+              placeholder="请填写作业描述"
+              v-model="$v.params.description.$model"
+            ></b-input>
+          </b-field>
+          <b-field
+            label="开始时间"
+            :type="$v.params.startAt.$error ? 'is-danger' : ''"
+            :message="$v.params.startAt.$error ? '请填写作业开始时间' : ''"
+          >
+            <flat-pickr
+              placeholder="Click to select..."
+              class="input"
+              v-model="$v.params.startAt.$model"
+              :config="startAtConfig"
+            ></flat-pickr>
+          </b-field>
+          <b-field
+            label="结束时间"
+            :type="$v.params.endAt.$error ? 'is-danger' : ''"
+            :message="$v.params.endAt.$error ? '请填写作业结束时间' : ''"
+          >
+            <flat-pickr
+              placeholder="Click to select..."
+              class="input"
+              v-model="$v.params.endAt.$model"
+              :config="endAtConfig"
+            ></flat-pickr>
+          </b-field>
+
+          <a class="button is-link" @click="createAssignment()"> 确认新建 </a>
+        </div>
+      </div>
+    </b-modal>
+
+    <!--搜索题目模态框-->
+    <b-modal :active.sync="isSearchModalActive">
+      <div class="card">
+        <div class="title">请先查找题目</div>
+        <div class="content">
+          <b-field
+            :type="$v.searchContent.$error ? 'is-danger' : ''"
+            :message="$v.params.endAt.$error ? '' : ''"
+          >
+            <b-input
+              placeholder="输入关键字模糊查找"
+              type="search"
+              v-model="$v.searchContent.$model"
+              expanded
+            >
+              <b-loading
+                :is-full-page="false"
+                :active.sync="isLoading"
+              ></b-loading>
+            </b-input>
+            <p class="control">
+              <button class="button is-link" @click="search(searchContent)">
+                查找
+              </button>
+            </p>
+          </b-field>
+        </div>
+      </div>
+    </b-modal>
+
+    <!--题目列表展示框-->
+    <b-modal :active.sync="isProblemListModalActive">
+      <div class="card">
+        <div class="title">点击选择题目</div>
+        <div class="content">
+          <div class="question-list">
+            <b-table :data="questions" detailed detail-key="id">
+              <template slot-scope="props">
+                <b-table-column
+                  field="id"
+                  label="ID"
+                  width="40"
+                  numeric
+                  sortable
+                >
+                  {{ props.row.id }}
+                </b-table-column>
+                <b-table-column label="题目名称">
+                  <a @click="selectAndCreate(props.row)">{{
+                    props.row.name
+                  }}</a>
+                </b-table-column>
+
+                <b-table-column label="题目描述" width="100">
+                  <div class="description">{{ props.row.description }}</div>
+                </b-table-column>
+
+                <b-table-column
+                  field="difficulty"
+                  label="题目难度"
+                  sortable
+                  centered
+                >
+                  <span
+                    :class="[
+                      'tag',
+                      `${getDifficultyClass(props.row.difficulty)}`
+                    ]"
+                  >
+                    {{ getDifficultyType(props.row.difficulty) }}
+                  </span>
+                </b-table-column>
+
+                <b-table-column
+                  label="平均时长"
+                  field="expectTime"
+                  sortable
+                  centered
+                >
+                  {{ props.row.expectTime }}分钟
+                </b-table-column>
+              </template>
+
+              <template slot="detail" slot-scope="props">
+                <article class="media">
+                  <div class="media-content">
+                    <div class="content">
+                      <p class="detail-content">{{ props.row.description }}</p>
+                    </div>
+                  </div>
+                </article>
+              </template>
+            </b-table>
+          </div>
+        </div>
+      </div>
+    </b-modal>
+  </div>
+</template>
+
+<script>
+import { getTeacherKeywordQuestions } from "@/api/question";
+import { postDocAssignment } from "@/api/assignment";
+import timeMixins from "@/mixins/time";
+import { required } from "vuelidate/lib/validators";
+import pathMixins from "@/mixins/path";
+import { difficultyType } from "@/data/questionDifficulty";
+import { difficultyClass } from "@/data/questionDifficulty";
+export default {
+  props: {
+    courseId: {
+      type: String
+    }
+  },
+  data() {
+    return {
+      params: {
+        name: null,
+        description: null,
+        startAt: null,
+        endAt: null,
+        problem: null //题目编号
+      },
+      problemName: "",
+      searchContent: "",
+      questions: [],
+      isCreateModalActive: false,
+      isSearchModalActive: false,
+      isProblemListModalActive: false,
+      isLoading: false,
+      startAtConfig: {
+        ...this.getDefaultConfig(),
+        minDate: "today",
+        maxDate: null
+      },
+      endAtConfig: {
+        ...this.getDefaultConfig(),
+        minDate: "today",
+        maxDate: null
+      }
+    };
+  },
+  methods: {
+    /**
+     * 搜索题目
+     * @param content
+     * @return {Promise<void>}
+     */
+    async search(content) {
+      this.$v.searchContent.$touch();
+      if (!this.$v.searchContent.$invalid) {
+        this.isLoading = true;
+        await getTeacherKeywordQuestions(content).then(res => {
+          this.questions = res.data;
+        });
+        this.isLoading = false;
+        this.isSearchModalActive = false;
+        this.isProblemListModalActive = true;
+      }
+    },
+    selectAndCreate(problem) {
+      this.params.problem = problem.id;
+      this.problemName = problem.name;
+      this.isProblemListModalActive = false;
+      this.isCreateModalActive = true;
+    },
+    /**
+     * 准备新建或者修改
+     */
+    startCreation() {
+      this.isSearchModalActive = true;
+    },
+    /**
+     * 确认新建或者修改
+     */
+    createAssignment() {
+      this.$v.params.$touch();
+      if (!this.$v.params.$invalid) {
+        this.isCreateModalActive = false;
+        this.params["type"] = "DOCUMENT";
+        this.parseParams();
+        postDocAssignment(this.params, parseInt(this.courseId)).then(res => {
+          if (res.code === 0) {
+            //创建成功
+            console.log(res.data);
+            this.$emit("sendCreatedAssignment", res.data);
+            this.isCreateModalActive = false;
+            this.$router.push({
+              path: `${this.prefix}/review?documentHwId=${res.data.id}`
+            });
+          } else {
+            //创建失败
+            this.$dialog.alert({
+              title: "创建失败",
+              message: res.message,
+              type: "is-danger",
+              hasIcon: true
+            });
+          }
+        });
+      } else {
+        console.log("参数太少");
+      }
+    },
+    getDifficultyType(level) {
+      return difficultyType(level);
+    },
+    getDifficultyClass(level) {
+      return difficultyClass(level);
+    },
+    parseParams() {
+      this.params.startAt = parseInt(this.params.startAt);
+      this.params.endAt = parseInt(this.params.endAt);
+    }
+  },
+  mixins: [timeMixins, pathMixins],
+  validations: {
+    params: {
+      name: {
+        required
+      },
+      description: {
+        required
+      },
+      startAt: {
+        required
+      },
+      endAt: {
+        required
+      }
+    },
+    searchContent: {
+      required
+    }
+  },
+  watch: {
+    isCreateModalActive(newValue) {
+      if (newValue === false) {
+        this.$v.$reset();
+      }
+    },
+    isSearchModalActive(newValue) {
+      if (newValue === false) {
+        this.$v.searchContent.$reset();
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.card {
+  padding: 30px;
+  .title {
+    font-size: 1.25rem;
+    small {
+      color: gray;
+      font-size: 1rem;
+    }
+  }
+  .content {
+    a {
+      margin-top: 30px;
+      width: 100%;
+    }
+  }
+}
+.description {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+  word-wrap: break-word;
+  word-break: break-all;
+  display: -webkit-box;
+}
+</style>

+ 39 - 0
src/views/teacher/Document/components/DeleteAssignment/index.vue

@@ -0,0 +1,39 @@
+<template>
+  <div><a style="color:#b34141" @click="confirmDelete()">删除</a></div>
+</template>
+
+<script>
+import { delDocAssignment } from "@/api/assignment";
+
+export default {
+  props: {
+    delId: {
+      type: Number
+    }
+  },
+  methods: {
+    confirmDelete() {
+      this.$dialog.confirm({
+        message: "确认删除?",
+        confirmText: "删除",
+        type: "is-danger",
+        onConfirm: () => {
+          delDocAssignment(this.delId).then(res => {
+            if (res.code === 0) {
+              this.$emit("del");
+              this.$toast.open("删除成功");
+            } else {
+              this.$dialog.alert({
+                title: "删除失败",
+                message: `${res.message}`,
+                type: "is-danger",
+                hasIcon: true
+              });
+            }
+          });
+        }
+      });
+    }
+  }
+};
+</script>

+ 174 - 0
src/views/teacher/Document/components/UpdateAssignment/index.vue

@@ -0,0 +1,174 @@
+<template>
+  <div>
+    <a @click="updateInfo()">修改</a>
+    <!--新建文档作业模态框-->
+    <b-modal :active.sync="isUpdateModalActive" :width="640" scroll="keep">
+      <div class="card">
+        <div class="title">修改文档作业</div>
+        <div class="content">
+          <b-field
+            label="作业名称"
+            :type="$v.params.name.$error ? 'is-danger' : ''"
+            :message="$v.params.name.$error ? '请填写作业名称' : ''"
+          >
+            <b-input
+              placeholder="请填写作业名称"
+              v-model="$v.params.name.$model"
+            ></b-input>
+          </b-field>
+          <b-field
+            label="作业描述"
+            :type="$v.params.description.$error ? 'is-danger' : ''"
+            :message="$v.params.description.$error ? '请填写作业描述' : ''"
+          >
+            <b-input
+              type="textarea"
+              placeholder="请填写作业描述"
+              v-model="$v.params.description.$model"
+            ></b-input>
+          </b-field>
+          <b-field
+            label="开始时间"
+            :type="$v.params.startAt.$error ? 'is-danger' : ''"
+            :message="$v.params.startAt.$error ? '请填写作业开始时间' : ''"
+          >
+            <flat-pickr
+              placeholder="Click to select..."
+              class="input"
+              v-model="$v.params.startAt.$model"
+              :config="startAtConfig"
+            ></flat-pickr>
+          </b-field>
+          <b-field
+            label="结束时间"
+            :type="$v.params.endAt.$error ? 'is-danger' : ''"
+            :message="$v.params.endAt.$error ? '请填写作业结束时间' : ''"
+          >
+            <flat-pickr
+              placeholder="Click to select..."
+              class="input"
+              v-model="$v.params.endAt.$model"
+              :config="endAtConfig"
+            ></flat-pickr>
+          </b-field>
+          <a class="button is-link" @click="createDocAssignment()">
+            确认修改
+          </a>
+        </div>
+      </div>
+    </b-modal>
+  </div>
+</template>
+
+<script>
+import timeMixins from "@/mixins/time";
+import { putDocAssignment } from "@/api/assignment";
+import { required } from "vuelidate/lib/validators";
+export default {
+  props: {
+    updateItem: {
+      type: Object
+    }
+  },
+  mixins: [timeMixins],
+  data() {
+    return {
+      isUpdateModalActive: false,
+      params: {
+        name: null,
+        description: null,
+        startAt: null,
+        endAt: null
+      },
+      startAtConfig: {
+        ...this.getDefaultConfig(),
+        minDate: "today",
+        maxDate: null
+      },
+      endAtConfig: {
+        ...this.getDefaultConfig(),
+        minDate: "today",
+        maxDate: null
+      }
+    };
+  },
+  methods: {
+    /**
+     * 准备修改
+     */
+    updateInfo() {
+      this.isUpdateModalActive = true;
+      this.params.name = this.updateItem.name;
+      this.params.description = this.updateItem.description;
+    },
+    /**
+     * 确认修改
+     */
+    createDocAssignment() {
+      this.$v.params.$touch();
+      if (!this.$v.params.$invalid) {
+        this.isUpdateModalActive = false;
+        this.parseParams();
+        putDocAssignment(this.params, this.updateItem.id).then(res => {
+          if (res.code === 0) {
+            this.$emit("updateDocData", res.data);
+          } else {
+            this.$dialog.alert({
+              title: "修改失败",
+              message: res.message,
+              type: "is-danger",
+              hasIcon: true
+            });
+          }
+        });
+      }
+    },
+    parseParams() {
+      this.params.startAt = parseInt(this.params.startAt);
+      this.params.endAt = parseInt(this.params.endAt);
+    }
+  },
+  validations: {
+    params: {
+      name: {
+        required
+      },
+      description: {
+        required
+      },
+      startAt: {
+        required
+      },
+      endAt: {
+        required
+      }
+    }
+  },
+  watch: {
+    isUpdateModalActive(newValue) {
+      if (newValue === false) {
+        this.$v.params.$reset();
+      }
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.card {
+  padding: 30px;
+  .title {
+    font-size: 1.25rem;
+    small {
+      color: gray;
+      font-size: 1rem;
+    }
+  }
+  .content {
+    a {
+      margin-top: 30px;
+      width: 100%;
+    }
+  }
+}
+</style>

+ 7 - 6
src/views/teacher/Document/detail.vue

@@ -7,10 +7,13 @@
       ]"
     >
       <template slot="title">
-        {{ assignmentInfo.name }}
+        {{ assignmentInfo.problem ? assignmentInfo.problem.name : "" }}
       </template>
       <template slot="content">
-        题目描述:{{ assignmentInfo.description }} <br />
+        题目描述:{{
+          assignmentInfo.problem ? assignmentInfo.problem.description : ""
+        }}
+        <br />
         题目进行阶段:{{ status }}
       </template>
     </page-header>
@@ -141,10 +144,9 @@ export default {
   mounted() {
     this.assignmentInfo = this.$route.query.assignmentInfo;
     this.title = this.$route.query.title;
-    console.log(this.assignmentInfo);
     getSubmittedDocResultListByDocId(this.assignmentInfo.id).then(res => {
-      this.status = res.status;
-      this.submittedData = res.data;
+      this.status = res.data.status;
+      this.submittedData = res.data.result;
       this.submitInfo.yes = "已提交:" + this.submittedData.length;
     });
     getUnsubmittedDocGroupsByDocId(this.assignmentInfo.id).then(res => {
@@ -152,7 +154,6 @@ export default {
       this.submitInfo.no = "未提交:" + this.unsubmitedGroups.length;
     });
   },
-
   data() {
     return {
       title: "",

+ 46 - 371
src/views/teacher/Document/index.vue

@@ -5,12 +5,13 @@
         文档作业列表
       </template>
       <template slot="content">
-        共有{{ docData.length }}份作业
+        共有 {{ docData.length }} 份作业
       </template>
       <template slot="action">
-        <b-field>
-          <a class="button is-link" @click="updateInfo(-1)">新建文档作业</a>
-        </b-field>
+        <create-assignment
+          @sendCreatedAssignment="pushNewAssignment($event)"
+          :course-id="course.id"
+        ></create-assignment>
       </template>
     </page-header>
 
@@ -27,7 +28,7 @@
                 :to="{
                   path: `document/${props.row.id}`,
                   query: {
-                    assignmentInfo: props.row.problem,
+                    assignmentInfo: props.row,
                     title: props.row.name
                   }
                 }"
@@ -47,12 +48,16 @@
               {{ displayUnixTime(props.row.endAt) }}
             </b-table-column>
             <b-table-column label="修改" centered>
-              <a @click="updateInfo(props.row.id)">修改</a>
+              <update-assignment
+                :update-item="props.row"
+                v-on:updateDocData="modifyDocData($event)"
+              ></update-assignment>
             </b-table-column>
             <b-table-column label="删除" centered>
-              <a style="color:#b34141" @click="confirmDelete(props.row.id)"
-                >删除</a
-              >
+              <delete-assignment
+                :del-id="props.row.id"
+                @del="deleteAssignment(props.row.id)"
+              ></delete-assignment>
             </b-table-column>
           </template>
 
@@ -71,159 +76,6 @@
         </b-table>
       </div>
     </page-body>
-
-    <!--新建文档作业模态框-->
-    <b-modal :active.sync="isCardModalActive" :width="640" scroll="keep">
-      <div class="card">
-        <div class="title">{{ modal.title }}</div>
-        <div class="content">
-          <b-field label="题目名称" v-if="display">
-            <b-input v-model="$v.problemName.$model"></b-input>
-          </b-field>
-          <b-field
-            label="作业名称"
-            :type="$v.params.name.$error ? 'is-danger' : ''"
-            :message="$v.params.name.$error ? '请填写作业名称' : ''"
-          >
-            <b-input
-              placeholder="请填写作业名称"
-              v-model="$v.params.name.$model"
-            ></b-input>
-          </b-field>
-          <b-field
-            label="作业描述"
-            :type="$v.params.description.$error ? 'is-danger' : ''"
-            :message="$v.params.description.$error ? '请填写作业描述' : ''"
-          >
-            <b-input
-              type="textarea"
-              placeholder="请填写作业描述"
-              v-model="$v.params.description.$model"
-            ></b-input>
-          </b-field>
-          <b-field
-            label="开始时间"
-            :type="$v.params.startAt.$error ? 'is-danger' : ''"
-            :message="$v.params.startAt.$error ? '请填写作业开始时间' : ''"
-          >
-            <flat-pickr
-              placeholder="Click to select..."
-              class="input"
-              v-model="$v.params.startAt.$model"
-              :config="startAtConfig"
-            ></flat-pickr>
-          </b-field>
-          <b-field
-            label="结束时间"
-            :type="$v.params.endAt.$error ? 'is-danger' : ''"
-            :message="$v.params.endAt.$error ? '请填写作业结束时间' : ''"
-          >
-            <flat-pickr
-              placeholder="Click to select..."
-              class="input"
-              v-model="$v.params.endAt.$model"
-              :config="endAtConfig"
-            ></flat-pickr>
-          </b-field>
-
-          <a class="button is-link" @click="createDocAssignment()">
-            {{ modal.submit }}
-          </a>
-        </div>
-      </div>
-    </b-modal>
-
-    <!--选择题目模态框-->
-    <b-modal :active.sync="isProblemModalActive">
-      <div class="card">
-        <div class="title">请先查找题目</div>
-        <div class="content">
-          <b-field :type="$v.searchContent.$error ? 'is-danger' : ''">
-            <b-input
-              placeholder="输入关键字模糊查找"
-              type="search"
-              v-model="$v.searchContent.$model"
-              expanded
-            >
-            </b-input>
-            <p class="control">
-              <button class="button is-link" @click="search(searchContent)">
-                查找
-              </button>
-            </p>
-          </b-field>
-        </div>
-      </div>
-    </b-modal>
-
-    <!--搜索题目展示框-->
-    <b-modal :active.sync="isProblemListModalActive">
-      <div class="card">
-        <div class="title">点击选择题目</div>
-        <div class="content">
-          <div class="question-list">
-            <b-table :data="questions" detailed detail-key="id">
-              <template slot-scope="props">
-                <b-table-column
-                  field="id"
-                  label="ID"
-                  width="40"
-                  numeric
-                  sortable
-                >
-                  {{ props.row.id }}
-                </b-table-column>
-
-                <b-table-column label="题目名称">
-                  <a @click="selectAndCreate(props.row)">{{
-                    props.row.name
-                  }}</a>
-                </b-table-column>
-
-                <b-table-column label="题目描述" width="400">
-                  <div class="description">{{ props.row.description }}</div>
-                </b-table-column>
-
-                <b-table-column
-                  field="difficulty"
-                  label="题目难度"
-                  sortable
-                  centered
-                >
-                  <span
-                    :class="[
-                      'tag',
-                      `${getDifficultyClass(props.row.difficulty)}`
-                    ]"
-                  >
-                    {{ getDifficultyType(props.row.difficulty) }}
-                  </span>
-                </b-table-column>
-
-                <b-table-column
-                  label="平均时长"
-                  field="expectTime"
-                  sortable
-                  centered
-                >
-                  {{ props.row.expectTime }}分钟
-                </b-table-column>
-              </template>
-
-              <template slot="detail" slot-scope="props">
-                <article class="media">
-                  <div class="media-content">
-                    <div class="content">
-                      <p class="detail-content">{{ props.row.description }}</p>
-                    </div>
-                  </div>
-                </article>
-              </template>
-            </b-table>
-          </div>
-        </div>
-      </div>
-    </b-modal>
   </div>
 </template>
 
@@ -231,16 +83,11 @@
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
 import { getDocAssignmentListTeacherByCrs } from "@/api/assignment";
-import { getTeacherKeywordQuestions } from "@/api/question";
-import { postDocAssignment } from "@/api/assignment";
-import { putDocAssignment } from "@/api/assignment";
-import { delDocAssignment } from "@/api/assignment";
 import timeMixins from "@/mixins/time";
-import { required } from "vuelidate/lib/validators";
-import pathMixins from "@/mixins/path";
 import { mapState } from "vuex";
-import { difficultyType } from "@/data/questionDifficulty";
-import { difficultyClass } from "@/data/questionDifficulty";
+import DeleteAssignment from "./components/DeleteAssignment";
+import UpdateAssignment from "./components/UpdateAssignment";
+import CreateAssignment from "./components/CreateAssignment";
 
 export default {
   computed: {
@@ -250,9 +97,12 @@ export default {
   },
   components: {
     PageBody,
-    PageHeader
+    PageHeader,
+    DeleteAssignment,
+    UpdateAssignment,
+    CreateAssignment
   },
-  mixins: [timeMixins, pathMixins],
+  mixins: [timeMixins],
   mounted() {
     getDocAssignmentListTeacherByCrs(this.course.id).then(res => {
       this.docData = res.data;
@@ -260,213 +110,29 @@ export default {
   },
   data() {
     return {
-      problemName: "",
-      searchContent: "",
-      questions: [],
-      docData: [],
-      params: {
-        name: null,
-        description: null,
-        startAt: null,
-        endAt: null,
-        problem: null //题目编号
-      },
-      // 返回的文档作业信息
-      isCardModalActive: false,
-      isProblemModalActive: false,
-      isProblemListModalActive: false,
-      modal: {
-        title: "新建文档作业",
-        submit: "确认创建"
-      },
-      flag: -1, //区分创建还是修改
-      display: false, //展示新建题目的名称
-      startAtConfig: {
-        ...this.getDefaultConfig(),
-        minDate: "today",
-        maxDate: null
-      },
-      endAtConfig: {
-        ...this.getDefaultConfig(),
-        minDate: "today",
-        maxDate: null
-      }
+      docData: []
     };
   },
-
   methods: {
-    /**
-     * 搜索题目
-     * @param content
-     * @return {Promise<void>}
-     */
-    async searchAssis(content) {
-      await getTeacherKeywordQuestions(content).then(res => {
-        this.questions = res.data;
-      });
-    },
-    search(content) {
-      this.searchAssis(content).then(() => {
-        this.isProblemModalActive = false;
-        this.isProblemListModalActive = true;
-      });
+    pushNewAssignment(item) {
+      this.docData.push(item);
     },
-    selectAndCreate(problem) {
-      console.log(problem);
-      this.modal.title = "新建文档作业";
-      this.modal.submit = "确认创建";
-      this.params.problem = problem.id;
-      this.isProblemListModalActive = false;
-      this.display = true;
-      this.isCardModalActive = true;
-      this.problemName = problem.name;
-    },
-
-    /**
-     * 确定删除(模块正常)
-     * @param id
-     */
-    confirmDelete(id) {
-      this.$dialog.confirm({
-        message: "确认删除?",
-        confirmText: "删除",
-        type: "is-danger",
-        onConfirm: () => {
-          delDocAssignment(id).then(res => {
-            if (res.err === 0) {
-              //删除成功
-              for (let item of this.docData) {
-                if (item.id === id) {
-                  this.docData.pop(item);
-                }
-              }
-              this.$toast.open("删除成功");
-            } else {
-              this.$dialog.alert({
-                title: "删除失败",
-                message: `${res.msg}`,
-                type: "is-danger",
-                hasIcon: true
-              });
-            }
-          });
-        }
-      });
-    },
-    /**
-     * 准备新建或者修改
-     * @param id
-     */
-    updateInfo(id) {
-      if (id === -1) {
-        // 准备新建
-        this.isProblemModalActive = true;
-        this.flag = -1;
-      } else {
-        this.isCardModalActive = true;
-        this.display = false;
-        // 准备修改
-        this.modal.title = "修改文档作业";
-        this.modal.submit = "确认修改";
-        for (let item of this.docData) {
-          if (item.id === id) {
-            this.params.name = item.name;
-            this.params.description = item.description;
-            break;
-          }
+    modifyDocData(modifiedItem) {
+      let length = this.docData.length;
+      for (let i = 0; i < length; i++) {
+        if (modifiedItem.id === this.docData[i].id) {
+          this.docData.splice(i, 1, modifiedItem);
+          break;
         }
-        this.flag = 0;
       }
     },
-    /**
-     * 确认新建或者修改
-     */
-    createDocAssignment(dd) {
-      console.log(dd);
-      this.$v.$touch();
-      if (!this.$v.params.$invalid) {
-        this.isCardModalActive = false;
-        if (this.flag === -1) {
-          // 确认新建作业
-          this.params["type"] = "DOCUMENT";
-          postDocAssignment(this.params, this.course.id).then(res => {
-            if (res.err === 0) {
-              //创建成功
-              this.docData.push(res.data);
-              this.$router.push({
-                path: `${this.prefix}/review?documentHwId=${res.data.id}`
-              });
-            } else {
-              //创建失败
-              this.$dialog.alert({
-                title: "创建失败",
-                message: res.msg,
-                type: "is-danger",
-                hasIcon: true
-              });
-            }
-          });
-        } else {
-          // 确认修改作业
-          putDocAssignment(this.params).then(res => {
-            if (res.err === 0) {
-              let id = res.data.id;
-              for (let item of this.docData) {
-                if (item.id === id) {
-                  item = res.data;
-                  break;
-                }
-              }
-            } else {
-              this.$dialog.alert({
-                title: "修改失败",
-                message: res.msg,
-                type: "is-danger",
-                hasIcon: true
-              });
-            }
-          });
+    deleteAssignment(delId) {
+      let length = this.docData.length;
+      for (let i = 0; i < length; i++) {
+        if (this.docData[i].id === delId) {
+          this.docData.splice(i, 1);
+          break;
         }
-      } else {
-        console.log("无效");
-      }
-    },
-    getDifficultyType(level) {
-      return difficultyType(level);
-    },
-    getDifficultyClass(level) {
-      return difficultyClass(level);
-    }
-  },
-  validations: {
-    params: {
-      name: {
-        required
-      },
-      description: {
-        required
-      },
-      startAt: {
-        required
-      },
-      endAt: {
-        required
-      }
-      // problem: {
-      //   required
-      // }
-    },
-    problemName: {
-      required
-    },
-    searchContent: {
-      required
-    }
-  },
-  watch: {
-    isCardModalActive(newValue) {
-      if (newValue === false) {
-        this.$v.$reset();
       }
     }
   }
@@ -490,4 +156,13 @@ export default {
     }
   }
 }
+.description {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  -webkit-box-orient: vertical;
+  -webkit-line-clamp: 1;
+  word-wrap: break-word;
+  word-break: break-all;
+  display: -webkit-box;
+}
 </style>

+ 0 - 1
vue.config.js

@@ -3,7 +3,6 @@ module.exports = {
     proxy: {
       "^/api": {
         target: "http://localhost:4000/",
-        // target: "http://172.19.131.216:8080/",
         // target: "http://10.1.2.3:8080/",
         ws: true,
         changeOrigin: true