Просмотр исходного кода

[新增] docDetail页面和相关组件

WuXinyu 7 лет назад
Родитель
Сommit
acfd7c2a61

+ 1 - 1
mock/serializers/user/UserSerializer.js

@@ -14,7 +14,7 @@ const makeId = require("../../util/makeId");
  * @param role
  * @returns {UserSerializerType}
  */
-module.exports = (role = "TEACHER") => {
+module.exports = (role = "STUDENT") => {
   return {
     id: makeId(),
     role: role,

+ 7 - 0
src/assets/scss/app.scss

@@ -73,3 +73,10 @@ $default-margin-between:1.5rem;
 .tabs ul{
   border-bottom-color: white;
 }
+
+.content blockquote {
+  background-color: #fbfbfb;
+  border-left: 3px solid #ced9ec;
+  padding: 1em;
+}
+

+ 0 - 0
src/components/CardJudgeItem/index.vue


+ 52 - 0
src/components/CheckListItem/index.vue

@@ -0,0 +1,52 @@
+<template>
+  <check-judge-item :success="checkListItem.level === 1">
+    <b-tooltip :label="checkListItem.explain" position="is-left">
+      <b-checkbox
+        v-model="checkListItem.level"
+        type="is-success"
+        :name="checkListItem.content"
+      >
+        Success
+      </b-checkbox>
+    </b-tooltip>
+    <input
+      v-model="checkListItem.comment"
+      class="input is-small"
+      type="text"
+      placeholder="填写备注"
+      style="box-shadow:none;border-color:white"
+    />
+  </check-judge-item>
+</template>
+
+<script>
+export default {
+  name: "CheckJudgeItem",
+  props: {
+    checkListItem: {
+      type: Object,
+      default: () => {}
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+@import "../../assets/scss/app";
+.judge-section {
+  background: $white;
+  border: 1px solid $grey-lighter;
+  border-left: 6px solid $danger;
+  padding: 10px;
+  margin-bottom: 10px;
+  box-shadow: 0 2px 10px rgba(161, 161, 161, 0.082);
+  position: relative;
+}
+
+.judge-success {
+  border-left: 6px solid $success;
+}
+.judge-primary {
+  border-left: 6px solid $info;
+}
+</style>

+ 21 - 0
src/components/ReviewStateTag/index.vue

@@ -0,0 +1,21 @@
+<template>
+  <div class="tag" :class="tagDetail.styledClass">{{ tagDetail.name }}</div>
+</template>
+
+<script>
+import { reviewStateHelperFectory, DEFAULT } from "../../data/reviewState";
+export default {
+  name: "ReviewStateTag",
+  props: {
+    state: {
+      type: String,
+      default: DEFAULT
+    }
+  },
+  computed: {
+    tagDetail() {
+      return reviewStateHelperFectory.getStateHelper(this.state);
+    }
+  }
+};
+</script>

+ 7 - 0
src/data/checkListItemState.js

@@ -0,0 +1,7 @@
+export const DEFAULT = "DEFAULT";
+export const SUBMITTED = "SUBMITTED";
+export const PENDING = "PENDING";
+export const SOLVING = "SOLVING";
+export const ARGUED = "ARGUED";
+
+export const ALL_STATE = [DEFAULT, SUBMITTED, PENDING, SOLVING, ARGUED];

+ 37 - 0
src/data/reviewState.js

@@ -0,0 +1,37 @@
+export const DEFAULT = "DEFAULT";
+export const REVIEWING = "REVIEWING";
+export const ARGUING = "ARGUING";
+export const SOLVING = "SOLVING";
+export const END = "END";
+export const ALL_STATE = [DEFAULT, REVIEWING, ARGUING, SOLVING, END];
+
+/**
+ * @typedef ReviewStateHelper
+ * @property {string} name
+ * @property {string} styledClass
+ */
+
+class ReviewStateHelperFectory {
+  /**
+   * @param state
+   * @return {ReviewStateHelper}
+   */
+  getStateHelper = state => {
+    switch (state) {
+      case DEFAULT:
+        return { name: "未开始", styledClass: "is-light" };
+      case REVIEWING:
+        return { name: "正在进行", styledClass: "is-success" };
+      case ARGUING:
+        return { name: "申请重判期间", styledClass: "is-warning" };
+      case SOLVING:
+        return { name: "处理重判期间", styledClass: "is-info" };
+      case END:
+        return { name: "已结束", styledClass: "is-danger" };
+      default:
+        console.log("Review state not found : ", state);
+    }
+  };
+}
+
+export const reviewStateHelperFectory = new ReviewStateHelperFectory();

+ 9 - 0
src/mixins/time.js

@@ -0,0 +1,9 @@
+import dayjs from "dayjs";
+
+export default {
+  methods: {
+    displayUnixTime(time) {
+      return dayjs.unix(time).format("YYYY年 MM月 DD日 HH:mm:ss");
+    }
+  }
+};

+ 4 - 0
src/router/routes.js

@@ -100,6 +100,10 @@ export default [
         path: "review/:reviewId",
         component: () => import("@/views/student/Review/ReviewDetail")
       },
+      {
+        path: "review/:reviewId/doc/:docReviewId",
+        component: () => import("@/views/student/Review/ReviewDocDetail")
+      },
       {
         path: "code",
         component: () => import("@/views/student/Code")

+ 33 - 8
src/views/student/Review/ReviewDetail/index.vue

@@ -9,15 +9,37 @@
       <template slot="title">
         {{ detail.name }}
       </template>
+      <template slot="content">
+        <div>
+          共需要处理 {{ detail.documents && detail.documents.length }} 组作业
+        </div>
+      </template>
+      <template slot="action">
+        <div><review-state-tag :state="detail.state"></review-state-tag></div>
+      </template>
+      <template slot="extraContent">
+        <div class="tag is-light" v-if="detail.state === 'REVIEWING'">
+          互评结束时间 : {{ displayUnixTime(detail.reviewDdl) }}
+        </div>
+        <div class="tag is-light" v-if="detail.state === 'ARGUING'">
+          申诉结束时间 : {{ displayUnixTime(detail.argueDdl) }}
+        </div>
+        <div class="tag is-light" v-if="detail.state === 'SOLVING'">
+          处理申诉结束时间 : {{ displayUnixTime(detail.endDdl) }}
+        </div>
+      </template>
     </page-header>
     <page-body>
-      <div class="review-body">
-        <div class="review-body__left page-section">
-          <div v-if="detail.docContent" class="content">
-            <vue-markdown>{{ detail.docContent }}</vue-markdown>
-          </div>
+      <div class="columns is-multiline is-desktop">
+        <div
+          :key="item.docReviewId"
+          v-for="item in detail.documents"
+          class="column is-4"
+        >
+          <router-link :to="`${$route.path}/doc/${item.docReviewId}`">
+            <card hoverable> {{ item.group.name }} </card>
+          </router-link>
         </div>
-        <div class="review-body__right"></div>
       </div>
     </page-body>
   </div>
@@ -25,15 +47,18 @@
 <script>
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
-import VueMarkdown from "vue-markdown";
+import Card from "@/components/Card";
 import { getStudentReviewDetail } from "@/api/review";
+import timeMixins from "@/mixins/time";
+import ReviewStateTag from "@/components/ReviewStateTag/index";
 export default {
-  components: { PageBody, PageHeader, VueMarkdown },
+  components: { ReviewStateTag, PageBody, PageHeader, Card },
   data() {
     return {
       detail: {}
     };
   },
+  mixins: [timeMixins],
   mounted() {
     const { reviewId } = this.$route.params;
     getStudentReviewDetail(reviewId).then(resp => (this.detail = resp.data));

+ 99 - 0
src/views/student/Review/ReviewDocDetail/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div>
+    <page-header
+      :routes="[
+        { name: '互评作业', path: 'review' },
+        { name: '文档详情', path: `review/${$route.params.reviewId}` },
+        { name: '被评审小组文档', path: $route.path }
+      ]"
+    >
+      <template slot="title">
+        {{ detail.review.name }}
+      </template>
+      <template slot="action">
+        <div>
+          <review-state-tag :state="detail.review.state"></review-state-tag>
+        </div>
+      </template>
+    </page-header>
+    <page-body>
+      <div class="columns">
+        <div class="column is-8">
+          <div class="page-section">
+            <div v-if="detail.docContent" class="content">
+              <vue-markdown>{{ detail.docContent }}</vue-markdown>
+            </div>
+          </div>
+        </div>
+        <div class="column is-4">
+          <div v-for="item in detail.checkList" :key="item.id">
+            <check-judge-item :success="item.level === 1">
+              <b-tooltip :label="item.explain" position="is-left">
+                <b-checkbox
+                  :value="true"
+                  type="is-success"
+                  :name="item.content"
+                >
+                  Success
+                </b-checkbox>
+              </b-tooltip>
+              <input
+                v-model="item.comment"
+                class="input is-small"
+                type="text"
+                placeholder="填写备注"
+                style="box-shadow:none;border-color:white"
+              />
+            </check-judge-item>
+          </div>
+        </div>
+      </div>
+    </page-body>
+  </div>
+</template>
+<script>
+import PageHeader from "@/components/PageHeader";
+import PageBody from "@/components/PageBody/index";
+import VueMarkdown from "vue-markdown";
+import { getStudentReviewDocDetail } from "@/api/review";
+import timeMixins from "@/mixins/time";
+import ReviewStateTag from "@/components/ReviewStateTag/index";
+import CheckJudgeItem from "@/components/CheckListItem/index";
+import BTooltip from "buefy/src/components/tooltip/Tooltip";
+export default {
+  components: {
+    BTooltip,
+    CheckJudgeItem,
+    ReviewStateTag,
+    PageBody,
+    PageHeader,
+    VueMarkdown
+  },
+  data() {
+    return {
+      detail: {
+        review: {}
+      }
+    };
+  },
+  mixins: [timeMixins],
+  mounted() {
+    const { reviewId, docReviewId } = this.$route.params;
+    getStudentReviewDocDetail(reviewId, docReviewId).then(
+      resp => (this.detail = resp.data)
+    );
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+@import "../../../../assets/scss/app";
+.right-part {
+  margin-top: -1.5rem;
+  margin-bottom: -1.5rem;
+  margin-right: -1.5rem;
+  background: white;
+  border-top: 1px solid #eff2f7;
+  box-shadow: $default-shadow-lighter;
+}
+</style>

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

@@ -11,8 +11,11 @@
     <page-body>
       <div class="columns is-multiline is-desktop">
         <div :key="item.id" v-for="item in review" class="column is-4">
-          <router-link :to="`${$route.path}/${item.id}`">
-            <card hoverable>{{ item.name }}</card>
+          <router-link :to="`${$route.path}/${item.reviewId}`">
+            <card hoverable>
+              {{ item.name }}
+              <div><review-state-tag :state="item.state" /></div>
+            </card>
           </router-link>
         </div>
       </div>
@@ -26,8 +29,10 @@ import { getStudentCourseReviewList } from "@/api/review";
 import Card from "@/components/Card";
 import PageHeader from "@/components/PageHeader";
 import PageBody from "@/components/PageBody/index";
+import ReviewStateTag from "@/components/ReviewStateTag/index";
 export default {
   components: {
+    ReviewStateTag,
     PageBody,
     PageHeader,
     Card