添加挑战

This commit is contained in:
2025-04-27 20:35:16 +08:00
parent d7f33bfca2
commit dd9233a6d6
19 changed files with 344 additions and 207 deletions

5
components.d.ts vendored
View File

@@ -8,11 +8,13 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
Challenge: typeof import('./src/components/Challenge.vue')['default']
Corner: typeof import('./src/components/Corner.vue')['default']
Editor: typeof import('./src/components/Editor.vue')['default']
Editors: typeof import('./src/components/Editors.vue')['default']
Login: typeof import('./src/components/Login.vue')['default']
NAlert: typeof import('naive-ui')['NAlert']
NameWithFilter: typeof import('./src/components/submissions/NameWithFilter.vue')['default']
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard']
NCode: typeof import('naive-ui')['NCode']
@@ -20,6 +22,7 @@ declare module 'vue' {
NDataTable: typeof import('naive-ui')['NDataTable']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDropdown: typeof import('naive-ui')['NDropdown']
NEmpty: typeof import('naive-ui')['NEmpty']
NFlex: typeof import('naive-ui')['NFlex']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
@@ -44,8 +47,8 @@ declare module 'vue' {
Preview: typeof import('./src/components/Preview.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Task: typeof import('./src/components/Task.vue')['default']
TaskTitle: typeof import('./src/components/submissions/TaskTitle.vue')['default']
Tutorial: typeof import('./src/components/Tutorial.vue')['default']
UserActions: typeof import('./src/components/dashboard/UserActions.vue')['default']
}
}

358
package-lock.json generated
View File

@@ -11,30 +11,30 @@
"@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.3",
"@fsegurai/codemirror-theme-github-light": "^6.1.2",
"@vueuse/core": "^13.0.0",
"axios": "^1.8.3",
"@fsegurai/codemirror-theme-github-light": "^6.1.4",
"@vueuse/core": "^13.1.0",
"axios": "^1.9.0",
"codemirror": "^6.0.1",
"copy-text-to-clipboard": "^3.2.0",
"github-markdown-css": "^5.8.1",
"highlight.js": "^11.11.1",
"marked": "^15.0.7",
"marked": "^15.0.11",
"marked-alert": "^2.1.2",
"marked-code-preview": "^1.3.7",
"marked-highlight": "^2.2.1",
"naive-ui": "^2.41.0",
"vue": "^3.5.13",
"vue-codemirror": "^6.1.1",
"vue-router": "^4.5.0"
"vue-router": "^4.5.1"
},
"devDependencies": {
"@iconify/vue": "^4.3.0",
"@rsbuild/core": "^1.2.19",
"@rsbuild/core": "^1.3.13",
"@rsbuild/plugin-vue": "^1.0.7",
"@vue/tsconfig": "^0.7.0",
"prettier": "^3.5.3",
"typescript": "^5.8.2",
"unplugin-vue-components": "^28.4.1"
"typescript": "^5.8.3",
"unplugin-vue-components": "^28.5.0"
}
},
"node_modules/@babel/helper-string-parser": {
@@ -233,9 +233,9 @@
"license": "MIT"
},
"node_modules/@fsegurai/codemirror-theme-github-light": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@fsegurai/codemirror-theme-github-light/-/codemirror-theme-github-light-6.1.2.tgz",
"integrity": "sha512-B/YvJ4mx1EuY5WvN+RrFd3uHoFhXiTZRDmSVEyctb/pQonKpgkblVN+FvLt9iRfVTJkkyBavjXJzT16ClaZcDg==",
"version": "6.1.4",
"resolved": "https://registry.npmjs.org/@fsegurai/codemirror-theme-github-light/-/codemirror-theme-github-light-6.1.4.tgz",
"integrity": "sha512-jO/P6j+YhlORYT/dpgV4kg+F3FIDt+CLEwPTBfgQ1a/4ts4uHxoAnTy+jWLdumOVe++pnfl4hdDXJNmLIxkPfw==",
"license": "MIT",
"peerDependencies": {
"@codemirror/language": "^6.0.0",
@@ -400,65 +400,74 @@
"license": "MIT"
},
"node_modules/@module-federation/error-codes": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.8.4.tgz",
"integrity": "sha512-55LYmrDdKb4jt+qr8qE8U3al62ZANp3FhfVaNPOaAmdTh0jHdD8M3yf5HKFlr5xVkVO4eV/F/J2NCfpbh+pEXQ==",
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.13.0.tgz",
"integrity": "sha512-4soAMLr7qcVWuvCsyRmBbiBfuhxmnDeyl+qzjMx8VurQgL+XQDQJapM9RXngNGT4g8FoCq9o7rM5YWNgFFNUiw==",
"dev": true,
"license": "MIT"
},
"node_modules/@module-federation/runtime": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.8.4.tgz",
"integrity": "sha512-yZeZ7z2Rx4gv/0E97oLTF3V6N25vglmwXGgoeju/W2YjsFvWzVtCDI7zRRb0mJhU6+jmSM8jP1DeQGbea/AiZQ==",
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.13.0.tgz",
"integrity": "sha512-Ne/3AEVWz6LL6G/i41O5MC6YYlg0SatNNqG/0XbuMAfyGM+llRmB6VKt0o2+JR4isxWuPNp97TbUkkfORit6Eg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/error-codes": "0.8.4",
"@module-federation/sdk": "0.8.4"
"@module-federation/error-codes": "0.13.0",
"@module-federation/runtime-core": "0.13.0",
"@module-federation/sdk": "0.13.0"
}
},
"node_modules/@module-federation/runtime-core": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@module-federation/runtime-core/-/runtime-core-0.13.0.tgz",
"integrity": "sha512-Oj/1p0mfxZ+8EbU7ND4gMvRmikFpIvPCbblOgat9N8ZIVAKYpTimCgMhzg4yRqAwzlGCVwnnW7XZ8UlA+Zqrvg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/error-codes": "0.13.0",
"@module-federation/sdk": "0.13.0"
}
},
"node_modules/@module-federation/runtime-tools": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.8.4.tgz",
"integrity": "sha512-fjVOsItJ1u5YY6E9FnS56UDwZgqEQUrWFnouRiPtK123LUuqUI9FH4redZoKWlE1PB0ir1Z3tnqy8eFYzPO38Q==",
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.13.0.tgz",
"integrity": "sha512-6ECWX18yGrQKcmkrQoNPd5VEpxZP1SMaB/Bp55xlpEhsrpn4zHnriQluxDw6xldjSOLl1qbokfxwCwjS2OaEbg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/runtime": "0.8.4",
"@module-federation/webpack-bundler-runtime": "0.8.4"
"@module-federation/runtime": "0.13.0",
"@module-federation/webpack-bundler-runtime": "0.13.0"
}
},
"node_modules/@module-federation/sdk": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.8.4.tgz",
"integrity": "sha512-waABomIjg/5m1rPDBWYG4KUhS5r7OUUY7S+avpaVIY/tkPWB3ibRDKy2dNLLAMaLKq0u+B1qIdEp4NIWkqhqpg==",
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.13.0.tgz",
"integrity": "sha512-JdMZaPD+EQvMJYS+/8/8QjaAHQ3qljogvioXBsAuedcStu/msn5e1Fswc0G34kXY9ixs2hUPZU2cAllfSKWIBQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"isomorphic-rslog": "0.0.6"
}
"license": "MIT"
},
"node_modules/@module-federation/webpack-bundler-runtime": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.8.4.tgz",
"integrity": "sha512-HggROJhvHPUX7uqBD/XlajGygMNM1DG0+4OAkk8MBQe4a18QzrRNzZt6XQbRTSG4OaEoyRWhQHvYD3Yps405tQ==",
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.13.0.tgz",
"integrity": "sha512-ycgAsFeCTo+3GR8JxkhCyg2UZm6Au98ISdLTdVXYphO4UDcO/KjqyJen1LXEslkpCEohDj68Prei2fUHRruK6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/runtime": "0.8.4",
"@module-federation/sdk": "0.8.4"
"@module-federation/runtime": "0.13.0",
"@module-federation/sdk": "0.13.0"
}
},
"node_modules/@rsbuild/core": {
"version": "1.2.19",
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.2.19.tgz",
"integrity": "sha512-k76is4HygmbYYMLG2V1d1yQeurHHC+ZEtGs/nwE11y6HmwSndoFhmjOeQbQ2Ul0b2B8HErksqSMtlCxd37YPPQ==",
"version": "1.3.13",
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.3.13.tgz",
"integrity": "sha512-FIRV1ncOYYLCEGJDL8ZPKyH4J15lJS54KfeGf3Eacy5zUhT+dAkI2+0ZWH/s9NlaXA/vlRq6SJF9Z2Y96dO13Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rspack/core": "1.2.8",
"@rspack/core": "1.3.7",
"@rspack/lite-tapable": "~1.0.1",
"@swc/helpers": "^0.5.15",
"@swc/helpers": "^0.5.17",
"core-js": "~3.41.0",
"jiti": "^2.4.2"
},
@@ -466,7 +475,7 @@
"rsbuild": "bin/rsbuild.js"
},
"engines": {
"node": ">=16.7.0"
"node": ">=16.10.0"
}
},
"node_modules/@rsbuild/plugin-vue": {
@@ -484,27 +493,27 @@
}
},
"node_modules/@rspack/binding": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.2.8.tgz",
"integrity": "sha512-T3FMB3N9P1AbSAryfkSRJkPtmeSYs/Gj9zUZoPz1ckPEIcWZmpUOQbJylldjbw5waxtCL1haHNbi0pcSvxiaJw==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.3.7.tgz",
"integrity": "sha512-jSXLktIGmNNZssxT+fjZ31IyUO7lRoFrFO+XuqKlMpbnHE8yCrpaHE6rLyDPVO4Vnl6xx/df8usUXtZwIc4jrw==",
"dev": true,
"license": "MIT",
"optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.2.8",
"@rspack/binding-darwin-x64": "1.2.8",
"@rspack/binding-linux-arm64-gnu": "1.2.8",
"@rspack/binding-linux-arm64-musl": "1.2.8",
"@rspack/binding-linux-x64-gnu": "1.2.8",
"@rspack/binding-linux-x64-musl": "1.2.8",
"@rspack/binding-win32-arm64-msvc": "1.2.8",
"@rspack/binding-win32-ia32-msvc": "1.2.8",
"@rspack/binding-win32-x64-msvc": "1.2.8"
"@rspack/binding-darwin-arm64": "1.3.7",
"@rspack/binding-darwin-x64": "1.3.7",
"@rspack/binding-linux-arm64-gnu": "1.3.7",
"@rspack/binding-linux-arm64-musl": "1.3.7",
"@rspack/binding-linux-x64-gnu": "1.3.7",
"@rspack/binding-linux-x64-musl": "1.3.7",
"@rspack/binding-win32-arm64-msvc": "1.3.7",
"@rspack/binding-win32-ia32-msvc": "1.3.7",
"@rspack/binding-win32-x64-msvc": "1.3.7"
}
},
"node_modules/@rspack/binding-darwin-arm64": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz",
"integrity": "sha512-bDlrlroY3iMlzna/3i1gD6eRmhJW2zRyC3Ov6aR1micshVQ9RteigYZWkjZuQfyC5Z8dCcLUQJVojz+pqp0JXg==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.3.7.tgz",
"integrity": "sha512-/5k4H0M7vvu7uorhc0OQKdQ7ybcjcJA//ptfYB646Ca/XY8FI1T/H88prPNrLNu97FGqUT4QWo5AHj01XymfDw==",
"cpu": [
"arm64"
],
@@ -516,9 +525,9 @@
]
},
"node_modules/@rspack/binding-darwin-x64": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz",
"integrity": "sha512-0/qOVbMuzZ+WbtDa4TbH46R4vph/W6MHcXbrXDO+vpdTMFDVJ64DnZXT7aqvGcY+7vTCIGm0GT+6ooR4KaIX8A==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.3.7.tgz",
"integrity": "sha512-/eNcZFDHxo5RVmIxgVM5zxCXmufeWpvviWJMDjhycS175nJb6103YWpu6H0lHgbj0GnHM/Q2VjVRFNhaGbXqdA==",
"cpu": [
"x64"
],
@@ -530,9 +539,9 @@
]
},
"node_modules/@rspack/binding-linux-arm64-gnu": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz",
"integrity": "sha512-En/SMl45s19iUVb1/ZDFQvFDxIjnlfk7yqV3drMWWAL5HSgksNejaTIFTO52aoohIBbmwuk5wSGcbU0G0IFiPg==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.3.7.tgz",
"integrity": "sha512-bSxA4MgGOdSvf/nTqNMuLeeyWS4Okh1iPskGuyAv/Sdf7cGbflUyZe6+w7A9BZEFR0CVTfj3f8kt73N+lu72Kg==",
"cpu": [
"arm64"
],
@@ -544,9 +553,9 @@
]
},
"node_modules/@rspack/binding-linux-arm64-musl": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz",
"integrity": "sha512-N1oZsXfJ9VLLcK7p1PS65cxLYQCZ7iqHW2OP6Ew2+hlz/d1hzngxgzrtZMCXFOHXDvTzVu5ff6jGS2v7+zv2tA==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.3.7.tgz",
"integrity": "sha512-i6QK6YodCA5R8/ShRylkyunwvNcRx/Q7af14jSCa7TPOi6pPoDUL2pmwGcJBk1uPc2wjQwAMZzfJjTWNjEyW2Q==",
"cpu": [
"arm64"
],
@@ -558,9 +567,9 @@
]
},
"node_modules/@rspack/binding-linux-x64-gnu": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz",
"integrity": "sha512-BdPaepoLKuaVwip4QK/nGqNi1xpbCWSxiycPbKRrGqKgt/QGihxxFgiqr4EpWQVIJNIMy4nCsg4arO0+H1KWGQ==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.3.7.tgz",
"integrity": "sha512-6AmOHLOv4XAK7Y5cFDBtnetIZ44MqG8Q6wZ20zjql/khTxsRZa/edis/eUppGb8fy5gzi+qqSAznEZ+Qj3LMrQ==",
"cpu": [
"x64"
],
@@ -572,9 +581,9 @@
]
},
"node_modules/@rspack/binding-linux-x64-musl": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz",
"integrity": "sha512-GFv0Bod268OcXIcjeLoPlK0oz8rClEIxIRFkz+ejhbvfCwRJ+Fd+EKaaKQTBfZQujPqc0h2GctIF25nN5pFTmA==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.3.7.tgz",
"integrity": "sha512-rPt0c9UHp5AxWHhjziEtd2uwiWyzM4UZLFJV6hawBWOoIQf2uLSl3fp0HTqxpslfTh3uo5ymhHN/bV48m5THzg==",
"cpu": [
"x64"
],
@@ -586,9 +595,9 @@
]
},
"node_modules/@rspack/binding-win32-arm64-msvc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz",
"integrity": "sha512-aEU+uJdbvJJGrzzAsjbjrPeNbG/bcG8JoXK2kSsUB+/sWHTIkHX0AQ3oX3aV/lcLKgZWrUxLAfLoCXEnIHMEyQ==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.3.7.tgz",
"integrity": "sha512-+Db7NGBzad1dCcSm94uARkIIhbVv1+BXAl1duLBnYQMfqsu/pirsInE9wbp7WVUbSl2hmdRi9MYgWACjoReo4g==",
"cpu": [
"arm64"
],
@@ -600,9 +609,9 @@
]
},
"node_modules/@rspack/binding-win32-ia32-msvc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.8.tgz",
"integrity": "sha512-GHYzNOSoiLyG9elLTmMqADJMQzjll+co4irp5AgZ+KHG9EVq0qEHxDqDIJxZnUA15U8JDvCgo6YAo3T0BFEL0Q==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.3.7.tgz",
"integrity": "sha512-VPqqC0U6FolGoonmZYBBiFyWjQ4+X+e/l/t4QZP2DRonlpE418+MdCxq2ldVGgvtxwERNlz61zxEX9yh/8KOfw==",
"cpu": [
"ia32"
],
@@ -614,9 +623,9 @@
]
},
"node_modules/@rspack/binding-win32-x64-msvc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz",
"integrity": "sha512-EigKLhKLH1kfv1e/ZgXuSKlIjkbyneJtiLbNDz7EeEVFGV1XMM6bsCea1sb2WOxsPYiOX4Q5JmR1j1KGrZS/LA==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.3.7.tgz",
"integrity": "sha512-zi9tKxlq85lSYTb1sbEluLjZlkbjuoJoy2TaNzVlfNkmiJ6EiqBbyCWoPPBJRP6HQ9pG25W0y4NWKp7iVhiBvg==",
"cpu": [
"x64"
],
@@ -628,28 +637,24 @@
]
},
"node_modules/@rspack/core": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.2.8.tgz",
"integrity": "sha512-ppj3uQQtkhgrYDLrUqb33YbpNEZCpAudpfVuOHGsvUrAnu1PijbfJJymoA5ZvUhM+HNMvPI5D1ie97TXyb0UVg==",
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.3.7.tgz",
"integrity": "sha512-InXnEmImLKkxzkY7XaAozycjMvS5myf/o3zu1rw5tNq3ONxWvW0QOHVTcrF0FbeKQ/jCOFSfdaoFjbXjdUs38w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@module-federation/runtime-tools": "0.8.4",
"@rspack/binding": "1.2.8",
"@module-federation/runtime-tools": "0.13.0",
"@rspack/binding": "1.3.7",
"@rspack/lite-tapable": "1.0.1",
"caniuse-lite": "^1.0.30001702"
"caniuse-lite": "^1.0.30001715"
},
"engines": {
"node": ">=16.0.0"
},
"peerDependencies": {
"@rspack/tracing": "^1.x",
"@swc/helpers": ">=0.5.1"
},
"peerDependenciesMeta": {
"@rspack/tracing": {
"optional": true
},
"@swc/helpers": {
"optional": true
}
@@ -666,9 +671,9 @@
}
},
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
"integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
"integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -874,14 +879,14 @@
}
},
"node_modules/@vueuse/core": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.0.0.tgz",
"integrity": "sha512-rkgb4a8/0b234lMGCT29WkCjPfsX0oxrIRR7FDndRoW3FsaC9NBzefXg/9TLhAgwM11f49XnutshM4LzJBrQ5g==",
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.1.0.tgz",
"integrity": "sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.21",
"@vueuse/metadata": "13.0.0",
"@vueuse/shared": "13.0.0"
"@vueuse/metadata": "13.1.0",
"@vueuse/shared": "13.1.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
@@ -891,18 +896,18 @@
}
},
"node_modules/@vueuse/metadata": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.0.0.tgz",
"integrity": "sha512-TRNksqmvtvqsuHf7bbgH9OSXEV2b6+M3BSN4LR5oxWKykOFT9gV78+C2/0++Pq9KCp9KQ1OQDPvGlWNQpOb2Mw==",
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.1.0.tgz",
"integrity": "sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.0.0.tgz",
"integrity": "sha512-9MiHhAPw+sqCF/RLo8V6HsjRqEdNEWVpDLm2WBRW2G/kSQjb8X901sozXpSCaeLG0f7TEfMrT4XNaA5m1ez7Dg==",
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.1.0.tgz",
"integrity": "sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
@@ -1087,9 +1092,9 @@
"license": "Apache-2.0"
},
"node_modules/acorn": {
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -1212,9 +1217,9 @@
}
},
"node_modules/axios": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
"integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
"integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -1302,9 +1307,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001706",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz",
"integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==",
"version": "1.0.30001715",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz",
"integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==",
"dev": true,
"funding": [
{
@@ -1429,9 +1434,9 @@
"license": "MIT"
},
"node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
"dev": true,
"license": "MIT"
},
@@ -1712,6 +1717,13 @@
"integrity": "sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==",
"license": "MIT"
},
"node_modules/exsolve": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz",
"integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2022,16 +2034,6 @@
"node": ">=0.12.0"
}
},
"node_modules/isomorphic-rslog": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/isomorphic-rslog/-/isomorphic-rslog-0.0.6.tgz",
"integrity": "sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14.17.6"
}
},
"node_modules/jest-worker": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
@@ -2107,14 +2109,15 @@
}
},
"node_modules/local-pkg": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.0.0.tgz",
"integrity": "sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.1.tgz",
"integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"mlly": "^1.7.3",
"pkg-types": "^1.3.0"
"mlly": "^1.7.4",
"pkg-types": "^2.0.1",
"quansync": "^0.2.8"
},
"engines": {
"node": ">=14"
@@ -2145,9 +2148,9 @@
}
},
"node_modules/marked": {
"version": "15.0.7",
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.7.tgz",
"integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==",
"version": "15.0.11",
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.11.tgz",
"integrity": "sha512-1BEXAU2euRCG3xwgLVT1y0xbJEld1XOrmRJpUwRCcy7rxhSCwMrmEu9LXoPhHSCJG41V7YcQ2mjKRr5BA3ITIA==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
@@ -2236,6 +2239,25 @@
"ufo": "^1.5.4"
}
},
"node_modules/mlly/node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"dev": true,
"license": "MIT"
},
"node_modules/mlly/node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.4",
"pathe": "^2.0.1"
}
},
"node_modules/moo": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
@@ -2358,15 +2380,15 @@
}
},
"node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz",
"integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
"dev": true,
"license": "MIT",
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.4",
"pathe": "^2.0.1"
"confbox": "^0.2.1",
"exsolve": "^1.0.1",
"pathe": "^2.0.3"
}
},
"node_modules/postcss": {
@@ -2419,6 +2441,23 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
"node_modules/quansync": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz",
"integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/antfu"
},
{
"type": "individual",
"url": "https://github.com/sponsors/sxzz"
}
],
"license": "MIT"
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -2679,9 +2718,9 @@
"license": "0BSD"
},
"node_modules/typescript": {
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"devOptional": true,
"license": "Apache-2.0",
"bin": {
@@ -2693,9 +2732,9 @@
}
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
"dev": true,
"license": "MIT"
},
@@ -2707,13 +2746,14 @@
"license": "MIT"
},
"node_modules/unplugin": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.2.0.tgz",
"integrity": "sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.2.tgz",
"integrity": "sha512-3n7YA46rROb3zSj8fFxtxC/PqoyvYQ0llwz9wtUPUutr9ig09C8gGo5CWCwHrUzlqC1LLR43kxp5vEIyH1ac1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"acorn": "^8.14.0",
"acorn": "^8.14.1",
"picomatch": "^4.0.2",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
@@ -2738,19 +2778,19 @@
}
},
"node_modules/unplugin-vue-components": {
"version": "28.4.1",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.4.1.tgz",
"integrity": "sha512-niGSc0vJD9ueAnsqcfAldmtpkppZ09B6p2G1dL7X5S8KPdgbk1P+txPwaaDCe7N+eZh2VG1aAypLXkuJs3OSUg==",
"version": "28.5.0",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.5.0.tgz",
"integrity": "sha512-o7fMKU/uI8NiP+E0W62zoduuguWqB0obTfHFtbr1AP2uo2lhUPnPttWUE92yesdiYfo9/0hxIrj38FMc1eaySg==",
"dev": true,
"license": "MIT",
"dependencies": {
"chokidar": "^3.6.0",
"debug": "^4.4.0",
"local-pkg": "^1.0.0",
"local-pkg": "^1.1.1",
"magic-string": "^0.30.17",
"mlly": "^1.7.4",
"tinyglobby": "^0.2.12",
"unplugin": "^2.2.0",
"unplugin": "^2.3.2",
"unplugin-utils": "^0.2.4"
},
"engines": {
@@ -2889,9 +2929,9 @@
}
},
"node_modules/vue-router": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.0.tgz",
"integrity": "sha512-HDuk+PuH5monfNuY+ct49mNmkCRK4xJAV9Ts4z9UFc4rzdDnxQLyCMGGc8pKhZhHTVzfanpNwB/lwqevcBwI4w==",
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz",
"integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^6.6.4"

View File

@@ -12,29 +12,29 @@
"@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.3",
"@fsegurai/codemirror-theme-github-light": "^6.1.2",
"@vueuse/core": "^13.0.0",
"axios": "^1.8.3",
"@fsegurai/codemirror-theme-github-light": "^6.1.4",
"@vueuse/core": "^13.1.0",
"axios": "^1.9.0",
"codemirror": "^6.0.1",
"copy-text-to-clipboard": "^3.2.0",
"github-markdown-css": "^5.8.1",
"highlight.js": "^11.11.1",
"marked": "^15.0.7",
"marked": "^15.0.11",
"marked-alert": "^2.1.2",
"marked-code-preview": "^1.3.7",
"marked-highlight": "^2.2.1",
"naive-ui": "^2.41.0",
"vue": "^3.5.13",
"vue-codemirror": "^6.1.1",
"vue-router": "^4.5.0"
"vue-router": "^4.5.1"
},
"devDependencies": {
"@iconify/vue": "^4.3.0",
"@rsbuild/core": "^1.2.19",
"@rsbuild/core": "^1.3.13",
"@rsbuild/plugin-vue": "^1.0.7",
"@vue/tsconfig": "^0.7.0",
"prettier": "^3.5.3",
"typescript": "^5.8.2",
"unplugin-vue-components": "^28.4.1"
"typescript": "^5.8.3",
"unplugin-vue-components": "^28.5.0"
}
}

View File

@@ -0,0 +1,14 @@
<template>
<div class="container" v-if="taskTab === TASK_TYPE.Challenge">
<n-empty>暂无挑战敬请期待</n-empty>
</div>
</template>
<script setup lang="ts">
import { taskTab } from "../store/task"
import { TASK_TYPE } from "../utils/const"
</script>
<style scoped>
.container {
padding: 16px;
}
</style>

View File

@@ -1,6 +1,8 @@
<template>
<n-flex align="center" class="corner">
<n-button quaternary v-if="!show" @click="showTutorial">教程</n-button>
<n-button quaternary v-if="!show" @click="showTutorial">
打开{{ TASK_LABEL[taskTab] }}
</n-button>
<template v-if="user.loaded && authed">
<n-button
quaternary
@@ -38,12 +40,12 @@ import { Icon } from "@iconify/vue"
import { authed, roleNormal, roleSuper, user } from "../store/user"
import { loginModal } from "../store/modal"
import { show, tutorialSize, step } from "../store/tutorial"
import { taskId } from "../store/task"
import { taskId, taskTab } from "../store/task"
import { html, css, js } from "../store/editors"
import { Account, Submission } from "../api"
import { Role } from "../utils/type"
import { router } from "../router"
import { ADMIN_URL } from "../utils/const"
import { ADMIN_URL, TASK_LABEL } from "../utils/const"
const message = useMessage()

View File

@@ -3,7 +3,13 @@
<n-flex align="center" justify="space-between" class="title">
<n-flex align="center">
<Icon icon="twemoji:open-book" :width="20"></Icon>
<n-tabs style="width: 140px" type="segment" animated>
<n-tabs
style="width: 140px"
type="segment"
animated
:value="taskTab"
@update:value="changeTab"
>
<n-tab name="tutorial" tab="教程"></n-tab>
<n-tab name="challenge" tab="挑战"></n-tab>
</n-tabs>
@@ -20,7 +26,12 @@
<n-button
text
v-if="authed && roleSuper"
@click="$router.push({ name: 'tutorial', params: { display: step } })"
@click="
$router.push({
name: taskTab,
params: taskTab === TASK_TYPE.Tutorial ? { display: step } : {},
})
"
>
<Icon :width="16" icon="lucide:edit"></Icon>
</n-button>
@@ -29,7 +40,13 @@
</n-button>
</n-flex>
</n-flex>
<div class="markdown-body" v-html="content" ref="$content"></div>
<div
v-if="taskTab === TASK_TYPE.Tutorial"
class="markdown-body"
v-html="content"
ref="$content"
/>
<Challenge v-else />
</div>
</template>
<script lang="ts" setup>
@@ -41,46 +58,65 @@ import { css, html, js, tab } from "../store/editors"
import { Tutorial } from "../api"
import { step } from "../store/tutorial"
import { authed, roleSuper } from "../store/user"
import { useStorage } from "@vueuse/core"
import { STORAGE_KEY } from "../utils/const"
import { taskId } from "../store/task"
import { taskId, taskTab } from "../store/task"
import { useRoute, useRouter } from "vue-router"
import { TASK_TYPE } from "../utils/const"
import Challenge from "./Challenge.vue"
const displays = ref<number[]>([])
const content = useStorage(STORAGE_KEY.CONTENT, "")
const route = useRoute()
const router = useRouter()
const tutorialIds = ref<number[]>([])
const content = ref("")
const $content = useTemplateRef<any>("$content")
defineEmits(["hide"])
const hideNav = computed(() => displays.value.length <= 1)
const hideNav = computed(
() => taskTab.value === TASK_TYPE.Challenge || tutorialIds.value.length <= 1,
)
function changeTab(v: TASK_TYPE) {
taskTab.value = v
const query = { task: v } as any
if (v === TASK_TYPE.Tutorial) query.step = step.value
router.push({ query })
}
const prevDisabled = computed(() => {
const i = displays.value.indexOf(step.value)
const i = tutorialIds.value.indexOf(step.value)
return i <= 0
})
const nextDisabled = computed(() => {
const i = displays.value.indexOf(step.value)
return i === displays.value.length - 1
const i = tutorialIds.value.indexOf(step.value)
return i === tutorialIds.value.length - 1
})
function prev() {
const i = displays.value.indexOf(step.value)
step.value = displays.value[i - 1]
const i = tutorialIds.value.indexOf(step.value)
step.value = tutorialIds.value[i - 1]
router.push({ query: { task: taskTab.value, step: step.value } })
}
function next() {
const i = displays.value.indexOf(step.value)
step.value = displays.value[i + 1]
const i = tutorialIds.value.indexOf(step.value)
step.value = tutorialIds.value[i + 1]
router.push({ query: { task: taskTab.value, step: step.value } })
}
async function getContent() {
displays.value = await Tutorial.listDisplay()
if (!displays.value.length) {
tutorialIds.value = await Tutorial.listDisplay()
if (!tutorialIds.value.length) {
content.value = "暂无教程"
return
}
if (!displays.value.includes(step.value)) {
step.value = displays.value[0]
if (route.query.step) {
step.value = Number(route.query.step)
} else {
step.value = 1
}
if (!tutorialIds.value.includes(step.value)) {
step.value = tutorialIds.value[0]
}
const data = await Tutorial.get(step.value)
taskId.value = data.task_ptr
@@ -136,14 +172,15 @@ function modifyLink() {
}
}
async function render() {
async function init() {
taskTab.value = route.query.task as TASK_TYPE
await getContent()
addButton()
modifyLink()
}
onMounted(render)
watch(step, render)
onMounted(init)
watch(step, init)
</script>
<style scoped>
.container {

View File

@@ -0,0 +1 @@
<template></template>

View File

@@ -16,15 +16,25 @@
>
挑战
</n-tag>
<n-button text>{{ props.submission.task_title }}</n-button>
<n-button text @click="open">{{ props.submission.task_title }}</n-button>
</n-flex>
</template>
<script setup lang="ts">
import { useRouter } from "vue-router"
import type { SubmissionOut } from "../../utils/type"
import { submission } from "../../store/submission"
interface Props {
submission: SubmissionOut
}
const props = defineProps<Props>()
const router = useRouter()
function open() {
router.push({
name: "home",
query: { [submission.value.task_type]: submission.value.task_id },
})
}
</script>

1
src/pages/Challenge.vue Normal file
View File

@@ -0,0 +1 @@
<template>Dashboard Challenge</template>

View File

@@ -1,9 +1,7 @@
<template>
<n-flex class="container" :wrap="false">
<n-flex vertical class="menu">
<n-button secondary @click="$router.push({ name: 'home' })">
返回
</n-button>
<n-button secondary @click="goHome"> 返回 </n-button>
<n-button
v-for="item in menu"
:key="item.label"
@@ -19,16 +17,31 @@
</n-flex>
</template>
<script lang="ts" setup>
import { useRouter } from "vue-router"
import { taskTab } from "../store/task"
import { step } from "../store/tutorial"
import { TASK_TYPE } from "../utils/const"
const router = useRouter()
const menu = [
{
label: "教程",
route: { name: "tutorial", params: { display: step.value } },
},
{ label: "挑战", route: { name: "challenge" } },
{ label: "用户", route: { name: "user-manage", params: { page: 1 } } },
{ label: "提交", route: { name: "submissions", params: { page: 1 } } },
]
function goHome() {
const query = { task: taskTab.value } as any
if (taskTab.value === TASK_TYPE.Tutorial) query.step = step.value
router.push({
name: "home",
query,
})
}
</script>
<style scoped>
.container {

View File

@@ -6,7 +6,7 @@
max="900px"
>
<template #1>
<Tutorial @hide="hide" />
<Task @hide="hide" />
</template>
<template #2>
<n-split direction="vertical" min="200px">
@@ -24,7 +24,7 @@
import { useMagicKeys, whenever } from "@vueuse/core"
import Editors from "../components/Editors.vue"
import Preview from "../components/Preview.vue"
import Tutorial from "../components/Tutorial.vue"
import Task from "../components/Task.vue"
import { show, tutorialSize } from "../store/tutorial"
import { html, css, js } from "../store/editors"

View File

@@ -179,6 +179,7 @@ onUnmounted(() => {
id: "",
userid: 0,
username: "",
task_id: 0,
task_title: "",
task_type: "tutorial",
score: 0,

View File

@@ -15,7 +15,7 @@ const routes = [
path: "/submission/:id",
name: "submission",
component: () => import("./pages/Submission.vue"),
props: true
props: true,
},
{
path: "/dashboard",
@@ -26,7 +26,12 @@ const routes = [
{
path: "tutorial/:display",
name: "tutorial",
component: () => import("./pages/Markdown.vue"),
component: () => import("./pages/Tutorial.vue"),
},
{
path: "challenge",
name: "challenge",
component: () => import("./pages/Challenge.vue"),
},
{
path: "user-manage/:page",

View File

@@ -5,6 +5,7 @@ export const submission = ref<SubmissionAll>({
id: "",
userid: 0,
username: "",
task_id: 0,
task_title: "",
task_type: "tutorial",
score: 0.0,

View File

@@ -1,3 +1,5 @@
import { ref } from "vue"
import { TASK_TYPE } from "../utils/const"
export const taskTab = ref(TASK_TYPE.Tutorial)
export const taskId = ref(0)

View File

@@ -1,8 +1,6 @@
import { ref } from "vue"
import { useStorage } from "@vueuse/core"
import { STORAGE_KEY } from "../utils/const"
export const step = useStorage(STORAGE_KEY.STEP, 1)
export const step = ref(1)
export const show = ref(true)
export const tutorialSize = ref(2 / 5)

View File

@@ -28,8 +28,6 @@ export const alertVariants = [
export const STORAGE_KEY = {
LOGIN: "web-isloggedin",
STEP: "web-turtorial-step",
CONTENT: "web-turtorial-content",
HTML: "web-html",
CSS: "web-css",
JS: "web-js",
@@ -46,3 +44,13 @@ export const BASE_URL =
import.meta.env.MODE === "development"
? "http://localhost:8000/api"
: "https://web.xuyue.cc/api"
export enum TASK_TYPE {
Tutorial = "tutorial",
Challenge = "challenge",
}
export const TASK_LABEL = {
[TASK_TYPE.Tutorial]: "教程",
[TASK_TYPE.Challenge]: "挑战",
} as const

View File

@@ -53,6 +53,7 @@ export interface SubmissionAll {
id: string
userid: number
username: string
task_id: number
task_type: string
task_title: string
score: number