From 230b189adbe6dd0706828b53662ed8e50ad4f06c Mon Sep 17 00:00:00 2001
From: 龚焕茏 <2842157468@qq.com>
Date: 星期四, 13 六月 2024 11:25:04 +0800
Subject: [PATCH] feat:答卷

---
 /dev/null                                   |    5 
 src/views/answer/detail.vue                 |  130 ++++++++++++++
 src/views/answer/info.vue                   |  126 ++++++++++++++
 src/components/questionAnswerShow/index.vue |  128 ++++++++++++++
 src/views/answer/list.vue                   |   73 ++++---
 src/api/examPaperAnswer.js                  |    7 
 src/router.js                               |   14 +
 7 files changed, 448 insertions(+), 35 deletions(-)

diff --git a/src/api/examPaperAnswer.js b/src/api/examPaperAnswer.js
new file mode 100644
index 0000000..d5dad9c
--- /dev/null
+++ b/src/api/examPaperAnswer.js
@@ -0,0 +1,7 @@
+import { post } from '@/utils/request'
+
+export default {
+  page: query => post('/api/admin/examPaperAnswer/page', query),
+  pageExamPaper: query => post('/api/admin/examPaperAnswer/pageExamPaper', query),
+  read: id => post('/api/admin/examPaperAnswer/read/' + id)
+}
diff --git a/src/api/examPaperAnwser.js b/src/api/examPaperAnwser.js
deleted file mode 100644
index c10dd2a..0000000
--- a/src/api/examPaperAnwser.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { post } from '@/utils/request'
-
-export default {
-  page: query => post('/api/admin/examPaperAnswer/page', query)
-}
diff --git a/src/components/questionAnswerShow/index.vue b/src/components/questionAnswerShow/index.vue
new file mode 100644
index 0000000..3258152
--- /dev/null
+++ b/src/components/questionAnswerShow/index.vue
@@ -0,0 +1,128 @@
+<template>
+  <div v-loading="qLoading" style="line-height:1.8">
+    <div v-if="qType == 1 || qType == 2 || qType == 3 || qType == 4 || qType == 5">
+      <div v-if="qType == 1">
+        <div class="q-title" v-html="question.title" />
+        <div class="q-content">
+          <el-radio-group v-model="answer.content">
+            <el-radio v-for="item in question.items" :key="item.prefix" :label="item.prefix">
+              <span class="question-prefix">{{ item.prefix }}.</span>
+              <span v-html="item.content" class="q-item-span-content"></span>
+            </el-radio>
+          </el-radio-group>
+        </div>
+      </div>
+      <div v-else-if="qType == 2">
+        <div class="q-title" v-html="question.title" />
+        <div class="q-content">
+          <el-checkbox-group v-model="answer.contentArray">
+            <el-checkbox v-for="item in question.items" :label="item.prefix" :key="item.prefix">
+              <span class="question-prefix">{{ item.prefix }}.</span>
+              <span v-html="item.content" class="q-item-span-content"></span>
+            </el-checkbox>
+          </el-checkbox-group>
+        </div>
+      </div>
+      <div v-else-if="qType == 3">
+        <div class="q-title" v-html="question.title" style="display: inline;margin-right: 10px" />
+        <span style="padding-right: 10px;">(</span>
+        <el-radio-group v-model="answer.content">
+          <el-radio v-for="item in question.items" :key="item.prefix" :label="item.prefix">
+            <span v-html="item.content" class="q-item-span-content"></span>
+          </el-radio>
+        </el-radio-group>
+        <span style="padding-left: 10px;">)</span>
+      </div>
+      <div v-else-if="qType == 4">
+        <div class="q-title" v-html="question.title" />
+        <div v-if="answer.contentArray !== null">
+          <el-form-item :label="item.prefix" :key="item.prefix" v-for="item in question.items" label-width="50px"
+            style="margin-top: 10px;margin-bottom: 10px;">
+            <el-input v-model="answer.contentArray[item.prefix - 1]" />
+          </el-form-item>
+        </div>
+      </div>
+      <div v-else-if="qType == 5">
+        <div class="q-title" v-html="question.title" />
+        <div>
+          <el-input v-model="answer.content" type="textarea" rows="5"></el-input>
+        </div>
+      </div>
+      <div class="question-answer-show-item" style="margin-top: 15px">
+        <span class="question-show-item">缁撴灉锛�</span>
+        <el-tag :type="doRightTagFormatter(answer.doRight)">
+          {{ doRightTextFormatter(answer.doRight) }}
+        </el-tag>
+      </div>
+      <div class="question-answer-show-item">
+        <span class="question-show-item">鍒嗘暟锛�</span>
+        <span>{{ question.score }}</span>
+      </div>
+      <div class="question-answer-show-item">
+        <span class="question-show-item">闅惧害锛�</span>
+        <el-rate disabled v-model="question.difficult" class="question-show-item"></el-rate>
+      </div>
+      <br />
+      <div class="question-answer-show-item" style="line-height: 1.8">
+        <span class="question-show-item">瑙f瀽锛�</span>
+        <span v-html="question.analyze" class="q-item-span-content" />
+      </div>
+      <div class="question-answer-show-item">
+        <span class="question-show-item">姝g‘绛旀锛�</span>
+        <span v-if="qType == 1 || qType == 2 || qType == 5" v-html="question.correct" class="q-item-span-content" />
+        <span v-if="qType == 3" v-html="trueFalseFormatter(question)" class="q-item-span-content" />
+        <span v-if="qType == 4">{{ question.correctArray }}</span>
+      </div>
+    </div>
+    <div v-else>
+    </div>
+  </div>
+
+</template>
+
+<script>
+import { mapState, mapGetters } from 'vuex'
+export default {
+  name: 'QuestionShow',
+  props: {
+    question: {
+      type: Object,
+      default: function () {
+        return {}
+      }
+    },
+    answer: {
+      type: Object,
+      default: function () {
+        return { id: null, content: '', contentArray: [], doRight: false }
+      }
+    },
+    qLoading: {
+      type: Boolean,
+      default: false
+    },
+    qType: {
+      type: Number,
+      default: 0
+    }
+  },
+  methods: {
+    trueFalseFormatter(question) {
+      return question.items.filter(d => d.prefix === question.correct)[0].content
+    },
+    doRightTagFormatter(status) {
+      return this.enumFormat(this.doRightTag, status)
+    },
+    doRightTextFormatter(status) {
+      return this.enumFormat(this.doRightEnum, status)
+    }
+  },
+  computed: {
+    ...mapGetters('enumItem', ['enumFormat']),
+    ...mapState('enumItem', {
+      doRightEnum: state => state.exam.question.answer.doRightEnum,
+      doRightTag: state => state.exam.question.answer.doRightTag
+    })
+  }
+}
+</script>
diff --git a/src/router.js b/src/router.js
index fd84032..4a24ef3 100644
--- a/src/router.js
+++ b/src/router.js
@@ -233,6 +233,20 @@
         component: () => import('@/views/answer/list'),
         name: 'AnswerPageList',
         meta: { title: '绛斿嵎鍒楄〃', noCache: true }
+      },
+      {
+        path: 'answer-list',
+        component: () => import('@/views/answer/info'),
+        name: 'answerList',
+        meta: { title: '绛斿嵎淇℃伅', noCache: true },
+        hidden: true
+      },
+      {
+        path: 'answer-detail',
+        component: () => import('@/views/answer/detail'),
+        name: 'answerDetail',
+        meta: { title: '绛斿嵎璇︽儏', noCache: true },
+        hidden: true
       }
     ]
   },
diff --git a/src/views/answer/detail.vue b/src/views/answer/detail.vue
new file mode 100644
index 0000000..799cd8a
--- /dev/null
+++ b/src/views/answer/detail.vue
@@ -0,0 +1,130 @@
+<template>
+    <div style="background-color: #FFFFFF; padding-top: 50px;min-height: 900px;">
+        <el-row class="do-exam-title" style="background-color: #F5F5DC">
+            <el-col :span="24">
+                <span :key="item.itemOrder" v-for="item in answer.answerItems">
+                    <el-tag :type="questionDoRightTag(item.doRight)" class="do-exam-title-tag"
+                        @click="goAnchor('#question-' + item.itemOrder)">{{ item.itemOrder }}</el-tag>
+                </span>
+            </el-col>
+        </el-row>
+        <el-row class="do-exam-title-hidden">
+            <el-col :span="24">
+                <span :key="item.itemOrder" v-for="item in answer.answerItems">
+                    <el-tag class="do-exam-title-tag">{{ item.itemOrder }}</el-tag>
+                </span>
+            </el-col>
+        </el-row>
+        <el-container class="app-item-contain">
+            <el-header class="align-center">
+                <h1>{{ form.name }}</h1>
+                <div>
+                    <span class="question-title-padding">璇曞嵎寰楀垎锛歿{ answer.score }}</span>
+                    <span class="question-title-padding">璇曞嵎鑰楁椂锛歿{ formatSeconds(answer.doTime) }}</span>
+                </div>
+            </el-header>
+            <el-main>
+                <el-form :model="form" ref="form" v-loading="formLoading" label-width="100px">
+                    <el-row :key="index" v-for="(titleItem, index) in form.titleItems">
+                        <h3>{{ titleItem.name }}</h3>
+                        <el-card class="exampaper-item-box" v-if="titleItem.questionItems.length !== 0">
+                            <el-form-item :key="questionItem.itemOrder" :label="questionItem.itemOrder + '.'"
+                                v-for="questionItem in titleItem.questionItems" class="exam-question-item"
+                                label-width="50px" :id="'question-' + questionItem.itemOrder">
+                                <QuestionAnswerShow :qType="questionItem.questionType" :question="questionItem"
+                                    :answer="answer.answerItems[questionItem.itemOrder - 1]" />
+                            </el-form-item>
+                        </el-card>
+                    </el-row>
+                </el-form>
+            </el-main>
+        </el-container>
+    </div>
+</template>
+
+<script>
+import { mapState, mapGetters } from 'vuex'
+import QuestionAnswerShow from '@/components/questionAnswerShow'
+import examPaperAnswerApi from '@/api/examPaperAnswer'
+export default {
+    components: { QuestionAnswerShow },
+    data() {
+        return {
+            form: {},
+            formLoading: false,
+            answer: {
+                id: null,
+                score: 0,
+                doTime: 0,
+                answerItems: [],
+                doRight: false
+            }
+        }
+    },
+    created() {
+        let id = this.$route.query.id
+        let _this = this
+        if (id && parseInt(id) !== 0) {
+            _this.formLoading = true
+            examPaperAnswerApi.read(id).then(re => {
+                _this.form = re.data.paper
+                _this.answer = re.data.answer
+                _this.formLoading = false
+            })
+        }
+    },
+    methods: {
+        formatSeconds(theTime) {
+            let theTime1 = 0
+            let theTime2 = 0
+            if (theTime > 60) {
+                theTime1 = parseInt(theTime / 60)
+                theTime = parseInt(theTime % 60)
+                if (theTime1 > 60) {
+                    theTime2 = parseInt(theTime1 / 60)
+                    theTime1 = parseInt(theTime1 % 60)
+                }
+            }
+            let result = '' + parseInt(theTime) + '绉�'
+            if (theTime1 > 0) {
+                result = '' + parseInt(theTime1) + '鍒�' + result
+            }
+            if (theTime2 > 0) {
+                result = '' + parseInt(theTime2) + '灏忔椂' + result
+            }
+            return result
+        },
+        questionDoRightTag(status) {
+            return this.enumFormat(this.doRightTag, status)
+        },
+        goAnchor(selector) {
+            this.$el.querySelector(selector).scrollIntoView({ behavior: 'instant', block: 'center', inline: 'nearest' })
+        }
+    },
+    computed: {
+        ...mapGetters('enumItem', ['enumFormat']),
+        ...mapState('enumItem', {
+            doRightTag: state => state.exam.question.answer.doRightTag
+        })
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.align-center {
+    text-align: center
+}
+
+.exam-question-item {
+    padding: 10px;
+
+    .el-form-item__label {
+        font-size: 15px !important;
+    }
+}
+
+.question-title-padding {
+    padding-left: 25px;
+    padding-right: 25px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/answer/info.vue b/src/views/answer/info.vue
new file mode 100644
index 0000000..55df334
--- /dev/null
+++ b/src/views/answer/info.vue
@@ -0,0 +1,126 @@
+<!-- 绛斿嵎绠$悊 -->
+<template>
+  <div class="c">
+    <div class="bg">
+      <div class="main">
+        <!-- 寰呰繑鍥炵殑鏍囬 -->
+        <TitleIndex title="绛斿嵎绠$悊" />
+        <div class="content">
+          <!-- 鎼滅储 -->
+          <div>
+            <el-form :inline="true" :model="queryParam" class="demo-form-inline" label-width="80px">
+              <el-form-item>
+                <el-input v-model="queryParam.userName" placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" clearable></el-input>
+              </el-form-item>
+              <el-form-item>
+                <el-button style="width:100px;" type="primary" size="small" @click="search()">鏌ヨ</el-button>
+                <el-button style="width:100px;" type="danger" size="small" @click="handleExport()">瀵煎嚭</el-button>
+              </el-form-item>
+            </el-form>
+          </div>
+          <!-- 琛ㄦ牸 -->
+          <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%">
+            <el-table-column prop="paperName" label="璇曞嵎鍚嶇О" align="center" />
+            <el-table-column prop="userName" label="鐢ㄦ埛鍚嶇О" align="center" />
+            <el-table-column label="寰楀垎" width="100px">
+              <template slot-scope="{row}">
+                {{ row.userScore }} / {{ row.paperScore }}
+              </template>
+            </el-table-column>
+            <el-table-column label="棰樼洰瀵归敊" width="100px" align="center">
+              <template slot-scope="{row}">
+                {{ row.questionCorrect }} / {{ row.questionCount }}
+              </template>
+            </el-table-column>
+            <el-table-column prop="doTime" label="鑰楁椂" width="80px" align="center" />
+            <el-table-column prop="createTime" label="鎻愪氦鏃堕棿" width="160px" align="center" />
+            <el-table-column label="鎿嶄綔" width="200px" align="center">
+              <template slot-scope="{row}">
+                <el-button size="mini" @click="view(row)">璇︽儏</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <pagination v-show="total > 0" :total="total" :page.sync="queryParam.pageIndex"
+            :limit.sync="queryParam.pageSize" @pagination="search" />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+// 寮曞叆褰堝嚭绐楀彛绲勪欢
+import examPaperAnswerApi from '@/api/examPaperAnswer'
+import Pagination from '@/components/Pagination'
+
+export default {
+  // 娉ㄥ唽
+  components: {
+    Pagination
+  },
+  data() {
+    return {
+      listLoading: true,
+      queryParam: {
+        examPaperId: '',
+        userName: '',
+        pageIndex: 1,
+        pageSize: 10
+      },
+      formLoading: false,
+      total: 0,
+      tableData: [],
+      visible: false,
+      subjects: []
+    };
+  },
+  created() {
+    this.queryParam.examPaperId = this.$route.query.id
+    this.search()
+  },
+  methods: {
+    // 鑾峰彇鍒楄〃
+    search() {
+      this.listLoading = true
+      examPaperAnswerApi.page(this.queryParam).then(re => {
+        this.tableData = re.data.list
+        this.total = re.data.total
+        this.queryParam.pageSize = re.data.pageSize
+        this.queryParam.pageIndex = re.data.pageNum
+        this.listLoading = false
+      })
+    },
+    view(row) {
+      this.$router.push({ path: '/answer/answer-detail', query: { id: row.id } });
+    },
+    handleExport() {
+      let that = this
+      let url = '/api/admin/examPaperAnswer/exportExcel?examPaperId=' + this.queryParam.examPaperId + '&userName=' + this.queryParam.userName
+      var x = new XMLHttpRequest();
+      x.open("POST", url, true);
+      x.responseType = "blob";
+      x.onload = function () {
+        var url = window.URL.createObjectURL(x.response);
+        var a = document.createElement("a");
+        a.href = url;
+        a.download = that.tableData[0].paperName + '.xlsx';
+        a.click();
+      };
+      x.send();
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+.flex {
+  display: flex;
+}
+
+// 鍐呭
+.content {
+  width: 1262px;
+  margin-bottom: 80px;
+  background-color: #fff;
+  padding: 20px 40px;
+  border-radius: 10px;
+}
+</style>
diff --git a/src/views/answer/list.vue b/src/views/answer/list.vue
index 08e7c74..4789557 100644
--- a/src/views/answer/list.vue
+++ b/src/views/answer/list.vue
@@ -1,35 +1,46 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParam" ref="queryForm" :inline="true">
-      <el-form-item label="瀛︾锛�" >
-        <el-select v-model="queryParam.subjectId"  clearable>
+    <el-form :inline="true" :model="queryParam" class="demo-form-inline" label-width="80px">
+      <el-form-item>
+        <el-input v-model="queryParam.name" placeholder="璇疯緭鍏ュ悕绉�" clearable></el-input>
+      </el-form-item>
+      <el-form-item>
+        <el-select v-model="queryParam.subjectId" placeholder="璇烽�夋嫨绉戠洰" clearable multiple @change="search">
           <el-option v-for="item in subjects" :key="item.id" :value="item.id" :label="item.name"></el-option>
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" @click="submitForm">鏌ヨ</el-button>
+        <el-button style="width:100px;" type="primary" size="small" @click="search()">鏌ヨ</el-button>
       </el-form-item>
     </el-form>
 
-    <el-table v-loading="listLoading" :data="tableData" border fit highlight-current-row style="width: 100%">
-      <el-table-column prop="id" label="Id"  width="100" />
-      <el-table-column prop="paperName" label="璇曞嵎鍚嶇О"/>
-      <el-table-column prop="userName" label="鐢ㄦ埛鍚嶇О"/>
-      <el-table-column  label="寰楀垎" width="100px" >
+    <el-table v-loading="listLoading" :data="tableData" border style="width: 100%;">
+      <el-table-column align="center" prop="paperName" label="璇曞嵎鍚嶇О" />
+      <el-table-column align="center" prop="subjectName" label="绉戠洰" />
+      <el-table-column align="center" prop="paperType" label="璇曞嵎绫诲瀷" width="150px">
         <template slot-scope="{row}">
-          {{row.userScore}} / {{row.paperScore}}
+          <span v-if="row.paperType === 1">鍥哄畾璇曞嵎</span>
+          <span v-if="row.paperType === 2">闅忔満璇曞嵎</span>
+          <span v-if="row.paperType === 3">椤哄簭璇曞嵎</span>
         </template>
       </el-table-column>
-      <el-table-column  label="棰樼洰瀵归敊" width="80px" >
+      <el-table-column align="center" prop="questionCount" label="棰樼洰鏁伴噺" width="100px" />
+      <el-table-column align="center" prop="systemScore" label="鎬诲垎" width="100px" />
+      <el-table-column align="center" prop="suggestTime" label="寤鸿鏃堕暱" width="100px" />
+      <el-table-column align="center" prop="personAnswerNum" label="鍙傝�冧汉鏁�" width="100px">
         <template slot-scope="{row}">
-          {{row.questionCorrect}} / {{row.questionCount}}
+          <span>{{ row.personAnswerNum + "/" + row.personTotalNum }}</span>
         </template>
       </el-table-column>
-      <el-table-column prop="doTime" label="鑰楁椂" width="100px"/>
-      <el-table-column prop="createTime" label="鎻愪氦鏃堕棿" width="160px"/>
+      <el-table-column align="center" prop="userName" label="鍒涘缓浜�" width="100px" />
+      <el-table-column label="鎿嶄綔" align="center">
+        <template slot-scope="{row}">
+          <el-button size="mini" @click="view(row)">鏌ョ湅</el-button>
+        </template>
+      </el-table-column>
     </el-table>
-    <pagination v-show="total>0" :total="total" :page.sync="queryParam.pageIndex" :limit.sync="queryParam.pageSize"
-                @pagination="search"/>
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParam.pageIndex"
+      :limit.sync="queryParam.pageSize" @pagination="search" />
   </div>
 </template>
 
@@ -37,40 +48,42 @@
 
 import { mapGetters, mapState, mapActions } from 'vuex'
 import Pagination from '@/components/Pagination'
-import examPaperAnswerApi from '@/api/examPaperAnwser'
+import examPaperAnswerApi from '@/api/examPaperAnswer'
 
 export default {
   components: { Pagination },
   data () {
     return {
+      listLoading: true,
       queryParam: {
-        subjectId: null,
+        name: '',
         pageIndex: 1,
         pageSize: 10
       },
-      listLoading: false,
+      formLoading: false,
+      total: 0,
       tableData: [],
-      total: 0
-    }
+      visible: false
+    };
   },
   created () {
     this.initSubject()
     this.search()
   },
   methods: {
-    search () {
+    // 鑾峰彇鍒楄〃
+    search() {
       this.listLoading = true
-      examPaperAnswerApi.page(this.queryParam).then(data => {
-        const re = data.data
-        this.tableData = re.list
-        this.total = re.total
-        this.queryParam.pageIndex = re.pageNum
+      examPaperAnswerApi.pageExamPaper(this.queryParam).then(re => {
+        this.tableData = re.data.list
+        this.total = re.data.total
+        this.queryParam.pageSize = re.data.pageSize
+        this.queryParam.pageIndex = re.data.pageNum
         this.listLoading = false
       })
     },
-    submitForm () {
-      this.queryParam.pageIndex = 1
-      this.search()
+    view(row) {
+      this.$router.push({ path: '/answer/answer-list', query: { id: row.id } });
     },
     ...mapActions('exam', { initSubject: 'initSubject' })
   },

--
Gitblit v1.8.0