Procházet zdrojové kódy

修改错题本知识点字段

wangguoxi před 3 měsíci
rodič
revize
e2b0abcae1

+ 16 - 48
package-lock.json

@@ -1998,7 +1998,6 @@
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
       "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
-      "dev": true,
       "hasInstallScript": true,
       "optional": true,
       "dependencies": {
@@ -2037,7 +2036,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "android"
@@ -2057,7 +2055,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "darwin"
@@ -2077,7 +2074,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "darwin"
@@ -2097,7 +2093,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "freebsd"
@@ -2117,7 +2112,6 @@
       "cpu": [
         "arm"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -2137,7 +2131,6 @@
       "cpu": [
         "arm"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -2157,7 +2150,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -2177,7 +2169,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -2197,7 +2188,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -2217,7 +2207,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "linux"
@@ -2237,7 +2226,6 @@
       "cpu": [
         "arm64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "win32"
@@ -2257,7 +2245,6 @@
       "cpu": [
         "ia32"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "win32"
@@ -2277,7 +2264,6 @@
       "cpu": [
         "x64"
       ],
-      "dev": true,
       "optional": true,
       "os": [
         "win32"
@@ -4633,7 +4619,7 @@
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
       "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
+      "devOptional": true,
       "dependencies": {
         "fill-range": "^7.1.1"
       },
@@ -6292,7 +6278,6 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
       "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
-      "dev": true,
       "optional": true,
       "bin": {
         "detect-libc": "bin/detect-libc.js"
@@ -7661,7 +7646,7 @@
       "version": "7.1.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
       "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
+      "devOptional": true,
       "dependencies": {
         "to-regex-range": "^5.0.1"
       },
@@ -9523,7 +9508,7 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
+      "devOptional": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -9586,7 +9571,7 @@
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
       "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
+      "devOptional": true,
       "dependencies": {
         "is-extglob": "^2.1.1"
       },
@@ -9635,7 +9620,7 @@
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
+      "devOptional": true,
       "engines": {
         "node": ">=0.12.0"
       }
@@ -10627,7 +10612,7 @@
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
       "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
-      "dev": true,
+      "devOptional": true,
       "dependencies": {
         "braces": "^3.0.3",
         "picomatch": "^2.3.1"
@@ -11069,7 +11054,6 @@
       "version": "7.1.1",
       "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
       "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
-      "dev": true,
       "optional": true
     },
     "node_modules/node-fetch": {
@@ -11696,7 +11680,7 @@
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
+      "devOptional": true,
       "engines": {
         "node": ">=8.6"
       },
@@ -14906,7 +14890,7 @@
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
       "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
+      "devOptional": true,
       "dependencies": {
         "is-number": "^7.0.0"
       },
@@ -17854,7 +17838,6 @@
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
       "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
-      "dev": true,
       "optional": true,
       "requires": {
         "@parcel/watcher-android-arm64": "2.5.1",
@@ -17880,91 +17863,78 @@
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
       "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-darwin-arm64": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
       "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-darwin-x64": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
       "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-freebsd-x64": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
       "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-linux-arm-glibc": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
       "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-linux-arm-musl": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
       "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-linux-arm64-glibc": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
       "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-linux-arm64-musl": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
       "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-linux-x64-glibc": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
       "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-linux-x64-musl": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
       "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-win32-arm64": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
       "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-win32-ia32": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
       "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
-      "dev": true,
       "optional": true
     },
     "@parcel/watcher-win32-x64": {
       "version": "2.5.1",
       "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
       "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
-      "dev": true,
       "optional": true
     },
     "@plotly/d3": {
@@ -19865,7 +19835,7 @@
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
       "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
+      "devOptional": true,
       "requires": {
         "fill-range": "^7.1.1"
       }
@@ -21143,7 +21113,6 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
       "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
-      "dev": true,
       "optional": true
     },
     "detect-node": {
@@ -22214,7 +22183,7 @@
       "version": "7.1.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
       "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
+      "devOptional": true,
       "requires": {
         "to-regex-range": "^5.0.1"
       }
@@ -23757,7 +23726,7 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true
+      "devOptional": true
     },
     "is-file-esm": {
       "version": "1.0.0",
@@ -23799,7 +23768,7 @@
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
       "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
+      "devOptional": true,
       "requires": {
         "is-extglob": "^2.1.1"
       }
@@ -23833,7 +23802,7 @@
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true
+      "devOptional": true
     },
     "is-obj": {
       "version": "1.0.1",
@@ -24646,7 +24615,7 @@
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
       "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
-      "dev": true,
+      "devOptional": true,
       "requires": {
         "braces": "^3.0.3",
         "picomatch": "^2.3.1"
@@ -25011,7 +24980,6 @@
       "version": "7.1.1",
       "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
       "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
-      "dev": true,
       "optional": true
     },
     "node-fetch": {
@@ -25494,7 +25462,7 @@
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true
+      "devOptional": true
     },
     "pkg-dir": {
       "version": "4.2.0",
@@ -27936,7 +27904,7 @@
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
       "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
+      "devOptional": true,
       "requires": {
         "is-number": "^7.0.0"
       }

+ 43 - 18
public/index.html

@@ -1,20 +1,45 @@
 <!DOCTYPE html>
 <html>
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-    <meta name="referrer" content="no-referrer" />
-    <script defer src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= htmlWebpackPlugin.options.title %></title>
-   
-    <link rel="stylesheet" href="//at.alicdn.com/t/c/font_4939100_wnefpnxejys.css">
-  </head>
-  <body>
-    <noscript>
-      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-    </noscript>
-    <div id="app"></div>
-  </body>
-</html>                         
+
+<head>
+  <meta charset="utf-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+  <meta name="referrer" content="no-referrer" />
+  <script defer src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
+  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+  <title>
+    <%= htmlWebpackPlugin.options.title %>
+  </title>
+
+  <script>
+    window.MathJax = {
+      loader: {
+        // 指定 mathjax 资源根路径为当前 public 目录(如需放到子目录请修改)
+        paths: { mathjax: './' },
+        // 只加载必要的输入/输出模块,避免自动加载辅助无障碍模块(会触发 speech-worker)
+        load: ['input/tex', 'output/chtml']
+      },
+      chtml: {
+        // 指向本地字体目录(建议把 MathJax 的 woff-v2 字体复制到 public/output/chtml/fonts/woff-v2)
+        fontURL: './output/chtml/fonts/woff-v2'
+      },
+      tex: {
+        inlineMath: [['\\(', '\\)'], ['$', '$']]
+      }
+    };
+  </script>
+  <script src="./math.js"></script>
+
+  <link rel="stylesheet" href="//at.alicdn.com/t/c/font_4939100_wnefpnxejys.css">
+</head>
+
+<body>
+  <noscript>
+    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
+        Please enable it to continue.</strong>
+  </noscript>
+  <div id="app"></div>
+</body>
+
+</html>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
public/math.js


+ 5 - 5
src/App.vue

@@ -6,23 +6,23 @@
 
 <script>
 import user from "@/http/api/user";
-import { setToken,getToken } from "@/utils/auth";
+import { setToken, getToken } from "@/utils/auth";
 import { encrypt } from "@/utils/jsencrypt";
 export default {
     name: "App",
     mounted() {
         // INFO: 本地调试,自动登录
         if (process.env.NODE_ENV === 'development') {
-            // this.SubmitLogin();
+            this.SubmitLogin();
         }
     },
     methods: {
         SubmitLogin() {
-            const username = '99689820200090';
-            const password = '996898@20200090';
+            const username = '500072347220708';
+            const password = '123456';
             // const type = '1';
             const schoolType = sessionStorage.getItem('schoolType');
-            if(getToken() && schoolType){
+            if (getToken() && schoolType) {
                 return
             }
             sessionStorage.setItem('schoolType', schoolType || 2);

+ 0 - 0
src/views/analysisReport/wrongQuestion/AllQuestion.vue


+ 0 - 0
src/views/analysisReport/wrongQuestion/HasQuestion.vue


+ 1 - 1
src/views/analysisReport/wrongQuestion/KnowledgePoint.vue

@@ -6,7 +6,7 @@
 export default {
     props: {
         text: String
-    }
+    },
 }
 </script>
 

+ 0 - 0
src/views/analysisReport/wrongQuestion/NoQuestion.vue


+ 11 - 0
src/views/analysisReport/wrongQuestion/Notbook.vue

@@ -0,0 +1,11 @@
+<template>
+
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style></style>

+ 153 - 0
src/views/analysisReport/wrongQuestion/Preview.vue

@@ -0,0 +1,153 @@
+<template>
+    <div>
+        <template v-if="isTextMode">
+            <div style="color: #000 !important;" ref="previewRoot" v-html="displayHtml"></div>
+        </template>
+
+        <template v-if="isImageMode">
+            <el-image class="question_img" :src="imgBase64" :preview-src-list="[imgBase64]">
+            </el-image>
+        </template>
+    </div>
+</template>
+
+<script>
+const FORMULA_SELECTOR = 'span[data-w-e-type="formula"][data-value]';
+
+function isWangEditorFormula(html = "") {
+    return html && html.indexOf('data-w-e-type="formula"') > -1;
+}
+
+export default {
+    name: "Preview",
+
+    props: {
+        content: {
+            type: String,
+            default: "",
+        },
+        type: [String, Number],
+        imgBase64: String
+    },
+
+    data() {
+        return {
+            displayHtml: "",
+        };
+    },
+
+    computed: {
+        isTextMode() {
+            return String(this.type) === "1";
+        },
+        isImageMode() {
+            return String(this.type) === "2";
+        },
+    },
+
+    watch: {
+        content: {
+            immediate: true,
+            handler() {
+                this.updateDisplay();
+            },
+        },
+
+        type() {
+            this.updateDisplay();
+        },
+    },
+
+    mounted() {
+        // mounted 保持空,渲染由 updateDisplay 控制
+    },
+
+    methods: {
+        async updateDisplay() {
+            if (!this.isTextMode) {
+                this.displayHtml = "";
+                return;
+            }
+
+            const value = this.content || "";
+            if (!value) {
+                this.displayHtml = "";
+                return;
+            }
+
+            // 如果没有编辑器公式,直接使用原始 HTML
+            if (!isWangEditorFormula(value)) {
+                this.displayHtml = value;
+                return;
+            }
+
+            // 将 HTML 放入临时容器,逐个替换公式 span 为 MathJax 渲染节点(优先使用 tex2svgPromise)
+            const container = document.createElement('div');
+            container.innerHTML = value;
+            const spans = Array.from(container.querySelectorAll(FORMULA_SELECTOR));
+
+            if (spans.length === 0) {
+                this.displayHtml = value;
+                return;
+            }
+
+            // 如果 MathJax 支持 tex2svgPromise,使用它逐个替换为渲染后的节点(避免 typeset 的双重渲染)
+            if (window.MathJax && window.MathJax.tex2svgPromise) {
+                for (const span of spans) {
+                    const latex = span.getAttribute('data-value') || '';
+                    try {
+                        const node = await window.MathJax.tex2svgPromise(latex, { display: false });
+                        // tex2svgPromise 返回一个包含 mjx-container 的节点,使用其 outerHTML 替换原始 span
+                        span.replaceWith(node);
+                    } catch (e) {
+                        console.warn('tex2svgPromise 渲染失败,保留原始公式标记', e);
+                    }
+                }
+
+                this.displayHtml = container.innerHTML;
+                this.$nextTick(() => {
+                    // 确保 MathJax 渲染节点的样式生效
+                    this.$emit('rendered');
+                });
+                return;
+            }
+
+            // 回退:没有 tex2svgPromise,则保留原始替换为 LaTeX 标记并调用 typeset
+            this.displayHtml = value.replace(/<span[^>]*data-w-e-type="formula"[^>]*data-value="([^"]+)"[^>]*><\/span>/g, (_, latex) => `\\(${latex}\\)`);
+
+            this.$nextTick(async () => {
+                try {
+                    if (window.MathJax && window.MathJax.typesetPromise) {
+                        await window.MathJax.typesetPromise([this.$refs.previewRoot]);
+                    }
+                } catch (error) {
+                    console.error('MathJax 加载失败', error);
+                } finally {
+                    this.$emit('rendered');
+                }
+            });
+        },
+    },
+};
+</script>
+
+<style scoped>
+/* MathJax CHTML 覆盖,缓解全局样式对公式的影响 */
+.mjx-chtml {
+    display: inline-block;
+    line-height: 1;
+    vertical-align: baseline;
+}
+
+.mjx-container,
+.mjx-char,
+.mjx-mfrac {
+    line-height: 1 !important;
+    display: inline-block !important;
+    vertical-align: baseline !important;
+}
+
+.mjx-msqrt>.mjx-surd {
+    vertical-align: -0.12em !important;
+}
+</style>

+ 31 - 42
src/views/analysisReport/wrongQuestion/index.vue

@@ -32,11 +32,9 @@
                                 </div>
                             </div>
 
-                            <div class="question_content line_height_20" v-if="question.sourceType === 1"
-                                v-html="question.questionData.questionStem"></div>
-
-                            <div class="question_content" v-if="question.sourceType === 2">
-                                <img :src="question.questionImg" alt="" width="100%">
+                            <div class="question_content line_height_20">
+                                <Preview :type="question.sourceType" :content="question.questionData.questionStem"
+                                    :imgBase64="question.questionImg" />
                             </div>
 
                             <div class="card_footer">
@@ -91,14 +89,16 @@
                                 </template>
 
                                 <template v-if="errorType === 1 || question.errorStatus === 1">
-                                    <span class="black ml_30" size="small" @click="_markStudentErrorQuestion(question, 0)">
+                                    <span class="black ml_30" size="small"
+                                        @click="_markStudentErrorQuestion(question, 0)">
                                         <i class="iconfont icon_biaojiweizhangwo"></i>
                                         标记为未掌握
                                     </span>
                                 </template>
 
                                 <template v-if="errorType === 2 || question.errorStatus === 2">
-                                    <span class="black ml_30" size="small" @click="_markStudentErrorQuestion(question, 0)">
+                                    <span class="black ml_30" size="small"
+                                        @click="_markStudentErrorQuestion(question, 0)">
                                         <i class="iconfont icon_yichufuxiben"></i>
                                         移除复习本
                                     </span>
@@ -110,8 +110,9 @@
                                     <div class="flex_left" style="line-height: 28px;">知识点:</div>
                                     <div class="flex_right">
                                         <template v-if="question.knowledgePoint && question.knowledgePoint.length > 0">
-                                            <KnowledgePoint v-for="(know, index) in question.knowledgePoint"
-                                                :key="index" :text="know" />
+                                            <template v-for="(know, index) in question.knowledgePoint">
+                                                <KnowledgePoint :text="know" />
+                                            </template>
                                         </template>
                                     </div>
                                 </div>
@@ -119,33 +120,23 @@
                                 <div class="flex">
                                     <div class="flex_left">答&nbsp;&nbsp;&nbsp;&nbsp;案:</div>
                                     <div class="flex_right">
-                                        <div v-if="question.sourceType === 1" v-html="question.questionData.answer">
-                                        </div>
-                                        <div v-if="question.sourceType === 2">
-                                            <img :src="question.answerImg" alt="" width="100%" />
-                                        </div>
+                                        <Preview :type="question.sourceType" :content="question.questionData.answer"
+                                            :imgBase64="question.answerImg" />
                                     </div>
                                 </div>
 
                                 <div class="flex">
                                     <div class="flex_left">解&nbsp;&nbsp;&nbsp;&nbsp;析:</div>
                                     <div class="flex_right">
-                                        <div style="line-height: 1.5;" v-show="question.sourceType === 1"
-                                            v-html="question.questionData.analysis">
-                                        </div>
-                                        <div v-if="question.sourceType === 2">
-                                            <img :src="question.parseImg" alt="" width="100%" />
-                                        </div>
+                                        <Preview :type="question.sourceType" :content="question.questionData.analysis"
+                                            :imgBase64="question.parseImg" />
                                     </div>
                                 </div>
                             </div>
 
                             <div class="content" v-if="question.answerShow && !question.parseShow">
-                                <div class="content_inner" v-if="question.sourceType === 1"
-                                    v-html="question.studentAnswer"></div>
-                                <div class="content_inner" v-if="question.sourceType === 2">
-                                    <img :src="question.studentAnswerImg" alt="" width="100%" />
-                                </div>
+                                <Preview :type="question.sourceType" :content="question.studentAnswer"
+                                    :imgBase64="question.studentAnswerImg" />
                             </div>
                         </div>
                     </div>
@@ -171,19 +162,21 @@
                                 </div>
                             </div>
 
-                            <div class="question_content line_height_20"
-                                v-html="question.variationQuestion.questionStem">这是题目内容</div>
+                            <div class="question_content line_height_20">
+                                <Preview :type="1" :content="question.variationQuestion.questionStem" />
+                            </div>
 
                             <!-- <div class="yuwen">
                                 <span class="btn_span active">1</span>
                                 <span class="btn_span">2</span>
-
                                 <div class="question_list"></div>
                             </div> -->
 
                             <div class="card_footer">
                                 <div class="gray">知识点:</div>
-                                <KnowledgePoint :text="question.variationQuestion.knowledgePoint" />
+                                <template v-for="(know, index) in question.variationQuestion.knowledgePoint">
+                                    <KnowledgePoint :text="know" />
+                                </template>
                             </div>
                         </div>
                     </div>
@@ -209,15 +202,19 @@ import {
     downloadStudentErrorQuestion,
 } from '../../../http/api/errorQuestion';
 import Download from './Download.vue';
-import loadImg from './loadImg.js'
+import { mergeImage } from './loadImg.js'
 import { Loading } from 'element-ui';
 import NoData from './NoData/NoData.vue';
 import KnowledgePoint from './KnowledgePoint.vue';
+import Preview from './Preview.vue';
+
 export default {
     components: {
         Download,
         NoData,
         KnowledgePoint,
+        Preview,
+
     },
 
     data() {
@@ -343,18 +340,10 @@ export default {
                     questionList[i].answerShow = false;
                     questionList[i].parseShow = false;
                     if (sourceType === 2) {
-                        const questionImg = await loadImg(this.uploadPaperUrls, titleCoordinates);
-                        questionList[i].questionImg = questionImg;
-
-                        const answerImg = await loadImg(this.answerUrls, answerCoordinates);
-                        questionList[i].answerImg = answerImg;
-
-                        const parseImg = await loadImg(this.answerUrls, parseCoordinates);
-                        questionList[i].parseImg = parseImg;
-
-                        // TODO: 学生答案图片加载,由于
-                        const studentAnswerImg = await loadImg(this.answerUrls, paintingPosition);
-                        questionList[i].studentAnswerImg = studentAnswerImg;
+                        questionList[i].questionImg = await mergeImage(this.uploadPaperUrls, titleCoordinates);;
+                        questionList[i].answerImg = await mergeImage(this.answerUrls, answerCoordinates);
+                        questionList[i].parseImg = await mergeImage(this.answerUrls, parseCoordinates);
+                        questionList[i].studentAnswerImg = await mergeImage(this.answerUrls, paintingPosition);
                     }
                 }
 

+ 87 - 86
src/views/analysisReport/wrongQuestion/loadImg.js

@@ -1,106 +1,107 @@
-export default async function loadImg(urlList, CoordinateList) {
-    /**
-     * urlList: 图片地址数组
-     * 数据格式为 [url1, url2, url3]
-     * 
-     * CoordinateList: 坐标数组
-     * 数据格式为 [
-     *      { page: 1, x: 10, y: 20, w: 100, h: 150 },
-     *      { page: 2, x: 30, y: 40, w: 120, h: 160 },
-     * ]
-     * 也可能为
-     * [
-     *      { page: 2, x: 30, y: 40, w: 120, h: 160 },
-     *      { page: 4, x: 50, y: 60, w: 140, h: 180 },
-     * ]
-     * 
-     * 注意:page 为 1 时,对应 urlList 中的第一个图片地址
-     * 
-     * 功能描述:将多张图片根据坐标裁剪并合并为一张图片。
-     * 注意:
-     * (1)有可能裁剪区域的宽度不一致,合并后图片宽度取最大宽度,其他图片按比例缩放。
-     * (2)裁剪区域按顺序垂直排列,之间无间距。
-     * (3)page 可能不从 1 开始,且不连续。我们只需根据 page 值找到对应图片即可。
-     * 返回值:返回一个 Promise,resolve 合并后的图片的 Base64 数据 URL。
-     * 
-    */
-
+export async function mergeImage(urlList, CoordinateList) {
     if (!Array.isArray(urlList) || !Array.isArray(CoordinateList)) {
-        return null;
+        return [];
     }
 
     if (CoordinateList.length === 0 || urlList.length === 0) {
-        return null;
-    }
-
-    let maxWidth = 0;
-    for (let coord of CoordinateList) {
-        if (coord.w > maxWidth) {
-            maxWidth = coord.w;
-        }
+        return [];
     }
 
-    const imgList = []
+    const imageUrlList = []
 
-    for (let urlIndex = 0; urlIndex < urlList.length; urlIndex++) {
+    for (let i = 0; i < CoordinateList.length; i++) {
+        const { page, x, y, w, h } = CoordinateList[i];
+        const urlIndex = page - 1;
         const url = urlList[urlIndex];
-        for (let i = 0; i < CoordinateList.length; i++) {
-            const coord = CoordinateList[i];
-            const page = coord.page;
-            // 根据 maxWidth 计算缩放比例
-            const scale = maxWidth / coord.w;
-            
-            // 计算高度
-            coord.w = maxWidth;
-            coord.h = coord.h * scale;
-
-            if (page - 1 === urlIndex) {
-                const img = await loadImage(url);
-                const tempCanvas = document.createElement('canvas');
-                const tempCtx = tempCanvas.getContext('2d');
-                tempCanvas.width = coord.w;
-                tempCanvas.height = coord.h;
-
-                // 此处按 计算后的宽高进行裁剪
-                tempCtx.drawImage(img, coord.x, coord.y, coord.w, coord.h, 0, 0, coord.w, coord.h);
-                imgList.push({
-                    img: tempCanvas,
-                    width: coord.w,
-                    height: coord.h
-                });
-            }
-        }
-    }
-
-    // 创建最终合并的画布
-    const finalCanvas = document.createElement('canvas');
-    const finalCtx = finalCanvas.getContext('2d');
-    finalCanvas.width = maxWidth;
-    let totalHeight = 0;
-    for (let i = 0; i < imgList.length; i++) {
-        totalHeight += imgList[i].height;
+        const _url = GetImageUrl(url, x, y, w, h);
+        imageUrlList.push(_url);
     }
-    finalCanvas.height = totalHeight;
 
-    let currentY = 0;
-    for (let i = 0; i < imgList.length; i++) {
-        const img = imgList[i].img;
-        finalCtx.drawImage(img, 
-            0, 0, maxWidth, imgList[i].height, 
-            0, currentY, maxWidth, imgList[i].height
-        );
-        currentY += imgList[i].height;
+    if (imageUrlList.length === 1) {
+        return imageUrlList[0];
+    } else {
+        // 多张图片合并
+        const finalImage = await MergerImage(imageUrlList);
+        return finalImage;
     }
-
-    return finalCanvas.toDataURL('image/png');
 }
 
 function loadImage(url) {
     return new Promise((resolve, reject) => {
         const img = new Image();
         img.crossOrigin = "Anonymous";
-        img.src = url;
-        img.onload = () => resolve(img);
+        // 在 onload 中读取宽高,确保为真实尺寸
+        img.onload = () => {
+            const width = img.naturalWidth || img.width;
+            const height = img.naturalHeight || img.height;
+            resolve({
+                img,
+                width,
+                height
+            });
+        };
         img.onerror = (err) => reject(err);
+        img.src = url;
     })
+}
+
+export function GetImageUrl(base, x, y, w, h) {
+    return `${base}?x-oss-process=image/crop,x_${x},y_${y},w_${w},h_${h}`
+}
+
+export function MergerImage(imageUrlList) {
+    // 简化:只接受 url 或 base64 字符串数组
+    return new Promise(async (resolve, reject) => {
+        try {
+            // 确保是数组并过滤出有效字符串
+            const inputs = imageUrlList.filter(item => item);
+            if (inputs.length === 0) return resolve(null);
+
+            // 使用 loadImage 加载并直接用返回的宽高创建 canvas(避免再去读取图片尺寸)
+            const canvases = [];
+            for (const url of inputs) {
+                const { img, width, height } = await loadImage(url);
+                const c = document.createElement('canvas');
+                c.width = width;
+                c.height = height;
+                const ctx = c.getContext('2d');
+                // 只绘制一次图片到 canvas 用于后续合并/缩放
+                ctx.drawImage(img, 0, 0, width, height);
+                canvases.push(c);
+            }
+
+            // 计算最大宽度并按比例缩放到该宽度
+            let maxWidth = 0;
+            for (const c of canvases) if (c.width > maxWidth) maxWidth = c.width;
+
+            const scaled = canvases.map(c => {
+                if (c.width === maxWidth) return c;
+                const scale = maxWidth / c.width;
+                const nc = document.createElement('canvas');
+                nc.width = maxWidth;
+                nc.height = Math.round(c.height * scale);
+                const ctx = nc.getContext('2d');
+                // 使用源 canvas 进行缩放绘制
+                ctx.drawImage(c, 0, 0, c.width, c.height, 0, 0, nc.width, nc.height);
+                return nc;
+            });
+
+            // 合并
+            let totalH = scaled.reduce((s, c) => s + c.height, 0);
+            const finalCanvas = document.createElement('canvas');
+            finalCanvas.width = maxWidth;
+            finalCanvas.height = totalH;
+            const fctx = finalCanvas.getContext('2d');
+
+            let y = 0;
+            for (const c of scaled) {
+                fctx.drawImage(c, 0, 0, c.width, c.height, 0, y, c.width, c.height);
+                y += c.height;
+            }
+
+            resolve(finalCanvas.toDataURL('image/jpeg'));
+        } catch (err) {
+            reject(err);
+        }
+    });
 }

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů