فهرست منبع

基础组件:题干和描述 部分

优化代码
zq 1 سال پیش
والد
کامیت
72a87556b6
23فایلهای تغییر یافته به همراه913 افزوده شده و 249 حذف شده
  1. 384 137
      package-lock.json
  2. 2 2
      package.json
  3. 15 0
      src/components/RichText.vue
  4. 1 2
      src/views/book/courseware/create/components/base/audio/AudioSetting.vue
  5. 138 0
      src/views/book/courseware/create/components/base/common/SelectSerialNumberStyle.vue
  6. 7 2
      src/views/book/courseware/create/components/base/describe/Describe.vue
  7. 58 7
      src/views/book/courseware/create/components/base/describe/DescribeSetting.vue
  8. 3 3
      src/views/book/courseware/create/components/base/label/Label.vue
  9. 47 7
      src/views/book/courseware/create/components/base/label/LabelSetting.vue
  10. 1 2
      src/views/book/courseware/create/components/base/picture/PictureSetting.vue
  11. 1 1
      src/views/book/courseware/create/components/base/stem/Stem.vue
  12. 41 28
      src/views/book/courseware/create/components/base/stem/StemSetting.vue
  13. 1 2
      src/views/book/courseware/create/components/base/video/VideoSetting.vue
  14. 12 3
      src/views/book/courseware/create/components/common/SettingMixin.js
  15. 17 11
      src/views/book/courseware/data/describe.js
  16. 15 10
      src/views/book/courseware/data/label.js
  17. 17 11
      src/views/book/courseware/data/stem.js
  18. 53 1
      src/views/book/courseware/preview/components/common/SerialNumberPosition.vue
  19. 6 0
      src/views/book/courseware/preview/components/common/data.js
  20. 32 0
      src/views/book/courseware/preview/components/describe/DescribePreview.vue
  21. 30 0
      src/views/book/courseware/preview/components/label/LabelPreview.vue
  22. 32 0
      src/views/book/courseware/preview/components/stem/StemPreview.vue
  23. 0 20
      src/views/book/courseware/preview/components/video/VideoPreview.vue

+ 384 - 137
package-lock.json

@@ -45,13 +45,13 @@
         "prettier": "^3.2.5",
         "sass": "^1.75.0",
         "sass-loader": "^14.2.1",
-        "stylelint": "^16.0.2",
+        "stylelint": "^15.11.0",
         "stylelint-config-recess-order": "^4.6.0",
         "stylelint-config-recommended-scss": "^14.0.0",
         "stylelint-config-recommended-vue": "^1.5.0",
         "stylelint-config-standard-scss": "^12.0.0",
         "stylelint-declaration-block-no-ignored-properties": "^2.8.0",
-        "stylelint-webpack-plugin": "^5.0.0",
+        "stylelint-webpack-plugin": "^4.1.1",
         "svg-sprite-loader": "^6.0.11",
         "svgo": "^3.2.0",
         "vue-template-compiler": "^2.6.14"
@@ -1951,16 +1951,6 @@
         "node": ">=10.0.0"
       }
     },
-    "node_modules/@dual-bundle/import-meta-resolve": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
-      "integrity": "sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==",
-      "dev": true,
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
     "node_modules/@electron/asar": {
       "version": "3.2.9",
       "resolved": "https://registry.npmmirror.com/@electron/asar/-/asar-3.2.9.tgz",
@@ -4686,6 +4676,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/arrify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/arrify/-/arrify-1.0.1.tgz",
+      "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/assign-symbols": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -5443,6 +5442,30 @@
         "node": ">=10"
       }
     },
+    "node_modules/camelcase-keys": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmmirror.com/camelcase-keys/-/camelcase-keys-7.0.2.tgz",
+      "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==",
+      "dev": true,
+      "dependencies": {
+        "camelcase": "^6.3.0",
+        "map-obj": "^4.1.0",
+        "quick-lru": "^5.1.1",
+        "type-fest": "^1.2.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/camelcase-keys/node_modules/type-fest": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz",
+      "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/caniuse-api": {
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/caniuse-api/-/caniuse-api-3.0.0.tgz",
@@ -6691,6 +6714,46 @@
         }
       }
     },
+    "node_modules/decamelize": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-5.0.1.tgz",
+      "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/decamelize-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
+      "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
+      "dev": true,
+      "dependencies": {
+        "decamelize": "^1.1.0",
+        "map-obj": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decamelize-keys/node_modules/decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decamelize-keys/node_modules/map-obj": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-1.0.1.tgz",
+      "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/decode-uri-component": {
       "version": "0.2.2",
       "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
@@ -9184,6 +9247,15 @@
       "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
       "dev": true
     },
+    "node_modules/hard-rejection": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/hard-rejection/-/hard-rejection-2.1.0.tgz",
+      "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/has-ansi": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/has-ansi/-/has-ansi-2.0.0.tgz",
@@ -9673,6 +9745,15 @@
         "node": ">=6"
       }
     },
+    "node_modules/import-lazy": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/import-lazy/-/import-lazy-4.0.0.tgz",
+      "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/imurmurhash": {
       "version": "0.1.4",
       "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -10817,6 +10898,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/map-obj": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz",
+      "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/map-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/map-visit/-/map-visit-1.0.0.tgz",
@@ -10896,17 +10986,175 @@
       }
     },
     "node_modules/meow": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmmirror.com/meow/-/meow-13.2.0.tgz",
-      "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
+      "version": "10.1.5",
+      "resolved": "https://registry.npmmirror.com/meow/-/meow-10.1.5.tgz",
+      "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==",
+      "dev": true,
+      "dependencies": {
+        "@types/minimist": "^1.2.2",
+        "camelcase-keys": "^7.0.0",
+        "decamelize": "^5.0.0",
+        "decamelize-keys": "^1.1.0",
+        "hard-rejection": "^2.1.0",
+        "minimist-options": "4.1.0",
+        "normalize-package-data": "^3.0.2",
+        "read-pkg-up": "^8.0.0",
+        "redent": "^4.0.0",
+        "trim-newlines": "^4.0.2",
+        "type-fest": "^1.2.2",
+        "yargs-parser": "^20.2.9"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      }
+    },
+    "node_modules/meow/node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/hosted-git-info": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+      "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
       "dev": true,
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
       "engines": {
-        "node": ">=18"
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
       },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/normalize-package-data": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+      "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+      "dev": true,
+      "dependencies": {
+        "hosted-git-info": "^4.0.1",
+        "is-core-module": "^2.5.0",
+        "semver": "^7.3.4",
+        "validate-npm-package-license": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/read-pkg": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-6.0.0.tgz",
+      "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==",
+      "dev": true,
+      "dependencies": {
+        "@types/normalize-package-data": "^2.4.0",
+        "normalize-package-data": "^3.0.2",
+        "parse-json": "^5.2.0",
+        "type-fest": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=12"
       }
     },
+    "node_modules/meow/node_modules/read-pkg-up": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-8.0.0.tgz",
+      "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==",
+      "dev": true,
+      "dependencies": {
+        "find-up": "^5.0.0",
+        "read-pkg": "^6.0.0",
+        "type-fest": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/meow/node_modules/semver": {
+      "version": "7.6.0",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.0.tgz",
+      "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+      "dev": true,
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/type-fest": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz",
+      "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/meow/node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
+    },
     "node_modules/merge-descriptors": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -11029,6 +11277,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/min-indent": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz",
+      "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/mini-css-extract-plugin": {
       "version": "2.8.1",
       "resolved": "https://registry.npmmirror.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz",
@@ -11114,6 +11371,29 @@
       "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
       "dev": true
     },
+    "node_modules/minimist-options": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/minimist-options/-/minimist-options-4.1.0.tgz",
+      "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+      "dev": true,
+      "dependencies": {
+        "arrify": "^1.0.1",
+        "is-plain-obj": "^1.1.0",
+        "kind-of": "^6.0.3"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/minimist-options/node_modules/is-plain-obj": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+      "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/minipass": {
       "version": "3.3.6",
       "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
@@ -13656,6 +13936,40 @@
         "node": ">=8.10.0"
       }
     },
+    "node_modules/redent": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/redent/-/redent-4.0.0.tgz",
+      "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==",
+      "dev": true,
+      "dependencies": {
+        "indent-string": "^5.0.0",
+        "strip-indent": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/redent/node_modules/indent-string": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz",
+      "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/redent/node_modules/strip-indent": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-4.0.0.tgz",
+      "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==",
+      "dev": true,
+      "dependencies": {
+        "min-indent": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/regenerate": {
       "version": "1.4.2",
       "resolved": "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz",
@@ -14980,6 +15294,12 @@
         "node": ">=8"
       }
     },
+    "node_modules/style-search": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmmirror.com/style-search/-/style-search-0.1.0.tgz",
+      "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==",
+      "dev": true
+    },
     "node_modules/stylehacks": {
       "version": "5.1.1",
       "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz",
@@ -14997,46 +15317,47 @@
       }
     },
     "node_modules/stylelint": {
-      "version": "16.3.1",
-      "resolved": "https://registry.npmmirror.com/stylelint/-/stylelint-16.3.1.tgz",
-      "integrity": "sha512-/JOwQnBvxEKOT2RtNgGpBVXnCSMBgKOL2k7w0K52htwCyJls4+cHvc4YZgXlVoAZS9QJd2DgYAiRnja96pTgxw==",
+      "version": "15.11.0",
+      "resolved": "https://registry.npmmirror.com/stylelint/-/stylelint-15.11.0.tgz",
+      "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==",
       "dev": true,
       "dependencies": {
-        "@csstools/css-parser-algorithms": "^2.6.1",
-        "@csstools/css-tokenizer": "^2.2.4",
-        "@csstools/media-query-list-parser": "^2.1.9",
-        "@csstools/selector-specificity": "^3.0.2",
-        "@dual-bundle/import-meta-resolve": "^4.0.0",
+        "@csstools/css-parser-algorithms": "^2.3.1",
+        "@csstools/css-tokenizer": "^2.2.0",
+        "@csstools/media-query-list-parser": "^2.1.4",
+        "@csstools/selector-specificity": "^3.0.0",
         "balanced-match": "^2.0.0",
         "colord": "^2.9.3",
-        "cosmiconfig": "^9.0.0",
+        "cosmiconfig": "^8.2.0",
         "css-functions-list": "^3.2.1",
         "css-tree": "^2.3.1",
         "debug": "^4.3.4",
-        "fast-glob": "^3.3.2",
+        "fast-glob": "^3.3.1",
         "fastest-levenshtein": "^1.0.16",
-        "file-entry-cache": "^8.0.0",
+        "file-entry-cache": "^7.0.0",
         "global-modules": "^2.0.0",
         "globby": "^11.1.0",
         "globjoin": "^0.1.4",
         "html-tags": "^3.3.1",
-        "ignore": "^5.3.1",
+        "ignore": "^5.2.4",
+        "import-lazy": "^4.0.0",
         "imurmurhash": "^0.1.4",
         "is-plain-object": "^5.0.0",
-        "known-css-properties": "^0.30.0",
+        "known-css-properties": "^0.29.0",
         "mathml-tag-names": "^2.1.3",
-        "meow": "^13.2.0",
+        "meow": "^10.1.5",
         "micromatch": "^4.0.5",
         "normalize-path": "^3.0.0",
         "picocolors": "^1.0.0",
-        "postcss": "^8.4.38",
+        "postcss": "^8.4.28",
         "postcss-resolve-nested-selector": "^0.1.1",
-        "postcss-safe-parser": "^7.0.0",
-        "postcss-selector-parser": "^6.0.16",
+        "postcss-safe-parser": "^6.0.0",
+        "postcss-selector-parser": "^6.0.13",
         "postcss-value-parser": "^4.2.0",
         "resolve-from": "^5.0.0",
         "string-width": "^4.2.3",
-        "strip-ansi": "^7.1.0",
+        "strip-ansi": "^6.0.1",
+        "style-search": "^0.1.0",
         "supports-hyperlinks": "^3.0.0",
         "svg-tags": "^1.0.0",
         "table": "^6.8.1",
@@ -15046,11 +15367,7 @@
         "stylelint": "bin/stylelint.mjs"
       },
       "engines": {
-        "node": ">=18.12.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/stylelint"
+        "node": "^14.13.1 || >=16.0.0"
       }
     },
     "node_modules/stylelint-config-html": {
@@ -15246,26 +15563,22 @@
       }
     },
     "node_modules/stylelint-webpack-plugin": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmmirror.com/stylelint-webpack-plugin/-/stylelint-webpack-plugin-5.0.0.tgz",
-      "integrity": "sha512-f56OmfvIYfZpL5+TKg3LZ+Ehzoar5GAwytUtsdti+W6WhR3UpQC36vmXHsKxx9ibj7dKXCIKea6w0U+LdVSBmg==",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/stylelint-webpack-plugin/-/stylelint-webpack-plugin-4.1.1.tgz",
+      "integrity": "sha512-yOyd2AfrxfawxKDememazGVJX2vMq9o11E6HvBu4+SKvgK3ZulkjpYdI1muBTxItwoxH2UmfIZzQM+/M5V3kTQ==",
       "dev": true,
       "dependencies": {
         "globby": "^11.1.0",
-        "jest-worker": "^29.7.0",
+        "jest-worker": "^29.5.0",
         "micromatch": "^4.0.5",
         "normalize-path": "^3.0.0",
-        "schema-utils": "^4.2.0"
+        "schema-utils": "^4.0.0"
       },
       "engines": {
-        "node": ">= 18.12.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/webpack"
+        "node": ">= 14.15.0"
       },
       "peerDependencies": {
-        "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
+        "stylelint": "^13.0.0 || ^14.0.0 || ^15.0.0",
         "webpack": "^5.0.0"
       }
     },
@@ -15350,18 +15663,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/stylelint/node_modules/ansi-regex": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz",
-      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
-      }
-    },
     "node_modules/stylelint/node_modules/balanced-match": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-2.0.0.tgz",
@@ -15369,22 +15670,19 @@
       "dev": true
     },
     "node_modules/stylelint/node_modules/cosmiconfig": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
-      "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+      "version": "8.3.6",
+      "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+      "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
       "dev": true,
       "dependencies": {
-        "env-paths": "^2.2.1",
         "import-fresh": "^3.3.0",
         "js-yaml": "^4.1.0",
-        "parse-json": "^5.2.0"
+        "parse-json": "^5.2.0",
+        "path-type": "^4.0.0"
       },
       "engines": {
         "node": ">=14"
       },
-      "funding": {
-        "url": "https://github.com/sponsors/d-fischer"
-      },
       "peerDependencies": {
         "typescript": ">=4.9.5"
       },
@@ -15395,28 +15693,15 @@
       }
     },
     "node_modules/stylelint/node_modules/file-entry-cache": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
-      "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
-      "dev": true,
-      "dependencies": {
-        "flat-cache": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/stylelint/node_modules/flat-cache": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz",
-      "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+      "version": "7.0.2",
+      "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-7.0.2.tgz",
+      "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==",
       "dev": true,
       "dependencies": {
-        "flatted": "^3.2.9",
-        "keyv": "^4.5.4"
+        "flat-cache": "^3.2.0"
       },
       "engines": {
-        "node": ">=16"
+        "node": ">=12.0.0"
       }
     },
     "node_modules/stylelint/node_modules/global-modules": {
@@ -15445,38 +15730,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/stylelint/node_modules/known-css-properties": {
-      "version": "0.30.0",
-      "resolved": "https://registry.npmmirror.com/known-css-properties/-/known-css-properties-0.30.0.tgz",
-      "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==",
-      "dev": true
-    },
-    "node_modules/stylelint/node_modules/postcss-safe-parser": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmmirror.com/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz",
-      "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "opencollective",
-          "url": "https://opencollective.com/postcss/"
-        },
-        {
-          "type": "tidelift",
-          "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
-        },
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/ai"
-        }
-      ],
-      "engines": {
-        "node": ">=18.0"
-      },
-      "peerDependencies": {
-        "postcss": "^8.4.31"
-      }
-    },
     "node_modules/stylelint/node_modules/resolve-from": {
       "version": "5.0.0",
       "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz",
@@ -15486,21 +15739,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/stylelint/node_modules/strip-ansi": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz",
-      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/strip-ansi?sponsor=1"
-      }
-    },
     "node_modules/sumchecker": {
       "version": "3.0.1",
       "resolved": "https://registry.npmmirror.com/sumchecker/-/sumchecker-3.0.1.tgz",
@@ -16475,6 +16713,15 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/trim-newlines": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-4.1.1.tgz",
+      "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/truncate-utf8-bytes": {
       "version": "1.0.2",
       "resolved": "https://registry.npmmirror.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",

+ 2 - 2
package.json

@@ -51,13 +51,13 @@
     "prettier": "^3.2.5",
     "sass": "^1.75.0",
     "sass-loader": "^14.2.1",
-    "stylelint": "^16.0.2",
+    "stylelint": "^15.11.0",
     "stylelint-config-recess-order": "^4.6.0",
     "stylelint-config-recommended-scss": "^14.0.0",
     "stylelint-config-recommended-vue": "^1.5.0",
     "stylelint-config-standard-scss": "^12.0.0",
     "stylelint-declaration-block-no-ignored-properties": "^2.8.0",
-    "stylelint-webpack-plugin": "^5.0.0",
+    "stylelint-webpack-plugin": "^4.1.1",
     "svg-sprite-loader": "^6.0.11",
     "svgo": "^3.2.0",
     "vue-template-compiler": "^2.6.14"

+ 15 - 0
src/components/RichText.vue

@@ -175,6 +175,7 @@ export default {
     if (this.isFill) {
       window.addEventListener('click', this.hideContentmenu);
     }
+    this.setBackgroundColor();
   },
   beforeDestroy() {
     window.removeEventListener('click', this.hideToolbarDrawer);
@@ -183,6 +184,20 @@ export default {
     }
   },
   methods: {
+    // 设置背景色
+    setBackgroundColor() {
+      let iframes = document.getElementsByTagName('iframe');
+      for (let i = 0; i < iframes.length; i++) {
+        let iframe = iframes[i];
+        // 获取 <iframe> 内部的文档对象
+        let iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
+        let bodyElement = iframeDocument.body;
+        if (bodyElement) {
+          // 设置背景色
+          bodyElement.style.backgroundColor = '#f2f3f5';
+        }
+      }
+    },
     /**
      * 图片上传自定义逻辑函数
      * @param {object} blobInfo 文件数据

+ 1 - 2
src/views/book/courseware/create/components/base/audio/AudioSetting.vue

@@ -35,7 +35,7 @@
 
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
-import { snGenerationMethodList, checkString } from '@/views/book/courseware/data/common';
+import { snGenerationMethodList } from '@/views/book/courseware/data/common';
 import { audioViewMethodList, getAudioProperty } from '@/views/book/courseware/data/audio';
 
 export default {
@@ -43,7 +43,6 @@ export default {
   mixins: [SettingMixin],
   data() {
     return {
-      checkString,
       audioViewMethodList,
       snGenerationMethodList,
       labelPosition: 'left',

+ 138 - 0
src/views/book/courseware/create/components/base/common/SelectSerialNumberStyle.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="sn-style">
+    <el-select ref="selectStyle" v-model="sn_style" class="style-shape" @change="changeSerialNumberStyle">
+      <el-option v-for="(item, i) in serialNumberStyleList" :key="i" :value="item.value">
+        <span class="sn-box" :style="serialNumberStyle(item.value)">{{ serialNumber }}</span>
+      </el-option>
+    </el-select>
+    <el-color-picker v-model="sn_background_color" class="style-color" @change="changeSerialNumberStyle" />
+    <div class="sn-box view-style" :style="serialNumberStyle(sn_style)">{{ serialNumber }}</div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'SelectSerialNumberStyle',
+  props: {
+    serialNumber: {
+      type: [Number, String],
+      required: true,
+    },
+    snStyle: {
+      type: String,
+      default: '',
+    },
+    snBackgroundColor: {
+      type: String,
+      default: '',
+    },
+  },
+  data() {
+    return {
+      serialNumberStyleList: [
+        { value: 'solidBlockStyle' },
+        { value: 'solidCircleStyle' },
+        { value: 'hollowBlockStyle' },
+        { value: 'hollowCircleStyle' },
+        { value: 'defaultStyle' },
+      ],
+      sn_style: '',
+      sn_background_color: '',
+    };
+  },
+  watch: {
+    snBackgroundColor: {
+      handler(val) {
+        this.sn_background_color = val;
+      },
+      deep: true,
+      immediate: true,
+    },
+    snStyle: {
+      handler(val) {
+        this.sn_style = val;
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  methods: {
+    // 序号样式
+    serialNumberStyle(styleType) {
+      let serialNumberStyle = {};
+      const _color = `${this.sn_background_color}`;
+      if (styleType === 'solidBlockStyle') {
+        serialNumberStyle = {
+          borderRadius: '4px',
+          backgroundColor: _color,
+          color: '#fff',
+        };
+      } else if (styleType === 'solidCircleStyle') {
+        serialNumberStyle = {
+          borderRadius: '40px',
+          backgroundColor: _color,
+          color: '#fff',
+        };
+      } else if (styleType === 'hollowBlockStyle') {
+        serialNumberStyle = {
+          border: `1px solid ${_color}`,
+          borderRadius: '4px',
+          color: _color,
+        };
+      } else if (styleType === 'hollowCircleStyle') {
+        serialNumberStyle = {
+          border: `1px solid ${_color}`,
+          borderRadius: '40px',
+          color: _color,
+        };
+      } else if (styleType === 'defaultStyle') {
+        serialNumberStyle = {
+          color: _color,
+        };
+      }
+      return serialNumberStyle;
+    },
+    // 设置序号样式
+    changeSerialNumberStyle() {
+      this.$emit('changeSerialNumberStyle', this.sn_style, this.sn_background_color);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.sn-style {
+  display: flex;
+  column-gap: 16px;
+
+  .style-shape {
+    width: 80px;
+
+    :deep .el-input {
+      &__inner {
+        color: rgba(0, 0, 0, 0%);
+      }
+    }
+  }
+
+  .style-color {
+    width: 40px;
+  }
+
+  .view-style {
+    position: absolute;
+    top: 0;
+    left: 10px;
+  }
+}
+
+.sn-box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 24px;
+  margin-top: 5px;
+  font-size: 16px;
+  font-weight: 500;
+}
+</style>

+ 7 - 2
src/views/book/courseware/create/components/base/describe/Describe.vue

@@ -1,21 +1,26 @@
 <template>
-  <ModuleBase :type="标签">
+  <ModuleBase :type="data.type">
     <template #content>
-      <div>农行</div>
+      <RichText v-model="data.content" :font-size="18" placeholder="输入描述" />
     </template>
   </ModuleBase>
 </template>
+
 <script>
 import { getDescribeData } from '@/views/book/courseware/data/describe';
 import ModuleMixin from '../../common/ModuleMixin';
+import RichText from '@/components/RichText.vue';
+
 export default {
   name: 'DescribePage',
+  components: { RichText },
   mixins: [ModuleMixin],
   data() {
     return {
       data: getDescribeData(),
     };
   },
+  methods: {},
 };
 </script>
 

+ 58 - 7
src/views/book/courseware/create/components/base/describe/DescribeSetting.vue

@@ -1,8 +1,50 @@
 <template>
   <div>
-    <el-form :model="property" :label-position="labelPosition" label-width="56px">
-      <el-form-item label="高度">
-        <el-input v-model="property.height" />
+    <el-form :model="property" :label-position="labelPosition" label-width="72px">
+      <el-form-item label="序号" class="serial-number">
+        <el-input v-model="property.serial_number" />
+        <SvgIcon icon-class="switch" size="14" @click="switchSerialNumber(property)" />
+      </el-form-item>
+      <el-form-item>
+        <el-radio
+          v-for="{ value, label } in snGenerationMethodList"
+          :key="value"
+          v-model="property.sn_generation_method"
+          :label="value"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item label="序号样式">
+        <SelectSerialNumberStyle
+          :serial-number="property.serial_number"
+          :sn-style="property.sn_style"
+          :sn-background-color="property.sn_background_color"
+          @changeSerialNumberStyle="changeSerialNumberStyle"
+        />
+      </el-form-item>
+      <el-form-item label="序号位置">
+        <SerialNumberPosition :position="property.sn_position" @changeNumberPosition="changeNumberPosition" />
+      </el-form-item>
+      <el-divider />
+      <el-form-item label="拼音">
+        <el-switch v-model="property.view_pinyin" active-value="true" inactive-value="false" />
+      </el-form-item>
+      <el-form-item label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionList"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item label="">
+        <el-checkbox v-model="property.sentence_case">句首大写</el-checkbox>
+      </el-form-item>
+      <el-form-item label="">
+        <el-button type="primary">校对拼音</el-button>
       </el-form-item>
     </el-form>
   </div>
@@ -10,20 +52,29 @@
 
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
+import { viewMethodList, pinyinPositionList, snGenerationMethodList } from '@/views/book/courseware/data/common';
+import { getDescribeProperty } from '@/views/book/courseware/data/describe';
 
 export default {
   name: 'DescribeSetting',
   mixins: [SettingMixin],
   data() {
     return {
+      viewMethodList,
+      pinyinPositionList,
+      snGenerationMethodList,
       labelPosition: 'left',
-      property: {
-        height: 40,
-      },
+      property: getDescribeProperty(),
     };
   },
   methods: {},
 };
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.el-form {
+  @include setting-base;
+}
+</style>

+ 3 - 3
src/views/book/courseware/create/components/base/label/Label.vue

@@ -1,12 +1,12 @@
 <template>
-  <ModuleBase :type="标签">
+  <ModuleBase :type="data.type">
     <template #content>
-      <div>农行</div>
+      <div></div>
     </template>
   </ModuleBase>
 </template>
 <script>
-import { getLabelData } from '@/views/book/courseware/data/video';
+import { getLabelData } from '@/views/book/courseware/data/label';
 import ModuleMixin from '../../common/ModuleMixin';
 export default {
   name: 'LabelPage',

+ 47 - 7
src/views/book/courseware/create/components/base/label/LabelSetting.vue

@@ -1,8 +1,41 @@
 <template>
   <div>
-    <el-form :model="property" :label-position="labelPosition" label-width="56px">
-      <el-form-item label="高度">
-        <el-input v-model="property.height" />
+    <el-form :model="property" :label-position="labelPosition" label-width="72px">
+      <el-form-item label="序号" class="serial-number">
+        <el-input v-model="property.serial_number" />
+        <SvgIcon icon-class="switch" size="14" @click="switchSerialNumber(property)" />
+      </el-form-item>
+      <el-form-item>
+        <el-radio
+          v-for="{ value, label } in snGenerationMethodList"
+          :key="value"
+          v-model="property.sn_generation_method"
+          :label="value"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item label="序号样式">
+        <SelectSerialNumberStyle
+          :serial-number="property.serial_number"
+          :sn-style="property.sn_style"
+          :sn-background-color="property.sn_background_color"
+          @changeSerialNumberStyle="changeSerialNumberStyle"
+        />
+      </el-form-item>
+      <el-form-item label="序号位置">
+        <SerialNumberPosition :position="property.sn_position" @changeNumberPosition="changeNumberPosition" />
+      </el-form-item>
+      <el-divider />
+      <el-form-item label="标签颜色">
+        <el-select v-model="property.label_color">
+          <el-option label="随机" value="random" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="标签字体">
+        <el-select v-model="property.label_font">
+          <el-option label="中文" value="chinese" />
+        </el-select>
       </el-form-item>
     </el-form>
   </div>
@@ -10,20 +43,27 @@
 
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
+import { snGenerationMethodList } from '@/views/book/courseware/data/common';
+import { getLabelProperty } from '@/views/book/courseware/data/label';
 
 export default {
   name: 'LabelSetting',
   mixins: [SettingMixin],
   data() {
     return {
+      snGenerationMethodList,
       labelPosition: 'left',
-      property: {
-        height: 40,
-      },
+      property: getLabelProperty(),
     };
   },
   methods: {},
 };
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.el-form {
+  @include setting-base;
+}
+</style>

+ 1 - 2
src/views/book/courseware/create/components/base/picture/PictureSetting.vue

@@ -30,7 +30,7 @@
 
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
-import { viewMethodList, snGenerationMethodList, checkString } from '@/views/book/courseware/data/common';
+import { viewMethodList, snGenerationMethodList } from '@/views/book/courseware/data/common';
 import { getPictureProperty } from '@/views/book/courseware/data/picture';
 
 export default {
@@ -38,7 +38,6 @@ export default {
   mixins: [SettingMixin],
   data() {
     return {
-      checkString,
       snGenerationMethodList,
       viewMethodList,
       labelPosition: 'left',

+ 1 - 1
src/views/book/courseware/create/components/base/stem/Stem.vue

@@ -1,7 +1,7 @@
 <template>
   <ModuleBase :type="data.type">
     <template #content>
-      <RichText v-model="data.stem" :font-size="18" placeholder="输入题干" />
+      <RichText v-model="data.content" :font-size="18" placeholder="输入题干" />
     </template>
   </ModuleBase>
 </template>

+ 41 - 28
src/views/book/courseware/create/components/base/stem/StemSetting.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <el-form :model="property" :label-position="labelPosition" label-width="56px">
+    <el-form :model="property" :label-position="labelPosition" label-width="72px">
       <el-form-item label="序号" class="serial-number">
         <el-input v-model="property.serial_number" />
         <SvgIcon icon-class="switch" size="14" @click="switchSerialNumber(property)" />
@@ -15,53 +15,66 @@
           {{ label }}
         </el-radio>
       </el-form-item>
+      <el-form-item label="序号样式">
+        <SelectSerialNumberStyle
+          :serial-number="property.serial_number"
+          :sn-style="property.sn_style"
+          :sn-background-color="property.sn_background_color"
+          @changeSerialNumberStyle="changeSerialNumberStyle"
+        />
+      </el-form-item>
       <el-form-item label="序号位置">
-        <div class="grid-container">
-          <el-button
-            v-for="{ value } in serialNumberPositionList"
-            :key="value"
-            :class="[value, { active: value === property.sn_position }]"
-            :style="{ gridArea: value }"
-            @click="changeNumberPosition(value)"
-          />
-          <div class="main"></div>
-        </div>
+        <SerialNumberPosition :position="property.sn_position" @changeNumberPosition="changeNumberPosition" />
       </el-form-item>
       <el-divider />
+      <el-form-item label="拼音">
+        <el-switch v-model="property.view_pinyin" active-value="true" inactive-value="false" />
+      </el-form-item>
+      <el-form-item label="拼音位置">
+        <el-radio
+          v-for="{ value, label } in pinyinPositionList"
+          :key="value"
+          v-model="property.pinyin_position"
+          :label="value"
+        >
+          {{ label }}
+        </el-radio>
+      </el-form-item>
+      <el-form-item label="">
+        <el-checkbox v-model="property.sentence_case">句首大写</el-checkbox>
+      </el-form-item>
+      <el-form-item label="">
+        <el-button type="primary">校对拼音</el-button>
+      </el-form-item>
     </el-form>
   </div>
 </template>
 
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
-import {
-  snGenerationMethodList,
-  switchSerialNumber,
-  checkString,
-  serialNumberPositionList,
-} from '@/views/book/courseware/data/common';
+import { viewMethodList, pinyinPositionList, snGenerationMethodList } from '@/views/book/courseware/data/common';
+import { getStemProperty } from '@/views/book/courseware/data/stem';
 
 export default {
   name: 'StemSetting',
   mixins: [SettingMixin],
   data() {
     return {
-      switchSerialNumber,
-      checkString,
-      serialNumberPositionList,
-      snGenerationMethodList,
       viewMethodList,
+      pinyinPositionList,
+      snGenerationMethodList,
       labelPosition: 'left',
-      property: {
-        serial_number: 1, // 序号
-        sn_type: 'number',
-        sn_position: 'top-start', // 序号位置:top-start top top-end 等
-        sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate 重新计算follow 跟随
-      },
+      property: getStemProperty(),
     };
   },
   methods: {},
 };
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.el-form {
+  @include setting-base;
+}
+</style>

+ 1 - 2
src/views/book/courseware/create/components/base/video/VideoSetting.vue

@@ -30,7 +30,7 @@
 
 <script>
 import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
-import { snGenerationMethodList, viewMethodList, checkString } from '@/views/book/courseware/data/common';
+import { snGenerationMethodList, viewMethodList } from '@/views/book/courseware/data/common';
 import { getVideoProperty } from '@/views/book/courseware/data/video';
 
 export default {
@@ -38,7 +38,6 @@ export default {
   mixins: [SettingMixin],
   data() {
     return {
-      checkString,
       snGenerationMethodList,
       viewMethodList,
       labelPosition: 'left',

+ 12 - 3
src/views/book/courseware/create/components/common/SettingMixin.js

@@ -1,7 +1,8 @@
-import { switchSerialNumber, computedQuestionNumber, isEnable } from '../../../data/common';
+import { switchSerialNumber, computedQuestionNumber } from '../../../data/common';
 import { snGenerationMethodList, checkString } from '@/views/book/courseware/data/common';
 
 import SerialNumberPosition from '@/views/book/courseware/create/components/common/SerialNumberPosition.vue';
+import SelectSerialNumberStyle from '@/views/book/courseware/create/components/base/common/SelectSerialNumberStyle.vue';
 
 const mixin = {
   data() {
@@ -10,10 +11,9 @@ const mixin = {
       computedQuestionNumber,
       snGenerationMethodList,
       checkString,
-      isEnable,
     };
   },
-  components: { SerialNumberPosition },
+  components: { SerialNumberPosition, SelectSerialNumberStyle },
   watch: {
     'property.serial_number': {
       handler(val) {
@@ -37,6 +37,15 @@ const mixin = {
     changeNumberPosition(sn_position) {
       this.property.sn_position = sn_position;
     },
+
+    /**
+     * @description 改变序号样式
+     * @param {String} sn_style,sn_background_color
+     */
+    changeSerialNumberStyle(sn_style, sn_background_color) {
+      this.property.sn_style = sn_style;
+      this.property.sn_background_color = sn_background_color;
+    },
   },
 };
 

+ 17 - 11
src/views/book/courseware/data/describe.js

@@ -5,20 +5,26 @@ import {
   pinyinPositionList,
 } from '@/views/book/courseware/data/common';
 
+export function getDescribeProperty() {
+  return {
+    serial_number: 1, // 序号
+    sn_type: serialNumberTypeList[0].value, // 序号类型:letter字母 number数字  capital大写字母 bracket_number括号数字
+    sn_position: serialNumberPositionList[0].value, // 序号位置:top-start top top-end,left-start left left-end等
+    sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate重新计算 follow 跟随
+    // 序号样式 solidBlockStyle实心方块 solidCircleStyle实心圆 hollowBlockStyle空心方块 hollowCircleStyle空心圆 defaultStyle默认无
+    sn_style: 'solidBlockStyle',
+    sn_background_color: '#ea3232', // 序号背景色
+    view_pinyin: 'true', // 显示拼音
+    pinyin_position: pinyinPositionList[0].value, // top bottom
+    sentence_case: 'true', // 句首大写
+  };
+}
+
 export function getDescribeData() {
   return {
     type: 'describe',
     title: '描述',
-    property: {
-      serial_number: 1, // 序号
-      sn_type: serialNumberTypeList[0].value, // 序号类型:letter字母 number数字  capital大写字母 bracket_number括号数字
-      sn_position: serialNumberPositionList[0].value, // 序号位置:top-start top top-end,left-start left left-end等
-      sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate重新计算 follow 跟随
-      sn_style: '', // 序号样式三角形 圆形
-      sn_background_color: '', // 序号背景色
-      view_pinyin: 'true', // 显示拼音
-      pinyin_position: pinyinPositionList[0].value, // top bottom
-      sentence_case: 'true', // 句首大写
-    },
+    content: '',
+    property: getDescribeProperty(),
   };
 }

+ 15 - 10
src/views/book/courseware/data/label.js

@@ -4,19 +4,24 @@ import {
   serialNumberPositionList,
 } from '@/views/book/courseware/data/common';
 
+export function getLabelProperty() {
+  return {
+    serial_number: 1, // 序号
+    sn_type: serialNumberTypeList[0].value, // 序号类型:letter字母 number数字  capital大写字母 bracket_number括号数字
+    sn_position: serialNumberPositionList[0].value, // 序号位置:top-start top top-end,left-start left left-end等
+    sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate重新计算 follow 跟随
+    // 序号样式 solidBlockStyle实心方块 solidCircleStyle实心圆 hollowBlockStyle空心方块 hollowCircleStyle空心圆 defaultStyle默认无
+    sn_style: 'solidBlockStyle',
+    sn_background_color: '#ea3232', // 序号背景色
+    label_color: '随机', // 标签颜色
+    label_font: '中文', // 标签字体
+  };
+}
+
 export function getLabelData() {
   return {
     type: 'label',
     title: '标签',
-    property: {
-      serial_number: 1, // 序号
-      sn_type: serialNumberTypeList[0].value, // 序号类型:letter字母 number数字  capital大写字母 bracket_number括号数字
-      sn_position: serialNumberPositionList[0].value, // 序号位置:top-start top top-end,left-start left left-end等
-      sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate重新计算 follow 跟随
-      sn_style: '', // 序号样式三角形 圆形
-      sn_background_color: '', // 序号背景色
-      label_color: '随机', // 标签颜色
-      label_font: '中文', // 标签字体
-    },
+    property: getLabelProperty(),
   };
 }

+ 17 - 11
src/views/book/courseware/data/stem.js

@@ -5,20 +5,26 @@ import {
   pinyinPositionList,
 } from '@/views/book/courseware/data/common';
 
+export function getStemProperty() {
+  return {
+    serial_number: 1, // 序号
+    sn_type: serialNumberTypeList[0].value, // 序号类型:letter字母 number数字  capital大写字母 bracket_number括号数字
+    sn_position: serialNumberPositionList[0].value, // 序号位置:top-start top top-end,left-start left left-end等
+    sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate重新计算 follow 跟随
+    // 序号样式 solidBlockStyle实心方块 solidCircleStyle实心圆 hollowBlockStyle空心方块 hollowCircleStyle空心圆 defaultStyle默认无
+    sn_style: 'solidBlockStyle',
+    sn_background_color: '#ea3232', // 序号背景色
+    view_pinyin: 'true', // 显示拼音
+    pinyin_position: pinyinPositionList[0].value, // top bottom
+    sentence_case: 'true', // 句首大写
+  };
+}
+
 export function getStemData() {
   return {
     type: 'stem',
     title: '题干',
-    property: {
-      serial_number: 1, // 序号
-      sn_type: serialNumberTypeList[0].value, // 序号类型:letter字母 number数字  capital大写字母 bracket_number括号数字
-      sn_position: serialNumberPositionList[0].value, // 序号位置:top-start top top-end,left-start left left-end等
-      sn_generation_method: snGenerationMethodList[0].value, // 序号生成方式:recalculate重新计算 follow 跟随
-      sn_style: '', // 序号样式三角形 圆形
-      sn_background_color: '', // 序号背景色
-      view_pinyin: 'true', // 显示拼音
-      pinyin_position: pinyinPositionList[0].value, // top bottom
-      sentence_case: 'true', // 句首大写
-    },
+    stem: '',
+    property: getStemProperty(),
   };
 }

+ 53 - 1
src/views/book/courseware/preview/components/common/SerialNumberPosition.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="sn-position" :style="getJustifyContentStyle()">
+  <div :class="['sn-position', property.sn_style ? 'sn-box' : '']" :style="getJustifyContentStyle()">
     {{ property.serial_number }}
   </div>
 </template>
@@ -29,10 +29,52 @@ export default {
         placeSelf = 'center';
       }
 
+      const snStyle = this.property.sn_style;
+      if (snStyle) {
+        return this.serialNumberStyle(snStyle, placeSelf);
+      }
+
       return {
         placeSelf,
       };
     },
+
+    // 题干与描述序号样式
+    serialNumberStyle(styleType, placeSelf) {
+      let serialNumberStyle = {};
+      const _color = `${this.property.sn_background_color}`;
+      if (styleType === 'solidBlockStyle') {
+        serialNumberStyle = {
+          borderRadius: '4px',
+          backgroundColor: _color,
+          color: '#fff',
+        };
+      } else if (styleType === 'solidCircleStyle') {
+        serialNumberStyle = {
+          borderRadius: '40px',
+          backgroundColor: _color,
+          color: '#fff',
+        };
+      } else if (styleType === 'hollowBlockStyle') {
+        serialNumberStyle = {
+          border: `1px solid ${_color}`,
+          borderRadius: '4px',
+          color: _color,
+        };
+      } else if (styleType === 'hollowCircleStyle') {
+        serialNumberStyle = {
+          border: `1px solid ${_color}`,
+          borderRadius: '40px',
+          color: _color,
+        };
+      } else if (styleType === 'defaultStyle') {
+        serialNumberStyle = {
+          color: _color,
+        };
+      }
+      serialNumberStyle.placeSelf = placeSelf;
+      return serialNumberStyle;
+    },
   },
 };
 </script>
@@ -41,4 +83,14 @@ export default {
 .sn-position {
   grid-area: position;
 }
+
+.sn-box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 24px;
+  font-size: 16px;
+  font-weight: 500;
+}
 </style>

+ 6 - 0
src/views/book/courseware/preview/components/common/data.js

@@ -3,6 +3,9 @@ import DividerPreview from '../divider/DividerPreview.vue';
 import SpacingPreview from '../spacing/SpacingPreview.vue';
 import PicturePreview from '../picture/PicturePreview.vue';
 import VideoPreview from '../video/VideoPreview.vue';
+import StemPreview from '../stem/StemPreview.vue';
+import DescribePreview from '../describe/DescribePreview.vue';
+import LabelPreview from '../label/LabelPreview.vue';
 import SelectPreview from '../select/SelectPreview.vue';
 
 export const previewComponentMap = {
@@ -11,5 +14,8 @@ export const previewComponentMap = {
   spacing: SpacingPreview,
   picture: PicturePreview,
   video: VideoPreview,
+  stem: StemPreview,
+  describe: DescribePreview,
+  label: LabelPreview,
   select: SelectPreview,
 };

+ 32 - 0
src/views/book/courseware/preview/components/describe/DescribePreview.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="describe-preview" :style="getAreaStyle()">
+    <SerialNumberPosition :property="data.property" />
+    <div class="main">
+      <span class="rich-text" v-html="sanitizeHTML(data.content)"></span>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getDescribeData } from '@/views/book/courseware/data/describe';
+import PreviewMixin from '../common/PreviewMixin';
+
+export default {
+  name: 'DescribePreview',
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      data: getDescribeData(),
+    };
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.describe-preview {
+  @include preview-base;
+}
+</style>

+ 30 - 0
src/views/book/courseware/preview/components/label/LabelPreview.vue

@@ -0,0 +1,30 @@
+<template>
+  <div class="label-preview" :style="getAreaStyle()">
+    <SerialNumberPosition :property="data.property" />
+    <div class="main"></div>
+  </div>
+</template>
+
+<script>
+import { getLabelData } from '@/views/book/courseware/data/label';
+import PreviewMixin from '../common/PreviewMixin';
+
+export default {
+  name: 'LabelPreview',
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      data: getLabelData(),
+    };
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.label-preview {
+  @include preview-base;
+}
+</style>

+ 32 - 0
src/views/book/courseware/preview/components/stem/StemPreview.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="stem-preview" :style="getAreaStyle()">
+    <SerialNumberPosition :property="data.property" />
+    <div class="main">
+      <span class="rich-text" v-html="sanitizeHTML(data.content)"></span>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getStemData } from '@/views/book/courseware/data/stem';
+import PreviewMixin from '../common/PreviewMixin';
+
+export default {
+  name: 'StemPreview',
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      data: getStemData(),
+    };
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.stem-preview {
+  @include preview-base;
+}
+</style>

+ 0 - 20
src/views/book/courseware/preview/components/video/VideoPreview.vue

@@ -103,26 +103,6 @@ export default {
         grid,
       };
     },
-
-    /**
-     * 得到序号位置样式
-     */
-    getJustifyContentStyle() {
-      const position = this.data.property.sn_position;
-      let placeSelf = '';
-
-      if (position.includes('start')) {
-        placeSelf = 'flex-start';
-      } else if (position.includes('end')) {
-        placeSelf = 'flex-end';
-      } else {
-        placeSelf = 'center';
-      }
-
-      return {
-        placeSelf,
-      };
-    },
   },
 };
 </script>