Pārlūkot izejas kodu

优化项目结构

dusenyao 2 gadi atpakaļ
vecāks
revīzija
6b841a97a3
22 mainītis faili ar 970 papildinājumiem un 302 dzēšanām
  1. 2 1
      .vscode/settings.json
  2. 61 99
      package-lock.json
  3. 5 5
      package.json
  4. 1 1
      src/api/select.js
  5. 43 10
      src/components/common/RichText.vue
  6. 0 99
      src/components/course/create_course/create_task/mouseEvent.js
  7. 6 3
      src/components/select/SelectCourse.vue
  8. 5 0
      src/icons/svg/microphone.svg
  9. 5 0
      src/icons/svg/videocamera.svg
  10. 0 0
      src/views/teacher/create_course/step_table/create_task/components/LeftSidebar.vue
  11. 57 0
      src/views/teacher/create_course/step_table/create_task/components/RightSidebar.vue
  12. 76 0
      src/views/teacher/create_course/step_table/create_task/components/SelectTaskClassify.vue
  13. 38 66
      src/views/teacher/create_course/step_table/create_task/components/TaskEditor.vue
  14. 6 6
      src/views/teacher/create_course/step_table/create_task/components/TaskExplain/ExpandContract.vue
  15. 0 0
      src/views/teacher/create_course/step_table/create_task/components/TaskExplain/index.vue
  16. 0 0
      src/views/teacher/create_course/step_table/create_task/components/createClassSection.vue
  17. 3 3
      src/views/teacher/create_course/step_table/create_task/components/drag.js
  18. 75 0
      src/views/teacher/create_course/step_table/create_task/components/mouseEvent.js
  19. 26 6
      src/views/teacher/create_course/step_table/create_task/components/taskType.js
  20. 557 0
      src/views/teacher/create_course/step_table/create_task/components/task_template/index.vue
  21. 0 0
      src/views/teacher/create_course/step_table/create_task/components/wheel.js
  22. 4 3
      src/views/teacher/create_course/step_table/create_task/index.vue

+ 2 - 1
.vscode/settings.json

@@ -5,7 +5,8 @@
     "titleBar.activeForeground": "#15202b",
     "titleBar.inactiveBackground": "#42b88399",
     "titleBar.inactiveForeground": "#15202b99",
-    "sash.hoverBorder": "#65c89b"
+    "sash.hoverBorder": "#65c89b",
+    "commandCenter.border": "#15202b99"
   },
   "peacock.color": "#42b883",
   "i18n-ally.localesPaths": ["src/locales/lang"],

+ 61 - 99
package-lock.json

@@ -1582,9 +1582,9 @@
       "dev": true
     },
     "@csstools/selector-specificity": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz",
-      "integrity": "sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA==",
+      "version": "2.0.2",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz",
+      "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==",
       "dev": true
     },
     "@eslint/eslintrc": {
@@ -3782,7 +3782,7 @@
     },
     "arrify": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/arrify/-/arrify-1.0.1.tgz",
       "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
       "dev": true
     },
@@ -4267,8 +4267,8 @@
       }
     },
     "book-ui": {
-      "version": "file:../book-ui-0.3.10.tgz",
-      "integrity": "sha512-q4/NSLrFXn+fvbjrOiiSSSqbXD947fgwCCi4uYO8Pxj6UlRuUcXlaPGPchMCrVSZCge1V0gvc5/ohi/agbNFwg==",
+      "version": "file:../book-ui-0.3.15.tgz",
+      "integrity": "sha512-z94IFAeVW/dAHGeiv1BNn0FFA4cCmDmXfczv19BTtNvM2cBVJDnjfRUF33IMpd9L9OqT+bqRiVFX2OaD3Bz2jw==",
       "requires": {
         "awe-dnd": "^0.3.4",
         "axios": "^0.21.1",
@@ -4809,15 +4809,6 @@
         }
       }
     },
-    "clone-regexp": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmmirror.com/clone-regexp/-/clone-regexp-2.2.0.tgz",
-      "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==",
-      "dev": true,
-      "requires": {
-        "is-regexp": "^2.0.0"
-      }
-    },
     "co": {
       "version": "4.6.0",
       "resolved": "https://registry.npmmirror.com/co/-/co-4.6.0.tgz",
@@ -5454,9 +5445,9 @@
       }
     },
     "dayjs": {
-      "version": "1.11.4",
-      "resolved": "https://repo.huaweicloud.com/repository/npm/dayjs/-/dayjs-1.11.4.tgz",
-      "integrity": "sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g=="
+      "version": "1.11.5",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/dayjs/-/dayjs-1.11.5.tgz",
+      "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA=="
     },
     "de-indent": {
       "version": "1.0.2",
@@ -5480,7 +5471,7 @@
     },
     "decamelize-keys": {
       "version": "1.1.0",
-      "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
       "integrity": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==",
       "dev": true,
       "requires": {
@@ -5981,9 +5972,9 @@
       "dev": true
     },
     "es5-ext": {
-      "version": "0.10.61",
-      "resolved": "https://repo.huaweicloud.com/repository/npm/es5-ext/-/es5-ext-0.10.61.tgz",
-      "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
+      "version": "0.10.62",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/es5-ext/-/es5-ext-0.10.62.tgz",
+      "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
       "requires": {
         "es6-iterator": "^2.0.3",
         "es6-symbol": "^3.1.3",
@@ -6587,15 +6578,6 @@
         }
       }
     },
-    "execall": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmmirror.com/execall/-/execall-2.0.0.tgz",
-      "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==",
-      "dev": true,
-      "requires": {
-        "clone-regexp": "^2.1.0"
-      }
-    },
     "exit": {
       "version": "0.1.2",
       "resolved": "https://registry.npmmirror.com/exit/-/exit-0.1.2.tgz",
@@ -6778,9 +6760,9 @@
       },
       "dependencies": {
         "type": {
-          "version": "2.6.0",
-          "resolved": "https://registry.npmmirror.com/type/-/type-2.6.0.tgz",
-          "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ=="
+          "version": "2.7.2",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/type/-/type-2.7.2.tgz",
+          "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
         }
       }
     },
@@ -6866,9 +6848,9 @@
       "dev": true
     },
     "fastest-levenshtein": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmmirror.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
-      "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+      "version": "1.0.16",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+      "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
       "dev": true
     },
     "fastq": {
@@ -7355,7 +7337,7 @@
     },
     "global-modules": {
       "version": "2.0.0",
-      "resolved": "https://registry.npmmirror.com/global-modules/-/global-modules-2.0.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/global-modules/-/global-modules-2.0.0.tgz",
       "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
       "dev": true,
       "requires": {
@@ -7364,7 +7346,7 @@
     },
     "global-prefix": {
       "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/global-prefix/-/global-prefix-3.0.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/global-prefix/-/global-prefix-3.0.0.tgz",
       "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
       "dev": true,
       "requires": {
@@ -7375,13 +7357,13 @@
       "dependencies": {
         "kind-of": {
           "version": "6.0.3",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/kind-of/-/kind-of-6.0.3.tgz",
           "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
           "dev": true
         },
         "which": {
           "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-1.3.1.tgz",
           "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
           "dev": true,
           "requires": {
@@ -7420,7 +7402,7 @@
     },
     "globjoin": {
       "version": "0.1.4",
-      "resolved": "https://registry.npmmirror.com/globjoin/-/globjoin-0.1.4.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/globjoin/-/globjoin-0.1.4.tgz",
       "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==",
       "dev": true
     },
@@ -7498,7 +7480,7 @@
     },
     "hard-rejection": {
       "version": "2.1.0",
-      "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/hard-rejection/-/hard-rejection-2.1.0.tgz",
       "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
       "dev": true
     },
@@ -7898,7 +7880,7 @@
     },
     "import-lazy": {
       "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/import-lazy/-/import-lazy-4.0.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/import-lazy/-/import-lazy-4.0.0.tgz",
       "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
       "dev": true
     },
@@ -8140,7 +8122,7 @@
     },
     "is-plain-object": {
       "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/is-plain-object/-/is-plain-object-5.0.0.tgz",
       "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
       "dev": true
     },
@@ -8150,12 +8132,6 @@
       "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
       "dev": true
     },
-    "is-regexp": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmmirror.com/is-regexp/-/is-regexp-2.1.0.tgz",
-      "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==",
-      "dev": true
-    },
     "is-stream": {
       "version": "1.1.0",
       "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz",
@@ -10587,7 +10563,7 @@
     },
     "mathml-tag-names": {
       "version": "2.1.3",
-      "resolved": "https://registry.npmmirror.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
       "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
       "dev": true
     },
@@ -10779,7 +10755,7 @@
     },
     "min-indent": {
       "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/min-indent/-/min-indent-1.0.1.tgz",
       "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
       "dev": true
     },
@@ -10854,7 +10830,7 @@
     },
     "minimist-options": {
       "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/minimist-options/-/minimist-options-4.1.0.tgz",
       "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
       "dev": true,
       "requires": {
@@ -10865,7 +10841,7 @@
       "dependencies": {
         "kind-of": {
           "version": "6.0.3",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/kind-of/-/kind-of-6.0.3.tgz",
           "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
           "dev": true
         }
@@ -12645,7 +12621,7 @@
     },
     "quick-lru": {
       "version": "4.0.1",
-      "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-4.0.1.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/quick-lru/-/quick-lru-4.0.1.tgz",
       "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
       "dev": true
     },
@@ -14236,7 +14212,7 @@
     },
     "style-search": {
       "version": "0.1.0",
-      "resolved": "https://registry.npmmirror.com/style-search/-/style-search-0.1.0.tgz",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/style-search/-/style-search-0.1.0.tgz",
       "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
       "dev": true
     },
@@ -14251,22 +14227,20 @@
       }
     },
     "stylelint": {
-      "version": "14.9.1",
-      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.9.1.tgz",
-      "integrity": "sha512-RdAkJdPiLqHawCSnu21nE27MjNXaVd4WcOHA4vK5GtIGjScfhNnaOuWR2wWdfKFAvcWQPOYe311iveiVKSmwsA==",
+      "version": "14.10.0",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/stylelint/-/stylelint-14.10.0.tgz",
+      "integrity": "sha512-VAmyKrEK+wNFh9R8mNqoxEFzaa4gsHGhcT4xgkQDuOA5cjF6CaNS8loYV7gpi4tIZBPUyXesotPXzJAMN8VLOQ==",
       "dev": true,
       "requires": {
-        "@csstools/selector-specificity": "^2.0.1",
+        "@csstools/selector-specificity": "^2.0.2",
         "balanced-match": "^2.0.0",
         "colord": "^2.9.2",
         "cosmiconfig": "^7.0.1",
         "css-functions-list": "^3.1.0",
         "debug": "^4.3.4",
-        "execall": "^2.0.0",
         "fast-glob": "^3.2.11",
-        "fastest-levenshtein": "^1.0.12",
+        "fastest-levenshtein": "^1.0.16",
         "file-entry-cache": "^6.0.1",
-        "get-stdin": "^8.0.0",
         "global-modules": "^2.0.0",
         "globby": "^11.1.0",
         "globjoin": "^0.1.4",
@@ -14281,7 +14255,7 @@
         "micromatch": "^4.0.5",
         "normalize-path": "^3.0.0",
         "picocolors": "^1.0.0",
-        "postcss": "^8.4.14",
+        "postcss": "^8.4.16",
         "postcss-media-query-parser": "^0.2.3",
         "postcss-resolve-nested-selector": "^0.1.1",
         "postcss-safe-parser": "^6.0.0",
@@ -14300,19 +14274,19 @@
       "dependencies": {
         "balanced-match": {
           "version": "2.0.0",
-          "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-2.0.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/balanced-match/-/balanced-match-2.0.0.tgz",
           "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
           "dev": true
         },
         "camelcase": {
           "version": "5.3.1",
-          "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/camelcase/-/camelcase-5.3.1.tgz",
           "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
           "dev": true
         },
         "camelcase-keys": {
           "version": "6.2.2",
-          "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
           "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
           "dev": true,
           "requires": {
@@ -14321,15 +14295,9 @@
             "quick-lru": "^4.0.1"
           }
         },
-        "get-stdin": {
-          "version": "8.0.0",
-          "resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-8.0.0.tgz",
-          "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
-          "dev": true
-        },
         "hosted-git-info": {
           "version": "4.1.0",
-          "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
           "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
           "dev": true,
           "requires": {
@@ -14338,19 +14306,19 @@
         },
         "ignore": {
           "version": "5.2.0",
-          "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.2.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/ignore/-/ignore-5.2.0.tgz",
           "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
           "dev": true
         },
         "map-obj": {
           "version": "4.3.0",
-          "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/map-obj/-/map-obj-4.3.0.tgz",
           "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
           "dev": true
         },
         "meow": {
           "version": "9.0.0",
-          "resolved": "https://registry.npmmirror.com/meow/-/meow-9.0.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/meow/-/meow-9.0.0.tgz",
           "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==",
           "dev": true,
           "requires": {
@@ -14370,7 +14338,7 @@
         },
         "normalize-package-data": {
           "version": "3.0.3",
-          "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
           "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
           "dev": true,
           "requires": {
@@ -14382,7 +14350,7 @@
         },
         "redent": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmmirror.com/redent/-/redent-3.0.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/redent/-/redent-3.0.0.tgz",
           "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
           "dev": true,
           "requires": {
@@ -14401,7 +14369,7 @@
         },
         "strip-indent": {
           "version": "3.0.0",
-          "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-3.0.0.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/strip-indent/-/strip-indent-3.0.0.tgz",
           "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
           "dev": true,
           "requires": {
@@ -14410,20 +14378,20 @@
         },
         "trim-newlines": {
           "version": "3.0.1",
-          "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/trim-newlines/-/trim-newlines-3.0.1.tgz",
           "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
           "dev": true
         },
         "type-fest": {
           "version": "0.18.1",
-          "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.18.1.tgz",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/type-fest/-/type-fest-0.18.1.tgz",
           "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
           "dev": true
         },
         "write-file-atomic": {
-          "version": "4.0.1",
-          "resolved": "https://registry.npmmirror.com/write-file-atomic/-/write-file-atomic-4.0.1.tgz",
-          "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==",
+          "version": "4.0.2",
+          "resolved": "https://repo.huaweicloud.com/repository/npm/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+          "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
           "dev": true,
           "requires": {
             "imurmurhash": "^0.1.4",
@@ -15435,8 +15403,7 @@
     "universalify": {
       "version": "0.1.2",
       "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-0.1.2.tgz",
-      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
-      "dev": true
+      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
     },
     "unpipe": {
       "version": "1.0.0",
@@ -15721,9 +15688,9 @@
       }
     },
     "vue-demi": {
-      "version": "0.13.7",
-      "resolved": "https://repo.huaweicloud.com/repository/npm/vue-demi/-/vue-demi-0.13.7.tgz",
-      "integrity": "sha512-hbhlvpx1gFW3TB5HxJ0mNxyA9Jh5iQt409taOs6zkhpvfJ7YzLs1rsLufJmDsjH5PI1cOyfikY1fE/meyHfU5A==",
+      "version": "0.13.8",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/vue-demi/-/vue-demi-0.13.8.tgz",
+      "integrity": "sha512-Vy1zbZhCOdsmvGR6tJhAvO5vhP7eiS8xkbYQSoVa7o6KlIy3W8Rc53ED4qI4qpeRDjv3mLfXSEpYU6Yq4pgXRg==",
       "dev": true
     },
     "vue-esign": {
@@ -16449,9 +16416,9 @@
       "dev": true
     },
     "xgplayer": {
-      "version": "2.31.6",
-      "resolved": "https://repo.huaweicloud.com/repository/npm/xgplayer/-/xgplayer-2.31.6.tgz",
-      "integrity": "sha512-95mEdChOam010QCKU+putYvjbN/MPwQZwECrlG+MbTy8e7REpVEgTmko6f5FRQoPAMV7k7veLgZrCaMUDuV81A==",
+      "version": "2.31.7",
+      "resolved": "https://repo.huaweicloud.com/repository/npm/xgplayer/-/xgplayer-2.31.7.tgz",
+      "integrity": "sha512-Wksoj/+BQgsDD7hVsd0d8jICHWWL7SGV6c6V01kH3LfLS6JgwVKyNnr4rRHZFFztlr/kOgBnqPqlV3Fiefmviw==",
       "requires": {
         "chalk": "^2.3.2",
         "commander": "^2.15.1",
@@ -16485,11 +16452,6 @@
           "requires": {
             "graceful-fs": "^4.1.6"
           }
-        },
-        "universalify": {
-          "version": "0.1.2",
-          "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
-          "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
         }
       }
     },

+ 5 - 5
package.json

@@ -17,9 +17,9 @@
     "ailp-book-question-ui": "file:../ailp-book-question-ui-0.1.1.tgz",
     "awe-dnd": "^0.3.4",
     "axios": "^0.27.2",
-    "book-ui": "file:../book-ui-0.3.10.tgz",
+    "book-ui": "file:../book-ui-0.3.15.tgz",
     "core-js": "^3.24.1",
-    "dayjs": "^1.11.4",
+    "dayjs": "^1.11.5",
     "element-ui": "^2.15.9",
     "gcls-book-question-ui": "file:../gcls-book-question-ui-0.1.0.tgz",
     "jquery": "^3.6.0",
@@ -60,10 +60,10 @@
     "postcss": "^8.4.16",
     "postcss-html": "^1.5.0",
     "prettier": "2.7.1",
-    "sass": "^1.54.3",
+    "sass": "^1.54.4",
     "sass-loader": "^10.3.1",
     "script-ext-html-webpack-plugin": "^2.1.5",
-    "stylelint": "14.9.1",
+    "stylelint": "14.10.0",
     "stylelint-config-prettier": "^9.0.3",
     "stylelint-config-recess-order": "^3.0.0",
     "stylelint-config-recommended-vue": "^1.4.0",
@@ -74,7 +74,7 @@
     "svgo": "^2.8.0",
     "vue-loader": "^15.10.0",
     "vue-template-compiler": "^2.7.8",
-    "vue-demi": "^0.13.6"
+    "vue-demi": "^0.13.8"
   },
   "browserslist": [
     "> 1%",

+ 1 - 1
src/api/select.js

@@ -28,7 +28,7 @@ export function GetTaskModeList() {
 }
 
 /**
- * 得到课程的授课列表
+ * 得到课程的授课教师列表
  * @param {Object} data {course_id 课程id}
  */
 export function GetTeacherListByCourseID(data) {

+ 43 - 10
src/components/common/RichText.vue

@@ -1,5 +1,13 @@
 <template>
-  <Editor v-bind="$attrs" class="rich-text" :init="init" v-on="$listeners" @input="handleInput" />
+  <Editor
+    v-bind="$attrs"
+    ref="richText"
+    :class="['rich-text', isBorder ? 'is-border' : '']"
+    :init="init"
+    :style="{ border: '3px' }"
+    v-on="$listeners"
+    @input="handleInput"
+  />
 </template>
 
 <script>
@@ -9,9 +17,9 @@ export default {
 </script>
 
 <script setup>
-import { onMounted } from 'vue';
+import { ref, onMounted } from 'vue';
 
-import tinymce from 'tinymce/tinymce';
+import 'tinymce/tinymce';
 import Editor from '@tinymce/tinymce-vue';
 import 'tinymce/icons/default/icons';
 import 'tinymce/themes/silver';
@@ -36,6 +44,10 @@ const props = defineProps({
   height: {
     type: [Number, String],
     default: 148
+  },
+  isBorder: {
+    type: Boolean,
+    default: false
   }
 });
 
@@ -54,21 +66,42 @@ const init = {
   statusbar: false
 }; // 富文本初始化
 
+let richText = ref();
+
 function handleInput(e) {
   // console.log(e);
 }
 
+function handleIframeWheel(e) {
+  if (e.ctrlKey) {
+    e.preventDefault();
+  }
+}
+
+function addWheelEvent() {
+  if (richText.value.$el.nextElementSibling.getElementsByTagName('iframe').length <= 0) {
+    return setTimeout(addWheelEvent, 100);
+  }
+  richText.value.$el.nextElementSibling
+    .getElementsByTagName('iframe')[0]
+    .contentDocument.addEventListener('wheel', handleIframeWheel, { passive: false });
+}
+
 onMounted(() => {
-  tinymce.init({
-    mode: 'textareas',
-    selector: 'rich-text'
-  });
+  addWheelEvent();
 });
 </script>
 
 <style lang="scss">
-.tox.tox-tinymce {
-  border-width: 0;
-  border-radius: 0;
+.rich-text {
+  + .tox.tox-tinymce {
+    border-width: 0;
+    border-radius: 0;
+  }
+
+  &.is-border + .tox.tox-tinymce {
+    border-width: 2px;
+    border-radius: 10px;
+  }
 }
 </style>

+ 0 - 99
src/components/course/create_course/create_task/mouseEvent.js

@@ -1,99 +0,0 @@
-// 鼠标事件
-import { onMounted, ref } from 'vue';
-
-/**
- * 处理鼠标点击事件
- * @param {Element} center
- */
-export function mouseEvent(center) {
-  const isMouseLeftPress = ref(false); // 鼠标左键是否按下
-  const mouseOnMain = ref(false); // 鼠标是否在主要位置
-
-  const mainCursorDisplayStyle = ref('default'); // 鼠标指针样式
-
-  const preOffsetX = ref(0);
-  const preOffsetY = ref(0);
-
-  // 按下空格时与鼠标左键时,移动鼠标移动主内容位置
-  function moveMainPosition() {
-    const timer = null;
-    let startTime = Date.now();
-    const duration = 17;
-
-    return ({ offsetX, offsetY }) => {
-      const curTime = Date.now();
-      const remaining = curTime - startTime;
-      clearTimeout(timer);
-      if (remaining > duration) {
-        if (isMouseLeftPress.value) {
-          const diffX = offsetX - preOffsetX.value;
-          const diffY = offsetY - preOffsetY.value;
-          preOffsetX.value = offsetX;
-          preOffsetY.value = offsetY;
-          center.value.scrollLeft += diffX;
-          center.value.scrollTop += diffY;
-        }
-        startTime = Date.now();
-      }
-    };
-  }
-
-  // 鼠标左键按下/放开事件
-  function centerMousedownLeft({ button, offsetX, offsetY }) {
-    if (button === 0) {
-      isMouseLeftPress.value = true;
-      preOffsetX.value = offsetX;
-      preOffsetY.value = offsetY;
-    }
-  }
-  function centerMouseupLeft({ button }) {
-    if (button === 0) {
-      isMouseLeftPress.value = false;
-    }
-  }
-
-  // 按下空格时添加鼠标事件
-  const throttleFn = moveMainPosition(); // 节流防抖函数需要这样处理才能被 removeEventListener 移除掉
-  function addHandleMouseEvent() {
-    document.addEventListener('mousedown', centerMousedownLeft);
-    document.addEventListener('mouseup', centerMouseupLeft);
-    center.value.addEventListener('mousemove', throttleFn);
-  }
-  // 放开空格时移除鼠标事件
-  function removeHandleMouseEvent() {
-    document.removeEventListener('mousedown', centerMousedownLeft);
-    document.removeEventListener('mouseup', centerMouseupLeft);
-    center.value.removeEventListener('mousemove', throttleFn);
-  }
-
-  onMounted(() => {
-    /*
-     * 按下空格,鼠标指针变为手型,松开恢复
-     */
-    document.addEventListener('keydown', (e) => {
-      if (e.key === ' ' && mouseOnMain && mainCursorDisplayStyle.value !== 'grab') {
-        e.preventDefault();
-        mainCursorDisplayStyle.value = 'grab';
-        addHandleMouseEvent();
-      }
-    });
-
-    document.addEventListener('keyup', (e) => {
-      if (e.key === ' ') {
-        mainCursorDisplayStyle.value = 'default';
-        removeHandleMouseEvent();
-      }
-    });
-
-    center.value.addEventListener('mouseenter', () => {
-      mouseOnMain.value = true;
-    });
-
-    center.value.addEventListener('mouseover', () => {
-      mouseOnMain.value = false;
-    });
-    /* 结束 */
-  });
-
-  return { mainCursorDisplayStyle, center };
-}

+ 6 - 3
src/components/select/SelectCourse.vue

@@ -2,7 +2,7 @@
   <el-dialog class="select-course" :visible="dialogVisible" width="1100px" :title="$t('Key373')" @close="dialogClose">
     <div>
       <el-dropdown trigger="click" placement="top" @command="selectBook">
-        <span class="el-dropdown-link">{{ curBook.book_name }} <i class="el-icon-arrow-down" /></span>
+        <span class="el-dropdown-link">{{ curBook.book_name }} <i class="el-icon-arrow-down"></i></span>
         <el-dropdown-menu slot="dropdown">
           <el-dropdown-item v-for="item in book_list" :key="item.book_id" :command="item">
             {{ item.book_name }}
@@ -82,11 +82,14 @@ export default {
   props: {
     dialogVisible: {
       default: false,
-      type: Boolean
+      type: Boolean,
+      required: true
     },
+    // 课节 id
     id: {
       default: '',
-      type: String
+      type: String,
+      required: true
     }
   },
   data() {

+ 5 - 0
src/icons/svg/microphone.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="5.66699" y="1.33398" width="4.66667" height="9" rx="2.33333" stroke="white" stroke-width="1.5" stroke-linejoin="round"/>
+<path d="M3 7.66602C3 10.4274 5.23858 12.666 8 12.666C10.7614 12.666 13 10.4274 13 7.66602" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8.00033 12.666V14.666" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 5 - 0
src/icons/svg/videocamera.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="1.33398" y="3.66602" width="10.6667" height="8.66667" rx="2" stroke="#DE4444" stroke-width="1.5"/>
+<ellipse cx="6.66602" cy="8" rx="2" ry="2" stroke="#DE4444" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12 9.66667L14.6667 11V5L12 6.33333" stroke="#DE4444" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 0 - 0
src/components/course/create_course/create_task/LeftSidebar.vue → src/views/teacher/create_course/step_table/create_task/components/LeftSidebar.vue


+ 57 - 0
src/views/teacher/create_course/step_table/create_task/components/RightSidebar.vue

@@ -0,0 +1,57 @@
+<template>
+  <div class="task-main-right">
+    <div
+      v-for="{ type, name, image } in taskClassify"
+      :key="type"
+      :style="{ cursor: type !== MORE_NAME ? 'pointer' : 'default' }"
+      class="task-classify-item"
+    >
+      <span class="task-classify-item-name">{{ name }}</span>
+      <img
+        :src="image"
+        :alt="name"
+        :draggable="type !== MORE_NAME"
+        @dragstart="dragstart($event, type)"
+        @dragend="dragend"
+      />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useTaskClassify } from './taskType.js';
+import { handleDrag } from './drag.js';
+
+const { taskClassify, MORE_NAME } = useTaskClassify();
+
+const { dragstart, dragend } = handleDrag();
+</script>
+
+<style lang="scss" scoped>
+$basic-background-color: #f7f7f7;
+
+.task-main-right {
+  width: 200px;
+  min-width: 200px;
+  padding-top: 16px;
+  background-color: $basic-background-color;
+
+  .task-classify-item {
+    display: flex;
+    flex-direction: column;
+    row-gap: 8px;
+    align-items: flex-start;
+    padding: 0 16px 12px;
+
+    &-name {
+      padding: 2px 12px;
+      font-weight: bold;
+      line-height: 22px;
+      color: #fff;
+      background-color: #666;
+      border: 1px solid $border-color;
+      border-radius: 19px;
+    }
+  }
+}
+</style>

+ 76 - 0
src/views/teacher/create_course/step_table/create_task/components/SelectTaskClassify.vue

@@ -0,0 +1,76 @@
+<template>
+  <el-dialog :visible="visible" width="610px" :before-close="handleClose" :modal="false">
+    <template v-for="{ type, image, name } in taskClassify">
+      <div v-if="type !== MORE_NAME" :key="type" :class="['task-classify']">
+        <div class="task-classify-item" @click="selectTaskClassify(type)">
+          <div class="taskClassify-name">
+            {{ name }}
+          </div>
+          <img draggable="false" :src="image" :alt="name" />
+        </div>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { useTaskClassify } from './taskType.js';
+
+defineProps({
+  visible: {
+    type: Boolean,
+    required: true
+  }
+});
+
+const emit = defineEmits(['select-task-classify', 'update:visible']);
+
+let { taskClassify, MORE_NAME } = useTaskClassify();
+
+function selectTaskClassify(type) {
+  emit('select-task-classify', type);
+}
+
+function handleClose() {
+  emit('update:visible', false);
+}
+</script>
+
+<style lang="scss" scoped>
+.el-dialog {
+  :deep &__header {
+    display: none;
+  }
+
+  :deep &__body {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+
+    .task-classify {
+      padding: 8px;
+      border-radius: 4px;
+
+      &:hover {
+        background-color: #f2f2f2;
+      }
+
+      &-item {
+        display: flex;
+        flex-direction: column;
+        row-gap: 8px;
+        align-items: flex-start;
+        cursor: pointer;
+
+        .taskClassify-name {
+          padding: 2px 12px;
+          line-height: 22px;
+          color: #fff;
+          background-color: #666;
+          border-radius: 19px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 38 - 66
src/components/course/create_course/create_task/TaskEditor.vue → src/views/teacher/create_course/step_table/create_task/components/TaskEditor.vue

@@ -1,3 +1,4 @@
+<!-- 任务编辑 -->
 <template>
   <div class="task-main">
     <LeftSidebar
@@ -6,71 +7,67 @@
       :cur-task-type-obj="curTaskTypeObj"
     />
 
-    <div ref="center" class="task-main-center" :style="{ cursor: mainCursorDisplayStyle }">
-      <template v-if="!isTaskExplain">
-        <span class="zoom-display">
-          <svg-icon icon-class="minus" class-name="zoom-display-minus" />
-          <span>{{ (scale * 100).toFixed(0) }}%</span>
-          <svg-icon icon-class="add" class-name="zoom-display-add" />
-        </span>
-        <div
-          class="task-main-center-container"
-          :style="{ transform: `scale(${scale})` }"
-          @dragover="dragover"
-          @drop="drop"
-        >
+    <div ref="center" class="task-main-center" :style="{ cursor: mainCursorDisplayStyle, 'user-select': 'none' }">
+      <span class="zoom-display">
+        <svg-icon icon-class="minus" class-name="zoom-display-minus" />
+        <span>{{ (scale * 100).toFixed(0) }}%</span>
+        <svg-icon icon-class="add" class-name="zoom-display-add" />
+      </span>
+      <div
+        class="task-main-center-container"
+        :style="{ transform: `scale(${scale})` }"
+        @dragover="dragover"
+        @drop="drop($event, setTaskClassifyType)"
+      >
+        <template v-if="curPageType === mainPageTypeList[0]">
           <div class="create-task">
             <svg-icon icon-class="add" class-name="create-task-add" />
             <span>创建{{ curTaskTypeObj.name }}</span>
           </div>
-        </div>
-      </template>
-      <template v-else>
-        <TaskExplain />
-      </template>
-    </div>
-
-    <div v-show="!isTaskExplain" class="task-main-right">
-      <div
-        v-for="{ type, name, image } in taskClassify"
-        :key="type"
-        :style="{ cursor: type !== MORE_NAME ? 'pointer' : 'default' }"
-        class="task-classify-item"
-      >
-        <span class="task-classify-item-name">{{ name }}</span>
-        <img
-          :src="image"
-          :alt="name"
-          :draggable="type !== MORE_NAME"
-          @dragstart="dragstart($event, type)"
-          @dragend="dragend"
-        />
+        </template>
+        <template v-else-if="curPageType === mainPageTypeList[1]">
+          <TaskExplain />
+        </template>
+        <template v-else-if="curPageType === mainPageTypeList[2]">
+          <TaskTemplate :cur-task-classify-type="curTaskClassifyType" />
+        </template>
       </div>
     </div>
+
+    <RightSidebar v-show="curPageType !== mainPageTypeList[1]" />
   </div>
 </template>
 
 <script setup>
 import { ref } from 'vue';
-import { useTaskType, useTaskClassify } from './taskType.js';
+import { useTaskType } from './taskType.js';
 import { mouseEvent } from './mouseEvent.js';
 import { handleWheel } from './wheel.js';
 import { handleDrag } from './drag.js';
 
 import TaskExplain from './TaskExplain/index.vue';
 import LeftSidebar from './LeftSidebar.vue';
+import TaskTemplate from './task_template';
+import RightSidebar from './RightSidebar.vue';
 
 const center = ref(); // vue3 获取 refs 写法,需要同名,且传空
 
-const { curTaskType, curTaskTypeObj, isTaskExplain, handleChangeTaskType } = useTaskType();
-
-const { taskClassify, MORE_NAME } = useTaskClassify();
+const { curTaskType, curTaskTypeObj, curPageType, mainPageTypeList, handleChangeTaskType, handleChangeCurPageType } =
+  useTaskType();
 
 const { mainCursorDisplayStyle } = mouseEvent(center);
 
 const { scale } = handleWheel(center);
 
-const { dragstart, dragover, dragend, drop } = handleDrag();
+const { dragover, drop } = handleDrag();
+
+const curTaskClassifyType = ref(''); // 当前任务分类类型
+
+function setTaskClassifyType(taskClassifyType) {
+  if (!taskClassifyType) return;
+  curTaskClassifyType.value = taskClassifyType;
+  handleChangeCurPageType(mainPageTypeList[2]);
+}
 </script>
 
 <style lang="scss" scoped>
@@ -78,7 +75,7 @@ $basic-background-color: #f7f7f7;
 
 .task-main {
   display: flex;
-  min-height: calc(100% - 98px);
+  height: calc(100% - 98px);
   letter-spacing: 0.01em;
 
   &-center {
@@ -133,30 +130,5 @@ $basic-background-color: #f7f7f7;
       }
     }
   }
-
-  &-right {
-    width: 200px;
-    min-width: 200px;
-    padding-top: 16px;
-    background-color: $basic-background-color;
-
-    .task-classify-item {
-      display: flex;
-      flex-direction: column;
-      row-gap: 8px;
-      align-items: flex-start;
-      padding: 0 16px 12px;
-
-      &-name {
-        padding: 2px 12px;
-        font-weight: bold;
-        line-height: 22px;
-        color: #fff;
-        background-color: #666;
-        border: 1px solid $border-color;
-        border-radius: 19px;
-      }
-    }
-  }
 }
 </style>

+ 6 - 6
src/components/course/create_course/create_task/TaskExplain/ExpandContract.vue → src/views/teacher/create_course/step_table/create_task/components/TaskExplain/ExpandContract.vue

@@ -1,10 +1,10 @@
 <template>
   <div>
-    <div ref="stretch" :class="['stretch', titleClass, isUnfoldState ? 'unfold' : 'contract']">
+    <div ref="stretch" :class="['stretch', titleClass, isUnfold ? 'unfold' : 'contract']">
       <span>{{ title }}</span>
       <div class="stretch-click" @click="handleStretch">
-        {{ isUnfoldState ? '收起' : '展开' }}
-        <i :class="[isUnfoldState ? 'el-icon-arrow-down' : 'el-icon-arrow-up']"></i>
+        {{ isUnfold ? '收起' : '展开' }}
+        <i :class="[isUnfold ? 'el-icon-arrow-down' : 'el-icon-arrow-up']"></i>
       </div>
     </div>
     <slot></slot>
@@ -30,12 +30,12 @@ const props = defineProps({
 });
 
 const stretch = ref();
-const isUnfoldState = ref(true);
+const isUnfold = ref(true); // 是否展开
 
 function handleStretch() {
-  isUnfoldState.value = !isUnfoldState.value;
+  isUnfold.value = !isUnfold.value;
 
-  stretch.value.nextSibling.nextSibling.style.height = isUnfoldState.value ? `${props.height}px` : 0;
+  stretch.value.nextSibling.nextSibling.style.height = isUnfold.value ? `${props.height}px` : 0;
 }
 </script>
 

+ 0 - 0
src/components/course/create_course/create_task/TaskExplain/index.vue → src/views/teacher/create_course/step_table/create_task/components/TaskExplain/index.vue


+ 0 - 0
src/components/course/create_course/create_task/createClassSection.vue → src/views/teacher/create_course/step_table/create_task/components/createClassSection.vue


+ 3 - 3
src/components/course/create_course/create_task/drag.js → src/views/teacher/create_course/step_table/create_task/components/drag.js

@@ -3,7 +3,7 @@
  */
 export function handleDrag() {
   function dragstart(e, type) {
-    e.dataTransfer.setData('type', type); // 设置拖拽数据
+    e.dataTransfer.setData('taskClassifyType', type); // 设置拖拽数据
     e.target.style.opacity = 0.5; // 使其半透明
   }
 
@@ -15,8 +15,8 @@ export function handleDrag() {
     e.target.style.opacity = ''; // 恢复透明度
   }
 
-  function drop(e) {
-    e.dataTransfer.getData('type'); // 获取数据
+  function drop(e, fn) {
+    fn(e.dataTransfer.getData('taskClassifyType'));
   }
 
   return {

+ 75 - 0
src/views/teacher/create_course/step_table/create_task/components/mouseEvent.js

@@ -0,0 +1,75 @@
+// 鼠标事件
+import { onMounted, ref } from 'vue';
+
+/**
+ * 处理鼠标点击事件
+ * @param {Element} center
+ */
+export function mouseEvent(center) {
+  const isMouseLeftPress = ref(false); // 鼠标左键是否按下
+  const mouseOnMain = ref(false); // 鼠标是否在主要位置
+  const mainCursorDisplayStyle = ref('default'); // 鼠标指针样式
+
+  /**
+   * 按下空格时与鼠标左键时,移动鼠标移动主内容位置
+   */
+  function moveMainPosition({ movementX, movementY }) {
+    if (isMouseLeftPress.value) {
+      center.value.scrollLeft += movementX;
+      center.value.scrollTop += movementY;
+    }
+  }
+
+  /**
+   * 鼠标左键按下事件
+   * @param { MouseEvent }
+   */
+  function centerMousedownLeft({ button }) {
+    if (button === 0) {
+      isMouseLeftPress.value = true;
+    }
+  }
+  /**
+   * 鼠标左键放开事件
+   * @param { MouseEvent }
+   */
+  function centerMouseupLeft({ button }) {
+    if (button === 0) {
+      isMouseLeftPress.value = false;
+    }
+  }
+
+  onMounted(() => {
+    /*
+     * 按下空格,鼠标指针变为手型,松开恢复
+     */
+    document.addEventListener('keydown', (e) => {
+      if (e.key === ' ') e.preventDefault();
+      if (e.key === ' ' && mouseOnMain && mainCursorDisplayStyle.value !== 'grab') {
+        mainCursorDisplayStyle.value = 'grab';
+        center.value.addEventListener('mousemove', moveMainPosition);
+      }
+    });
+
+    document.addEventListener('mousedown', centerMousedownLeft);
+    document.addEventListener('mouseup', centerMouseupLeft);
+
+    document.addEventListener('keyup', (e) => {
+      if (e.key === ' ') {
+        e.preventDefault();
+        mainCursorDisplayStyle.value = 'default';
+        center.value.removeEventListener('mousemove', moveMainPosition);
+      }
+    });
+
+    center.value.addEventListener('mouseenter', () => {
+      mouseOnMain.value = true;
+    });
+
+    center.value.addEventListener('mouseleave', () => {
+      mouseOnMain.value = false;
+    });
+  });
+
+  return { mainCursorDisplayStyle, center };
+}

+ 26 - 6
src/components/course/create_course/create_task/taskType.js → src/views/teacher/create_course/step_table/create_task/components/taskType.js

@@ -45,28 +45,43 @@ export function useTaskType() {
     }
   ];
 
-  let isTaskExplain = ref(false); // 当前是否任务说明
+  const mainPageTypeList = ['create', 'taskExplain', 'task']; // 主页面类型列表
+  let curPageType = ref(mainPageTypeList[0]); // 当前页面类型
   let _selectTaskType = ref('pre'); // 选中的任务类型
 
   let curTaskType = computed(() => {
-    if (isTaskExplain.value) return TASK_EXPLAIN;
+    if (curPageType.value === mainPageTypeList[1]) return TASK_EXPLAIN;
     return _selectTaskType.value;
   }); // 当前任务类型
 
   // 当前任务类型对象
   let curTaskTypeObj = computed(() => taskTypeArray.find(({ type }) => type === curTaskType.value));
 
+  // 切换当前页面类型
+  function handleChangeCurPageType(type) {
+    curPageType.value = type;
+  }
+
   // 切换任务类型
   function handleChangeTaskType(type) {
     if (type === TASK_EXPLAIN) {
-      isTaskExplain.value = true;
+      handleChangeCurPageType(mainPageTypeList[1]);
     } else {
       _selectTaskType.value = type;
-      isTaskExplain.value = false;
+      handleChangeCurPageType(mainPageTypeList[0]);
     }
   }
 
-  return { curTaskType, curTaskTypeObj, taskTypeArray, isTaskExplain, TASK_EXPLAIN, handleChangeTaskType };
+  return {
+    curTaskType,
+    curTaskTypeObj,
+    taskTypeArray,
+    curPageType,
+    mainPageTypeList,
+    TASK_EXPLAIN,
+    handleChangeTaskType,
+    handleChangeCurPageType
+  };
 }
 
 /**
@@ -108,5 +123,10 @@ export function useTaskClassify() {
     }
   ];
 
-  return { taskClassify, MORE_NAME };
+  function getTaskClassifyName(type) {
+    if (!type) return '';
+    return taskClassify.find((item) => item.type === type).name;
+  }
+
+  return { taskClassify, MORE_NAME, getTaskClassifyName };
 }

+ 557 - 0
src/views/teacher/create_course/step_table/create_task/components/task_template/index.vue

@@ -0,0 +1,557 @@
+<template>
+  <div class="task-template">
+    <div>
+      <span class="task-template-index">1</span>
+      <span class="task-template-taskClassify-name">{{ getTaskClassifyName(curTaskClassifyType) }}</span>
+    </div>
+    <div class="task-template-content">
+      <div>任务标题</div>
+      <el-input placeholder="点击输入" />
+      <div class="task-time">
+        <div class="task-time-item">
+          <span>开始时间</span>
+          <el-date-picker
+            v-model="value1"
+            :style="{ width: '186px' }"
+            size="small"
+            type="datetime"
+            placeholder="选择日期时间"
+          />
+        </div>
+        <div class="task-time-item">
+          <span>持续时长</span>
+          <el-select v-model="duration" size="small" :style="{ width: '90px' }">
+            <el-option v-for="{ name, value } in durationList" :key="value" :label="name" :value="value" />
+          </el-select>
+        </div>
+      </div>
+      <div>执教教师</div>
+      <el-select v-model="selectTeacher" multiple collapse-tags>
+        <el-option
+          v-for="{ teacher_id, teacher_name } in teacherList"
+          :key="teacher_id"
+          :value="teacher_id"
+          :label="teacher_name"
+        />
+      </el-select>
+      <div>参加学生</div>
+      <el-select v-model="selectStudent" multiple collapse-tags>
+        <el-option
+          v-for="{ student_id, student_name } in studentList"
+          :key="student_id"
+          :value="student_id"
+          :label="student_name"
+        />
+      </el-select>
+      <div>任务说明</div>
+      <RichText :height="209" :is-border="true" />
+      <hr />
+
+      <!-- 课件 -->
+      <template v-if="taskClassify[1].type === curTaskClassifyType">
+        <div class="courseware">
+          <el-button size="small" class="courseware-select">选择课件</el-button>
+          <span class="tip">仅支持选择已购买的教材</span>
+        </div>
+        <div class="courseware-list">
+          <div class="courseware-list-title">
+            <div class="file-name">文件名</div>
+            <div class="operation">操作</div>
+          </div>
+          <ul v-if="value1 !== ''">
+            <li class="courseware-list-item">
+              <span class="file-name">发了发动机考虑到非了富家大室李逵负荆as抵抗力 </span>
+              <span class="operation">删除</span>
+            </li>
+          </ul>
+          <div v-else class="courseware-list-none">点击上方“选择课件”</div>
+        </div>
+      </template>
+      <!-- 文件 -->
+      <template v-if="taskClassify[2].type === curTaskClassifyType">
+        <div class="file">
+          <el-button size="small" class="file-select">上传文件</el-button>
+          <span class="tip">支持批量上传,上传格式支持mp3; mp4; jpg; png文件</span>
+        </div>
+        <div class="file-list">
+          <div class="file-list-title">
+            <div class="file-name">文件名</div>
+            <div class="file-size">大小</div>
+            <div class="file-status">状态</div>
+            <div class="file-operation">操作</div>
+          </div>
+          <ul v-if="value1 !== ''">
+            <li class="file-list-item">
+              <span class="file-name">1</span>
+              <span class="file-size">2</span>
+              <span class="file-status">3</span>
+              <span class="file-operation">4</span>
+            </li>
+          </ul>
+          <div v-else class="file-list-none">点击上方“上传文件”或将文件拖拽到此区域</div>
+        </div>
+        <div class="file-upload">
+          <el-button size="small" class="cancel">取消</el-button>
+          <el-button size="small" class="start-upload">开始上传</el-button>
+        </div>
+      </template>
+      <!-- 录音/录影 -->
+      <div v-if="taskClassify[3].type === curTaskClassifyType">
+        <template v-if="curRecord === audioAndVideo[0].type">
+          <div class="sound-recording"></div>
+          <el-input type="textarea" class="sound-input" resize="none" placeholder="输入" />
+        </template>
+        <template v-else>
+          <div class="video-recording"></div>
+        </template>
+        <div class="recording-operation">
+          <div class="switch">
+            <span
+              v-for="{ type, name } in audioAndVideo"
+              :key="type"
+              :class="[type === curRecord ? 'active' : '']"
+              @click="selectRecord(type)"
+            >
+              {{ name }}
+            </span>
+          </div>
+          <template v-for="{ icon, buttonName, type } in audioAndVideo">
+            <div v-if="curRecord === type" :key="icon" :class="['press-sound', icon]">
+              <svg-icon :icon-class="icon" class-name="button-icon" />{{ buttonName }}
+            </div>
+          </template>
+        </div>
+      </div>
+      <!-- 直播 -->
+      <template v-if="taskClassify[4].type === curTaskClassifyType">
+        <div class="courseware">
+          <el-button size="small" class="courseware-select">选择课件</el-button>
+          <span class="tip">仅支持选择已购买的教材</span>
+        </div>
+        <div class="courseware-list">
+          <div class="courseware-list-title">
+            <div class="file-name">文件名</div>
+            <div class="operation">操作</div>
+          </div>
+          <ul v-if="value1 !== ''">
+            <li class="courseware-list-item">
+              <span class="file-name">发了发动机考虑到非了富家大室李逵负荆as抵抗力 </span>
+              <span class="operation">删除</span>
+            </li>
+          </ul>
+          <div v-else class="courseware-list-none">点击上方“选择课件”</div>
+        </div>
+        <hr />
+        <div class="file">
+          <el-button size="small" class="file-select">上传文件</el-button>
+          <span class="tip">支持批量上传,上传格式支持mp3; mp4; jpg; png文件</span>
+        </div>
+        <div class="file-list">
+          <div class="file-list-title">
+            <div class="file-name">文件名</div>
+            <div class="file-size">大小</div>
+            <div class="file-status">状态</div>
+            <div class="file-operation">操作</div>
+          </div>
+          <ul v-if="value1 !== ''">
+            <li class="file-list-item">
+              <span class="file-name">1</span>
+              <span class="file-size">2</span>
+              <span class="file-status">3</span>
+              <span class="file-operation">4</span>
+            </li>
+          </ul>
+          <div v-else class="file-list-none">点击上方“上传文件”或将文件拖拽到此区域</div>
+        </div>
+        <div class="file-upload">
+          <el-button size="small" class="cancel">取消</el-button>
+          <el-button size="small" class="start-upload">开始上传</el-button>
+        </div>
+      </template>
+
+      <hr v-if="curTaskClassifyType !== taskClassify[0].type" />
+      <el-button class="add-subtask" @click="selectTaskType">
+        <svg-icon icon-class="plus" class-name="plus" />添加子任务
+      </el-button>
+    </div>
+    <SelectTaskClassify :visible.sync="visible" @select-task-classify="addSubtask" />
+    <!-- TODO 改为课节id -->
+    <SelectCourse :id="id" :dialog-visible="dialogVisible" />
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'TaskTemplate'
+};
+</script>
+
+<script setup>
+import { ref, inject } from 'vue';
+import { useTaskClassify } from '../taskType.js';
+import { GetTeacherListByCourseID, GetCourseStudentList } from '@/api/select.js';
+
+import RichText from '@/components/common/RichText.vue';
+import SelectTaskClassify from '../SelectTaskClassify.vue';
+import SelectCourse from '@/components/select/SelectCourse.vue';
+
+defineProps({
+  curTaskClassifyType: {
+    type: String,
+    required: true
+  }
+});
+
+const { taskClassify, getTaskClassifyName } = useTaskClassify();
+
+const id = inject('id');
+let value1 = ref('');
+let duration = ref(1); // 持续时长
+let durationList = []; // 持续时长列表
+for (let i = 1; i <= 12; i++) {
+  durationList.push({ name: `${i}小时`, value: i });
+}
+let visible = ref(false);
+
+function selectTaskType() {
+  visible.value = true;
+}
+
+function addSubtask(type) {
+  console.log(type);
+}
+
+let dialogVisible = ref(false);
+
+// 选择教师
+let selectTeacher = ref([]);
+let teacherList = ref([]);
+GetTeacherListByCourseID({ course_id: id }).then(({ teacher_list }) => {
+  teacherList.value = teacher_list;
+});
+
+// 选择学生
+let selectStudent = ref([]);
+let studentList = ref([]);
+GetCourseStudentList({ course_id: id, audit_status_list: [1], pay_status: 1 }).then(({ student_list }) => {
+  studentList.value = student_list;
+});
+
+// 录音/录影
+let audioAndVideo = ref([
+  {
+    type: 'audio',
+    name: '录音',
+    icon: 'microphone',
+    buttonName: '按住录音'
+  },
+  {
+    type: 'video',
+    name: '录影',
+    icon: 'videocamera',
+    buttonName: '开始录制视频'
+  }
+]);
+let curRecord = ref(audioAndVideo.value[0].type);
+
+function selectRecord(type) {
+  curRecord.value = type;
+}
+</script>
+
+<style lang="scss" scoped>
+$tip-color: #999;
+
+.task-template {
+  width: 828px;
+  margin: 56px auto;
+
+  &-index {
+    display: inline-block;
+    width: 26px;
+    height: 26px;
+    margin-right: 8px;
+    line-height: 26px;
+    color: #fff;
+    text-align: center;
+    background-color: #5498ff;
+    border-radius: 50%;
+  }
+
+  &-taskClassify-name {
+    display: inline-block;
+    padding: 2px 12px;
+    line-height: 22px;
+    color: #fff;
+    background-color: #666;
+    border-radius: 19px;
+  }
+
+  &-content {
+    display: flex;
+    flex-direction: column;
+    row-gap: 8px;
+    padding: 24px;
+    margin-top: 8px;
+    background-color: #fff;
+    border: 1px solid $border-color;
+    border-radius: 8px;
+    box-shadow: 0 2px 4px $border-color;
+
+    // 公用
+    .task-time {
+      display: flex;
+      column-gap: 8px;
+
+      &-item {
+        display: flex;
+        flex-direction: column;
+        row-gap: 8px;
+      }
+    }
+
+    hr {
+      width: 100%;
+      margin: 23px 0;
+      border: 1px dashed $border-color;
+    }
+
+    .add-subtask {
+      width: 106px;
+      padding: 4px;
+      line-height: 22px;
+      color: #fff;
+      background-color: #67cfcf;
+
+      .plus {
+        width: 18px;
+        height: 18px;
+        margin-right: 4px;
+        vertical-align: sub;
+      }
+    }
+
+    // 课件
+    %courseware,
+    .courseware {
+      display: flex;
+      column-gap: 16px;
+      align-items: center;
+
+      &-select {
+        width: 90px;
+        color: #191919;
+      }
+
+      .tip {
+        color: $tip-color;
+      }
+    }
+
+    .courseware-list {
+      color: $tip-color;
+      border: 1px solid $border-color;
+
+      &-title {
+        display: flex;
+        border-bottom: 1px solid $border-color;
+
+        .file-name {
+          flex: 1;
+          padding: 10px 24px;
+          border-right: 1px solid $border-color;
+        }
+
+        .operation {
+          padding: 10px 24px;
+          text-align: center;
+        }
+      }
+
+      &-item {
+        display: flex;
+        align-items: center;
+        word-break: break-all;
+
+        > span {
+          padding: 10px 24px;
+        }
+
+        .file-name {
+          flex: 1;
+        }
+      }
+
+      &-none {
+        height: 210px;
+        line-height: 210px;
+        color: $tip-color;
+        text-align: center;
+        vertical-align: middle;
+      }
+    }
+
+    // 文件
+    .file {
+      @extend %courseware;
+    }
+
+    .file-list {
+      border: 1px solid $border-color;
+
+      &-title {
+        display: flex;
+        color: $tip-color;
+        border-bottom: 1px solid $border-color;
+
+        > div {
+          padding: 10px 24px;
+          border-right: 1px solid $border-color;
+        }
+
+        .file-name {
+          width: 310px;
+        }
+
+        .file-size {
+          width: 78px;
+        }
+
+        .file-status {
+          width: 310px;
+        }
+
+        .file-operation {
+          flex: 1;
+        }
+      }
+
+      &-item {
+        display: flex;
+        align-items: center;
+        word-break: break-all;
+
+        > span {
+          padding: 10px 24px;
+        }
+
+        .file-name {
+          width: 310px;
+        }
+
+        .file-size {
+          width: 78px;
+          text-align: center;
+        }
+
+        .file-status {
+          width: 310px;
+        }
+
+        .file-operation {
+          flex: 1;
+        }
+      }
+
+      &-none {
+        height: 210px;
+        line-height: 210px;
+        color: $tip-color;
+        text-align: center;
+      }
+    }
+
+    .file-upload {
+      display: flex;
+      justify-content: flex-end;
+      margin-top: 16px;
+
+      .cancel {
+        background-color: #e7e7e7;
+      }
+
+      .start-upload {
+        color: #fff;
+        background-color: #d4e3fc;
+      }
+    }
+
+    // 录音/录影
+    .sound-recording {
+      height: 230px;
+      background-color: #f4f4f4;
+      border: 1px solid $border-color;
+    }
+
+    .sound-input {
+      :deep .el-textarea__inner {
+        height: 92px;
+        padding: 8px 12px;
+        font-size: 16px;
+        border: 1px solid $border-color;
+        border-top-width: 0;
+      }
+    }
+
+    .video-recording {
+      height: 342px;
+      padding: 8px;
+      border: 1px solid $border-color;
+    }
+
+    .recording-operation {
+      display: flex;
+      justify-content: space-between;
+      padding: 8px 16px;
+      border: 1px solid $border-color;
+      border-top-width: 0;
+
+      .switch {
+        background-color: #e7e7e7;
+        border: 1px solid $border-color;
+        border-radius: 4px;
+
+        > span {
+          display: inline-block;
+          height: 28px;
+          padding: 2px 8px;
+          font-size: 16px;
+          line-height: 24px;
+          color: $tip-color;
+          cursor: pointer;
+          background-color: #e7e7e7;
+          border-radius: 3px;
+
+          &.active {
+            color: #000;
+            background-color: #fff;
+            box-shadow: 0 2px 4px rgba(0, 0, 0, 25%);
+          }
+        }
+      }
+
+      .press-sound {
+        padding: 4px 8px;
+        line-height: 22px;
+        cursor: pointer;
+        border-radius: 40px;
+
+        &.microphone {
+          color: #fff;
+          background-color: #de4444;
+        }
+
+        &.videocamera {
+          color: #de4444;
+          background-color: #fff;
+          border: 1px solid #de4444;
+        }
+
+        .button-icon {
+          margin-right: 4px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 0 - 0
src/components/course/create_course/create_task/wheel.js → src/views/teacher/create_course/step_table/create_task/components/wheel.js


+ 4 - 3
src/views/teacher/create_course/step_table/create_task/index.vue

@@ -37,8 +37,8 @@
 </template>
 
 <script>
-import TaskEditor from '@/components/course/create_course/create_task/TaskEditor.vue';
-import CreateClassSection from '@/components/course/create_course/create_task/createClassSection.vue';
+import TaskEditor from './components/TaskEditor.vue';
+import CreateClassSection from './components/createClassSection.vue';
 
 export default {
   components: {
@@ -55,7 +55,7 @@ export default {
     const is_template = 'is_template' in query ? query.is_template === 'true' : false;
 
     return {
-      id: this.$route.params.id,
+      id: this.$route.params.id, // 课程 id
       is_template,
       name: '',
       closeLink: JSON.parse(is_template) ? '/main?tab=TemplateList' : '/create_course',
@@ -105,6 +105,7 @@ $basic-background-color: #f7f7f7;
     .back {
       width: 74px;
       padding: 12px;
+      cursor: pointer;
 
       .svg-icon.back-black {
         margin-right: 6px;