Преглед изворни кода

答题回显答案及控制,选择、连线、判断、填空、朗读

dusenyao пре 1 година
родитељ
комит
08e8b1f761

+ 128 - 89
package-lock.json

@@ -48,21 +48,21 @@
       "dev": true
     },
     "@babel/core": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.3.tgz",
-      "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.5.tgz",
+      "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==",
       "dev": true,
       "requires": {
         "@ampproject/remapping": "^2.2.0",
-        "@babel/code-frame": "^7.22.13",
-        "@babel/generator": "^7.23.3",
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.5",
         "@babel/helper-compilation-targets": "^7.22.15",
         "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helpers": "^7.23.2",
-        "@babel/parser": "^7.23.3",
+        "@babel/helpers": "^7.23.5",
+        "@babel/parser": "^7.23.5",
         "@babel/template": "^7.22.15",
-        "@babel/traverse": "^7.23.3",
-        "@babel/types": "^7.23.3",
+        "@babel/traverse": "^7.23.5",
+        "@babel/types": "^7.23.5",
         "convert-source-map": "^2.0.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -70,13 +70,23 @@
         "semver": "^6.3.1"
       },
       "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.23.5.tgz",
+          "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.23.4",
+            "chalk": "^2.4.2"
+          }
+        },
         "@babel/generator": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.23.3.tgz",
-          "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.23.5.tgz",
+          "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.23.3",
+            "@babel/types": "^7.23.5",
             "@jridgewell/gen-mapping": "^0.3.2",
             "@jridgewell/trace-mapping": "^0.3.17",
             "jsesc": "^2.5.1"
@@ -95,37 +105,54 @@
             "@babel/helper-validator-identifier": "^7.22.20"
           }
         },
+        "@babel/helper-string-parser": {
+          "version": "7.23.4",
+          "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
+          "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+          "dev": true
+        },
+        "@babel/highlight": {
+          "version": "7.23.4",
+          "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.23.4.tgz",
+          "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.22.20",
+            "chalk": "^2.4.2",
+            "js-tokens": "^4.0.0"
+          }
+        },
         "@babel/parser": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.3.tgz",
-          "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.5.tgz",
+          "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==",
           "dev": true
         },
         "@babel/traverse": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.3.tgz",
-          "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.5.tgz",
+          "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==",
           "dev": true,
           "requires": {
-            "@babel/code-frame": "^7.22.13",
-            "@babel/generator": "^7.23.3",
+            "@babel/code-frame": "^7.23.5",
+            "@babel/generator": "^7.23.5",
             "@babel/helper-environment-visitor": "^7.22.20",
             "@babel/helper-function-name": "^7.23.0",
             "@babel/helper-hoist-variables": "^7.22.5",
             "@babel/helper-split-export-declaration": "^7.22.6",
-            "@babel/parser": "^7.23.3",
-            "@babel/types": "^7.23.3",
+            "@babel/parser": "^7.23.5",
+            "@babel/types": "^7.23.5",
             "debug": "^4.1.0",
             "globals": "^11.1.0"
           }
         },
         "@babel/types": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.3.tgz",
-          "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.5.tgz",
+          "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==",
           "dev": true,
           "requires": {
-            "@babel/helper-string-parser": "^7.22.5",
+            "@babel/helper-string-parser": "^7.23.4",
             "@babel/helper-validator-identifier": "^7.22.20",
             "to-fast-properties": "^2.0.0"
           }
@@ -377,76 +404,88 @@
       }
     },
     "@babel/helpers": {
-      "version": "7.23.2",
-      "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.23.2.tgz",
-      "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.23.5.tgz",
+      "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==",
       "dev": true,
       "requires": {
         "@babel/template": "^7.22.15",
-        "@babel/traverse": "^7.23.2",
-        "@babel/types": "^7.23.0"
+        "@babel/traverse": "^7.23.5",
+        "@babel/types": "^7.23.5"
       },
       "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.23.5.tgz",
+          "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.23.4",
+            "chalk": "^2.4.2"
+          }
+        },
         "@babel/generator": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.23.3.tgz",
-          "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.23.5.tgz",
+          "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==",
           "dev": true,
           "requires": {
-            "@babel/types": "^7.23.3",
+            "@babel/types": "^7.23.5",
             "@jridgewell/gen-mapping": "^0.3.2",
             "@jridgewell/trace-mapping": "^0.3.17",
             "jsesc": "^2.5.1"
-          },
-          "dependencies": {
-            "@babel/types": {
-              "version": "7.23.3",
-              "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.3.tgz",
-              "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==",
-              "dev": true,
-              "requires": {
-                "@babel/helper-string-parser": "^7.22.5",
-                "@babel/helper-validator-identifier": "^7.22.20",
-                "to-fast-properties": "^2.0.0"
-              }
-            }
+          }
+        },
+        "@babel/helper-string-parser": {
+          "version": "7.23.4",
+          "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
+          "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+          "dev": true
+        },
+        "@babel/highlight": {
+          "version": "7.23.4",
+          "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.23.4.tgz",
+          "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.22.20",
+            "chalk": "^2.4.2",
+            "js-tokens": "^4.0.0"
           }
         },
         "@babel/parser": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.3.tgz",
-          "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.5.tgz",
+          "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==",
           "dev": true
         },
         "@babel/traverse": {
-          "version": "7.23.3",
-          "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.3.tgz",
-          "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==",
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.5.tgz",
+          "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==",
           "dev": true,
           "requires": {
-            "@babel/code-frame": "^7.22.13",
-            "@babel/generator": "^7.23.3",
+            "@babel/code-frame": "^7.23.5",
+            "@babel/generator": "^7.23.5",
             "@babel/helper-environment-visitor": "^7.22.20",
             "@babel/helper-function-name": "^7.23.0",
             "@babel/helper-hoist-variables": "^7.22.5",
             "@babel/helper-split-export-declaration": "^7.22.6",
-            "@babel/parser": "^7.23.3",
-            "@babel/types": "^7.23.3",
+            "@babel/parser": "^7.23.5",
+            "@babel/types": "^7.23.5",
             "debug": "^4.1.0",
             "globals": "^11.1.0"
-          },
-          "dependencies": {
-            "@babel/types": {
-              "version": "7.23.3",
-              "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.3.tgz",
-              "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==",
-              "dev": true,
-              "requires": {
-                "@babel/helper-string-parser": "^7.22.5",
-                "@babel/helper-validator-identifier": "^7.22.20",
-                "to-fast-properties": "^2.0.0"
-              }
-            }
+          }
+        },
+        "@babel/types": {
+          "version": "7.23.5",
+          "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.5.tgz",
+          "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==",
+          "dev": true,
+          "requires": {
+            "@babel/helper-string-parser": "^7.23.4",
+            "@babel/helper-validator-identifier": "^7.22.20",
+            "to-fast-properties": "^2.0.0"
           }
         }
       }
@@ -1411,9 +1450,9 @@
       "dev": true
     },
     "@eslint/eslintrc": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz",
-      "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==",
+      "version": "2.1.4",
+      "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+      "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
       "dev": true,
       "requires": {
         "ajv": "^6.12.4",
@@ -1445,9 +1484,9 @@
       }
     },
     "@eslint/js": {
-      "version": "8.54.0",
-      "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.54.0.tgz",
-      "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==",
+      "version": "8.55.0",
+      "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-8.55.0.tgz",
+      "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==",
       "dev": true
     },
     "@gar/promisify": {
@@ -4933,15 +4972,15 @@
       "dev": true
     },
     "eslint": {
-      "version": "8.54.0",
-      "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.54.0.tgz",
-      "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==",
+      "version": "8.55.0",
+      "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.55.0.tgz",
+      "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==",
       "dev": true,
       "requires": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.6.1",
-        "@eslint/eslintrc": "^2.1.3",
-        "@eslint/js": "8.54.0",
+        "@eslint/eslintrc": "^2.1.4",
+        "@eslint/js": "8.55.0",
         "@humanwhocodes/config-array": "^0.11.13",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -5160,9 +5199,9 @@
       }
     },
     "eslint-plugin-vue": {
-      "version": "9.18.1",
-      "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz",
-      "integrity": "sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg==",
+      "version": "9.19.2",
+      "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz",
+      "integrity": "sha512-CPDqTOG2K4Ni2o4J5wixkLVNwgctKXFu6oBpVJlpNq7f38lh9I80pRTouZSJ2MAebPJlINU/KTFSXyQfBUlymA==",
       "dev": true,
       "requires": {
         "@eslint-community/eslint-utils": "^4.4.0",
@@ -10980,9 +11019,9 @@
       "dev": true
     },
     "svgo": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmmirror.com/svgo/-/svgo-3.0.4.tgz",
-      "integrity": "sha512-T+Xul3JwuJ6VGXKo/p2ndqx1ibxNKnLTvRc1ZTWKCfyKS/GgNjRZcYsK84fxTsy/izr91g/Rwx6fGnVgaFSI5g==",
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/svgo/-/svgo-3.0.5.tgz",
+      "integrity": "sha512-HQKHEo73pMNOlDlBcLgZRcHW2+1wo7bFYayAXkGN0l/2+h68KjlfZyMRhdhaGvoHV2eApOovl12zoFz42sT6rQ==",
       "dev": true,
       "requires": {
         "@trysound/sax": "0.2.0",

+ 4 - 4
package.json

@@ -27,7 +27,7 @@
     "vuex": "^3.6.2"
   },
   "devDependencies": {
-    "@babel/core": "^7.23.3",
+    "@babel/core": "^7.23.5",
     "@babel/eslint-parser": "^7.23.3",
     "@rushstack/eslint-patch": "^1.6.0",
     "@vue/cli-plugin-babel": "~5.0.8",
@@ -37,9 +37,9 @@
     "@vue/preload-webpack-plugin": "^2.0.0",
     "babel-plugin-dynamic-import-node": "^2.3.3",
     "compression-webpack-plugin": "^6.1.1",
-    "eslint": "^8.54.0",
+    "eslint": "^8.55.0",
     "eslint-plugin-prettier": "^5.0.1",
-    "eslint-plugin-vue": "^9.18.1",
+    "eslint-plugin-vue": "^9.19.2",
     "patch-package": "^8.0.0",
     "postcss-html": "^1.5.0",
     "prettier": "^3.1.0",
@@ -53,7 +53,7 @@
     "stylelint-declaration-block-no-ignored-properties": "^2.7.0",
     "stylelint-webpack-plugin": "^4.1.1",
     "svg-sprite-loader": "^6.0.11",
-    "svgo": "^3.0.4",
+    "svgo": "^3.0.5",
     "vue-template-compiler": "^2.6.14"
   },
   "engines": {

+ 1 - 0
src/styles/variables.scss

@@ -16,6 +16,7 @@ $border: 1px solid $border-color;
 $hanzi-writer-color: #de4444;
 $error-color: #f2555a;
 $right-color: #30a47d;
+$right-bc-color: #e8f7f2;
 
 // px
 $header-h: 64px;

+ 10 - 9
src/views/exercise_questions/create/index.vue

@@ -254,15 +254,16 @@ export default {
     },
     // 完整预览
     fullPreview() {
-      window.open(
-        this.$router.resolve({
-          path: '/answer',
-          query: {
-            id: this.exercise_id,
-          },
-        }).href,
-        '_blank',
-      );
+      // TODO 待完善
+      // window.open(
+      //   this.$router.resolve({
+      //     path: '/answer',
+      //     query: {
+      //       id: this.exercise_id,
+      //     },
+      //   }).href,
+      //   '_blank',
+      // );
     },
     // 预览
     setPreview() {

+ 83 - 8
src/views/exercise_questions/preview/FillPreview.vue

@@ -20,14 +20,20 @@
       <p v-for="(item, i) in modelEssay" :key="i">
         <template v-for="(li, j) in item">
           <span v-if="li.type === 'text'" :key="j" v-html="sanitizeHTML(li.content)"></span>
-          <el-input
-            v-if="li.type === 'input'"
-            :key="j"
-            v-model="li.content"
-            :style="{ width: Math.max(80, li.content.length * 16) + 'px' }"
-            @focus="handleInputFocus(i, j)"
-            @blur="handleTone(li.content, i, j)"
-          />
+          <template v-if="li.type === 'input'">
+            <el-input
+              :key="j"
+              v-model="li.content"
+              :disabled="disabled"
+              :class="[...computedAnswerClass(li.mark)]"
+              :style="[{ width: Math.max(80, li.content.length * 16) + 'px' }]"
+              @focus="handleInputFocus(i, j)"
+              @blur="handleTone(li.content, i, j)"
+            />
+            <span v-show="computedAnswerText(li.mark).length > 0" :key="`answer-${j}`" class="right-answer">
+              {{ computedAnswerText(li.mark) }}
+            </span>
+          </template>
         </template>
       </p>
     </div>
@@ -57,6 +63,9 @@ export default {
     descriptionList() {
       return this.data.description.split(/\s+/);
     },
+    disabled() {
+      return this.isJudgingRightWrong || this.isShowRightAnswer;
+    },
   },
   watch: {
     'data.model_essay': {
@@ -133,6 +142,48 @@ export default {
         .filter((item) => item.length > 0)
         .join(' ');
     },
+    /**
+     * 计算答题对错选项字体颜色
+     * @param {string} mark 选项标识
+     */
+    computedAnswerClass(mark) {
+      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
+        return '';
+      }
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 是否已选中的选项
+      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark); // 是否正确的选项
+      if (!selectOption) return '';
+      let selectValue = selectOption.value;
+      let answerValue = answerOption.value;
+      let type = answerOption.type;
+      let classList = [];
+      let isRight =
+        (type === 'only_one' && selectValue === answerValue) ||
+        (type === 'any_one' && answerValue.split('/').includes(selectValue));
+
+      if (this.isJudgingRightWrong) {
+        isRight ? classList.push('right') : classList.push('wrong');
+      }
+
+      if (this.isShowRightAnswer && !isRight) {
+        classList.push('show-right-answer');
+      }
+      return classList;
+    },
+    computedAnswerText(mark) {
+      if (!this.isShowRightAnswer) return '';
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 是否已选中的选项
+      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark); // 是否正确的选项
+      if (!selectOption) return '';
+      let selectValue = selectOption.value;
+      let answerValue = answerOption.value;
+      let type = answerOption.type;
+      let isRight =
+        (type === 'only_one' && selectValue === answerValue) ||
+        (type === 'any_one' && answerValue.split('/').includes(selectValue));
+      if (isRight) return '';
+      return `(${answerValue})`;
+    },
   },
 };
 </script>
@@ -160,9 +211,33 @@ export default {
 
   .fill-wrapper {
     .el-input {
+      display: inline-flex;
+      align-items: center;
       width: 120px;
       margin: 0 2px;
 
+      &.right {
+        :deep input.el-input__inner {
+          color: $right-color;
+        }
+      }
+
+      &.wrong {
+        :deep input.el-input__inner {
+          color: $error-color;
+        }
+      }
+
+      & + .right-answer {
+        position: relative;
+        left: -4px;
+        display: inline-block;
+        height: 32px;
+        line-height: 28px;
+        vertical-align: bottom;
+        border-bottom: 1px solid $font-color;
+      }
+
       :deep input.el-input__inner {
         padding: 0;
         font-size: 16px;

+ 44 - 1
src/views/exercise_questions/preview/JudgePreview.vue

@@ -16,7 +16,7 @@
         :key="mark"
         :class="['option-item', { active: isAnswer(mark) }]"
       >
-        <div class="option-content">
+        <div :class="['option-content', computedIsJudgeRight(mark)]">
           <span class="serial-number">{{ computedQuestionNumber(i, data.option_number_show_mode) }}</span>
           <div v-html="sanitizeHTML(content)"></div>
         </div>
@@ -24,11 +24,13 @@
           <div
             v-for="option_type in data.property.option_type_list"
             :key="option_type"
+            :style="{ cursor: isJudgingRightWrong || isShowRightAnswer ? 'not-allowed' : 'pointer' }"
             :class="[
               'option-type-item',
               {
                 active: isAnswer(mark, option_type),
               },
+              computedIsShowRightAnswer(mark, option_type),
             ]"
             @click="selectAnswer(mark, option_type)"
           >
@@ -63,6 +65,7 @@ export default {
     },
 
     selectAnswer(mark, option_type) {
+      if (this.isJudgingRightWrong || this.isShowRightAnswer) return;
       const index = this.answer.answer_list.findIndex((li) => li.mark === mark);
       if (index === -1) {
         this.answer.answer_list.push({ mark, option_type });
@@ -70,6 +73,33 @@ export default {
         this.answer.answer_list[index].option_type = option_type;
       }
     },
+
+    /**
+     * 计算是否显示正确答案的样式
+     * @param {string} mark 选项标识
+     * @param {string} option_type 选项类型
+     */
+    computedIsShowRightAnswer(mark, option_type) {
+      if (!this.isShowRightAnswer) return '';
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 查找是否已选中的选项
+      if (!selectOption) return '';
+      return this.data.answer.answer_list.find((item) => item.mark === mark).option_type === option_type &&
+        !(selectOption.option_type === option_type)
+        ? 'answer-right'
+        : '';
+    },
+    /**
+     * 计算判断题题干的样式
+     * @param {string} mark 选项标识
+     */
+    computedIsJudgeRight(mark) {
+      if (!this.isJudgingRightWrong) return '';
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 查找是否已选中的选项
+      if (!selectOption) return 'wrong';
+      return this.data.answer.answer_list.find((item) => item.mark === mark).option_type === selectOption.option_type
+        ? 'right'
+        : 'wrong';
+    },
   },
 };
 </script>
@@ -98,6 +128,14 @@ export default {
         background-color: $content-color;
         border-radius: 40px;
 
+        &.right {
+          background-color: $right-bc-color;
+        }
+
+        &.wrong {
+          box-shadow: 0 0 0 1px $error-color;
+        }
+
         .serial-number {
           color: #000;
         }
@@ -123,6 +161,11 @@ export default {
             color: #fff;
             background-color: $light-main-color;
           }
+
+          &.answer-right {
+            color: $right-color;
+            border: 1px solid $right-color;
+          }
         }
       }
     }

+ 84 - 8
src/views/exercise_questions/preview/ListenFillPreview.vue

@@ -20,14 +20,21 @@
       <p v-for="(item, i) in modelEssay" :key="i">
         <template v-for="(li, j) in item">
           <span v-if="li.type === 'text'" :key="j" v-html="sanitizeHTML(li.content)"></span>
-          <el-input
-            v-if="li.type === 'input'"
-            :key="j"
-            v-model="li.content"
-            :style="{ width: Math.max(80, li.content.length * 16) + 'px' }"
-            @focus="handleInputFocus(i, j)"
-            @blur="handleTone(li.content, i, j)"
-          />
+          <template v-if="li.type === 'input'">
+            <el-input
+              v-if="li.type === 'input'"
+              :key="j"
+              v-model="li.content"
+              :disabled="disabled"
+              :class="[...computedAnswerClass(li.mark)]"
+              :style="[{ width: Math.max(80, li.content.length * 16) + 'px' }]"
+              @focus="handleInputFocus(i, j)"
+              @blur="handleTone(li.content, i, j)"
+            />
+            <span v-show="computedAnswerText(li.mark).length > 0" :key="`answer-${j}`" class="right-answer">
+              {{ computedAnswerText(li.mark) }}
+            </span>
+          </template>
         </template>
       </p>
     </div>
@@ -57,6 +64,9 @@ export default {
     descriptionList() {
       return this.data.description.split(/\s+/);
     },
+    disabled() {
+      return this.isJudgingRightWrong || this.isShowRightAnswer;
+    },
   },
   watch: {
     'data.model_essay': {
@@ -133,6 +143,48 @@ export default {
         .filter((item) => item.length > 0)
         .join(' ');
     },
+    /**
+     * 计算答题对错选项字体颜色
+     * @param {string} mark 选项标识
+     */
+    computedAnswerClass(mark) {
+      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
+        return '';
+      }
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 是否已选中的选项
+      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark); // 是否正确的选项
+      if (!selectOption) return '';
+      let selectValue = selectOption.value;
+      let answerValue = answerOption.value;
+      let type = answerOption.type;
+      let classList = [];
+      let isRight =
+        (type === 'only_one' && selectValue === answerValue) ||
+        (type === 'any_one' && answerValue.split('/').includes(selectValue));
+
+      if (this.isJudgingRightWrong) {
+        isRight ? classList.push('right') : classList.push('wrong');
+      }
+
+      if (this.isShowRightAnswer && !isRight) {
+        classList.push('show-right-answer');
+      }
+      return classList;
+    },
+    computedAnswerText(mark) {
+      if (!this.isShowRightAnswer) return '';
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 是否已选中的选项
+      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark); // 是否正确的选项
+      if (!selectOption) return '';
+      let selectValue = selectOption.value;
+      let answerValue = answerOption.value;
+      let type = answerOption.type;
+      let isRight =
+        (type === 'only_one' && selectValue === answerValue) ||
+        (type === 'any_one' && answerValue.split('/').includes(selectValue));
+      if (isRight) return '';
+      return `(${answerValue})`;
+    },
   },
 };
 </script>
@@ -160,9 +212,33 @@ export default {
 
   .fill-wrapper {
     .el-input {
+      display: inline-flex;
+      align-items: center;
       width: 120px;
       margin: 0 2px;
 
+      &.right {
+        :deep input.el-input__inner {
+          color: $right-color;
+        }
+      }
+
+      &.wrong {
+        :deep input.el-input__inner {
+          color: $error-color;
+        }
+      }
+
+      & + .right-answer {
+        position: relative;
+        left: -4px;
+        display: inline-block;
+        height: 32px;
+        line-height: 28px;
+        vertical-align: bottom;
+        border-bottom: 1px solid $font-color;
+      }
+
       :deep input.el-input__inner {
         padding: 0;
         font-size: 16px;

+ 44 - 1
src/views/exercise_questions/preview/ListenJudgePreview.vue

@@ -16,7 +16,7 @@
         :key="mark"
         :class="['option-item', { active: isAnswer(mark) }]"
       >
-        <div class="option-content">
+        <div :class="['option-content', computedIsJudgeRight(mark)]">
           <span class="serial-number">{{ computedQuestionNumber(i, data.option_number_show_mode) }}</span>
           <div v-html="sanitizeHTML(content)"></div>
         </div>
@@ -24,11 +24,13 @@
           <div
             v-for="option_type in data.property.option_type_list"
             :key="option_type"
+            :style="{ cursor: isJudgingRightWrong || isShowRightAnswer ? 'not-allowed' : 'pointer' }"
             :class="[
               'option-type-item',
               {
                 active: isAnswer(mark, option_type),
               },
+              computedIsShowRightAnswer(mark, option_type),
             ]"
             @click="selectAnswer(mark, option_type)"
           >
@@ -63,6 +65,7 @@ export default {
     },
 
     selectAnswer(mark, option_type) {
+      if (this.isJudgingRightWrong || this.isShowRightAnswer) return;
       const index = this.answer.answer_list.findIndex((li) => li.mark === mark);
       if (index === -1) {
         this.answer.answer_list.push({ mark, option_type });
@@ -70,6 +73,33 @@ export default {
         this.answer.answer_list[index].option_type = option_type;
       }
     },
+
+    /**
+     * 计算是否显示正确答案的样式
+     * @param {string} mark 选项标识
+     * @param {string} option_type 选项类型
+     */
+    computedIsShowRightAnswer(mark, option_type) {
+      if (!this.isShowRightAnswer) return '';
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 查找是否已选中的选项
+      if (!selectOption) return '';
+      return this.data.answer.answer_list.find((item) => item.mark === mark).option_type === option_type &&
+        !(selectOption.option_type === option_type)
+        ? 'answer-right'
+        : '';
+    },
+    /**
+     * 计算判断题题干的样式
+     * @param {string} mark 选项标识
+     */
+    computedIsJudgeRight(mark) {
+      if (!this.isJudgingRightWrong) return '';
+      let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 查找是否已选中的选项
+      if (!selectOption) return 'wrong';
+      return this.data.answer.answer_list.find((item) => item.mark === mark).option_type === selectOption.option_type
+        ? 'right'
+        : 'wrong';
+    },
   },
 };
 </script>
@@ -98,6 +128,14 @@ export default {
         background-color: $content-color;
         border-radius: 40px;
 
+        &.right {
+          background-color: $right-bc-color;
+        }
+
+        &.wrong {
+          box-shadow: 0 0 0 1px $error-color;
+        }
+
         .serial-number {
           color: #000;
         }
@@ -123,6 +161,11 @@ export default {
             color: #fff;
             background-color: $light-main-color;
           }
+
+          &.answer-right {
+            color: $right-color;
+            border: 1px solid $right-color;
+          }
         }
       }
     }

+ 56 - 4
src/views/exercise_questions/preview/ListenSelectPreview.vue

@@ -14,12 +14,13 @@
       <li
         v-for="({ content, mark }, i) in data.option_list"
         :key="mark"
-        :class="['option-item', { active: isAnswer(mark) }]"
+        :style="{ cursor: isJudgingRightWrong || isShowRightAnswer ? 'not-allowed' : 'pointer' }"
+        :class="['option-item', { active: isAnswer(mark) }, ...computedAnswerClass(mark)]"
         @click="selectAnswer(mark)"
       >
         <span class="selectionbox"></span>
         <span>{{ computeOptionMethods[data.option_number_show_mode](i) }} </span>
-        <span v-html="sanitizeHTML(content)"></span>
+        <span class="content" v-html="sanitizeHTML(content)"></span>
       </li>
     </ul>
   </div>
@@ -40,9 +41,10 @@ export default {
   },
   methods: {
     isAnswer(mark) {
-      return this.answer.answer_list.indexOf(mark) !== -1;
+      return this.answer.answer_list.includes(mark);
     },
     selectAnswer(mark) {
+      if (this.isJudgingRightWrong || this.isShowRightAnswer) return;
       const index = this.answer.answer_list.indexOf(mark);
       if (this.data.property.select_type === selectTypeList[0].value) {
         this.answer.answer_list = [mark];
@@ -55,6 +57,20 @@ export default {
         }
       }
     },
+    computedAnswerClass(mark) {
+      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
+        return [];
+      }
+      let isHas = this.answer.answer_list.includes(mark); // 是否已选中的选项
+      if (!isHas && this.isShowRightAnswer) {
+        return this.data.answer.answer_list.includes(mark) ? ['answer-right'] : [];
+      }
+      // 判断是否是正确答案
+      if (this.isJudgingRightWrong) {
+        return this.data.answer.answer_list.includes(mark) ? ['right'] : ['wrong'];
+      }
+      return [];
+    },
   },
 };
 </script>
@@ -88,14 +104,50 @@ export default {
         border-radius: 50%;
       }
 
+      .content {
+        flex: 1;
+      }
+
+      &.answer-right {
+        background-color: #e8f7f2;
+
+        &::after {
+          font-size: 14px;
+          color: $right-color;
+          content: '正确答案';
+        }
+      }
+
       &.active {
         color: #34343a;
-        background-color: #e7eeff;
+        background-color: $main-active-color;
 
         .selectionbox {
           border-color: $light-main-color;
           border-width: 4px;
         }
+
+        &.right {
+          background-color: $content-color;
+          border: 1px solid $right-color;
+
+          &::after {
+            font-size: 14px;
+            color: $right-color;
+            content: '已选';
+          }
+        }
+
+        &.wrong {
+          background-color: $content-color;
+          box-shadow: 0 0 0 1px $error-color;
+
+          &::after {
+            font-size: 14px;
+            color: #a09fa6;
+            content: '已选';
+          }
+        }
       }
     }
   }

+ 123 - 9
src/views/exercise_questions/preview/MatchingPreview.vue

@@ -9,10 +9,11 @@
 
     <ul ref="list" class="option-list">
       <li v-for="(item, i) in optionList" :key="i" class="list-item">
-        <div v-for="({ content, mark }, j) in item" :key="mark" class="item-wrapper">
+        <div v-for="({ content, mark }, j) in item" :key="mark" :class="['item-wrapper', computedAnswerClass(mark)]">
           <span
             v-if="j > 0 && j < item.length"
             :class="['connection', `pre-line-${i}-${j}`]"
+            :style="{ cursor: disabled ? 'default' : 'pointer' }"
             @mousedown="mousedown($event, i, j, 'pre', mark)"
             @mouseup="mouseup($event, i, j, 'pre', mark)"
             @click="handleClickConnection($event, i, j, 'pre', mark)"
@@ -21,6 +22,7 @@
           <span
             v-if="j < item.length - 1"
             :class="['connection', `next-line-${i}-${j}`]"
+            :style="{ cursor: disabled ? 'default' : 'pointer' }"
             @mousedown="mousedown($event, i, j, 'next', mark)"
             @mouseup="mouseup($event, i, j, 'next', mark)"
             @click="handleClickConnection($event, i, j, 'next', mark)"
@@ -28,6 +30,20 @@
         </div>
       </li>
     </ul>
+
+    <div v-if="isShowRightAnswer" class="right-answer">
+      <div class="title">正确答案</div>
+
+      <ul ref="answer-list" class="option-list">
+        <li v-for="(item, i) in optionList" :key="i" class="list-item">
+          <div v-for="({ content, mark }, j) in item" :key="mark" :class="'item-wrapper'">
+            <span v-if="j > 0 && j < item.length" :class="['connection', `answer-pre-line-${i}-${j}`]"></span>
+            <span class="content" v-html="sanitizeHTML(content)"></span>
+            <span v-if="j < item.length - 1" :class="['connection', `answer-next-line-${i}-${j}`]"></span>
+          </div>
+        </li>
+      </ul>
+    </div>
   </div>
 </template>
 
@@ -63,6 +79,9 @@ export default {
       }
       return arr;
     },
+    disabled() {
+      return this.isJudgingRightWrong || this.isShowRightAnswer;
+    },
   },
   watch: {
     optionList: {
@@ -104,7 +123,6 @@ export default {
           this.answer.answer_list = arr;
           return;
         }
-
         // 从后向前遍历,如果有 preMark,就往前找,直到没有 preMark,并过滤掉无数据的列
         let preArr = [];
         list.forEach((item) => {
@@ -123,7 +141,7 @@ export default {
             }
             _preMark = fMark;
           }
-          if (_arr.every((li) => li.length <= 0)) return;
+          if (_arr.every((li) => li.length <= 0) || _arr.every((li) => li.length > 0)) return;
           preArr.push(_arr);
         });
         // 将 preArr 中的数据填充到 arr 无数据的位置中
@@ -136,6 +154,19 @@ export default {
       },
       deep: true,
     },
+    isJudgingRightWrong(cur) {
+      if (cur) {
+        this.clearLine();
+        this.circulateAnswerList();
+      }
+    },
+    isShowRightAnswer(cur) {
+      if (cur) {
+        this.$nextTick(() => {
+          this.circulateAnswerList(true);
+        });
+      }
+    },
   },
   mounted() {
     document.addEventListener('click', this.handleEventConnection);
@@ -151,6 +182,7 @@ export default {
     /* 用 mouse 事件模拟拖拽 开始*/
     documentMousemouse(e) {
       if (!this.drag) return;
+      if (this.disabled) return;
       // 使用 svg 绘制跟随鼠标移动的连接线
       let svg = document.querySelector('.move-connection');
       if (!svg) {
@@ -226,6 +258,7 @@ export default {
      * @param {String} mark 选项标识
      */
     handleClickConnection(e, i, j, position, mark) {
+      if (this.disabled) return;
       let { i: curI, j: curJ, position: curPosition, mark: curMark } = this.curConnectionPoint;
       // 如果当前连线点不存在,则设置当前连线点
       if (curI === -1 && curJ === -1) {
@@ -248,6 +281,36 @@ export default {
       this.createLine(i, j, position, mark);
     },
 
+    // 循环答案列表
+    circulateAnswerList(isShowRightAnswer = false) {
+      let answer_list = isShowRightAnswer ? this.data.answer.answer_list : this.answer.answer_list;
+      answer_list.forEach((item) => {
+        item.forEach((mark, j) => {
+          if (mark.length <= 0 || j >= item.length - 1) return;
+
+          let cur = { i: -1, j: -1 }; // 当前连线点
+          this.answerList.findIndex((item, i) => {
+            return item.some((li, j) => {
+              if (li.mark === mark) {
+                cur = { i, j };
+                return true;
+              }
+            });
+          });
+          let next = { i: -1, j: -1 }; // 下一个连线点
+          this.answerList.findIndex((_item, i) => {
+            let itemJ = _item.findIndex((li) => li.mark === item[j + 1]);
+            if (itemJ !== -1) {
+              next = { i, j: itemJ };
+              return true;
+            }
+          });
+          this.curConnectionPoint = { i: cur.i, j: cur.j, position: 'next', mark };
+          this.createLine(next.i, next.j, 'pre', item[j + 1], false, isShowRightAnswer);
+        });
+      });
+    },
+
     /**
      * 创建连接线
      * @param {Number} i 选项列表索引
@@ -255,10 +318,13 @@ export default {
      * @param {'pre'|'next'} position
      * @param {String} mark 选项标识
      * @param {Boolean} isDrag 是否是拖拽
+     * @param {Boolean} isShowRightAnswer 是否是显示正确答案
      */
-    createLine(i, j, position, mark, isDrag = false) {
-      let { offsetLeft, offsetTop } = document.getElementsByClassName(`${position}-line-${i}-${j}`)[0];
-      const { curOffsetLeft, curOffsetTop, curMark } = this.computedCurConnectionPoint(isDrag);
+    createLine(i, j, position, mark, isDrag = false, isShowRightAnswer = false) {
+      let { offsetLeft, offsetTop } = document.getElementsByClassName(
+        `${isShowRightAnswer ? 'answer-' : ''}${position}-line-${i}-${j}`,
+      )[0];
+      const { curOffsetLeft, curOffsetTop, curMark } = this.computedCurConnectionPoint(isDrag, isShowRightAnswer);
       let top = Math.min(offsetTop, curOffsetTop) + 5;
       let left = Math.min(offsetLeft, curOffsetLeft) + 5;
       let width = Math.abs(offsetLeft - curOffsetLeft);
@@ -277,7 +343,7 @@ export default {
       path.setAttribute('d', `M ${size ? 0 : width} 0 L ${size ? width : 0} ${height}`); // 设置路径数据
       this.setPathAttr(path);
       svg.appendChild(path);
-      this.$refs.list.appendChild(svg); // 将SVG元素插入到文档中
+      this.$refs[isShowRightAnswer ? 'answer-list' : 'list'].appendChild(svg); // 将SVG元素插入到文档中
 
       // 清除当前连线点
       this.resetCurConnectionPoint();
@@ -292,10 +358,11 @@ export default {
     /**
      * 计算当前连线点的位置
      * @param {Boolean} isDrag 是否是拖拽
+     * @param {Boolean} isShowRightAnswer 是否是显示正确答案
      */
-    computedCurConnectionPoint(isDrag = false) {
+    computedCurConnectionPoint(isDrag = false, isShowRightAnswer = false) {
       const { i, j, position, mark } = isDrag ? this.mousePointer : this.curConnectionPoint;
-      let dom = document.getElementsByClassName(`${position}-line-${i}-${j}`)[0];
+      let dom = document.getElementsByClassName(`${isShowRightAnswer ? 'answer-' : ''}${position}-line-${i}-${j}`)[0];
       return { curOffsetLeft: dom.offsetLeft, curOffsetTop: dom.offsetTop, curMark: mark };
     },
 
@@ -383,6 +450,33 @@ export default {
       });
       return fMark;
     },
+
+    computedAnswerClass(mark) {
+      if (!this.isJudgingRightWrong) return '';
+      let answer = this.data.answer.answer_list.find((item) => {
+        return item.some((li) => li === mark);
+      });
+      return this.is2DArrayContains1DArray(this.answer.answer_list, answer) ? 'right' : 'wrong';
+    },
+    is2DArrayContains1DArray(arr2D, arr1D) {
+      for (let i = 0; i < arr2D.length; i++) {
+        const currentArray = arr2D[i];
+        if (currentArray.length !== arr1D.length) {
+          continue;
+        }
+        let found = true;
+        for (let j = 0; j < currentArray.length; j++) {
+          if (currentArray[j] !== arr1D[j]) {
+            found = false;
+            break;
+          }
+        }
+        if (found) {
+          return true;
+        }
+      }
+      return false;
+    },
   },
 };
 </script>
@@ -413,6 +507,14 @@ export default {
         background-color: $fill-color;
         border-radius: 40px;
 
+        &.right {
+          background-color: $right-bc-color;
+        }
+
+        &.wrong {
+          box-shadow: 0 0 0 1px $error-color;
+        }
+
         .content {
           flex: 1;
         }
@@ -434,5 +536,17 @@ export default {
       }
     }
   }
+
+  .right-answer {
+    .title {
+      margin-bottom: 24px;
+    }
+
+    .option-list {
+      .connection {
+        cursor: default !important;
+      }
+    }
+  }
 }
 </style>

+ 23 - 8
src/views/exercise_questions/preview/SelectPreview.vue

@@ -14,6 +14,7 @@
       <li
         v-for="({ content, mark }, i) in data.option_list"
         :key="mark"
+        :style="{ cursor: isJudgingRightWrong || isShowRightAnswer ? 'not-allowed' : 'pointer' }"
         :class="['option-item', { active: isAnswer(mark) }, ...computedAnswerClass(mark)]"
         @click="selectAnswer(mark)"
       >
@@ -43,6 +44,7 @@ export default {
       return this.answer.answer_list.includes(mark);
     },
     selectAnswer(mark) {
+      if (this.isJudgingRightWrong || this.isShowRightAnswer) return;
       const index = this.answer.answer_list.indexOf(mark);
       if (this.data.property.select_type === selectTypeList[0].value) {
         this.answer.answer_list = [mark];
@@ -59,12 +61,15 @@ export default {
       if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
         return [];
       }
-      let isHas = this.answer.answer_list.includes(mark);
-      if (!isHas) {
-        return [];
+      let isHas = this.answer.answer_list.includes(mark); // 是否已选中的选项
+      if (!isHas && this.isShowRightAnswer) {
+        return this.data.answer.answer_list.includes(mark) ? ['answer-right'] : [];
+      }
+      // 判断是否是正确答案
+      if (this.isJudgingRightWrong) {
+        return this.data.answer.answer_list.includes(mark) ? ['right'] : ['wrong'];
       }
-      let isRight = this.data.answer.answer_list.includes(mark) && this.isJudgingRightWrong;
-      return isRight ? ['right'] : ['wrong'];
+      return [];
     },
   },
 };
@@ -103,9 +108,19 @@ export default {
         flex: 1;
       }
 
+      &.answer-right {
+        background-color: #e8f7f2;
+
+        &::after {
+          font-size: 14px;
+          color: $right-color;
+          content: '正确答案';
+        }
+      }
+
       &.active {
         color: #34343a;
-        background-color: #e7eeff;
+        background-color: $main-active-color;
 
         .selectionbox {
           border-color: $light-main-color;
@@ -125,11 +140,11 @@ export default {
 
         &.wrong {
           background-color: $content-color;
-          border: 1px solid $error-color;
+          box-shadow: 0 0 0 1px $error-color;
 
           &::after {
             font-size: 14px;
-            color: $error-color;
+            color: #a09fa6;
             content: '已选';
           }
         }

+ 6 - 1
src/views/exercise_questions/preview/components/common/SoundRecordPreview.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :class="['sound-record-wrapper', 'sound-record-wrapper-' + type]">
+  <div :class="['sound-record-wrapper', 'sound-record-wrapper-' + type]" :style="{ justifyContent: position }">
     <div class="sound-item sound-item-luyin">
       <img
         v-if="microphoneStatus"
@@ -57,6 +57,11 @@ export default {
       type: Boolean,
       default: false,
     },
+    // 播放按钮位置
+    position: {
+      type: String,
+      default: 'left',
+    },
   },
   data() {
     return {