23 次代碼提交 cace91fcfb ... 7a5a268c27

作者 SHA1 備註 提交日期
  Johnson 7a5a268c27 解决冲突 7 年之前
  Johnson 75c7d2aee0 新增老师查看代码作业详情页面 7 年之前
  WuXinyu c81bdb9a0e Merge branch 'hotfix/bay' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into develop 7 年之前
  Kunduin fb0e82715e [FIX] courseId 7 年之前
  Johnson f689f1d316 解决冲突 7 年之前
  Johnson b9769d6d1e fix bug 7 年之前
  WuXinyu 3e25f1726a Merge branch 'develop' of SEEC-II-FrontEnd-Team/SEEC-II-FrontEnd into hotfix/bay 7 年之前
  soleil f5095d0b35 [修改]代码作业-学生 7 年之前
  Kunduin f478fefb0e [FIX] 字数过长换行 7 年之前
  soleil 041edb040e [修改]学生代码作业接口 7 年之前
  Johnson dda47c698d 展示时修改部分代码 7 年之前
  Johnson 06be05973b 修复vue.config.js 7 年之前
  Johnson bf89b2d788 在dev上修改了一些 7 年之前
  kunduin 7a824beed8 [FIX] api bug 7 年之前
  soleil 2f5e156537 [修改]问题全部类型筛选,成绩管理 7 年之前
  soleil 3ee0f281bb [修改]解决控制台courseId报错 7 年之前
  Johnson 7d6338829a Merge branch 'develop' into feature/assignment-zhangyasen 7 年之前
  Johnson 498566fd00 合并周玮璐代码 7 年之前
  soleil 013874a495 Merge branch 'develop' into hotfix/zhouweilu 7 年之前
  soleil 61e3df87e0 [修改] 7 年之前
  soleil eb681748e4 [修改]成绩统计接口、课程细节 7 年之前
  soleil 5695b32a4f [修改]题目页空列表展示、关键字搜索接口、按题目分类查找题目接口 7 年之前
  soleil aa9998b573 [修改]题目模块细节 7 年之前

+ 1 - 1
mock/modules/assignment/index.js

@@ -43,7 +43,7 @@ router.route("/teacher/course/:courseId/code").get((req, res) => {
 });
 
 //老师查看单个代码作业
-router.route("/teacher/:codeId").get((req, res) => {
+router.route("/teacher/code/:codeId").get((req, res) => {
   res.send({
     code: 0,
     data: CodeSerializer()

+ 2 - 2
mock/serializers/assignment/DocumentResultSerializer.js

@@ -23,7 +23,7 @@ module.exports = () => {
     group: groupSerializer(),
     state: "互评中",
     result: "A",
-    url: "https://github.com",
-    reviewGroup: [1, 2, 3]
+    url: "https://github.com"
+    // reviewGroup: [1, 2, 3] 不显示,防止学生之间讨论
   };
 };

+ 1 - 0
src/App.vue

@@ -7,5 +7,6 @@
 
 #app {
   background: $default-background;
+  word-wrap: break-word;
 }
 </style>

+ 2 - 20
src/api/assignment.js

@@ -77,7 +77,7 @@ export const getCodeAssignmentListByTeacher = courseId => {
  * @returns {Promise<{data:CodeSerializerType}>}
  */
 export const getCodeAssignmentByTeacher = codeId => {
-  return request(`${ASSIGNMENT_MODULE}/teacher/${codeId}`);
+  return request(`${ASSIGNMENT_MODULE}/teacher/code/${codeId}`);
 };
 
 /**
@@ -86,7 +86,7 @@ export const getCodeAssignmentByTeacher = codeId => {
  * @returns {Promise<{data:CodeSerializerType[]}>}
  */
 export const getCodeAssignmentListByStu = courseId => {
-  return request(`${ASSIGNMENT_MODULE}/student/course/${courseId}}/code`);
+  return request(`${ASSIGNMENT_MODULE}/student/course/${courseId}/code`);
 };
 
 /**
@@ -98,15 +98,6 @@ export const getCodeAssignmentByStu = codeId => {
   return request(`${ASSIGNMENT_MODULE}/student/code/${codeId}`);
 };
 
-/**
- * 学生查看单个代码作业下的项目信息列表
- * @param codeId
- * @returns {Promise<{data:ProjectSerializerType}>}
- */
-export const getProjectListByCode = codeId => {
-  return request(`${ASSIGNMENT_MODULE}/student/code/${codeId}/project`);
-};
-
 /**
  * 学生查看单个代码作业下的成绩
  * @param codeId
@@ -138,15 +129,6 @@ export const getUnsubmittedCodeGroupsList = codeId => {
   );
 };
 
-/**
- * 老师查看单个代码作业的成绩列表(所有组的)
- * @param codeId
- * @returns {Promise<{data:CodeResultSerializerType}>}
- */
-export const getCodeResultListByCode = codeId => {
-  return request(`${ASSIGNMENT_MODULE}/teacher/code/${codeId}/result`);
-};
-
 /* 文档作业*/
 /**
  * 老师新建文档作业

+ 2 - 3
src/api/course.js

@@ -25,7 +25,6 @@ export const getStudentCourses = () => {
  * @throws {StatusException} "课程名重复" | "课程选课码重复"
  */
 export const postTeacherCourse = ({ name, code }) => {
-  console.log(`name${name} code ${code}`);
   return request(`${COURSE_MODULE}/teacher`, {
     method: "POST",
     body: {
@@ -42,10 +41,10 @@ export const postTeacherCourse = ({ name, code }) => {
  * @throws {StatusException} "选课码不存在" | "已经加入课程"
  */
 export const postStudentCourse = code => {
-  return request(`${COURSE_MODULE}/student`, {
+  return request(`${COURSE_MODULE}/register`, {
     method: "POST",
     body: {
-      code
+      code: code
     }
   });
 };

+ 27 - 4
src/api/question.js

@@ -25,17 +25,40 @@ export const getQuestionsByAssignType = ({ type, page, limit }) => {
  */
 export const getQuestionByQuesType = ({ type, page, limit }) => {
   return request(
-    `${QUESTION_MODULE}/teacher/questions/type?type=${type || ""}&page=${page ||
-      1}&limit=${limit || 10}`
+    `${QUESTION_MODULE}/teacher/questions/type?type=${type || ""}&page=${
+      page >= 0 ? page : 0
+    }&limit=${limit || 10}`
   );
 };
+
+/**
+ * 根据关键字进行查找
+ * @param {string} keyword
+ * @param {string} type
+ * @returns {Promise<{data:QuestionSerializer[]}>}
+ */
+export const getTeacherKeywordQuestionsByCode = (
+  keyword = "123",
+  type = "CODE"
+) => {
+  return request(
+    `${QUESTION_MODULE}/teacher/keyword?keyword=${keyword}&type=${type}`
+  );
+};
+
 /**
  * 根据关键字进行查找
  * @param {string} keyword
+ * @param {string} type
  * @returns {Promise<{data:QuestionSerializer[]}>}
  */
-export const getTeacherKeywordQuestions = (keyword = "123") => {
-  return request(`${QUESTION_MODULE}/teacher/keyword?keyword=${keyword}`);
+export const getTeacherKeywordQuestionsByDoc = (
+  keyword = "123",
+  type = "DOCUMENT"
+) => {
+  return request(
+    `${QUESTION_MODULE}/teacher/keyword?keyword=${keyword}&type=${type}`
+  );
 };
 
 /**

+ 20 - 10
src/components/AssignmentCRUD/CreateAssignment/index.vue

@@ -165,7 +165,8 @@
 </template>
 
 <script>
-import { getTeacherKeywordQuestions } from "@/api/question";
+import { getTeacherKeywordQuestionsByCode } from "@/api/question";
+import { getTeacherKeywordQuestionsByDoc } from "@/api/question";
 import { postDocAssignment } from "@/api/assignment";
 import { postCodeAssignment } from "@/api/assignment";
 import timeMixins from "@/mixins/time";
@@ -206,9 +207,12 @@ export default {
       problemName: "",
       searchContent: "",
       questions: [],
+
+      // 控制modal活动
       isCreateModalActive: false,
       isSearchModalActive: false,
       isProblemListModalActive: false,
+
       startAtConfig: {
         ...this.getDefaultConfig(),
         minDate: "today",
@@ -222,6 +226,7 @@ export default {
       errorMassage: null,
       isServerError: false,
       submitting: false,
+
       // 转圈圈
       loadingSearchQuestions: false,
       loadingCreateAssignment: false
@@ -246,7 +251,13 @@ export default {
         this.loadingSearchQuestions = true;
         this.submitting = true;
         try {
-          getTeacherKeywordQuestions(content).then(res => {
+          let questionPromise = null;
+          if (this.assignType === 1) {
+            questionPromise = getTeacherKeywordQuestionsByDoc(content);
+          } else {
+            questionPromise = getTeacherKeywordQuestionsByCode(content);
+          }
+          questionPromise.then(res => {
             this.questions = res.data;
             this.isSearchModalActive = false;
             this.loadingSearchQuestions = false;
@@ -277,18 +288,17 @@ export default {
         this.submitting = true;
         this.params["type"] = this.postParam;
         this.parseParams();
+        const param = {
+          ...this.params,
+          startAt: parseInt(this.params.startAt),
+          endAt: parseInt(this.params.endAt)
+        };
         if (this.assignType === 1) {
           // 文档作业
-          this.myPromise = postDocAssignment(
-            this.params,
-            parseInt(this.courseId)
-          );
+          this.myPromise = postDocAssignment(param, this.courseId);
         } else {
           // 代码作业
-          this.myPromise = postCodeAssignment(
-            this.params,
-            parseInt(this.courseId)
-          );
+          this.myPromise = postCodeAssignment(param, this.courseId);
         }
         this.myPromise.then(res => {
           //创建成功

+ 1 - 1
src/components/AssignmentCRUD/DeleteAssignment/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div><a style="color:#b34141" @click="confirmDelete()">删除</a></div>
+  <div><a style="color:#827b7b">删除</a></div>
 </template>
 
 <script>

+ 7 - 11
src/components/AssignmentCRUD/UpdateAssignment/index.vue

@@ -27,17 +27,11 @@
               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 label="开始时间">
+            <b-input
+              disabled
+              :value="displayUnixTime(params.startAt)"
+            ></b-input>
           </b-field>
           <b-field
             label="结束时间"
@@ -69,7 +63,9 @@ import timeMixins from "@/mixins/time";
 import { putDocAssignment } from "@/api/assignment";
 import { putCodeAssignment } from "@/api/assignment";
 import { required } from "vuelidate/lib/validators";
+import BInput from "buefy/src/components/input/Input";
 export default {
+  components: { BInput },
   props: {
     updateItem: {
       type: Object

+ 0 - 3
src/layouts/LoginLayout.vue

@@ -11,9 +11,6 @@
         </div>
       </div>
     </section>
-    <!--<footer class="footer is-transparent" style="background: #f4f7fb">-->
-    <!--<div class="content has-text-centered">@nju software</div>-->
-    <!--</footer>-->
   </section>
 </template>
 

+ 29 - 2
src/router/routes.js

@@ -85,8 +85,35 @@ export default [
         component: () => import("@/views/teacher/Code/detail")
       },
       {
-        path: "code/:codeId/test/:testId",
-        component: () => import("@/views/teacher/Code/test")
+        path: "code/:homeworkId/:projectId",
+        component: () => import("@/views/teacher/Code/test"),
+        children: [
+          {
+            path: "",
+            component: () =>
+              import("@/views/student/Code/ProjectDetail/BuildDetail")
+          },
+          {
+            path: "deploy",
+            component: () =>
+              import("@/views/student/Code/ProjectDetail/DeployDetail")
+          },
+          {
+            path: "test",
+            component: () =>
+              import("@/views/student/Code/ProjectDetail/TestDetail")
+          }
+        ]
+      },
+      {
+        path: "code/:homeworkId/:projectId/test/unit/:unitTestId",
+        component: () =>
+          import("@/views/student/Code/ProjectDetail/Test/UnitTestDetail")
+      },
+      {
+        path: "code/:homeworkId/:projectId/test/functional/:functionalTestId",
+        component: () =>
+          import("@/views/student/Code/ProjectDetail/Test/FunctionalTestDetail")
       },
 
       {

+ 1 - 1
src/views/login/Login.vue

@@ -36,7 +36,7 @@
         class="button login"
         @click="loginAction"
       >
-        登 
+        登 
       </button>
     </div>
     <div>

+ 1 - 1
src/views/login/Register.vue

@@ -82,7 +82,7 @@
       :class="{ 'is-text': true }"
       class="button login"
       type="submit"
-      >已有账户,登
+      >已有账户,登
     </router-link>
   </div>
 </template>

+ 4 - 2
src/views/student/Code/ProjectDetail/BuildDetail.vue

@@ -12,14 +12,16 @@
             <div class="level-left">
               <build-tag :build-state="item.buildState" />
               <strong style="padding-left: 10px">
-                {{ item.commitMessage }} · #{{ item.branchId }}
+                {{ item.commitMessage }} · #构建ID:{{ item.id }}
               </strong>
             </div>
             <div v-if="item.buildState === 1" class="level-right">
               <strong>mirror : {{ item.mirrorId }}</strong>
             </div>
           </div>
-          <div class="code-section">{{ item.buildMessage }}</div>
+          <div class="code-section">
+            {{ item.buildMessage }} 构建时间: {{ item.time }}ms
+          </div>
         </div>
       </div>
     </div>

+ 2 - 2
src/views/student/Code/ProjectList/index.vue

@@ -22,7 +22,7 @@
           v-for="item in projectList"
           class="column is-4"
         >
-          <router-link :to="`${$route.path}/${item.projectId}`">
+          <router-link :to="`${$route.path}/${item.id}`">
             <card hoverable>{{ item.name }}</card>
           </router-link>
         </div>
@@ -56,7 +56,7 @@ export default {
   },
   async mounted() {
     this.projectListLoading = true;
-    const list = await getProjectList(this.course.id);
+    const list = await getProjectList(this.$route.params.homeworkId);
     this.projectList = list.data;
     this.projectListLoading = false;
   }

+ 6 - 5
src/views/student/Code/index.vue

@@ -18,12 +18,12 @@
         </div>
         <div
           v-else
-          :key="item.homeworkId"
+          :key="item.id"
           v-for="item in codeHomeworkList"
           class="column is-4-desktop"
         >
-          <router-link :to="`${$route.path}/${item.homeworkId}`">
-            <card hoverable>{{ item.description }}</card>
+          <router-link :to="`${$route.path}/${item.id}`">
+            <card hoverable>{{ item.name }}</card>
           </router-link>
         </div>
       </div>
@@ -33,10 +33,10 @@
 
 <script>
 import { mapState } from "vuex";
-import { getCodeHomeworkList } from "@/api/codehw";
 import Card from "@/components/Card";
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
+import { getCodeAssignmentListByStu } from "@/api/assignment";
 export default {
   components: {
     PageBody,
@@ -56,7 +56,8 @@ export default {
   },
   async mounted() {
     this.codeHomeworkListLoading = true;
-    const list = await getCodeHomeworkList(this.course.id);
+    const { courseId } = this.$route.params;
+    const list = await getCodeAssignmentListByStu(courseId);
     this.codeHomeworkList = list.data;
     this.codeHomeworkListLoading = false;
   }

+ 2 - 7
src/views/student/Document/index.vue

@@ -37,7 +37,6 @@
 </template>
 
 <script>
-import { mapState } from "vuex";
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
 import { getDocAssignmentListByCrs } from "@/api/assignment";
@@ -54,16 +53,12 @@ export default {
   mixins: [timeMixins],
   mounted() {
     this.loadingDocList = true;
-    getDocAssignmentListByCrs(this.course.id).then(res => {
+    const { courseId } = this.$route.params;
+    getDocAssignmentListByCrs(courseId).then(res => {
       this.docList = res.data;
       this.loadingDocList = false;
     });
   },
-  computed: {
-    ...mapState({
-      course: state => state.course.currentCourse
-    })
-  },
   data() {
     return {
       docList: [],

File diff suppressed because it is too large
+ 529 - 2
src/views/student/Home/index.vue


+ 2 - 7
src/views/student/Review/index.vue

@@ -35,7 +35,6 @@
 </template>
 
 <script>
-import { mapState } from "vuex";
 import { getStudentCourseReviewList } from "@/api/review";
 import Card from "@/components/Card";
 import PageHeader from "@/components/PageHeader";
@@ -48,11 +47,6 @@ export default {
     PageHeader,
     Card
   },
-  computed: {
-    ...mapState({
-      course: state => state.course.currentCourse
-    })
-  },
   data() {
     return {
       courses: [],
@@ -62,7 +56,8 @@ export default {
   },
   mounted() {
     this.loadingReviewList = true;
-    getStudentCourseReviewList(this.courses.id).then(value => {
+    const { courseId } = this.$route.params;
+    getStudentCourseReviewList(courseId).then(value => {
       this.review = value.data;
       this.loadingReviewList = false;
     });

+ 7 - 23
src/views/teacher/Code/detail.vue

@@ -89,7 +89,7 @@
                 <b-table-column label="详情" centered>
                   <router-link
                     :to="{
-                      path: `${$route.path}/test/${props.row.id}`
+                      path: `${$route.path}/${props.row.id}`
                     }"
                     >查看详情</router-link
                   >
@@ -132,7 +132,7 @@
                 <b-table-column label="小组名称" centered>
                   {{ props.row.name }}
                 </b-table-column>
-                <b-table-column label="小组a成员" centered>
+                <b-table-column label="小组成员" centered>
                   <span v-for="member in props.row.members" :key="member.id"
                     >{{ member.username }}&emsp;</span
                   >
@@ -174,18 +174,19 @@ export default {
     PageSectionLoading
   },
   mounted() {
-    this.codeId = this.$route.params;
+    const { codeId } = this.$route.params;
+    this.codeId = codeId;
     this.loadingUncommittedGroups = true;
     this.loadingCommittedGroups = true;
-    getCodeAssignmentByTeacher(this.codeId).then(res => {
+    getCodeAssignmentByTeacher(codeId).then(res => {
       this.problemInfo = res.data.problem;
     });
-    getCodeProcedureListByCodeId(this.codeId).then(res => {
+    getCodeProcedureListByCodeId(codeId).then(res => {
       this.codeProcedureList = res.data;
       this.submitInfo.yes = "已提交:" + this.codeProcedureList.length;
       this.loadingCommittedGroups = false;
     });
-    getUnsubmittedCodeGroupsList(this.codeId).then(res => {
+    getUnsubmittedCodeGroupsList(codeId).then(res => {
       this.unsubmitedGroups = res.data;
       this.submitInfo.no = "未提交:" + this.unsubmitedGroups.length;
       this.loadingUncommittedGroups = false;
@@ -222,23 +223,6 @@ export default {
         showTag = tag.success;
       }
       return showTag;
-    },
-    geneTitleAndTag(state) {
-      let data = {
-        title: "",
-        tag: ""
-      };
-      if (state === -1) {
-        data.title = status.failed;
-        data.tag = tag.failed;
-      } else if (state === 0) {
-        data.title = status.uncommitted;
-        data.tag = tag.uncommitted;
-      } else {
-        data.title = status.success;
-        data.tag = tag.success;
-      }
-      return data;
     }
   }
 };

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

@@ -91,8 +91,8 @@
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
 import { getCodeAssignmentListByTeacher } from "@/api/assignment";
-import timeMixins from "@/mixins/time";
 import { mapState } from "vuex";
+import timeMixins from "@/mixins/time";
 import DeleteAssignment from "@/components/AssignmentCRUD/DeleteAssignment";
 import UpdateAssignment from "@/components/AssignmentCRUD/UpdateAssignment";
 import CreateAssignment from "@/components/AssignmentCRUD/CreateAssignment";
@@ -110,7 +110,8 @@ export default {
   mixins: [timeMixins],
   mounted() {
     this.loadingCodeList = true;
-    getCodeAssignmentListByTeacher(this.course.id).then(res => {
+    const { courseId } = this.$route.params;
+    getCodeAssignmentListByTeacher(courseId).then(res => {
       this.codeData = res.data;
       this.loadingCodeList = false;
     });
@@ -122,6 +123,11 @@ export default {
       loadingCodeList: false
     };
   },
+  computed: {
+    ...mapState({
+      course: state => state.course.currentCourse
+    })
+  },
   methods: {
     pushNewAssignment(item) {
       this.codeData.push(item);
@@ -144,11 +150,6 @@ export default {
         }
       }
     }
-  },
-  computed: {
-    ...mapState({
-      course: state => state.course.currentCourse
-    })
   }
 };
 </script>

+ 45 - 15
src/views/teacher/Code/test.vue

@@ -6,22 +6,44 @@
         { name: '作业详情', path: `code/${$route.params.codeId}` },
         { name: '测试信息', path: `${$route.path}` }
       ]"
+      :tab-list="[
+        {
+          name: '构建',
+          path: `code/${$route.params.homeworkId}/${$route.params.projectId}`
+        },
+        {
+          name: '部署',
+          path: `code/${$route.params.homeworkId}/${
+            $route.params.projectId
+          }/deploy`
+        },
+        {
+          name: '测试',
+          path: `code/${$route.params.homeworkId}/${
+            $route.params.projectId
+          }/test`
+        }
+      ]"
     >
       <template slot="title">
-        测试信息
+        测试信息: {{ projectDetail.name }}
       </template>
       <template slot="content">
-        可查看最近五条测试数据
+        <strong>git 地址 : </strong>
+        <a :href="projectDetail.url">{{ projectDetail.url }}</a>
       </template>
     </page-header>
-
     <page-body>
-      <div class="data-table">和学生代码作业的测试信息的显示格式和接口相同</div>
+      <router-view
+        :project-detail="projectDetail"
+        :detail-loading="detailLoading"
+      />
     </page-body>
   </div>
 </template>
 
 <script>
+import { getProjectDetail } from "@/api/codehw";
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
 
@@ -30,22 +52,30 @@ export default {
     PageBody,
     PageHeader
   },
-  mounted() {
-    const { testId } = this.$route.params;
-    console.log(testId);
-  },
   data() {
-    return {};
+    return {
+      projectDetail: {},
+      detailLoading: false
+    };
+  },
+  async mounted() {
+    // console.log(
+    //   "code/" +
+    //     this.$route.params.homeworkId +
+    //     "/" +
+    //     this.$route.params.projectId
+    // );
+    const { projectId } = this.$route.params;
+    this.detailLoading = true;
+    const detail = await getProjectDetail(projectId);
+    this.projectDetail = detail.data;
+    this.detailLoading = false;
   }
 };
 </script>
 
 <style scoped>
-.breadcrumb a {
-  /*color: #7957d5;*/
-  font-weight: bold;
-}
-.collapseeeeeee {
-  margin-bottom: 10px;
+.top-nav-section {
+  padding: 0 40px;
 }
 </style>

+ 0 - 9
src/views/teacher/Dashboard/index.vue

@@ -7,15 +7,6 @@
       <template slot="content">
         当前<strong>&nbsp;5&nbsp;</strong>份作业进行中
       </template>
-      <!--<template slot="extraContent">-->
-      <!--Here might be a page title-->
-      <!--</template>-->
-      <!--<template slot="logo">-->
-      <!--Here might-->
-      <!--</template>-->
-      <!--<template slot="action">-->
-      <!--Here might be a page title-->
-      <!--</template>-->
     </page-header>
     <page-body>
       <div class="data-table">

+ 4 - 8
src/views/teacher/Document/detail.vue

@@ -8,10 +8,10 @@
       ]"
     >
       <template slot="title">
-        {{ problem.name }}
+        {{ problem ? problem.name : "" }}
       </template>
       <template slot="content">
-        题目描述:{{ problem.description }}
+        题目描述:{{ problem ? problem.description : "" }}
       </template>
       <template slot="extraContent">
         题目进行阶段:{{ status }}
@@ -138,7 +138,7 @@ export default {
     PageSectionLoading
   },
   mounted() {
-    const { documentId } = this.$route.query;
+    const { documentId } = this.$route.params;
     this.loadingCommittedGroups = true;
     this.loadingUncommittedGroups = true;
     getDocAssignmentTeacherByCrs(documentId).then(res => {
@@ -158,11 +158,7 @@ export default {
   },
   data() {
     return {
-      problem: {
-        id: null,
-        name: null,
-        description: null
-      },
+      problem: null,
       submittedData: [],
       unsubmitedGroups: [],
       status: "",

+ 2 - 1
src/views/teacher/Document/index.vue

@@ -112,7 +112,8 @@ export default {
   mixins: [timeMixins],
   mounted() {
     this.loadingDocList = true;
-    getDocAssignmentListTeacherByCrs(this.course.id).then(res => {
+    const { courseId } = this.$route.params;
+    getDocAssignmentListTeacherByCrs(courseId).then(res => {
       this.docData = res.data;
       this.loadingDocList = false;
     });

File diff suppressed because it is too large
+ 529 - 2
src/views/teacher/Home/index.vue


+ 396 - 13
src/views/teacher/Question/index.vue

@@ -16,7 +16,7 @@
         <div class="form-group">
           <!--下拉框-->
           <b-field>
-            <b-select placeholder="选择题目类型">
+            <b-select v-model="selectedType">
               <option
                 v-for="(option, index) in questionType"
                 :value="option"
@@ -45,7 +45,12 @@
         </div>
         <!--题目table-->
         <div class="question-list">
-          <b-table :data="data" detailed detail-key="id">
+          <b-table
+            :data="data"
+            detailed
+            detail-key="id"
+            v-if="data && data.length > 0"
+          >
             <template slot-scope="props">
               <b-table-column field="id" label="ID" width="40" numeric sortable>
                 {{ props.row.id }}
@@ -60,6 +65,7 @@
                       questionId: props.row.id
                     }
                   }"
+                  target="_blank"
                   >{{ props.row.name }}</router-link
                 >
               </b-table-column>
@@ -87,7 +93,7 @@
                 sortable
                 centered
               >
-                {{ props.row.expect_time }}分钟
+                {{ props.row.expectTime }}分钟
               </b-table-column>
             </template>
 
@@ -126,6 +132,302 @@
               </article>
             </template>
           </b-table>
+          <!--表格页标-->
+          <div
+            class="level-item"
+            v-if="paginationInfo.display && data && data.length > 0"
+          >
+            <div class="pagination">
+              <a
+                role="button"
+                href="#"
+                :disabled="{ disabled: paginationInfo.currentPage == 0 }"
+                class="pagination-previous"
+                ><span class="icon"
+                  ><i class="mdi mdi-chevron-left mdi-24px"></i></span
+              ></a>
+              <a
+                role="button"
+                href="#"
+                :disabled="{
+                  disabled:
+                    paginationInfo.currentPage == paginationInfo.totalPage
+                }"
+                class="pagination-next"
+                ><span class="icon"
+                  ><i class="mdi mdi-chevron-right mdi-24px"></i></span
+              ></a>
+              <!--页数较少的显示情况-->
+              <ul class="pagination-list" v-if="paginationInfo.totalPage < 6">
+                <li v-for="index in paginationInfo.pageList" :key="index">
+                  <a
+                    role="button"
+                    href="#"
+                    :class="[
+                      'pagination-link',
+                      { 'is-current': paginationInfo.currentPage == index }
+                    ]"
+                    >1</a
+                  >
+                </li>
+              </ul>
+            </div>
+          </div>
+          <!--当没有数据时页面展示-->
+          <div class="no-data" v-if="data.length <= 0">
+            <svg
+              id="f20e0c25-d928-42cc-98d1-13cc230663ea"
+              data-name="Layer 1"
+              xmlns="http://www.w3.org/2000/svg"
+              xmlns:xlink="http://www.w3.org/1999/xlink"
+              width="620.16"
+              height="500.81"
+              viewBox="0 0 820.16 780.81"
+            >
+              <defs>
+                <linearGradient
+                  id="07332201-7176-49c2-9908-6dc4a39c4716"
+                  x1="539.63"
+                  y1="734.6"
+                  x2="539.63"
+                  y2="151.19"
+                  gradientTransform="translate(-3.62 1.57)"
+                  gradientUnits="userSpaceOnUse"
+                >
+                  <stop offset="0" stop-color="gray" stop-opacity="0.25" />
+                  <stop offset="0.54" stop-color="gray" stop-opacity="0.12" />
+                  <stop offset="1" stop-color="gray" stop-opacity="0.1" />
+                </linearGradient>
+                <linearGradient
+                  id="0ee1ab3f-7ba2-4205-9d4a-9606ad702253"
+                  x1="540.17"
+                  y1="180.2"
+                  x2="540.17"
+                  y2="130.75"
+                  gradientTransform="translate(-63.92 7.85)"
+                  xlink:href="#07332201-7176-49c2-9908-6dc4a39c4716"
+                />
+                <linearGradient
+                  id="abca9755-bed1-4a97-b027-7f02ee3ffa09"
+                  x1="540.17"
+                  y1="140.86"
+                  x2="540.17"
+                  y2="82.43"
+                  gradientTransform="translate(-84.51 124.6) rotate(-12.11)"
+                  xlink:href="#07332201-7176-49c2-9908-6dc4a39c4716"
+                />
+                <linearGradient
+                  id="2632d424-e666-4ee4-9508-a494957e14ab"
+                  x1="476.4"
+                  y1="710.53"
+                  x2="476.4"
+                  y2="127.12"
+                  gradientTransform="matrix(1, 0, 0, 1, 0, 0)"
+                  xlink:href="#07332201-7176-49c2-9908-6dc4a39c4716"
+                />
+                <linearGradient
+                  id="97571ef7-1c83-4e06-b701-c2e47e77dca3"
+                  x1="476.94"
+                  y1="156.13"
+                  x2="476.94"
+                  y2="106.68"
+                  gradientTransform="matrix(1, 0, 0, 1, 0, 0)"
+                  xlink:href="#07332201-7176-49c2-9908-6dc4a39c4716"
+                />
+                <linearGradient
+                  id="7d32e13e-a0c7-49c4-af0e-066a2f8cb76e"
+                  x1="666.86"
+                  y1="176.39"
+                  x2="666.86"
+                  y2="117.95"
+                  gradientTransform="matrix(1, 0, 0, 1, 0, 0)"
+                  xlink:href="#07332201-7176-49c2-9908-6dc4a39c4716"
+                />
+              </defs>
+              <title>no data</title>
+              <rect
+                x="317.5"
+                y="142.55"
+                width="437.02"
+                height="603.82"
+                transform="translate(-271.22 62.72) rotate(-12.11)"
+                fill="#e0e0e0"
+              />
+              <g opacity="0.5">
+                <rect
+                  x="324.89"
+                  y="152.76"
+                  width="422.25"
+                  height="583.41"
+                  transform="translate(-271.22 62.72) rotate(-12.11)"
+                  fill="url(#07332201-7176-49c2-9908-6dc4a39c4716)"
+                />
+              </g>
+              <rect
+                x="329.81"
+                y="157.1"
+                width="411.5"
+                height="570.52"
+                transform="translate(-270.79 62.58) rotate(-12.11)"
+                fill="#fafafa"
+              />
+              <rect
+                x="374.18"
+                y="138.6"
+                width="204.14"
+                height="49.45"
+                transform="translate(-213.58 43.93) rotate(-12.11)"
+                fill="url(#0ee1ab3f-7ba2-4205-9d4a-9606ad702253)"
+              />
+              <path
+                d="M460.93,91.9c-15.41,3.31-25.16,18.78-21.77,34.55s18.62,25.89,34,22.58,25.16-18.78,21.77-34.55S476.34,88.59,460.93,91.9ZM470.6,137A16.86,16.86,0,1,1,483.16,117,16.66,16.66,0,0,1,470.6,137Z"
+                transform="translate(-189.92 -59.59)"
+                fill="url(#abca9755-bed1-4a97-b027-7f02ee3ffa09)"
+              />
+              <rect
+                x="375.66"
+                y="136.55"
+                width="199.84"
+                height="47.27"
+                transform="translate(-212.94 43.72) rotate(-12.11)"
+                fill="#6c63ff"
+              />
+              <path
+                d="M460.93,91.9a27.93,27.93,0,1,0,33.17,21.45A27.93,27.93,0,0,0,460.93,91.9ZM470.17,135a16.12,16.12,0,1,1,12.38-19.14A16.12,16.12,0,0,1,470.17,135Z"
+                transform="translate(-189.92 -59.59)"
+                fill="#6c63ff"
+              />
+              <rect
+                x="257.89"
+                y="116.91"
+                width="437.02"
+                height="603.82"
+                fill="#e0e0e0"
+              />
+              <g opacity="0.5">
+                <rect
+                  x="265.28"
+                  y="127.12"
+                  width="422.25"
+                  height="583.41"
+                  fill="url(#2632d424-e666-4ee4-9508-a494957e14ab)"
+                />
+              </g>
+              <rect
+                x="270.65"
+                y="131.42"
+                width="411.5"
+                height="570.52"
+                fill="#fff"
+              />
+              <rect
+                x="374.87"
+                y="106.68"
+                width="204.14"
+                height="49.45"
+                fill="url(#97571ef7-1c83-4e06-b701-c2e47e77dca3)"
+              />
+              <path
+                d="M666.86,118c-15.76,0-28.54,13.08-28.54,29.22s12.78,29.22,28.54,29.22,28.54-13.08,28.54-29.22S682.62,118,666.86,118Zm0,46.08a16.86,16.86,0,1,1,16.46-16.86A16.66,16.66,0,0,1,666.86,164Z"
+                transform="translate(-189.92 -59.59)"
+                fill="url(#7d32e13e-a0c7-49c4-af0e-066a2f8cb76e)"
+              />
+              <rect
+                x="377.02"
+                y="104.56"
+                width="199.84"
+                height="47.27"
+                fill="#6c63ff"
+              />
+              <path
+                d="M666.86,118a27.93,27.93,0,1,0,27.93,27.93A27.93,27.93,0,0,0,666.86,118Zm0,44.05A16.12,16.12,0,1,1,683,145.89,16.12,16.12,0,0,1,666.86,162Z"
+                transform="translate(-189.92 -59.59)"
+                fill="#6c63ff"
+              />
+              <g opacity="0.5">
+                <rect
+                  x="15.27"
+                  y="737.05"
+                  width="3.76"
+                  height="21.33"
+                  fill="#47e6b1"
+                />
+                <rect
+                  x="205.19"
+                  y="796.65"
+                  width="3.76"
+                  height="21.33"
+                  transform="translate(824.47 540.65) rotate(90)"
+                  fill="#47e6b1"
+                />
+              </g>
+              <g opacity="0.5">
+                <rect x="451.49" width="3.76" height="21.33" fill="#47e6b1" />
+                <rect
+                  x="641.4"
+                  y="59.59"
+                  width="3.76"
+                  height="21.33"
+                  transform="translate(523.63 -632.62) rotate(90)"
+                  fill="#47e6b1"
+                />
+              </g>
+              <path
+                d="M961,832.15a4.61,4.61,0,0,1-2.57-5.57,2.22,2.22,0,0,0,.1-.51h0a2.31,2.31,0,0,0-4.15-1.53h0a2.22,2.22,0,0,0-.26.45,4.61,4.61,0,0,1-5.57,2.57,2.22,2.22,0,0,0-.51-.1h0a2.31,2.31,0,0,0-1.53,4.15h0a2.22,2.22,0,0,0,.45.26,4.61,4.61,0,0,1,2.57,5.57,2.22,2.22,0,0,0-.1.51h0a2.31,2.31,0,0,0,4.15,1.53h0a2.22,2.22,0,0,0,.26-.45,4.61,4.61,0,0,1,5.57-2.57,2.22,2.22,0,0,0,.51.1h0a2.31,2.31,0,0,0,1.53-4.15h0A2.22,2.22,0,0,0,961,832.15Z"
+                transform="translate(-189.92 -59.59)"
+                fill="#4d8af0"
+                opacity="0.5"
+              />
+              <path
+                d="M326.59,627.09a4.61,4.61,0,0,1-2.57-5.57,2.22,2.22,0,0,0,.1-.51h0a2.31,2.31,0,0,0-4.15-1.53h0a2.22,2.22,0,0,0-.26.45,4.61,4.61,0,0,1-5.57,2.57,2.22,2.22,0,0,0-.51-.1h0a2.31,2.31,0,0,0-1.53,4.15h0a2.22,2.22,0,0,0,.45.26,4.61,4.61,0,0,1,2.57,5.57,2.22,2.22,0,0,0-.1.51h0a2.31,2.31,0,0,0,4.15,1.53h0a2.22,2.22,0,0,0,.26-.45A4.61,4.61,0,0,1,325,631.4a2.22,2.22,0,0,0,.51.1h0a2.31,2.31,0,0,0,1.53-4.15h0A2.22,2.22,0,0,0,326.59,627.09Z"
+                transform="translate(-189.92 -59.59)"
+                fill="#fdd835"
+                opacity="0.5"
+              />
+              <path
+                d="M855,127.77a4.61,4.61,0,0,1-2.57-5.57,2.22,2.22,0,0,0,.1-.51h0a2.31,2.31,0,0,0-4.15-1.53h0a2.22,2.22,0,0,0-.26.45,4.61,4.61,0,0,1-5.57,2.57,2.22,2.22,0,0,0-.51-.1h0a2.31,2.31,0,0,0-1.53,4.15h0a2.22,2.22,0,0,0,.45.26,4.61,4.61,0,0,1,2.57,5.57,2.22,2.22,0,0,0-.1.51h0a2.31,2.31,0,0,0,4.15,1.53h0a2.22,2.22,0,0,0,.26-.45,4.61,4.61,0,0,1,5.57-2.57,2.22,2.22,0,0,0,.51.1h0a2.31,2.31,0,0,0,1.53-4.15h0A2.22,2.22,0,0,0,855,127.77Z"
+                transform="translate(-189.92 -59.59)"
+                fill="#fdd835"
+                opacity="0.5"
+              />
+              <circle
+                cx="812.64"
+                cy="314.47"
+                r="7.53"
+                fill="#f55f44"
+                opacity="0.5"
+              />
+              <circle
+                cx="230.73"
+                cy="746.65"
+                r="7.53"
+                fill="#f55f44"
+                opacity="0.5"
+              />
+              <circle
+                cx="735.31"
+                cy="477.23"
+                r="7.53"
+                fill="#f55f44"
+                opacity="0.5"
+              />
+              <circle
+                cx="87.14"
+                cy="96.35"
+                r="7.53"
+                fill="#4d8af0"
+                opacity="0.5"
+              />
+              <circle
+                cx="7.53"
+                cy="301.76"
+                r="7.53"
+                fill="#47e6b1"
+                opacity="0.5"
+              />
+            </svg>
+            <span>暂无符合要求的题目</span>
+          </div>
         </div>
       </div>
     </page-body>
@@ -136,12 +438,15 @@ import { mapState } from "vuex";
 import {
   getQuestionsByAssignType,
   getTeacherQuestionType,
-  getTeacherKeywordQuestions
+  getTeacherKeywordQuestions,
+  getQuestionByQuesType
 } from "@/api/question";
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
 import PageSectionLoading from "@/components/PageBody/PageSectionLoading/index";
 
+const pageLimit = 10;
+
 export default {
   components: {
     PageHeader,
@@ -161,37 +466,106 @@ export default {
       data: [],
       keyWord: "",
       errorMessage: "服务器错误,请稍后再试",
-      loadingQuestionList: true
+      loadingQuestionList: true,
+      selectedType: "全部类型",
+      paginationInfo: {
+        display: true,
+        totalPage: 0,
+        currentPage: 0,
+        pageList: []
+      }
     };
   },
+  watch: {
+    selectedType(val) {
+      let type = val;
+      type = type == "全部类型" ? "" : type;
+      this.getQuestionsByQType(type, 0, pageLimit);
+    }
+  },
   mounted() {
     //获取全部题目分类
     this.getQuestionType();
     //获取全部题目
-    this.getQuestions();
+    this.getQuestions("", 0, pageLimit);
 
     this.loadingQuestionList = false;
   },
   methods: {
+    //分页信息处理
+    pagnationHandler(total, current, elements) {
+      if (elements == 0) {
+        this.paginationInfo = {
+          display: false,
+          totalPage: 0,
+          currentPage: 0,
+          pageList: []
+        };
+      } else {
+        let paginationInfo = {};
+        let pageList = [];
+        paginationInfo.totalPage = total;
+        paginationInfo.currentPage = current;
+        for (let i = 0; i < total; i++) {
+          pageList.push(i);
+        }
+        paginationInfo.pageList = pageList;
+        paginationInfo.display = true;
+        this.paginationInfo = paginationInfo;
+      }
+    },
     //获取全部题目分类
     getQuestionType() {
       getTeacherQuestionType()
         .then(value => {
-          this.questionType = value.data;
+          // this.questionType = value.data;
+          let questionType = value.res;
+          questionType.unshift("全部类型");
+          this.questionType = questionType;
         })
         .catch(e => {
           this.$toast.open({
             message: e.message,
-            type: "is-link"
+            type: "is-danger"
           });
         });
     },
-    //获取全部题目
-    getQuestions() {
-      getQuestionsByAssignType({ type: "DOCUMENT", page: 0, limit: 10 })
+    //获取指定题目类型的题目
+    getQuestionsByQType(questionType, pageNum, pageLimit) {
+      getQuestionByQuesType({
+        type: questionType,
+        page: pageNum,
+        limit: pageLimit
+      })
         .then(value => {
-          // this.data = value.res.content;
-          this.data = value.data;
+          this.data = value.data.content;
+          this.pagnationHandler(
+            value.data.totalPages,
+            pageNum,
+            value.data.umberOfElements
+          );
+        })
+        .catch(e => {
+          this.$toast.open({
+            message: e.message,
+            type: "is-danger"
+          });
+        });
+    },
+    //获取指定作业类型的题目
+    getQuestions(questionType, pageNum, pageLimit) {
+      getQuestionsByAssignType({
+        type: questionType,
+        page: pageNum,
+        limit: pageLimit
+      })
+        .then(value => {
+          this.data = value.data.content;
+          this.pagnationHandler(
+            value.data.totalPages,
+            pageNum,
+            value.data.umberOfElements
+          );
         })
         .catch(e => {
           this.$toast.open({
@@ -245,6 +619,15 @@ export default {
   /*color: #7957d5;*/
   font-weight: bold;
 }
+.no-data {
+  display: flex;
+  align-items: center;
+  span {
+    font-size: 2rem;
+    font-weight: bold;
+    color: #6c63ff;
+  }
+}
 /*.data-table {*/
 /*width: 100%;*/
 /*padding: 30px;*/

+ 8 - 2
src/views/teacher/Question/questionDetail.vue

@@ -12,10 +12,10 @@
       </template>
       <template slot="content">
         <b-tag class="tag" type="is-link" rounded>{{
-          questionInfo.assignmentType ? questionInfo.assignmentType.value : ""
+          questionInfo.assignmentType || ""
         }}</b-tag>
         <b-tag class="tag" type="is-link" rounded>{{
-          questionInfo.type ? questionInfo.type.value : ""
+          questionInfo.questionType || ""
         }}</b-tag>
       </template>
     </page-header>
@@ -50,6 +50,12 @@
                 <a>{{ item.filename }}</a>
               </div>
             </div>
+            <div
+              class="empty"
+              v-if="!(questionInfo.file && questionInfo.file.length > 0)"
+            >
+              当前题目暂无文件信息
+            </div>
           </div>
         </div>
       </div>

+ 50 - 17
src/views/teacher/Result/index.vue

@@ -189,6 +189,18 @@ import { required, numeric, between } from "vuelidate/lib/validators";
 import { getStudentFinaleResult } from "@/api/resultstatistics";
 import PageSectionLoading from "@/components/PageBody/PageSectionLoading/index";
 
+const RESULT_SECTION = [
+  "0分",
+  "1-29分",
+  "30-59分段",
+  "60-69分段",
+  "70-79分段",
+  "80-89分段",
+  "90-99分段",
+  "100分"
+];
+const RESULT_PARTITION = [0, 29, 59, 69, 79, 89, 99, 100];
+
 export default {
   components: {
     BInput,
@@ -225,6 +237,32 @@ export default {
     };
   },
   methods: {
+    //统计学生成绩分段
+    studenResultStatistics(studentResults) {
+      let resultStatisticsData = [];
+      for (let i = 0; i < RESULT_PARTITION.length; i++) {
+        let count = 0;
+        if (i == 0) {
+          for (let result in studentResults) {
+            if (this.getFinalResult(result.row) == 0) count++;
+          }
+        } else if (i == RESULT_PARTITION.length - 1) {
+          for (let result in studentResults) {
+            if (this.getFinalResult(result.row) == 100) count++;
+          }
+        } else {
+          for (let result in studentResults) {
+            if (
+              this.getFinalResult(result.row) > RESULT_PARTITION[i - 1] &&
+              this.getFinalResult(result.row) <= RESULT_PARTITION[i]
+            )
+              count++;
+          }
+        }
+        resultStatisticsData.push(count);
+      }
+      return resultStatisticsData;
+    },
     type(value) {
       const number = parseFloat(value);
       if (number < 60) {
@@ -237,6 +275,9 @@ export default {
     },
     //计算平均成绩
     average(resultList) {
+      if (resultList.length < 1) {
+        return "--";
+      }
       let res = 0;
       for (let item of resultList) {
         res += item.score;
@@ -272,28 +313,20 @@ export default {
       });
     }
   },
-  mounted() {
+  async mounted() {
     //获取成绩信息
-    getStudentFinaleResult(this.courses.id).then(res => {
-      console.log(res.data);
-      this.data = res.data;
-      this.isResultLoading = false;
-    });
+    const resultData = await getStudentFinaleResult(
+      this.$route.params.courseId
+    );
+    this.data = resultData;
+    //统计学生分数
+    let studentResultStatistics = this.studenResultStatistics(this.data);
     //绘制图表
     let resultChart = document.getElementById("result-chart");
     let myChart2 = new Chart(resultChart, {
       type: "bar",
       data: {
-        labels: [
-          "0分",
-          "1-29分",
-          "30-59分段",
-          "60-69分段",
-          "70-79分段",
-          "80-89分段",
-          "90-99分段",
-          "100分"
-        ],
+        labels: RESULT_SECTION,
         datasets: [
           {
             label: "人数",
@@ -302,7 +335,7 @@ export default {
             borderWidth: 1,
             pointStrokeColor: "#fff",
             pointStyle: "crossRot",
-            data: [2, 6, 10, 34, 50, 80, 30, 2],
+            data: studentResultStatistics,
             cubicInterpolationMode: "monotone",
             spanGaps: "false",
             fill: "false"

+ 4 - 3
src/views/teacher/Review/index.vue

@@ -135,7 +135,7 @@ import Card from "@/components/Card";
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
 import ReviewStateTag from "@/components/ReviewStateTag/index";
-import { getDocAssignmentListByCrs } from "@/api/assignment";
+import { getDocAssignmentListTeacherByCrs } from "@/api/assignment";
 import timeMixins from "@/mixins/time";
 import { required } from "vuelidate/lib/validators";
 export default {
@@ -257,13 +257,14 @@ export default {
   },
   methods: {
     async getReviewList() {
-      const { data } = await getTeacherCourseReviewList(this.courses.id);
+      const { courseId } = this.$route.params;
+      const { data } = await getTeacherCourseReviewList(courseId);
       this.review = data;
     },
     async getDocHomework() {
       this.docHomeworkLoading = true;
       const { courseId } = this.$route.params;
-      const { data } = await getDocAssignmentListByCrs(courseId);
+      const { data } = await getDocAssignmentListTeacherByCrs(courseId);
       this.docHomework = data;
       this.docHomeworkLoading = false;
     },

+ 5 - 2
vue.config.js

@@ -2,8 +2,11 @@ module.exports = {
   devServer: {
     proxy: {
       "^/api": {
-        target: "http://localhost:4000/",
-        // target: "http://10.1.2.2:8080/",
+        // target: "http://localhost:4000/",
+        // target: "http://10.1.1.198:8080/",
+        target: "http://192.168.0.101:8080",
+        // target: "http://10.1.2.3:8080/",
+
         ws: true,
         changeOrigin: true
       }

Some files were not shown because too many files changed in this diff