浏览代码

feat: 创建、修改题目的时候增加知识点的选择

ChenYangfan 6 年之前
父节点
当前提交
e50646b432

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@riophae/vue-treeselect": "^0.4.0",
     "core-js": "^3.4.3",
     "highlight.js": "^9.17.1",
     "laue": "^0.2.1",

+ 5 - 0
src/config/server-info.js

@@ -29,6 +29,10 @@ const useCourseServer = postfix => postfix ? courseUrl + postfix : courseUrl
 const courseFileUrl = host + '/api/course-file'
 const useCourseFileServer = postfix => postfix ? courseFileUrl + postfix : courseFileUrl
 
+// 知识点相关接口
+const knowledgeUrl = host + '/api/knowledge'
+const useKnowledgeServer = (postfix = '') => knowledgeUrl + postfix
+
 // 系统提示消息
 const messageUrl = host + '/api/message'
 const useMessageServer = postfix => postfix ? messageUrl + postfix : messageUrl
@@ -64,6 +68,7 @@ export {
   useCommentWsServer,
   useCourseServer,
   useCourseFileServer,
+  useKnowledgeServer,
   useMessageServer,
   useNoticeServer,
   useQuestionServer,

+ 7 - 0
src/server/knowledge.js

@@ -0,0 +1,7 @@
+import axios from '@/plugins/axios'
+import { useKnowledgeServer } from '@/config/server-info'
+
+export function getKnowledgeNodes () {
+  return axios.get(useKnowledgeServer())
+    .then(res => res.data)
+}

+ 6 - 4
src/server/question.js

@@ -29,12 +29,13 @@ export function getOneQuestion ({ questionId }) {
 
 // 创建题目
 // todo keyPoints tags knowledgeId
-export function createQuestion ({ stem = '', analysis, type, options = [], answer }) {
+export function createQuestion ({ stem = '', analysis, type, options = [], answer, knowledgeId }) {
   const data = {
     stem,
     analysis,
     type,
-    answer
+    answer,
+    knowledgeId
   }
   if (type === kinds.choice) {
     data.options = options
@@ -45,12 +46,13 @@ export function createQuestion ({ stem = '', analysis, type, options = [], answe
 }
 
 // 修改题目
-export function modifyQuestion ({ questionId, stem = '', analysis, type, options = [], answer }) {
+export function modifyQuestion ({ questionId, stem = '', analysis, type, options = [], answer, knowledgeId }) {
   const data = {
     stem,
     analysis,
     type,
-    answer
+    answer,
+    knowledgeId
   }
   if (type === kinds.choice) {
     data.options = options

+ 27 - 0
src/utils/construct-tree.js

@@ -0,0 +1,27 @@
+export function constructTree (knowledgeList) {
+  if (!Array.isArray(knowledgeList)) return
+
+  const lookup = new Map()
+
+  for (const item of knowledgeList) {
+    lookup.set(item.id, {
+      id: item.abbreviation,
+      label: item.name,
+      rawId: item.id,
+      raw: item
+    })
+  }
+
+  for (const value of lookup.values()) {
+    const parentId = value.raw.parentId
+    if (parentId !== undefined && parentId !== null) {
+      const parent = lookup.get(parentId)
+      if (parent) {
+        value.parent = parent
+        parent.children = [...(parent.children || []), value]
+      }
+    }
+  }
+
+  return Array.from(lookup.values()).filter((item) => !item.parent)
+}

+ 47 - 12
src/views/quiz/components/QuestionEditorFactory.vue

@@ -1,11 +1,23 @@
 <template>
-  <slide-in-same-transition>
-    <keep-alive>
-      <choice-question-editor v-if="kind === QuestionKind.choice" :initValue="initValue" @submit="handleSubmit"/>
-      <true-false-question-editor v-else-if="kind === QuestionKind.trueOrFalse" :initValue="initValue"
-                                  @submit="handleSubmit"/>
-    </keep-alive>
-  </slide-in-same-transition>
+  <div>
+    <div>知识点(选填)</div>
+    <treeselect
+      class="mt-16"
+      v-if="knowledgeTree"
+      v-model="selectedKnowledgeIdList"
+      :multiple="true"
+      :options="knowledgeTree ? knowledgeTree : null"
+      placeholder="选择相关知识点"
+    />
+    <div v-else class="mt-24">知识点加载中...</div>
+    <slide-in-same-transition>
+      <keep-alive>
+        <choice-question-editor v-if="kind === QuestionKind.choice" :initValue="initValue" @submit="handleSubmit"/>
+        <true-false-question-editor v-else-if="kind === QuestionKind.trueOrFalse" :initValue="initValue"
+                                    @submit="handleSubmit"/>
+      </keep-alive>
+    </slide-in-same-transition>
+  </div>
 </template>
 
 <script>
@@ -13,9 +25,14 @@ import QuestionKind from '@/enums/question-kind'
 import ChoiceQuestionEditor from '@/views/quiz/components/ChoiceQuestionEditor'
 import TrueFalseQuestionEditor from '@/views/quiz/components/TrueFalseQuestionEditor'
 import SlideInSameTransition from '@/animations/SlideInSameTransition'
+import { getKnowledgeNodes } from '@/server/knowledge'
+import Treeselect from '@riophae/vue-treeselect'
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { constructTree } from '@/utils/construct-tree'
+
 export default {
   name: 'QuestionEditorFactory',
-  components: { TrueFalseQuestionEditor, ChoiceQuestionEditor, SlideInSameTransition },
+  components: { Treeselect, TrueFalseQuestionEditor, ChoiceQuestionEditor, SlideInSameTransition },
   props: {
     initValue: {
       type: Object,
@@ -26,17 +43,35 @@ export default {
       default: ''
     }
   },
+  created () {
+    this.getKnowledgeNodes()
+  },
   data () {
-    return { QuestionKind }
+    return {
+      knowledgeTree: null,
+      selectedKnowledgeIdList: this.initValue.knowledgeId,
+      QuestionKind
+    }
+  },
+  watch: {
+    initValue (value) {
+      this.selectedKnowledgeIdList = value.knowledgeId
+    }
   },
   methods: {
+    getKnowledgeNodes () {
+      getKnowledgeNodes()
+        .then(res => {
+          this.knowledgeTree = constructTree(res)
+        })
+        .catch(err => this.$setErrorMessage(err.response.data.msg))
+    },
     handleSubmit (event) {
-      this.$emit('submit', { ...this.initValue, ...event })
+      this.$emit('submit', { ...this.initValue, ...event, knowledgeId: this.selectedKnowledgeIdList })
     }
   }
 }
 </script>
 
-<style scoped>
-
+<style lang="scss" scoped>
 </style>

+ 51 - 0
yarn.lock

@@ -712,6 +712,13 @@
   dependencies:
     regenerator-runtime "^0.13.2"
 
+"@babel/runtime@^7.3.1":
+  version "7.9.2"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06"
+  integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
 "@babel/template@^7.4.0", "@babel/template@^7.7.4":
   version "7.7.4"
   resolved "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.7.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftemplate%2Fdownload%2F%40babel%2Ftemplate-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
@@ -1012,6 +1019,20 @@
     "@nodelib/fs.scandir" "2.1.3"
     fastq "^1.6.0"
 
+"@riophae/vue-treeselect@^0.4.0":
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/@riophae/vue-treeselect/-/vue-treeselect-0.4.0.tgz#0baed5a794cffc580b63591f35c125e51c0df241"
+  integrity sha512-J4atYmBqXQmiPFK/0B5sXKjtnGc21mBJEiyKIDZwk0Q9XuynVFX6IJ4EpaLmUgL5Tve7HAS7wkiGGSti6Uaxcg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    babel-helper-vue-jsx-merge-props "^2.0.3"
+    easings-css "^1.0.0"
+    fuzzysearch "^1.0.3"
+    is-promise "^2.1.0"
+    lodash "^4.0.0"
+    material-colors "^1.2.6"
+    watch-size "^2.0.0"
+
 "@samverschueren/stream-to-observable@^0.3.0":
   version "0.3.0"
   resolved "https://registry.npm.taobao.org/@samverschueren/stream-to-observable/download/@samverschueren/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
@@ -2003,6 +2024,11 @@ babel-extract-comments@^1.0.0:
   dependencies:
     babylon "^6.18.0"
 
+babel-helper-vue-jsx-merge-props@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
+  integrity sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==
+
 babel-jest@^24.9.0:
   version "24.9.0"
   resolved "https://registry.npm.taobao.org/babel-jest/download/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54"
@@ -3894,6 +3920,11 @@ duplexify@^3.4.2, duplexify@^3.6.0:
     readable-stream "^2.0.0"
     stream-shift "^1.0.0"
 
+easings-css@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/easings-css/-/easings-css-1.0.0.tgz#dde569003bb7a4a0c0b77878f5db3e0be5679c81"
+  integrity sha512-7Uq7NdazNfVtr0RNmPAys8it0zKCuaqxJStYKEl72D3j4gbvXhhaM7iWNbqhA4C94ygCye6VuyhzBRQC4szeBg==
+
 easy-stack@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npm.taobao.org/easy-stack/download/easy-stack-1.0.0.tgz#12c91b3085a37f0baa336e9486eac4bf94e3e788"
@@ -4899,6 +4930,11 @@ functional-red-black-tree@^1.0.1:
   resolved "https://registry.npm.taobao.org/functional-red-black-tree/download/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
   integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
 
+fuzzysearch@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/fuzzysearch/-/fuzzysearch-1.0.3.tgz#dffc80f6d6b04223f2226aa79dd194231096d008"
+  integrity sha1-3/yA9tawQiPyImqnndGUIxCW0Ag=
+
 gauge@~2.7.3:
   version "2.7.4"
   resolved "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -7222,6 +7258,11 @@ marked@^0.8.0:
   resolved "https://registry.yarnpkg.com/marked/-/marked-0.8.0.tgz#ec5c0c9b93878dc52dd54be8d0e524097bd81a99"
   integrity sha512-MyUe+T/Pw4TZufHkzAfDj6HarCBWia2y27/bhuYkTaiUnfDYFnCP3KUN+9oM7Wi6JA2rymtVYbQu3spE0GCmxQ==
 
+material-colors@^1.2.6:
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
+  integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
+
 md5.js@^1.3.4:
   version "1.3.5"
   resolved "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -9330,6 +9371,11 @@ regenerator-runtime@^0.13.2:
   resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
   integrity sha1-fPanfY9cb2Drc8X8GVWyzrAea/U=
 
+regenerator-runtime@^0.13.4:
+  version "0.13.5"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
+  integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
+
 regenerator-transform@^0.14.0:
   version "0.14.1"
   resolved "https://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
@@ -11238,6 +11284,11 @@ walker@^1.0.7, walker@~1.0.5:
   dependencies:
     makeerror "1.0.x"
 
+watch-size@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/watch-size/-/watch-size-2.0.0.tgz#096ee28d0365bd7ea03d9c8bf1f2f50a73be1474"
+  integrity sha512-M92R89dNoTPWyCD+HuUEDdhaDnh9jxPGOwlDc0u51jAgmjUvzqaEMynXSr3BaWs+QdHYk4KzibPy1TFtjLmOZQ==
+
 watchpack@^1.6.0:
   version "1.6.0"
   resolved "https://registry.npm.taobao.org/watchpack/download/watchpack-1.6.0.tgz?cache=0&sync_timestamp=1573060318538&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwatchpack%2Fdownload%2Fwatchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"