zhangjie 3 yıl önce
ebeveyn
işleme
160670104f

+ 128 - 128
src/modules/grading/marker/MarkerImageView.vue

@@ -1,128 +1,128 @@
-<template>
-  <div class="marker-image-view">
-    <image-view-contain
-      ref="ImageViewContain"
-      :image="image"
-      @to-review="toReview"
-    ></image-view-contain>
-    <div class="image-view-footer">
-      <slot>
-        <div v-if="IS_LEVEL" class="image-info">
-          <div v-if="image.level" class="image-level">{{ image.level }}</div>
-          <div v-if="image.sample" class="image-sample">标</div>
-          <div
-            v-else
-            :class="[
-              'image-checkbox',
-              {
-                'image-selected': image.selected
-              }
-            ]"
-            @click="toSelect"
-          >
-            <Icon v-if="image.selected" type="md-checkmark" />
-          </div>
-          <div class="image-title" @click="toSelect">
-            {{ image.title }}
-          </div>
-        </div>
-        <div v-else class="image-info">
-          <div v-if="image.level" class="image-level">{{ image.level }}</div>
-          <div v-if="image.score" class="image-level">{{ image.score }}</div>
-        </div>
-        <div class="image-action">
-          <div class="image-action-li" @click="toMark">
-            <Icon :class="{ 'mark-act': image.isMark }" type="md-bookmark" />
-          </div>
-          <div class="image-action-li" @click="toRotate">
-            <Icon type="md-refresh-circle" />
-          </div>
-        </div>
-      </slot>
-    </div>
-  </div>
-</template>
-
-<script>
-import ImageViewContain from "@/components/ImageViewContain";
-import { markTask } from "@/api";
-
-export default {
-  name: "marker-image-view",
-  components: { ImageViewContain },
-  props: {
-    data: {
-      type: Object,
-      default() {
-        return {};
-      }
-    },
-    stage: {
-      type: String,
-      default: "LEVEL"
-    },
-    canSelect: {
-      type: Boolean,
-      default: true
-    }
-  },
-  computed: {
-    IS_LEVEL() {
-      return this.stage === "LEVEL";
-    }
-  },
-  created() {
-    this.image = this.$objAssign(this.initImage, this.data);
-  },
-  data() {
-    return {
-      initImage: {
-        id: "",
-        thumbSrc: "",
-        title: "",
-        level: "",
-        score: "",
-        deg: 0,
-        isMark: false,
-        sample: false,
-        selected: false
-      },
-      loading: false,
-      image: {}
-    };
-  },
-  methods: {
-    toReview() {
-      this.$emit("to-review", this.data);
-    },
-    toRotate() {
-      const image = this.image;
-      image.deg += 90;
-      if (image.deg === 360) image.deg = 0;
-
-      this.$refs.ImageViewContain.resizeImage(image.deg);
-    },
-    async toMark() {
-      if (this.loading) return;
-      this.loading = true;
-      const res = await markTask({
-        markTaskId: this.image.id,
-        isMark: !this.image.isMark
-      }).catch(() => {});
-      this.loading = false;
-      if (!res) return;
-      this.image.isMark = !this.image.isMark;
-    },
-    toSelect() {
-      if (this.image.sample) return;
-      this.image.selected = !this.image.selected;
-      this.$emit("to-select", this.image);
-    },
-    changeSelect(selected) {
-      if (this.image.sample) return;
-      this.image.selected = selected;
-      this.$emit("to-select", this.image);
-    }
-  }
-};
-</script>
+<template>
+  <div class="marker-image-view">
+    <image-view-contain
+      ref="ImageViewContain"
+      :image="image"
+      @to-review="toReview"
+    ></image-view-contain>
+    <div class="image-view-footer">
+      <slot>
+        <div v-if="IS_LEVEL" class="image-info">
+          <div v-if="image.level" class="image-level">{{ image.level }}</div>
+          <div v-if="image.sample" class="image-sample">标</div>
+          <div
+            v-else
+            :class="[
+              'image-checkbox',
+              {
+                'image-selected': image.selected
+              }
+            ]"
+            @click="toSelect"
+          >
+            <Icon v-if="image.selected" type="md-checkmark" />
+          </div>
+          <div class="image-title" @click="toSelect">
+            {{ image.title }}
+          </div>
+        </div>
+        <div v-else class="image-info">
+          <div v-if="image.level" class="image-level">{{ image.level }}</div>
+          <div v-if="image.score" class="image-level">{{ image.score }}</div>
+        </div>
+        <div class="image-action">
+          <div class="image-action-li" @click="toMark">
+            <Icon :class="{ 'mark-act': image.mark }" type="md-bookmark" />
+          </div>
+          <div class="image-action-li" @click="toRotate">
+            <Icon type="md-refresh-circle" />
+          </div>
+        </div>
+      </slot>
+    </div>
+  </div>
+</template>
+
+<script>
+import ImageViewContain from "@/components/ImageViewContain";
+import { markTask } from "@/api";
+
+export default {
+  name: "marker-image-view",
+  components: { ImageViewContain },
+  props: {
+    data: {
+      type: Object,
+      default() {
+        return {};
+      }
+    },
+    stage: {
+      type: String,
+      default: "LEVEL"
+    },
+    canSelect: {
+      type: Boolean,
+      default: true
+    }
+  },
+  computed: {
+    IS_LEVEL() {
+      return this.stage === "LEVEL";
+    }
+  },
+  created() {
+    this.image = this.$objAssign(this.initImage, this.data);
+  },
+  data() {
+    return {
+      initImage: {
+        id: "",
+        thumbSrc: "",
+        title: "",
+        level: "",
+        score: "",
+        deg: 0,
+        mark: false,
+        sample: false,
+        selected: false
+      },
+      loading: false,
+      image: {}
+    };
+  },
+  methods: {
+    toReview() {
+      this.$emit("to-review", this.data);
+    },
+    toRotate() {
+      const image = this.image;
+      image.deg += 90;
+      if (image.deg === 360) image.deg = 0;
+
+      this.$refs.ImageViewContain.resizeImage(image.deg);
+    },
+    async toMark() {
+      if (this.loading) return;
+      this.loading = true;
+      const res = await markTask({
+        markTaskId: this.image.id,
+        isMark: !this.image.mark
+      }).catch(() => {});
+      this.loading = false;
+      if (!res) return;
+      this.image.mark = !this.image.mark;
+    },
+    toSelect() {
+      if (this.image.sample) return;
+      this.image.selected = !this.image.selected;
+      this.$emit("to-select", this.image);
+    },
+    changeSelect(selected) {
+      if (this.image.sample) return;
+      this.image.selected = selected;
+      this.$emit("to-select", this.image);
+    }
+  }
+};
+</script>

+ 329 - 329
src/modules/main/PaperManage.vue

@@ -1,329 +1,329 @@
-<template>
-  <div class="paper-manage page-container-flex ">
-    <div class="part-box part-box-filter">
-      <Form ref="FilterForm" label-position="left" inline>
-        <FormItem>
-          <Select
-            v-model="filter.subject"
-            @on-change="subjectChange"
-            placeholder="科目"
-          >
-            <Option
-              v-for="(item, index) in subjects"
-              :key="index"
-              :value="item.subject"
-              :label="item.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.areaCode" placeholder="选择考区" clearable>
-            <Option
-              v-for="area in areas"
-              :key="area.id"
-              :value="area.areaCode"
-              :label="area.areaName"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model="filter.startNumber"
-            type="text"
-            placeholder="输入开始编号"
-            clearable
-          />
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model="filter.endNumber"
-            type="text"
-            placeholder="输入结束编号"
-            clearable
-          />
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="paperType"
-            @on-change="typeChange"
-            placeholder="类型"
-          >
-            <Option
-              v-for="(val, key) in CAFA_EXCEPTION_TYPE"
-              :key="key"
-              :value="key"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Select
-            v-model="filter.scanUserId"
-            placeholder="选择采集账号"
-            clearable
-          >
-            <Option
-              v-for="user in scanUsers"
-              :key="user.id"
-              :value="user.name"
-              :label="user.name"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Input
-            v-model.trim="filter.studentName"
-            placeholder="输入姓名"
-            clearable
-          ></Input>
-        </FormItem>
-        <FormItem>
-          <Select v-model="filter.sortBy" placeholder="排序方式" clearable>
-            <Option
-              v-for="(val, key) in SORT_RULE_TYPE"
-              :key="key"
-              :value="key"
-              :label="val"
-            ></Option>
-          </Select>
-        </FormItem>
-        <FormItem>
-          <Button
-            size="small"
-            class="btn-form-search"
-            type="primary"
-            @click="toPage(1)"
-            >查询</Button
-          >
-        </FormItem>
-      </Form>
-    </div>
-
-    <image-action-list
-      v-if="papers.length"
-      :data="papers"
-      :actions="actions"
-      @on-review="toReview"
-      ref="ImageActionList"
-    ></image-action-list>
-
-    <div class="part-page" v-if="total > size">
-      <Page
-        :current="current"
-        :total="total"
-        :page-size="size"
-        show-total
-        show-elevator
-        @on-change="toPage"
-      ></Page>
-    </div>
-
-    <!-- image-preview -->
-    <simple-image-preview
-      :cur-image="curPaper"
-      @on-prev="toPrevPaper"
-      @on-next="toNextPaper"
-      ref="SimpleImagePreview"
-    ></simple-image-preview>
-  </div>
-</template>
-
-<script>
-import { paperPageList, subjectList, areaList, clientUserQuery } from "@/api";
-import { SORT_RULE_TYPE, CAFA_EXCEPTION_TYPE } from "@/constants/enumerate";
-import ImageActionList from "./components/ImageActionList";
-import SimpleImagePreview from "@/components/SimpleImagePreview";
-
-export default {
-  name: "paper-manage",
-  components: { ImageActionList, SimpleImagePreview },
-  data() {
-    return {
-      filter: {
-        workId: this.$route.params.workId,
-        studentName: "",
-        areaCode: "",
-        startNumber: null,
-        endNumber: null,
-        subject: "",
-        sortBy: "",
-        scanUserId: "",
-        isManual: null,
-        missing: null,
-        isRelate: null,
-        isMark: null
-      },
-      SORT_RULE_TYPE,
-      CAFA_EXCEPTION_TYPE: {},
-      paperType: "9",
-      confirmPaperType: "9",
-      current: 1,
-      size: this.GLOBAL.pageSize,
-      total: 0,
-      totalPage: 0,
-      papers: [],
-      subjects: [],
-      scanUsers: [],
-      areas: [],
-      curPaper: {},
-      curPaperIndex: 0
-    };
-  },
-  computed: {
-    actions() {
-      return this.confirmPaperType === "1"
-        ? ["mark"]
-        : ["rotate", "absent", "mark"];
-    }
-  },
-  mounted() {
-    this.CAFA_EXCEPTION_TYPE = {
-      ...CAFA_EXCEPTION_TYPE,
-      8: "已标记",
-      9: "全部"
-    };
-    this.initData();
-  },
-  methods: {
-    async initData() {
-      await this.getSubjects();
-      this.filter.subject = this.subjects[0].subject;
-      this.filter.areaCode = "";
-      this.areas = [];
-      await this.getAreaList();
-      if (!this.filter.areaCode) {
-        this.filter.areaCode = this.areas[0].areaCode;
-      }
-      this.getScanUsers();
-      this.toPage(1);
-    },
-    async getList() {
-      const datas = {
-        ...this.filter,
-        page: this.current - 1,
-        size: this.size
-      };
-      this.papers = [];
-      const data = await paperPageList(datas);
-      this.papers = data.data.map(paper => {
-        const title = paper.manual
-          ? `${paper.examNumber} ${paper.studentName}`
-          : paper.examNumber;
-        return {
-          id: paper.id,
-          key: this.$randomCode(),
-          title,
-          imgSrc: paper.imgSrc,
-          thumbSrc: paper.thumbSrc,
-          missing: paper.missing,
-          isMark: paper.isMark,
-          stage: paper.stage,
-          styles: {},
-          deg: 0
-        };
-      });
-      this.total = data.totalCount;
-      this.totalPage = data.pageCount;
-    },
-    toPage(page) {
-      if (!this.filter.subject || !this.filter.areaCode) {
-        this.$Message.error("请选择科目和考区!");
-        return;
-      }
-      this.confirmPaperType = this.paperType;
-      this.current = page;
-      this.getList();
-    },
-    subjectChange() {
-      this.filter.areaCode = "";
-      this.areas = [];
-      if (!this.filter.subject) return;
-      this.getAreaList();
-    },
-    async getAreaList() {
-      const data = await areaList({
-        workId: this.filter.workId,
-        subject: this.filter.subject
-      });
-      this.areas = data.map(item => {
-        return {
-          id: item.id,
-          areaName: item.areaName,
-          areaCode: item.areaCode
-        };
-      });
-      if (this.areas.length === 1) {
-        this.filter.areaCode = this.areas[0].areaCode;
-      }
-    },
-    async getSubjects() {
-      const data = await subjectList(this.filter.workId);
-      this.subjects = data.filter(item => item.enable);
-    },
-    async getScanUsers() {
-      const data = await clientUserQuery(this.filter.workId);
-      this.scanUsers = data.data;
-    },
-    typeChange() {
-      const typeToField = {
-        0: "missing",
-        1: "isManual",
-        2: "isRelate",
-        8: "isMark"
-      };
-      Object.values(typeToField).forEach(val => {
-        this.filter[val] = typeToField[this.paperType] === val ? true : null;
-      });
-    },
-    // paper view
-    toReview(index) {
-      this.selectPaper(index);
-      this.$refs.SimpleImagePreview.open();
-    },
-    selectPaper(index) {
-      let nindex = index;
-      if (!this.papers.length) {
-        nindex = 0;
-      } else if (index > this.papers.length - 1) {
-        nindex = this.papers.length - 1;
-      } else if (index < 0) {
-        nindex = 0;
-      }
-      this.curPaperIndex = nindex;
-      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
-    },
-    async toPrevPaper() {
-      if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
-          await this.getList();
-        } else {
-          this.$Message.warning("当前已经是第一条数据了");
-          return;
-        }
-      } else {
-        this.curPaperIndex--;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    },
-    async toNextPaper() {
-      if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
-          this.$Message.warning("当前已经是最后一条数据了");
-          return;
-        } else {
-          this.current++;
-          this.curPaperIndex = 0;
-          await this.getList();
-        }
-      } else {
-        this.curPaperIndex++;
-      }
-
-      this.selectPaper(this.curPaperIndex);
-    }
-  }
-};
-</script>
+<template>
+  <div class="paper-manage page-container-flex ">
+    <div class="part-box part-box-filter">
+      <Form ref="FilterForm" label-position="left" inline>
+        <FormItem>
+          <Select
+            v-model="filter.subject"
+            @on-change="subjectChange"
+            placeholder="科目"
+          >
+            <Option
+              v-for="(item, index) in subjects"
+              :key="index"
+              :value="item.subject"
+              :label="item.name"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.areaCode" placeholder="选择考区" clearable>
+            <Option
+              v-for="area in areas"
+              :key="area.id"
+              :value="area.areaCode"
+              :label="area.areaName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model="filter.startNumber"
+            type="text"
+            placeholder="输入开始编号"
+            clearable
+          />
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model="filter.endNumber"
+            type="text"
+            placeholder="输入结束编号"
+            clearable
+          />
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="paperType"
+            @on-change="typeChange"
+            placeholder="类型"
+          >
+            <Option
+              v-for="(val, key) in CAFA_EXCEPTION_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Select
+            v-model="filter.scanUserId"
+            placeholder="选择采集账号"
+            clearable
+          >
+            <Option
+              v-for="user in scanUsers"
+              :key="user.id"
+              :value="user.loginName"
+              :label="user.loginName"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Input
+            v-model.trim="filter.studentName"
+            placeholder="输入姓名"
+            clearable
+          ></Input>
+        </FormItem>
+        <FormItem>
+          <Select v-model="filter.sortBy" placeholder="排序方式" clearable>
+            <Option
+              v-for="(val, key) in SORT_RULE_TYPE"
+              :key="key"
+              :value="key"
+              :label="val"
+            ></Option>
+          </Select>
+        </FormItem>
+        <FormItem>
+          <Button
+            size="small"
+            class="btn-form-search"
+            type="primary"
+            @click="toPage(1)"
+            >查询</Button
+          >
+        </FormItem>
+      </Form>
+    </div>
+
+    <image-action-list
+      v-if="papers.length"
+      :data="papers"
+      :actions="actions"
+      @on-review="toReview"
+      ref="ImageActionList"
+    ></image-action-list>
+
+    <div class="part-page" v-if="total > size">
+      <Page
+        :current="current"
+        :total="total"
+        :page-size="size"
+        show-total
+        show-elevator
+        @on-change="toPage"
+      ></Page>
+    </div>
+
+    <!-- image-preview -->
+    <simple-image-preview
+      :cur-image="curPaper"
+      @on-prev="toPrevPaper"
+      @on-next="toNextPaper"
+      ref="SimpleImagePreview"
+    ></simple-image-preview>
+  </div>
+</template>
+
+<script>
+import { paperPageList, subjectList, areaList, clientUserQuery } from "@/api";
+import { SORT_RULE_TYPE, CAFA_EXCEPTION_TYPE } from "@/constants/enumerate";
+import ImageActionList from "./components/ImageActionList";
+import SimpleImagePreview from "@/components/SimpleImagePreview";
+
+export default {
+  name: "paper-manage",
+  components: { ImageActionList, SimpleImagePreview },
+  data() {
+    return {
+      filter: {
+        workId: this.$route.params.workId,
+        studentName: "",
+        areaCode: "",
+        startNumber: null,
+        endNumber: null,
+        subject: "",
+        sortBy: "",
+        scanUserId: "",
+        isManual: null,
+        missing: null,
+        isRelate: null,
+        isMark: null
+      },
+      SORT_RULE_TYPE,
+      CAFA_EXCEPTION_TYPE: {},
+      paperType: "9",
+      confirmPaperType: "9",
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      totalPage: 0,
+      papers: [],
+      subjects: [],
+      scanUsers: [],
+      areas: [],
+      curPaper: {},
+      curPaperIndex: 0
+    };
+  },
+  computed: {
+    actions() {
+      return this.confirmPaperType === "1"
+        ? ["mark"]
+        : ["rotate", "absent", "mark"];
+    }
+  },
+  mounted() {
+    this.CAFA_EXCEPTION_TYPE = {
+      ...CAFA_EXCEPTION_TYPE,
+      8: "已标记",
+      9: "全部"
+    };
+    this.initData();
+  },
+  methods: {
+    async initData() {
+      await this.getSubjects();
+      this.filter.subject = this.subjects[0].subject;
+      this.filter.areaCode = "";
+      this.areas = [];
+      await this.getAreaList();
+      if (!this.filter.areaCode) {
+        this.filter.areaCode = this.areas[0].areaCode;
+      }
+      this.getScanUsers();
+      this.toPage(1);
+    },
+    async getList() {
+      const datas = {
+        ...this.filter,
+        page: this.current - 1,
+        size: this.size
+      };
+      this.papers = [];
+      const data = await paperPageList(datas);
+      this.papers = data.data.map(paper => {
+        const title = paper.manual
+          ? `${paper.examNumber} ${paper.studentName}`
+          : paper.examNumber;
+        return {
+          id: paper.id,
+          key: this.$randomCode(),
+          title,
+          imgSrc: paper.imgSrc,
+          thumbSrc: paper.thumbSrc,
+          missing: paper.missing,
+          mark: paper.mark,
+          stage: paper.stage,
+          styles: {},
+          deg: 0
+        };
+      });
+      this.total = data.totalCount;
+      this.totalPage = data.pageCount;
+    },
+    toPage(page) {
+      if (!this.filter.subject || !this.filter.areaCode) {
+        this.$Message.error("请选择科目和考区!");
+        return;
+      }
+      this.confirmPaperType = this.paperType;
+      this.current = page;
+      this.getList();
+    },
+    subjectChange() {
+      this.filter.areaCode = "";
+      this.areas = [];
+      if (!this.filter.subject) return;
+      this.getAreaList();
+    },
+    async getAreaList() {
+      const data = await areaList({
+        workId: this.filter.workId,
+        subject: this.filter.subject
+      });
+      this.areas = data.map(item => {
+        return {
+          id: item.id,
+          areaName: item.areaName,
+          areaCode: item.areaCode
+        };
+      });
+      if (this.areas.length === 1) {
+        this.filter.areaCode = this.areas[0].areaCode;
+      }
+    },
+    async getSubjects() {
+      const data = await subjectList(this.filter.workId);
+      this.subjects = data.filter(item => item.enable);
+    },
+    async getScanUsers() {
+      const data = await clientUserQuery(this.filter.workId);
+      this.scanUsers = data;
+    },
+    typeChange() {
+      const typeToField = {
+        0: "missing",
+        1: "isManual",
+        2: "isRelate",
+        8: "isMark"
+      };
+      Object.values(typeToField).forEach(val => {
+        this.filter[val] = typeToField[this.paperType] === val ? true : null;
+      });
+    },
+    // paper view
+    toReview(index) {
+      this.selectPaper(index);
+      this.$refs.SimpleImagePreview.open();
+    },
+    selectPaper(index) {
+      let nindex = index;
+      if (!this.papers.length) {
+        nindex = 0;
+      } else if (index > this.papers.length - 1) {
+        nindex = this.papers.length - 1;
+      } else if (index < 0) {
+        nindex = 0;
+      }
+      this.curPaperIndex = nindex;
+      this.curPaper = this.papers[nindex] ? { ...this.papers[nindex] } : {};
+    },
+    async toPrevPaper() {
+      if (this.curPaperIndex === 0) {
+        if (this.current > 1) {
+          this.current--;
+          this.curPaperIndex = this.size - 1;
+          await this.getList();
+        } else {
+          this.$Message.warning("当前已经是第一条数据了");
+          return;
+        }
+      } else {
+        this.curPaperIndex--;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    },
+    async toNextPaper() {
+      if (this.curPaperIndex === this.papers.length - 1) {
+        if (this.current === this.totalPage) {
+          this.$Message.warning("当前已经是最后一条数据了");
+          return;
+        } else {
+          this.current++;
+          this.curPaperIndex = 0;
+          await this.getList();
+        }
+      } else {
+        this.curPaperIndex++;
+      }
+
+      this.selectPaper(this.curPaperIndex);
+    }
+  }
+};
+</script>

+ 155 - 156
src/modules/main/components/ImageActionList.vue

@@ -1,156 +1,155 @@
-<template>
-  <div :class="classes">
-    <div class="image-view" v-for="(image, index) in data" :key="image.key">
-      <div class="image-view-container">
-        <h5 class="image-view-title">{{ image.title }}</h5>
-        <image-view-contain
-          v-if="canRotate"
-          :ref="`image${image.id}`"
-          :image="image"
-          @to-review="toReview(index)"
-        ></image-view-contain>
-        <div v-else class="image-view-contain">
-          <img
-            :src="image.thumbSrc"
-            :alt="image.title"
-            :style="image.styles"
-            @click="toReview(index)"
-          />
-        </div>
-        <div class="image-view-actions" v-if="actions.length">
-          <div>
-            <Button
-              class="view-action-rotate"
-              size="small"
-              icon="md-refresh"
-              @click="toRotate(image)"
-              v-if="canRotate"
-            ></Button>
-            <Button
-              class="view-action-save"
-              size="small"
-              type="primary"
-              @click="toSaveRotate(image)"
-              :disabled="saving"
-              v-if="canRotate && image['stepDeg']"
-              >保存</Button
-            >
-          </div>
-          <div>
-            <Button
-              class="view-action-absent"
-              :type="image.missing ? 'error' : 'default'"
-              size="small"
-              @click="toSignAbsent(image)"
-              v-if="canAbsent"
-              >缺考</Button
-            >
-            <Button
-              v-if="canMark"
-              :class="['view-action-mark', { 'mark-act': image.isMark }]"
-              :type="image.missing ? 'error' : 'default'"
-              size="small"
-              icon="md-bookmark"
-              @click="toMark(image)"
-            ></Button>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { rotatePaper, absentPaper, markPaper } from "@/api";
-import ImageViewContain from "../../../components/ImageViewContain";
-
-export default {
-  name: "image-action-list",
-  components: { ImageViewContain },
-  props: {
-    data: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    actions: {
-      type: Array,
-      default() {
-        return [];
-      }
-    },
-    columnNumber: {
-      type: Number,
-      default: 5
-    }
-  },
-  data() {
-    return {
-      curImageIndex: 0,
-      stepDeg: 0,
-      saving: false
-    };
-  },
-  computed: {
-    classes() {
-      return [
-        "image-action-list",
-        "image-view-list",
-        `image-view-list-${this.columnNumber}`
-      ];
-    },
-    canRotate() {
-      return this.actions.includes("rotate");
-    },
-    canAbsent() {
-      return this.actions.includes("absent");
-    },
-    canMark() {
-      return this.actions.includes("mark");
-    }
-  },
-  methods: {
-    toRotate(image) {
-      if (!image["stepDeg"]) this.$set(image, "stepDeg", 0);
-      image.deg += 90;
-      if (image.deg === 360) image.deg = 0;
-      image.stepDeg += 90;
-      if (image.stepDeg === 360) image.stepDeg = 0;
-      image.styles = {
-        transform: `rotate(${image.deg}deg)`
-      };
-
-      this.$refs[`image${image.id}`][0].resizeImage(image.deg);
-    },
-    async toSaveRotate(image) {
-      if (this.saving) return;
-      if (!image.stepDeg) return;
-      this.saving = true;
-
-      let result = true;
-      await rotatePaper(image.id, image.stepDeg).catch(() => {
-        result = false;
-      });
-      this.saving = false;
-      if (!result) return;
-      image.stepDeg = 0;
-      this.$Message.success("保存成功!");
-    },
-    async toSignAbsent(image) {
-      await absentPaper(image.id);
-      image.missing = !image.missing;
-    },
-    async toMark(image) {
-      await markPaper({
-        paperId: image.id,
-        isMark: !image.isMark
-      });
-      image.isMark = !image.isMark;
-    },
-    toReview(index) {
-      this.$emit("on-review", index);
-    }
-  }
-};
-</script>
+<template>
+  <div :class="classes">
+    <div class="image-view" v-for="(image, index) in data" :key="image.key">
+      <div class="image-view-container">
+        <h5 class="image-view-title">{{ image.title }}</h5>
+        <image-view-contain
+          v-if="canRotate"
+          :ref="`image${image.id}`"
+          :image="image"
+          @to-review="toReview(index)"
+        ></image-view-contain>
+        <div v-else class="image-view-contain">
+          <img
+            :src="image.thumbSrc"
+            :alt="image.title"
+            :style="image.styles"
+            @click="toReview(index)"
+          />
+        </div>
+        <div class="image-view-actions" v-if="actions.length">
+          <div>
+            <Button
+              class="view-action-rotate"
+              size="small"
+              icon="md-refresh"
+              @click="toRotate(image)"
+              v-if="canRotate"
+            ></Button>
+            <Button
+              class="view-action-save"
+              size="small"
+              type="primary"
+              @click="toSaveRotate(image)"
+              :disabled="saving"
+              v-if="canRotate && image['stepDeg']"
+              >保存</Button
+            >
+          </div>
+          <div>
+            <Button
+              class="view-action-absent"
+              :type="image.missing ? 'error' : 'default'"
+              size="small"
+              @click="toSignAbsent(image)"
+              v-if="canAbsent"
+              >缺考</Button
+            >
+            <Button
+              v-if="canMark"
+              :class="['view-action-mark', { 'mark-act': image.mark }]"
+              size="small"
+              icon="md-bookmark"
+              @click="toMark(image)"
+            ></Button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { rotatePaper, absentPaper, markPaper } from "@/api";
+import ImageViewContain from "../../../components/ImageViewContain";
+
+export default {
+  name: "image-action-list",
+  components: { ImageViewContain },
+  props: {
+    data: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    actions: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    columnNumber: {
+      type: Number,
+      default: 5
+    }
+  },
+  data() {
+    return {
+      curImageIndex: 0,
+      stepDeg: 0,
+      saving: false
+    };
+  },
+  computed: {
+    classes() {
+      return [
+        "image-action-list",
+        "image-view-list",
+        `image-view-list-${this.columnNumber}`
+      ];
+    },
+    canRotate() {
+      return this.actions.includes("rotate");
+    },
+    canAbsent() {
+      return this.actions.includes("absent");
+    },
+    canMark() {
+      return this.actions.includes("mark");
+    }
+  },
+  methods: {
+    toRotate(image) {
+      if (!image["stepDeg"]) this.$set(image, "stepDeg", 0);
+      image.deg += 90;
+      if (image.deg === 360) image.deg = 0;
+      image.stepDeg += 90;
+      if (image.stepDeg === 360) image.stepDeg = 0;
+      image.styles = {
+        transform: `rotate(${image.deg}deg)`
+      };
+
+      this.$refs[`image${image.id}`][0].resizeImage(image.deg);
+    },
+    async toSaveRotate(image) {
+      if (this.saving) return;
+      if (!image.stepDeg) return;
+      this.saving = true;
+
+      let result = true;
+      await rotatePaper(image.id, image.stepDeg).catch(() => {
+        result = false;
+      });
+      this.saving = false;
+      if (!result) return;
+      image.stepDeg = 0;
+      this.$Message.success("保存成功!");
+    },
+    async toSignAbsent(image) {
+      await absentPaper(image.id);
+      image.missing = !image.missing;
+    },
+    async toMark(image) {
+      await markPaper({
+        paperId: image.id,
+        isMark: !image.mark
+      });
+      image.mark = !image.mark;
+    },
+    toReview(index) {
+      this.$emit("on-review", index);
+    }
+  }
+};
+</script>