diff --git a/.gitignore b/.gitignore index 16b24ca..1139e42 100644 --- a/.gitignore +++ b/.gitignore @@ -170,4 +170,6 @@ dist # Vite 临时文件 vite.config.*.timestamp-*.mjs -*.timestamp-* \ No newline at end of file +*.timestamp-* + +kv-admin \ No newline at end of file diff --git a/package.json b/package.json index 9f448e2..01e1b34 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "lint": "eslint . --fix" }, "dependencies": { + "@examaware-cs/core": "^1.0.0", + "@examaware-cs/player": "^1.0.2", "@mdi/font": "7.4.47", "@microsoft/clarity": "^1.0.0", "axios": "^1.11.0", @@ -19,6 +21,7 @@ "pinyin-pro": "^3.27.0", "ratelimit-header-parser": "^0.1.0", "roboto-fontface": "*", + "tdesign-vue-next": "^1.17.1", "typewriter-effect": "^2.21.0", "uuid": "^9.0.1", "vue": "^3.5.20", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a33e1e1..47676e0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,12 @@ importers: .: dependencies: + '@examaware-cs/core': + specifier: ^1.0.0 + version: 1.0.0 + '@examaware-cs/player': + specifier: ^1.0.2 + version: 1.0.2(tdesign-vue-next@1.17.1(vue@3.5.20))(vue@3.5.20) '@mdi/font': specifier: 7.4.47 version: 7.4.47 @@ -35,6 +41,9 @@ importers: roboto-fontface: specifier: '*' version: 0.10.0 + tdesign-vue-next: + specifier: ^1.17.1 + version: 1.17.1(vue@3.5.20) typewriter-effect: specifier: ^2.21.0 version: 2.21.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -816,6 +825,15 @@ packages: resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@examaware-cs/core@1.0.0': + resolution: {integrity: sha512-JSnyYe4/wpKfoPdA1CVNjLyBSpFSL+H/rKTZlbJyFCymtBRlXthzswKzLCwioyw7y/C3lioUFXLJ2g+CwDnS6w==} + + '@examaware-cs/player@1.0.2': + resolution: {integrity: sha512-Fid58JL0X5TP/O3DNp8QY0B5B8Svv1I8Qi8AObw5HK571/UU6/ri1YQS03ujxt6yupzd7qhiX+7C7EO4nLglJg==} + peerDependencies: + tdesign-vue-next: ^1.15.5 + vue: ^3.0.0 + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1062,6 +1080,9 @@ packages: resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@quansync/fs@0.1.2': resolution: {integrity: sha512-ezIadUb1aFhwJLd++WVqVpi9rnlX8vnd4ju7saPhwLHJN1mJgOv0puePTGV+FbtSnWtwoHDT8lAm4kagDZmpCg==} engines: {node: '>=20.0.0'} @@ -1236,12 +1257,27 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/sortablejs@1.15.8': + resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} + + '@types/tinycolor2@1.4.6': + resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/validator@13.15.3': + resolution: {integrity: sha512-7bcUmDyS6PN3EuD9SlGGOxM77F8WLVsrwkxyWxKnxzmXoequ6c7741QBrANq6htVRGOITJ7z72mTP6Z4XyuG+Q==} + '@vite-pwa/assets-generator@1.0.0': resolution: {integrity: sha512-tWRF/tsqGkND5+dDVnJz7DzQkIRjtTRRYvA3y6l4FwTwK47OK72p1X7ResSz6T7PimIZMuFd+arsB8NRIG+Sww==} engines: {node: '>=16.14.0'} @@ -1611,6 +1647,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dayjs@1.11.18: + resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -2413,6 +2452,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -2475,6 +2517,9 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + misans@4.1.0: + resolution: {integrity: sha512-CcIRrIVhnt+OpGXvw1Q8llGBVAy5P2mdov/kJ0gGa81sJ0RY7mZp2fNAt2ySTCeZos+wo7ZnzDZxl1In//7FdA==} + mitt@3.0.1: resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} @@ -2542,6 +2587,9 @@ packages: resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} + ogl@1.0.11: + resolution: {integrity: sha512-kUpC154AFfxi16pmZUK4jk3J+8zxwTWGPo03EoYA8QPbzikHoaC82n6pNTbd+oEaJonaE8aPWBlX7ad9zrqLsA==} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2993,12 +3041,18 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + simple-keyboard@3.8.85: + resolution: {integrity: sha512-ewZgPgisKsRsBpBW8wfOoR/fn4ApxD6lhhfw6u354fLAM6fHnkJLOHs8o1q5S/zhJQF0sSDPoIO0EojveNylfQ==} + simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} smob@1.5.0: resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} + sortablejs@1.15.6: + resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -3089,6 +3143,17 @@ packages: resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==} engines: {node: '>=16.0.0'} + tdesign-icons-vue-next@0.4.1: + resolution: {integrity: sha512-uDPuTLRORnGcTyVGNoentNaK4V+ZcBmhYwcY3KqDaQQ5rrPeLMxu0ZVmgOEf0JtF2QZiqAxY7vodNEiLUdoRKA==} + peerDependencies: + vue: ^3.0.0 + + tdesign-vue-next@1.17.1: + resolution: {integrity: sha512-rqRPHSfPn5Y7Nxffa9Q6JumPguc+K2YfcaaxrvyYkZIQwCQ8Fwi2rhh6KpgQud2SAPMP/N1SxfIvYJVS5Lyu8Q==} + engines: {node: '>= 18'} + peerDependencies: + vue: '>=3.1.0' + temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} @@ -3102,6 +3167,9 @@ packages: engines: {node: '>=10'} hasBin: true + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + tinyglobby@0.2.12: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} @@ -3291,6 +3359,10 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + validator@13.15.15: + resolution: {integrity: sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==} + engines: {node: '>= 0.10'} + varint@6.0.0: resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} @@ -4288,6 +4360,17 @@ snapshots: dependencies: levn: 0.4.1 + '@examaware-cs/core@1.0.0': {} + + '@examaware-cs/player@1.0.2(tdesign-vue-next@1.17.1(vue@3.5.20))(vue@3.5.20)': + dependencies: + '@examaware-cs/core': 1.0.0 + misans: 4.1.0 + ogl: 1.0.11 + simple-keyboard: 3.8.85 + tdesign-vue-next: 1.17.1(vue@3.5.20) + vue: 3.5.20 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.6': @@ -4475,6 +4558,8 @@ snapshots: '@parcel/watcher-win32-x64': 2.5.1 optional: true + '@popperjs/core@2.11.8': {} + '@quansync/fs@0.1.2': dependencies: quansync: 0.2.10 @@ -4606,10 +4691,22 @@ snapshots: '@types/json5@0.0.29': {} + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.20 + + '@types/lodash@4.17.20': {} + '@types/resolve@1.20.2': {} + '@types/sortablejs@1.15.8': {} + + '@types/tinycolor2@1.4.6': {} + '@types/trusted-types@2.0.7': {} + '@types/validator@13.15.3': {} + '@vite-pwa/assets-generator@1.0.0': dependencies: cac: 6.7.14 @@ -5086,6 +5183,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dayjs@1.11.18: {} + debug@3.2.7: dependencies: ms: 2.1.3 @@ -6036,6 +6135,8 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash-es@4.17.21: {} + lodash.debounce@4.0.8: {} lodash.merge@4.6.2: {} @@ -6093,6 +6194,8 @@ snapshots: minimist@1.2.8: {} + misans@4.1.0: {} + mitt@3.0.1: {} mlly@1.7.4: @@ -6162,6 +6265,8 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + ogl@1.0.11: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -6653,12 +6758,16 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + simple-keyboard@3.8.85: {} + simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 smob@1.5.0: {} + sortablejs@1.15.6: {} + source-map-js@1.2.1: {} source-map-support@0.5.21: @@ -6764,6 +6873,28 @@ snapshots: sync-message-port@1.1.3: {} + tdesign-icons-vue-next@0.4.1(vue@3.5.20): + dependencies: + '@babel/runtime': 7.27.0 + vue: 3.5.20 + + tdesign-vue-next@1.17.1(vue@3.5.20): + dependencies: + '@babel/runtime': 7.27.0 + '@popperjs/core': 2.11.8 + '@types/lodash-es': 4.17.12 + '@types/sortablejs': 1.15.8 + '@types/tinycolor2': 1.4.6 + '@types/validator': 13.15.3 + dayjs: 1.11.18 + lodash-es: 4.17.21 + mitt: 3.0.1 + sortablejs: 1.15.6 + tdesign-icons-vue-next: 0.4.1(vue@3.5.20) + tinycolor2: 1.6.0 + validator: 13.15.15 + vue: 3.5.20 + temp-dir@2.0.0: {} tempy@0.6.0: @@ -6780,6 +6911,8 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + tinycolor2@1.6.0: {} + tinyglobby@0.2.12: dependencies: fdir: 6.4.3(picomatch@4.0.2) @@ -7027,6 +7160,8 @@ snapshots: uuid@9.0.1: {} + validator@13.15.15: {} + varint@6.0.0: {} vite-plugin-pwa@1.0.3(@vite-pwa/assets-generator@1.0.0)(vite@5.4.17(sass-embedded@1.86.3)(sass@1.86.3)(terser@5.39.0))(workbox-build@7.3.0)(workbox-window@7.3.0): diff --git a/src/assets/fonts/TCloudNumberVF.ttf b/src/assets/fonts/TCloudNumberVF.ttf new file mode 100644 index 0000000..6abfb92 Binary files /dev/null and b/src/assets/fonts/TCloudNumberVF.ttf differ diff --git a/src/components/ExamConfigEditor.vue b/src/components/ExamConfigEditor.vue index a7cf125..d3efa2b 100644 --- a/src/components/ExamConfigEditor.vue +++ b/src/components/ExamConfigEditor.vue @@ -1073,6 +1073,8 @@ export default { } }, + + /** * 确认删除配置 */ diff --git a/src/components/MigrationTool.vue b/src/components/MigrationTool.vue index a10c655..ed5993d 100644 --- a/src/components/MigrationTool.vue +++ b/src/components/MigrationTool.vue @@ -225,7 +225,7 @@ + + diff --git a/src/pages/exam-player.vue b/src/pages/exam-player.vue new file mode 100644 index 0000000..b03877a --- /dev/null +++ b/src/pages/exam-player.vue @@ -0,0 +1,216 @@ + + + + diff --git a/src/utils/api.js b/src/utils/api.js index 34a7d16..69be721 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -44,4 +44,4 @@ export const getNamespaceInfo = async () => { } catch (error) { throw new Error(error.response?.data?.message || "获取命名空间信息失败"); } -}; \ No newline at end of file +}; diff --git a/src/utils/providers/kvServerProvider.js b/src/utils/providers/kvServerProvider.js index fca4f2a..72d9dcc 100644 --- a/src/utils/providers/kvServerProvider.js +++ b/src/utils/providers/kvServerProvider.js @@ -23,7 +23,6 @@ export const kvServerProvider = { async loadNamespaceInfo() { try { // 使用 Classworks Cloud 或者用户配置的服务器域名 - const provider = getSetting("server.provider"); const serverUrl = getSetting("server.domain"); const res = await axios.get(`${serverUrl}/kv/_info`, { diff --git a/vite.config.mjs b/vite.config.mjs index 1f73778..b4354a5 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -7,6 +7,7 @@ import Vue from '@vitejs/plugin-vue' import VueRouter from 'unplugin-vue-router/vite' import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify' import { VitePWA } from 'vite-plugin-pwa' +import { TDesignResolver } from 'unplugin-vue-components/resolvers' // Utilities import { defineConfig } from 'vite' @@ -154,7 +155,13 @@ export default defineConfig({ configFile: 'src/styles/settings.scss', }, }), - Components(), + Components({ + resolvers: [ + TDesignResolver({ + library: 'vue-next' + }) + ] + }), Fonts({ google: { families: [{