feat(router): 添加路由配置并重构页面结构

This commit is contained in:
cc 2026-03-19 10:49:19 +08:00
parent 802b39baa5
commit d0993a2ef4
10 changed files with 2240 additions and 298 deletions

452
package-lock.json generated
View File

@ -8,13 +8,30 @@
"name": "ai-demo",
"version": "0.0.0",
"dependencies": {
"vue": "^3.5.30"
"vue": "^3.5.30",
"vue-router": "^5.0.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.5",
"vite": "^8.0.0"
}
},
"node_modules/@babel/generator": {
"version": "7.29.1",
"resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz",
"integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.0",
"@babel/types": "^7.29.0",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
@ -95,12 +112,51 @@
"tslib": "^2.4.0"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/remapping": {
"version": "2.3.5",
"resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
@ -428,6 +484,33 @@
"vue": "^3.2.25"
}
},
"node_modules/@vue-macros/common": {
"version": "3.1.2",
"resolved": "https://registry.npmmirror.com/@vue-macros/common/-/common-3.1.2.tgz",
"integrity": "sha512-h9t4ArDdniO9ekYHAD95t9AZcAbb19lEGK+26iAjUODOIJKmObDNBSe4+6ELQAA3vtYiFPPBtHh7+cQCKi3Dng==",
"license": "MIT",
"dependencies": {
"@vue/compiler-sfc": "^3.5.22",
"ast-kit": "^2.1.2",
"local-pkg": "^1.1.2",
"magic-string-ast": "^1.0.2",
"unplugin-utils": "^0.3.0"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/sponsors/vue-macros"
},
"peerDependencies": {
"vue": "^2.7.0 || ^3.2.25"
},
"peerDependenciesMeta": {
"vue": {
"optional": true
}
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.30",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.30.tgz",
@ -478,6 +561,33 @@
"@vue/shared": "3.5.30"
}
},
"node_modules/@vue/devtools-api": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-8.1.0.tgz",
"integrity": "sha512-O44X57jjkLKbLEc4OgL/6fEPOOanRJU8kYpCE8qfKlV96RQZcdzrcLI5mxMuVRUeXhHKIHGhCpHacyCk0HyO4w==",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^8.1.0"
}
},
"node_modules/@vue/devtools-kit": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.1.0.tgz",
"integrity": "sha512-/NZlS4WtGIB54DA/z10gzk+n/V7zaqSzYZOVlg2CfdnpIKdB61bd7JDIMxf/zrtX41zod8E2/bbEBoW/d7x70Q==",
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^8.1.0",
"birpc": "^2.6.1",
"hookable": "^5.5.3",
"perfect-debounce": "^2.0.0"
}
},
"node_modules/@vue/devtools-shared": {
"version": "8.1.0",
"resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-8.1.0.tgz",
"integrity": "sha512-h8uCb4Qs8UT8VdTT5yjY6tOJ//qH7EpxToixR0xqejR55t5OdISIg7AJ7eBkhBs8iu1qG5gY3QQNN1DF1EelAA==",
"license": "MIT"
},
"node_modules/@vue/reactivity": {
"version": "3.5.30",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.30.tgz",
@ -528,6 +638,80 @@
"integrity": "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ==",
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.16.0",
"resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ast-kit": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/ast-kit/-/ast-kit-2.2.0.tgz",
"integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.5",
"pathe": "^2.0.3"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/ast-walker-scope": {
"version": "0.8.3",
"resolved": "https://registry.npmmirror.com/ast-walker-scope/-/ast-walker-scope-0.8.3.tgz",
"integrity": "sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.4",
"ast-kit": "^2.1.3"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/birpc": {
"version": "2.9.0",
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz",
"integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/chokidar": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz",
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"license": "MIT",
"dependencies": {
"readdirp": "^5.0.0"
},
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/confbox": {
"version": "0.2.4",
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.2.4.tgz",
"integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
@ -562,11 +746,16 @@
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"license": "MIT"
},
"node_modules/exsolve": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/exsolve/-/exsolve-1.0.8.tgz",
"integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==",
"license": "MIT"
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
@ -595,6 +784,36 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"license": "MIT"
},
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
"node": ">=6"
}
},
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"license": "MIT",
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/lightningcss": {
"version": "1.32.0",
"resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.32.0.tgz",
@ -856,6 +1075,23 @@
"url": "https://opencollective.com/parcel"
}
},
"node_modules/local-pkg": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.1.2.tgz",
"integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==",
"license": "MIT",
"dependencies": {
"mlly": "^1.7.4",
"pkg-types": "^2.3.0",
"quansync": "^0.2.11"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
@ -865,6 +1101,56 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/magic-string-ast": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/magic-string-ast/-/magic-string-ast-1.0.3.tgz",
"integrity": "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==",
"license": "MIT",
"dependencies": {
"magic-string": "^0.30.19"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/mlly": {
"version": "1.8.1",
"resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.8.1.tgz",
"integrity": "sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==",
"license": "MIT",
"dependencies": {
"acorn": "^8.16.0",
"pathe": "^2.0.3",
"pkg-types": "^1.3.1",
"ufo": "^1.6.3"
}
},
"node_modules/mlly/node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"license": "MIT"
},
"node_modules/mlly/node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.1.tgz",
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
"license": "MIT",
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.4",
"pathe": "^2.0.1"
}
},
"node_modules/muggle-string": {
"version": "0.4.1",
"resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz",
"integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
@ -883,6 +1169,18 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz",
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"license": "MIT"
},
"node_modules/perfect-debounce": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-2.1.0.tgz",
"integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==",
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@ -893,7 +1191,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
@ -902,6 +1199,17 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pkg-types": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-2.3.0.tgz",
"integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
"license": "MIT",
"dependencies": {
"confbox": "^0.2.2",
"exsolve": "^1.0.7",
"pathe": "^2.0.3"
}
},
"node_modules/postcss": {
"version": "8.5.8",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz",
@ -930,6 +1238,35 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/quansync": {
"version": "0.2.11",
"resolved": "https://registry.npmmirror.com/quansync/-/quansync-0.2.11.tgz",
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/antfu"
},
{
"type": "individual",
"url": "https://github.com/sponsors/sxzz"
}
],
"license": "MIT"
},
"node_modules/readdirp": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz",
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
"license": "MIT",
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/rolldown": {
"version": "1.0.0-rc.9",
"resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.0.0-rc.9.tgz",
@ -971,6 +1308,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/scule": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"license": "MIT"
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
@ -984,7 +1327,6 @@
"version": "0.2.15",
"resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
@ -1005,6 +1347,42 @@
"license": "0BSD",
"optional": true
},
"node_modules/ufo": {
"version": "1.6.3",
"resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.6.3.tgz",
"integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==",
"license": "MIT"
},
"node_modules/unplugin": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-3.0.0.tgz",
"integrity": "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==",
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.5",
"picomatch": "^4.0.3",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/unplugin-utils": {
"version": "0.3.1",
"resolved": "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.3.1.tgz",
"integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==",
"license": "MIT",
"dependencies": {
"pathe": "^2.0.3",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/sponsors/sxzz"
}
},
"node_modules/vite": {
"version": "8.0.0",
"resolved": "https://registry.npmmirror.com/vite/-/vite-8.0.0.tgz",
@ -1104,6 +1482,72 @@
"optional": true
}
}
},
"node_modules/vue-router": {
"version": "5.0.3",
"resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-5.0.3.tgz",
"integrity": "sha512-nG1c7aAFac7NYj8Hluo68WyWfc41xkEjaR0ViLHCa3oDvTQ/nIuLJlXJX1NUPw/DXzx/8+OKMng045HHQKQKWw==",
"license": "MIT",
"dependencies": {
"@babel/generator": "^7.28.6",
"@vue-macros/common": "^3.1.1",
"@vue/devtools-api": "^8.0.6",
"ast-walker-scope": "^0.8.3",
"chokidar": "^5.0.0",
"json5": "^2.2.3",
"local-pkg": "^1.1.2",
"magic-string": "^0.30.21",
"mlly": "^1.8.0",
"muggle-string": "^0.4.1",
"pathe": "^2.0.3",
"picomatch": "^4.0.3",
"scule": "^1.3.0",
"tinyglobby": "^0.2.15",
"unplugin": "^3.0.0",
"unplugin-utils": "^0.3.1",
"yaml": "^2.8.2"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@pinia/colada": ">=0.21.2",
"@vue/compiler-sfc": "^3.5.17",
"pinia": "^3.0.4",
"vue": "^3.5.0"
},
"peerDependenciesMeta": {
"@pinia/colada": {
"optional": true
},
"@vue/compiler-sfc": {
"optional": true
},
"pinia": {
"optional": true
}
}
},
"node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"license": "MIT"
},
"node_modules/yaml": {
"version": "2.8.2",
"resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.2.tgz",
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
}
}
}

View File

@ -9,7 +9,8 @@
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.5.30"
"vue": "^3.5.30",
"vue-router": "^5.0.3"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.5",

View File

@ -1,116 +1,7 @@
<script setup>
import { ref, onMounted } from 'vue'
const features = ref([
{
id: 1,
title: 'AI听力考试音频生成',
desc: '基于先进TTS技术根据文本快速合成全真模拟的英语听力考试音频。',
class: 'card-1',
icon: 'audio',
url: 'https://jz5k88k7vv.coze.site'
},
{
id: 2,
title: 'AI口语对话',
desc: '全天候1对1外教级对练实时纠正发音与语法快速提升口语表达。',
class: 'card-2',
icon: 'mic'
},
{
id: 3,
title: 'AI作文原图批改',
desc: '一键上传手写作文图片AI智能OCR识别并提供词汇、语法深度批改。',
class: 'card-3',
icon: 'edit'
},
{
id: 4,
title: '英语试题AI分析',
desc: '深度解析长难句、阅读理解及语法考点,为您提供专属错题讲解。',
class: 'card-4',
icon: 'analytics'
},
{
id: 5,
title: 'AI单词听写',
desc: '自适应发音报词,智能追踪拼写薄弱点,让词汇记忆更高效。',
class: 'card-5',
icon: 'spell'
},
{
id: 6,
title: 'AI英语发音',
desc: '输入英语单词或长难句一键调用AI为您进行标准地道的语音朗读示范。',
class: 'card-6',
icon: 'speaker'
}
])
// Hover effect for glassmorphism glare
const handleMouseMove = (e) => {
const cards = document.querySelectorAll('.feature-card')
for (const card of cards) {
const rect = card.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
card.style.setProperty('--mouse-x', `${x}px`)
card.style.setProperty('--mouse-y', `${y}px`)
}
}
onMounted(() => {
document.getElementById('app').addEventListener('mousemove', handleMouseMove)
})
import HomePage from './components/HomePage.vue'
</script>
<template>
<header>
<h1>AI 英语学习辅助平台</h1>
<p class="subtitle">全方位智能化辅助让英语学习更加简单高效</p>
</header>
<main class="grid-container">
<a v-for="feature in features" :key="feature.id" :href="feature.url || '#'" :target="feature.url ? '_blank' : '_self'" class="feature-card" :class="feature.class">
<div class="icon-wrapper">
<!-- Audio Icon (Headphones) -->
<svg v-if="feature.icon === 'audio'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
</svg>
<!-- Mic Icon (Chat/Mic) -->
<svg v-else-if="feature.icon === 'mic'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z" />
</svg>
<!-- Edit Icon (Document Text / Pen) -->
<svg v-else-if="feature.icon === 'edit'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
</svg>
<!-- Analytics Icon (Chart/Sparkles) -->
<svg v-else-if="feature.icon === 'analytics'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
</svg>
<!-- Spell Icon (Book Open) -->
<svg v-else-if="feature.icon === 'spell'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25" />
</svg>
<!-- Speaker Icon (Megaphone/Speaker) -->
<svg v-else-if="feature.icon === 'speaker'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z" />
</svg>
</div>
<h2 class="card-title">{{ feature.title }}</h2>
<p class="card-desc">{{ feature.desc }}</p>
<svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
</svg>
</a>
</main>
<HomePage />
</template>

7
src/MainLayout.vue Normal file
View File

@ -0,0 +1,7 @@
<script setup>
import { RouterView } from 'vue-router'
</script>
<template>
<RouterView />
</template>

327
src/components/HomePage.vue Normal file
View File

@ -0,0 +1,327 @@
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const features = ref([
{
id: 1,
title: 'AI听力考试音频生成',
desc: '基于先进TTS技术根据文本快速合成全真模拟的英语听力考试音频。',
class: 'card-1',
icon: 'audio',
url: 'https://jz5k88k7vv.coze.site'
},
{
id: 2,
title: 'AI口语对话',
desc: '全天候1对1外教级对练实时纠正发音与语法快速提升口语表达。',
class: 'card-2',
icon: 'mic',
route: null
},
{
id: 3,
title: 'AI作文原图批改',
desc: '一键上传手写作文图片AI智能OCR识别并提供词汇、语法深度批改。',
class: 'card-3',
icon: 'edit',
route: null
},
{
id: 4,
title: '英语试题AI分析',
desc: '深度解析长难句、阅读理解及语法考点,为您提供专属错题讲解。',
class: 'card-4',
icon: 'analytics',
route: null
},
{
id: 5,
title: 'AI单词听写',
desc: '自适应发音报词,智能追踪拼写薄弱点,让词汇记忆更高效。',
class: 'card-5',
icon: 'spell',
route: null
},
{
id: 6,
title: 'AI英语发音',
desc: '输入英语单词或长难句一键调用AI为您进行标准地道的语音朗读示范。',
class: 'card-6',
icon: 'speaker',
route: '/pronunciation'
}
])
// Hover effect for glassmorphism glare
const handleMouseMove = (e) => {
const cards = document.querySelectorAll('.homepage-feature-card')
for (const card of cards) {
const rect = card.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
card.style.setProperty('--mouse-x', `${x}px`)
card.style.setProperty('--mouse-y', `${y}px`)
}
}
const handleCardClick = (feature) => {
if (feature.url) {
window.open(feature.url, '_blank')
} else if (feature.route) {
router.push(feature.route)
}
}
onMounted(() => {
const container = document.querySelector('.homepage-container')
if (container) {
container.addEventListener('mousemove', handleMouseMove)
}
})
onUnmounted(() => {
const container = document.querySelector('.homepage-container')
if (container) {
container.removeEventListener('mousemove', handleMouseMove)
}
})
</script>
<template>
<div class="homepage-container">
<header>
<h1>AI 英语学习辅助平台</h1>
<p class="subtitle">全方位智能化辅助让英语学习更加简单高效</p>
</header>
<main class="grid-container">
<div v-for="feature in features" :key="feature.id" @click="handleCardClick(feature)" class="homepage-feature-card" :class="feature.class">
<div class="icon-wrapper">
<!-- Audio Icon (Headphones) -->
<svg v-if="feature.icon === 'audio'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
</svg>
<!-- Mic Icon (Chat/Mic) -->
<svg v-else-if="feature.icon === 'mic'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z" />
</svg>
<!-- Edit Icon (Document Text / Pen) -->
<svg v-else-if="feature.icon === 'edit'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
</svg>
<!-- Analytics Icon (Chart/Sparkles) -->
<svg v-else-if="feature.icon === 'analytics'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
</svg>
<!-- Spell Icon (Book Open) -->
<svg v-else-if="feature.icon === 'spell'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25" />
</svg>
<!-- Speaker Icon (Megaphone/Speaker) -->
<svg v-else-if="feature.icon === 'speaker'" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z" />
</svg>
</div>
<h2 class="card-title">{{ feature.title }}</h2>
<p class="card-desc">{{ feature.desc }}</p>
<svg class="arrow-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
</svg>
</div>
</main>
</div>
</template>
<style scoped>
.homepage-container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 4rem 2rem;
box-sizing: border-box;
}
header {
text-align: center;
margin-bottom: 4rem;
}
h1 {
font-size: 3.5rem;
font-weight: 800;
letter-spacing: -0.05em;
margin: 0;
background: linear-gradient(135deg, #fff 0%, #a5b4fc 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 40px rgba(99, 102, 241, 0.3);
}
.subtitle {
font-size: 1.25rem;
color: #94a3b8;
margin-top: 1rem;
font-weight: 400;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 2rem;
}
.homepage-feature-card {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20px;
padding: 2.5rem 2rem;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
cursor: pointer;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
display: flex;
flex-direction: column;
align-items: flex-start;
text-decoration: none;
color: inherit;
}
.homepage-feature-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(800px circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(255, 255, 255, 0.06), transparent 40%);
opacity: 0;
transition: opacity 0.4s;
z-index: 1;
pointer-events: none;
}
.homepage-feature-card:hover::before {
opacity: 1;
}
.homepage-feature-card:hover {
transform: translateY(-8px);
background: rgba(255, 255, 255, 0.06);
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.5);
}
.icon-wrapper {
width: 60px;
height: 60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1.5rem;
font-size: 1.75rem;
color: #fff;
position: relative;
z-index: 2;
transition: transform 0.3s ease;
}
.homepage-feature-card:hover .icon-wrapper {
transform: scale(1.1) rotate(5deg);
}
.icon-wrapper svg {
width: 32px;
height: 32px;
}
/* Colors for specific cards */
.card-1 .icon-wrapper {
background: linear-gradient(135deg, #6366f1, #4f46e5);
box-shadow: 0 8px 20px -6px rgba(99, 102, 241, 0.5);
}
.card-2 .icon-wrapper {
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
box-shadow: 0 8px 20px -6px rgba(139, 92, 246, 0.5);
}
.card-3 .icon-wrapper {
background: linear-gradient(135deg, #ec4899, #db2777);
box-shadow: 0 8px 20px -6px rgba(236, 72, 153, 0.5);
}
.card-4 .icon-wrapper {
background: linear-gradient(135deg, #14b8a6, #0d9488);
box-shadow: 0 8px 20px -6px rgba(20, 184, 166, 0.5);
}
.card-5 .icon-wrapper {
background: linear-gradient(135deg, #f59e0b, #d97706);
box-shadow: 0 8px 20px -6px rgba(245, 158, 11, 0.5);
}
.card-6 .icon-wrapper {
background: linear-gradient(135deg, #ef4444, #dc2626);
box-shadow: 0 8px 20px -6px rgba(239, 68, 68, 0.5);
}
.card-title {
font-size: 1.5rem;
font-weight: 600;
margin: 0 0 0.75rem 0;
color: #f8fafc;
z-index: 2;
}
.card-desc {
font-size: 1rem;
color: #94a3b8;
line-height: 1.6;
margin: 0;
z-index: 2;
}
.arrow-icon {
position: absolute;
bottom: 2rem;
right: 2rem;
width: 24px;
height: 24px;
color: rgba(255, 255, 255, 0.2);
transition: all 0.3s ease;
z-index: 2;
}
.homepage-feature-card:hover .arrow-icon {
color: #fff;
transform: translateX(4px);
}
@media (max-width: 768px) {
h1 {
font-size: 2.5rem;
}
.homepage-container {
padding: 2rem 1rem;
}
.homepage-feature-card {
padding: 2rem 1.5rem;
}
}
</style>

View File

@ -1,5 +1,9 @@
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import MainLayout from './MainLayout.vue'
import router from './router'
createApp(App).mount('#app')
const app = createApp(MainLayout)
app.use(router)
app.mount('#app')

21
src/router/index.js Normal file
View File

@ -0,0 +1,21 @@
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../App.vue'
import Pronunciation from '../views/Pronunciation.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/pronunciation',
name: 'pronunciation',
component: Pronunciation
}
]
})
export default router

View File

@ -33,183 +33,4 @@ body {
-webkit-font-smoothing: antialiased;
}
#app {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 4rem 2rem;
box-sizing: border-box;
}
header {
text-align: center;
margin-bottom: 4rem;
}
h1 {
font-size: 3.5rem;
font-weight: 800;
letter-spacing: -0.05em;
margin: 0;
background: linear-gradient(135deg, #fff 0%, #a5b4fc 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 40px rgba(99, 102, 241, 0.3);
}
.subtitle {
font-size: 1.25rem;
color: var(--text-secondary);
margin-top: 1rem;
font-weight: 400;
}
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 2rem;
}
.feature-card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 20px;
padding: 2.5rem 2rem;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
cursor: pointer;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
display: flex;
flex-direction: column;
align-items: flex-start;
text-decoration: none;
color: inherit;
}
.feature-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(800px circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(255, 255, 255, 0.06), transparent 40%);
opacity: 0;
transition: opacity 0.4s;
z-index: 1;
pointer-events: none;
}
.feature-card:hover::before {
opacity: 1;
}
.feature-card:hover {
transform: translateY(-8px);
background: var(--card-hover-bg);
border-color: var(--card-hover-border);
box-shadow: 0 20px 40px -15px rgba(0, 0, 0, 0.5);
}
.icon-wrapper {
width: 60px;
height: 60px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 1.5rem;
font-size: 1.75rem;
color: #fff;
position: relative;
z-index: 2;
transition: transform 0.3s ease;
}
.feature-card:hover .icon-wrapper {
transform: scale(1.1) rotate(5deg);
}
.icon-wrapper svg {
width: 32px;
height: 32px;
}
/* Colors for specific cards */
.card-1 .icon-wrapper {
background: linear-gradient(135deg, var(--accent-1), #4f46e5);
box-shadow: 0 8px 20px -6px rgba(99, 102, 241, 0.5);
}
.card-2 .icon-wrapper {
background: linear-gradient(135deg, var(--accent-2), #7c3aed);
box-shadow: 0 8px 20px -6px rgba(139, 92, 246, 0.5);
}
.card-3 .icon-wrapper {
background: linear-gradient(135deg, var(--accent-3), #db2777);
box-shadow: 0 8px 20px -6px rgba(236, 72, 153, 0.5);
}
.card-4 .icon-wrapper {
background: linear-gradient(135deg, var(--accent-4), #0d9488);
box-shadow: 0 8px 20px -6px rgba(20, 184, 166, 0.5);
}
.card-5 .icon-wrapper {
background: linear-gradient(135deg, var(--accent-5), #d97706);
box-shadow: 0 8px 20px -6px rgba(245, 158, 11, 0.5);
}
.card-6 .icon-wrapper {
background: linear-gradient(135deg, var(--accent-6), #dc2626);
box-shadow: 0 8px 20px -6px rgba(239, 68, 68, 0.5);
}
.card-title {
font-size: 1.5rem;
font-weight: 600;
margin: 0 0 0.75rem 0;
color: #f8fafc;
z-index: 2;
}
.card-desc {
font-size: 1rem;
color: var(--text-secondary);
line-height: 1.6;
margin: 0;
z-index: 2;
}
.arrow-icon {
position: absolute;
bottom: 2rem;
right: 2rem;
width: 24px;
height: 24px;
color: rgba(255, 255, 255, 0.2);
transition: all 0.3s ease;
z-index: 2;
}
.feature-card:hover .arrow-icon {
color: #fff;
transform: translateX(4px);
}
@media (max-width: 768px) {
h1 {
font-size: 2.5rem;
}
#app {
padding: 2rem 1rem;
}
.feature-card {
padding: 2rem 1.5rem;
}
}
/* App-wide styles only - component-specific styles should be defined in component scoped styles */

1417
src/views/Pronunciation.vue Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,4 +4,13 @@ import vue from '@vitejs/plugin-vue'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/tts-api': {
target: 'https://openspeech.bytedance.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/tts-api/, '')
}
}
}
})