checkQuestionCard.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <template>
  2. <el-card class="cQuestion-card" shadow="hover">
  3. <template #header>
  4. <el-row>
  5. <el-col :span="3">
  6. <span><strong>S/N: </strong>{{curNum+1}} / {{totalNum}}</span>
  7. </el-col>
  8. <el-col :span="5">
  9. <span><strong>题目类型: </strong>{{questionvo.type}}</span>
  10. </el-col>
  11. <el-col :span="6">
  12. <div class="bQuestion-card-body-knowledgeID">
  13. <span v-if="questionvo.knowledgeId && questionvo.knowledgeId.length !== 0">
  14. <span><strong>KnowledgeId: </strong></span>
  15. <el-tooltip v-for="item in questionvo.knowledgeId" effect="dark" placement="bottom">
  16. <template #content>
  17. {{map(item)}}
  18. </template>
  19. <el-tag effect="dark" style="margin-right: 2px">{{item}}</el-tag>
  20. </el-tooltip>
  21. </span>
  22. <span v-else>
  23. <span><strong>KnowledgeId: </strong>null</span>
  24. </span>
  25. </div>
  26. </el-col>
  27. <el-col :span="6"></el-col>
  28. <el-col :span="2">
  29. <el-button type="text" circle @click="expand" v-if="!isAll"><strong>展开</strong></el-button>
  30. <el-button type="text" circle @click="withdraw" v-if="isAll"><strong>收起</strong></el-button>
  31. </el-col>
  32. <el-col :span="1">
  33. <el-button type="primary" icon="el-icon-check" circle @click="approve"></el-button>
  34. </el-col>
  35. <el-col :span="1">
  36. <el-button type="warning" icon="el-icon-close" circle @click="checkDialogVisible=true"></el-button>
  37. </el-col>
  38. </el-row>
  39. </template>
  40. <div class="question-body">
  41. <div class="bQuestion-card-body">
  42. <div class="bQuestion-card-body-stem">
  43. <div>
  44. <MarkdownText :raw="'<strong>题目: </strong>'+questionvo.stem"></MarkdownText>
  45. </div>
  46. <div class="stem-extension" v-if="isAll">
  47. <div class="bQuestion-card-body-options" v-if="questionvo.type === 'choice'">
  48. <div v-for="(item,index) in questionvo.options" >
  49. <div v-if="questionvo.answer.split('').indexOf(index) !== -1" class="underline-correct-answer">
  50. <MarkdownText :raw="index+': '+item"></MarkdownText>
  51. </div>
  52. <div v-else>
  53. <MarkdownText :raw="index+': '+item"></MarkdownText>
  54. </div>
  55. </div>
  56. </div>
  57. <div class="bQuestion-card-body-options" v-if="questionvo.type === 'multiple_choice'">
  58. <div v-for="(item,index) in questionvo.options" >
  59. <div v-if="questionvo.answer.split(';').indexOf(index) !== -1" class="underline-correct-answer">
  60. <MarkdownText :raw="index+': '+item"></MarkdownText>
  61. </div>
  62. <div v-else>
  63. <MarkdownText :raw="index+': '+item"></MarkdownText>
  64. </div>
  65. </div>
  66. </div>
  67. <div class="bQuestion-card-body-blanks" v-if="questionvo.type === 'blank'">
  68. <div v-for="index in Object.keys(questionvo.blanks).length">
  69. <div class="correct_answer">
  70. __{{index}}__: {{questionvo.blanks['__'+index+'__']}}
  71. </div>
  72. </div>
  73. </div>
  74. <div class="bQuestion-card-body-true_false" v-if="questionvo.type === 'true_false'">
  75. <div class="correct_answer"> {{questionvo.answer}}</div>
  76. </div>
  77. </div>
  78. </div>
  79. <el-divider v-if="isAll"></el-divider>
  80. <div class="bQuestion-card-body-info" v-if="isAll">
  81. <div class="info-block">
  82. <el-row>
  83. <el-col :span="10">
  84. <strong>KeyPoints: </strong>{{questionvo.keyPoints}}
  85. </el-col>
  86. <el-col :span="6">
  87. <strong>题目难度: </strong>{{questionvo.weight}}/5
  88. </el-col>
  89. <el-col :span="4">
  90. <span><strong>Tags: </strong></span>
  91. <span v-if="questionvo.tags && questionvo.tags.length !== 0">
  92. <el-tag v-for="(item, index) in questionvo.tags" effect="dark">{{item}}</el-tag>
  93. </span>
  94. <span v-else>
  95. <span>no tags</span>
  96. </span>
  97. </el-col>
  98. </el-row>
  99. </div>
  100. <div>
  101. <div class="info-block"
  102. v-if="questionvo.type === 'choice' ||
  103. questionvo.type === 'multiple_choice' ||
  104. questionvo.type === 'true_false' ||
  105. questionvo.type === 'short_answer'">
  106. <MarkdownText :raw="'<strong>正确答案: </strong>'+questionvo.answer"></MarkdownText>
  107. </div>
  108. </div>
  109. <div>
  110. <div class="info-block"
  111. v-if="questionvo.type === 'choice' ||
  112. questionvo.type === 'multiple_choice' ||
  113. questionvo.type === 'true_false'">
  114. <MarkdownText :raw="'<strong>解析: </strong>'+questionvo.analysis"></MarkdownText>
  115. </div>
  116. <div class="info-block" v-if="questionvo.type === 'blank' && questionvo.analysis.length > 5">
  117. <MarkdownText :raw="'<strong>解析: </strong>'+questionvo.analysis"></MarkdownText>
  118. </div>
  119. <div class="info-block" v-if="questionvo.type === 'short_answer' && questionvo.analysis.length > 5">
  120. <MarkdownText :raw="'<strong>解析: </strong>'+questionvo.analysis"></MarkdownText>
  121. </div>
  122. </div>
  123. </div>
  124. </div>
  125. <el-divider v-if="isAll"></el-divider>
  126. <div class="bQuestion-card-footer" v-show="isAll">
  127. <div class="footer">
  128. <el-row>
  129. <el-col :span="3">
  130. <div><strong>状态: </strong>{{questionvo.state}}</div>
  131. </el-col>
  132. <el-col :span="5">
  133. <div><strong>申请人: </strong>{{savedUserName}}</div>
  134. </el-col>
  135. <el-col :span="10"></el-col>
  136. <el-col :span="6">
  137. <div>
  138. <strong>申请日期: </strong> {{toMyDate(questionvo.createdTime)}}
  139. </div>
  140. </el-col>
  141. </el-row>
  142. </div>
  143. <div class="footer" v-if="recordList.length !== 0">
  144. <el-table :data="recordTable" style="width: 100%;background-color: transparent" height="100">
  145. <el-table-column prop="序号" label="序号" width="240" />
  146. <el-table-column prop="操作时间" label="操作时间" width="360" />
  147. <el-table-column prop="操作人" label="操作人" width="240" />
  148. <el-table-column prop="操作类型" label="操作类型" />
  149. </el-table>
  150. </div>
  151. <div class="footer" v-else>
  152. <p>No Record!</p>
  153. </div>
  154. </div>
  155. </div>
  156. </el-card>
  157. <el-dialog title="审核不通过原因" v-model="checkDialogVisible" width="30%" center
  158. :before-close="handleCheckDialogClose">
  159. <el-space direction="vertical">
  160. <el-space direction="vertical" :fill="true">
  161. <el-checkbox-group v-model="failCheckList">
  162. <el-checkbox v-for="(item, index) in failCheckOption" :label="item" class="fail-check-option"/>
  163. </el-checkbox-group>
  164. <el-input v-model="failCheckInput" placeholder="请输入原因"/>
  165. </el-space>
  166. <el-button type="primary" @click="deny">提交</el-button>
  167. </el-space>
  168. </el-dialog>
  169. </template>
  170. <script>
  171. import MarkdownText from "./MarkdownText";
  172. import {toMyDate} from "../utils/dateConvertor";
  173. import {map} from "../utils/knowledgeMapper";
  174. import store from "../store";
  175. export default {
  176. name: "checkCard",
  177. components:{
  178. MarkdownText,
  179. },
  180. props: {
  181. questionvo: Object,
  182. curNum: Number,
  183. totalNum: Number,
  184. },
  185. data(){
  186. return{
  187. isAll: false,
  188. savedUserName: '',
  189. // 审核dialog的可视化
  190. checkDialogVisible: false,
  191. // 审核失败的原因
  192. failCheckOption: [
  193. '题目中存在错误','题目与相关内容无关','题目中存在敏感词','其他'
  194. ],
  195. // 详细解释
  196. failCheckInput: "",
  197. failCheckList: [],
  198. recordList: [],
  199. recordNameDict: {},
  200. }
  201. },
  202. computed: {
  203. recordTable(){
  204. let recordTable1 = [];
  205. let length = this.recordList.length;
  206. for (let i = 0; i < length; i++) {
  207. let recordDict = {};
  208. recordDict["序号"] = i+1;
  209. recordDict["操作时间"] = this.toMyDate(this.recordList[length-i-1].time);
  210. recordDict["操作人"] = this.recordNameDict[this.recordList[length-i-1].userId];
  211. recordDict["操作类型"] = this.recordList[length-i-1].operationType;
  212. recordTable1.push(recordDict);
  213. }
  214. return recordTable1;
  215. },
  216. denyReason(){
  217. let denyReason = "";
  218. for (let reason of this.failCheckList) {
  219. denyReason += reason+", ";
  220. }
  221. denyReason += this.failCheckInput;
  222. return denyReason;
  223. }
  224. },
  225. methods: {
  226. map,
  227. toMyDate,
  228. expand(){
  229. if(!this.isAll){
  230. this.isAll = true;
  231. }
  232. },
  233. withdraw(){
  234. if(this.isAll){
  235. this.isAll = false;
  236. }
  237. },
  238. approve(){ // 通过审核
  239. this.questionvo.state = "APPROVED";
  240. let record = {
  241. userId: store.state.user.id,
  242. operationType: "Approve",
  243. }
  244. this.$api.updateQuestion(this.questionvo)
  245. .then(res => {
  246. this.$message({
  247. type: 'success',
  248. message: '通过成功!'
  249. });
  250. console.log("checkQuestionCard-approve");
  251. console.log(res);
  252. record.questionId = res.data.result.id;
  253. record.time = new Date();
  254. // 审核通过,添加操作记录
  255. this.$api.createRecord(record)
  256. .then(res1 => {
  257. console.log("checkQuestionCard-approve-createRecord");
  258. console.log(res1);
  259. }).catch(err1 => {
  260. console.log(err1);
  261. })
  262. })
  263. .catch(err => {
  264. this.$notify.error({
  265. title: '错误',
  266. message: '通过失败'
  267. });
  268. console.log(err);
  269. })
  270. },
  271. deny(){ // 拒绝通过
  272. let reason = this.denyReason
  273. this.questionvo.state = "REFUSED";
  274. let record = {
  275. userId: store.state.user.id,
  276. operationType: "Refuse",
  277. }
  278. this.$api.updateQuestion(this.questionvo)
  279. .then(res => {
  280. this.$message({
  281. type: 'success',
  282. message: '拒绝成功!'
  283. });
  284. console.log("checkQuestionCard-deny")
  285. console.log(res);
  286. record.questionId = res.data.result.id;
  287. record.time = new Date();
  288. // todo 这里直接调用denyReason就为空?
  289. record.remark = reason;
  290. // 审核通过,添加操作记录
  291. this.$api.createRecord(record)
  292. .then(res1 => {
  293. console.log("checkQuestionCard-deny-createRecord");
  294. console.log(res1);
  295. }).catch(err1 => {
  296. console.log(err1);
  297. })
  298. })
  299. .catch(err => {
  300. this.$notify.error({
  301. title: '错误',
  302. message: '拒绝失败'
  303. });
  304. console.log(err);
  305. })
  306. this.failCheckList = []
  307. this.failCheckInput = ""
  308. this.checkDialogVisible = false
  309. },
  310. // 关闭审核dialog前的方法
  311. handleCheckDialogClose(done){
  312. const _this = this
  313. _this.$confirm('此操作将丢失填写信息, 是否继续?', '提示')
  314. .then(() => {
  315. _this.failCheckList = []
  316. _this.failCheckInput = ""
  317. done()})
  318. .catch(()=>{})
  319. },
  320. },
  321. mounted() {
  322. if(this.questionvo.savedUserId){
  323. this.$api.getUserById(this.questionvo.savedUserId)
  324. .then(res => {
  325. if(res.data.result.name){
  326. this.savedUserName = res.data.result.name;
  327. }
  328. }).catch(err => {
  329. console.log(err);
  330. })
  331. }
  332. this.$api.getRecordByQid(this.questionvo.id) // 异步函数2:根据题目id获得ope_record
  333. .then(res1 => {
  334. let tempList = res1.data.result.content;
  335. this.recordList = tempList;
  336. for (let record of tempList) { //这里换成this.recordList是没问题的
  337. if(!this.recordNameDict[record.userId]){
  338. this.$api.getUserById(record.userId) //异步函数3:根据记录中的用户ID获得其name
  339. .then(res2 => {
  340. if(res2.data.result.name){
  341. this.recordNameDict[record.userId] = res2.data.result.name;
  342. }
  343. }).catch(err2 => {
  344. console.log(err2);
  345. })
  346. }
  347. }
  348. }).catch(err1 => {
  349. console.log(err1);
  350. });
  351. }
  352. }
  353. </script>
  354. <style>
  355. .cQuestion-card{
  356. margin: 20px;
  357. font-size: 18px;
  358. background-color: #eef7f2;
  359. }
  360. </style>