diff --git a/$null b/$null deleted file mode 100644 index 32eecff..0000000 --- a/$null +++ /dev/null @@ -1 +0,0 @@ -mysql: [Warning] Using a password on the command line interface can be insecure. diff --git a/contact_screenshot.png b/contact_screenshot.png deleted file mode 100644 index e37f554..0000000 Binary files a/contact_screenshot.png and /dev/null differ diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/website/.vscode/extensions.json b/website/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/website/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000..33895ab --- /dev/null +++ b/website/README.md @@ -0,0 +1,5 @@ +# Vue 3 + TypeScript + Vite + +This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` + + diff --git a/website/package-lock.json b/website/package-lock.json new file mode 100644 index 0000000..9e87f3b --- /dev/null +++ b/website/package-lock.json @@ -0,0 +1,1729 @@ +{ + "name": "website", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "website", + "version": "0.0.0", + "dependencies": { + "vue": "^3.5.42", + "vue-router": "^4.6.4", + "vuex": "^4.0.2" + }, + "devDependencies": { + "@types/node": "^24.13.3", + "@vitejs/plugin-vue": "^6.0.8", + "@vue/tsconfig": "^0.9.1", + "amfe-flexible": "^2.2.1", + "autoprefixer": "^10.6.0", + "less": "^4.9.1", + "less-loader": "^12.3.3", + "postcss-pxtorem": "^6.1.0", + "typescript": "~6.0.2", + "vite": "^8.3.0", + "vue-tsc": "^3.3.11" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@oxc-project/types": { + "version": "0.149.0", + "resolved": "https://registry.npmmirror.com/@oxc-project/types/-/types-0.149.0.tgz", + "integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz", + "integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz", + "integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz", + "integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz", + "integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz", + "integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz", + "integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz", + "integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz", + "integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz", + "integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz", + "integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz", + "integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz", + "integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz", + "integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz", + "integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz", + "integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.4", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.13.4.tgz", + "integrity": "sha512-YJ7EqCstVTzIr0fMr7qul/977en+pQHrfmuKIo6Zr9i75Be21dr3MovcfvGtyvi2HAUrRerWps5sMO9I7WaxDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.9", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.9.tgz", + "integrity": "sha512-rD/MORlhaZMlXWW0rEn4FB4wMinWC0z/D7Ye160S5+Rs1mC8ZDAdcDp4SjKfUhG5t8q1ktcPVw4xuTkPRlzrSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.42.tgz", + "integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.42", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz", + "integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz", + "integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.42", + "@vue/compiler-dom": "3.5.42", + "@vue/compiler-ssr": "3.5.42", + "@vue/shared": "3.5.42", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz", + "integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-3.3.11.tgz", + "integrity": "sha512-QJmpliwAVpC/OxubIByPAhNzsQPRc8/gxlN2qnVzVfIMjMDz/9RnXRFoetjz5yEgXVXyp4LqhXq3V53PjmNzFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.1", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.42.tgz", + "integrity": "sha512-TzNNfKpb7hDxbQltwAut8VDQA5YP+BuRlxntHUuRjyKwlMvmAPbs3unhCvieijifY6vFfVBwsS7wG/C7uq+bEQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.42.tgz", + "integrity": "sha512-9uACtuHs7vJGkm5Bp3xu4xRDLFTIYy5DgxpToVjqGIAhAEKwQfsaLvKINhM6nFVp6bZPRFGdDqd1g52MqKsotA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.42.tgz", + "integrity": "sha512-rsCmhiWLaRxGltLwhlCWyYkFn7WAbKRh0q17eZ1A6Dq6eqc2ACQ61IIryxz0LrsvCzHSilLA9JHovVwM8CNE2g==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.42", + "@vue/runtime-core": "3.5.42", + "@vue/shared": "3.5.42", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.42.tgz", + "integrity": "sha512-2++5dUyYS4gvo7xQXSECUDhB7TS0aOl5SeVfC5qSq1Jgfhjvegw1zqhwTIR3imZ+QYPJQw9gfcFvXGAjGZ7ajQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.42", + "@vue/runtime-dom": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.42.tgz", + "integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.9.1", + "resolved": "https://registry.npmmirror.com/@vue/tsconfig/-/tsconfig-0.9.1.tgz", + "integrity": "sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 5.8", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/amfe-flexible": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/amfe-flexible/-/amfe-flexible-2.2.1.tgz", + "integrity": "sha512-L2VfvDzoETBjhRptg5u/IUuzHSuxm22JpSRb404p/TBGeRfwWmmNEbB+TFPIP/sS/+pbM18bCFH9QnMojLuPNw==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.6.0.tgz", + "integrity": "sha512-A26d6qs9kqGgkmImIXMYvXTzqb4Qv7AVgpY1NXzr9Y659J8qHHnLOO/zE8ewIGFMprOolAoRAQYDgNryXIJKBw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.9", + "caniuse-lite": "^1.0.30001810", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.23", + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.23.tgz", + "integrity": "sha512-le521dGVfxM7yRX0EikCoSz+rOK+hHzdDt/E7mG1jOJB/6WAAUuwVroLwaB7ApaUsz5Q0kFlDXLSA9MheUIfRQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.9", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.9.tgz", + "integrity": "sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.20", + "caniuse-lite": "^1.0.30001810", + "electron-to-chromium": "^1.5.420", + "node-releases": "^2.0.54", + "update-browserslist-db": "^1.3.2" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.427", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.427.tgz", + "integrity": "sha512-n14zb3FdsChZ2BNobqNHAJMcP3ifFv4paox2LvCrfVAQcqGiSURgbJl+PfMpHVCNFkStnNc+RRVtPBTVW5PDgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "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" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/less": { + "version": "4.9.1", + "resolved": "https://registry.npmmirror.com/less/-/less-4.9.1.tgz", + "integrity": "sha512-orp15PfJvvNDIqJdVWzMI9Sjpjp3VTiw3sfvbB+67LlISTEn8uVT2EdYSuyl02BLvaftv6sdk9Umnxmm5rckmg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "copy-anything": "^3.0.5", + "parse-node-version": "^1.0.1" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "make-dir": "^5.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "probe-image-size": "^7.2.3", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "12.3.3", + "resolved": "https://registry.npmmirror.com/less-loader/-/less-loader-12.3.3.tgz", + "integrity": "sha512-F0+ErFFDj3Pt+nVrCN6VlEGEzocv9s7x/aR9v2riI+WM83UAfTYBDBjGPJnT55lBLR6JSI4fmWblt+aA2JN6/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmmirror.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-5.1.0.tgz", + "integrity": "sha512-IfpFq6UM39dUNiphpA6uDezNx/AvWyhwfICWPR3t1VspkgkMZrL+Rk1RbN1bx+aeNYwOrqGJgEgV3yotk+ZUVw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.19", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/needle": { + "version": "3.5.0", + "resolved": "https://registry.npmmirror.com/needle/-/needle-3.5.0.tgz", + "integrity": "sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/node-releases": { + "version": "2.0.55", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.55.tgz", + "integrity": "sha512-mIrE/Cw9y+9Au6dS5vDKDhQza9YvG6w+ZrS6X+ZzA7yFW/soAeaups4Qzn1bL6g5FVy8WtP79+0j82oPIbqRjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-pxtorem": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/postcss-pxtorem/-/postcss-pxtorem-6.1.0.tgz", + "integrity": "sha512-ROODSNci9ADal3zUcPHOF/K83TiCgNSPXQFSbwyPHNV8ioHIE4SaC+FPOufd8jsr5jV2uIz29v1Uqy1c4ov42g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/probe-image-size": { + "version": "7.4.0", + "resolved": "https://registry.npmmirror.com/probe-image-size/-/probe-image-size-7.4.0.tgz", + "integrity": "sha512-cdEprVtZxV+awMde9X+4jILBFYh4CARxVrQaMl4wY4YcPWbul9jntXrIW95NInBDyJwcVUP3U0T6yukN8rMBaQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "lodash.merge": "^4.6.2", + "needle": "^2.5.2", + "stream-parser": "~0.3.1" + } + }, + "node_modules/probe-image-size/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/probe-image-size/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/probe-image-size/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/probe-image-size/node_modules/needle": { + "version": "2.9.1", + "resolved": "https://registry.npmmirror.com/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/rolldown": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/rolldown/-/rolldown-1.2.8.tgz", + "integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.149.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.8", + "@rolldown/binding-android-arm64": "1.2.8", + "@rolldown/binding-darwin-arm64": "1.2.8", + "@rolldown/binding-darwin-x64": "1.2.8", + "@rolldown/binding-freebsd-x64": "1.2.8", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", + "@rolldown/binding-linux-arm64-gnu": "1.2.8", + "@rolldown/binding-linux-arm64-musl": "1.2.8", + "@rolldown/binding-linux-ppc64-gnu": "1.2.8", + "@rolldown/binding-linux-s390x-gnu": "1.2.8", + "@rolldown/binding-linux-x64-gnu": "1.2.8", + "@rolldown/binding-linux-x64-musl": "1.2.8", + "@rolldown/binding-openharmony-arm64": "1.2.8", + "@rolldown/binding-win32-arm64-msvc": "1.2.8", + "@rolldown/binding-win32-x64-msvc": "1.2.8" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/stream-parser/-/stream-parser-0.3.1.tgz", + "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "2" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz", + "integrity": "sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/vite/-/vite-8.3.0.tgz", + "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.28", + "rolldown": "~1.2.6", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.7.1", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.2.0.tgz", + "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.42.tgz", + "integrity": "sha512-4RyHQTbQvOPs3MfvUO1Sg0YRrKNnA0mAVtvpd12Tg1fKDN7OHBUl1IqSn8zGJjK9nI3NkNp8cgTpVrSZC5TTcA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.42", + "@vue/compiler-sfc": "3.5.42", + "@vue/runtime-dom": "3.5.42", + "@vue/server-renderer": "3.5.42", + "@vue/shared": "3.5.42" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-tsc": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-3.3.11.tgz", + "integrity": "sha512-gOb0B9rtU2+f1dszwPqSH5kAieIF9ReeLhD3kSRNHv5WZZUQz/JdVXW0RTdqhNTMlQkqKzrTTviqKr/4FYZraQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.11" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/vuex": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.0.2.tgz", + "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.0.2" + } + } + } +} diff --git a/website/package.json b/website/package.json new file mode 100644 index 0000000..ef74a9b --- /dev/null +++ b/website/package.json @@ -0,0 +1,29 @@ +{ + "name": "website", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.5.42", + "vue-router": "^4.6.4", + "vuex": "^4.0.2" + }, + "devDependencies": { + "@types/node": "^24.13.3", + "@vitejs/plugin-vue": "^6.0.8", + "@vue/tsconfig": "^0.9.1", + "amfe-flexible": "^2.2.1", + "autoprefixer": "^10.6.0", + "less": "^4.9.1", + "less-loader": "^12.3.3", + "postcss-pxtorem": "^6.1.0", + "typescript": "~6.0.2", + "vite": "^8.3.0", + "vue-tsc": "^3.3.11" + } +} diff --git a/website/postcss.config.cjs b/website/postcss.config.cjs new file mode 100644 index 0000000..84eaa88 --- /dev/null +++ b/website/postcss.config.cjs @@ -0,0 +1,9 @@ +// postcss.config.cjs +// 说明:package.json 中声明了 "type": "module",因此 PostCSS 配置需使用 .cjs 后缀 +module.exports = { + plugins: { + autoprefixer: { + overrideBrowserslist: ["> 0.5%", "last 2 versions", "not dead"], + }, + }, +}; diff --git a/website/public/favicon.svg b/website/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/website/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/public/icons.svg b/website/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/website/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/src/App.vue b/website/src/App.vue new file mode 100644 index 0000000..a38cf33 --- /dev/null +++ b/website/src/App.vue @@ -0,0 +1,7 @@ + + + diff --git a/website/src/api/content.ts b/website/src/api/content.ts new file mode 100644 index 0000000..6d04d28 --- /dev/null +++ b/website/src/api/content.ts @@ -0,0 +1,120 @@ +import type { + ContentItem, + ListQuery, + ListResult, + SectionKey, + SinglePage, +} from "@/types/content"; +import { products } from "@/data/products"; +import { solutions } from "@/data/solutions"; +import { cases } from "@/data/cases"; +import { news } from "@/data/news"; +import { events } from "@/data/events"; +import { singlePages } from "@/data/pages"; + +/** + * 内容数据访问层 + * 目前读取本地 mock 数据,接入后端 CMS 后只需把下面几个方法 + * 换成 request.get("/cms/...") 即可,调用方无需改动。 + */ + +const registry: Record = { + news, + products, + solutions, + cases, + events, +}; + +/** 模拟一次异步请求,保证调用方始终按异步处理 */ +const tick = () => new Promise((resolve) => setTimeout(resolve, 0)); + +/** 列表 / 分类 / 搜索(带分页) */ +export async function fetchList(query: ListQuery): Promise { + await tick(); + + const { section, category, keyword, page = 1, pageSize = 6 } = query; + let list = [...(registry[section] ?? [])]; + + if (category) { + list = list.filter((item) => item.category === category); + } + + const kw = keyword?.trim().toLowerCase(); + if (kw) { + list = list.filter((item) => + [item.title, item.subtitle, item.summary, ...(item.tags ?? [])] + .join(" ") + .toLowerCase() + .includes(kw) + ); + } + + list.sort((a, b) => (b.date ?? "").localeCompare(a.date ?? "")); + + const total = list.length; + const totalPages = Math.max(1, Math.ceil(total / pageSize)); + const safePage = Math.min(Math.max(1, page), totalPages); + const start = (safePage - 1) * pageSize; + + return { + list: list.slice(start, start + pageSize), + total, + page: safePage, + pageSize, + totalPages, + }; +} + +/** 详情 */ +export async function fetchDetail( + section: SectionKey, + slug: string +): Promise { + await tick(); + return (registry[section] ?? []).find((item) => item.slug === slug); +} + +/** 相关推荐:同分类优先,不足时用同栏目其它内容补齐 */ +export async function fetchRelated( + section: SectionKey, + slug: string, + limit = 3 +): Promise { + await tick(); + + const all = registry[section] ?? []; + const current = all.find((item) => item.slug === slug); + if (!current) return all.slice(0, limit); + + const sameCategory = all.filter( + (item) => item.slug !== slug && item.category === current.category + ); + const others = all.filter( + (item) => item.slug !== slug && item.category !== current.category + ); + + return [...sameCategory, ...others].slice(0, limit); +} + +/** 统计各分类下的内容数量,用于筛选条上的角标 */ +export async function fetchCategoryCounts( + section: SectionKey +): Promise> { + await tick(); + + const counts: Record = {}; + (registry[section] ?? []).forEach((item) => { + counts[item.category] = (counts[item.category] ?? 0) + 1; + }); + counts.__all__ = (registry[section] ?? []).length; + return counts; +} + +/** 单页:key 为去掉前导斜杠的路径,例如 about、support/docs */ +export async function fetchSinglePage( + key: string +): Promise { + await tick(); + return singlePages[key]; +} diff --git a/website/src/assets/images/hero-cover.svg b/website/src/assets/images/hero-cover.svg new file mode 100644 index 0000000..5f3c791 --- /dev/null +++ b/website/src/assets/images/hero-cover.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/src/assets/images/news-cover.svg b/website/src/assets/images/news-cover.svg new file mode 100644 index 0000000..a7bbb4c --- /dev/null +++ b/website/src/assets/images/news-cover.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/src/components/AppIcon.vue b/website/src/components/AppIcon.vue new file mode 100644 index 0000000..319b5db --- /dev/null +++ b/website/src/components/AppIcon.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/website/src/components/BlockRenderer.vue b/website/src/components/BlockRenderer.vue new file mode 100644 index 0000000..c2c2bfe --- /dev/null +++ b/website/src/components/BlockRenderer.vue @@ -0,0 +1,593 @@ + + + + + diff --git a/website/src/components/ContentCard.vue b/website/src/components/ContentCard.vue new file mode 100644 index 0000000..1594cac --- /dev/null +++ b/website/src/components/ContentCard.vue @@ -0,0 +1,284 @@ + + + + + diff --git a/website/src/components/FilterBar.vue b/website/src/components/FilterBar.vue new file mode 100644 index 0000000..28d7bc2 --- /dev/null +++ b/website/src/components/FilterBar.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/website/src/components/PageHero.vue b/website/src/components/PageHero.vue new file mode 100644 index 0000000..482ecb3 --- /dev/null +++ b/website/src/components/PageHero.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/website/src/components/PagerBar.vue b/website/src/components/PagerBar.vue new file mode 100644 index 0000000..38ef4a8 --- /dev/null +++ b/website/src/components/PagerBar.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/website/src/config/sections.ts b/website/src/config/sections.ts new file mode 100644 index 0000000..f310836 --- /dev/null +++ b/website/src/config/sections.ts @@ -0,0 +1,123 @@ +import type { Category, SectionKey } from "@/types/content"; + +export interface SectionConfig { + key: SectionKey; + title: string; + subtitle: string; + /** 列表页路径 */ + basePath: string; + /** 详情页路径前缀 */ + detailPath: string; + /** 分类页路径前缀 */ + categoryPath: string; + /** 计数单位 */ + unit: string; + /** 列表布局:list = 横向大卡;grid = 竖向卡片网格 */ + layout: "list" | "grid"; + /** 是否提供关键字搜索 */ + searchable: boolean; + categories: Category[]; +} + +export const sections: Record = { + news: { + key: "news", + title: "新闻中心", + subtitle: "了解云泽科技的产品动态、公司公告与行业活动。", + basePath: "/news", + detailPath: "/news/detail", + categoryPath: "/news/category", + unit: "条", + layout: "list", + searchable: true, + categories: [ + { slug: "company", name: "公司公告", desc: "融资、认证、人事与经营相关的官方信息。" }, + { slug: "product", name: "产品发布", desc: "版本更新、新功能上线与产品路线说明。" }, + { slug: "event", name: "市场活动", desc: "大会、公开课、巡展等线上线下活动。" }, + { slug: "case", name: "客户案例", desc: "各行业客户的落地实践与项目成果。" }, + ], + }, + products: { + key: "products", + title: "产品中心", + subtitle: "从云原生底座到数据智能应用,构建完整的产品矩阵。", + basePath: "/products", + detailPath: "/products/detail", + categoryPath: "/products/category", + unit: "款", + layout: "grid", + searchable: true, + categories: [ + { slug: "platform", name: "平台产品", desc: "支撑业务运行的底层技术平台。" }, + { slug: "data", name: "数据产品", desc: "数据采集、治理与分析类产品。" }, + { slug: "app", name: "应用产品", desc: "面向具体业务场景的智能应用。" }, + ], + }, + solutions: { + key: "solutions", + title: "解决方案", + subtitle: "面向重点行业的场景化方案,从诊断到落地全程陪跑。", + basePath: "/solutions", + detailPath: "/solutions/detail", + categoryPath: "/solutions/category", + unit: "套", + layout: "grid", + searchable: true, + categories: [ + { slug: "manufacturing", name: "制造业", desc: "离散与流程制造的生产数字化。" }, + { slug: "retail", name: "零售消费", desc: "会员、商品与门店的数据运营。" }, + { slug: "energy", name: "能源电力", desc: "设备状态监测与预测性维护。" }, + { slug: "finance", name: "金融", desc: "数据合规、风控与实时报表。" }, + ], + }, + cases: { + key: "cases", + title: "客户案例", + subtitle: "超过 1000 家企业客户,在这些场景里跑通了数字化。", + basePath: "/cases", + detailPath: "/cases/detail", + categoryPath: "/cases/category", + unit: "个", + layout: "grid", + searchable: true, + categories: [ + { slug: "manufacturing", name: "制造业", desc: "" }, + { slug: "retail", name: "零售消费", desc: "" }, + { slug: "energy", name: "能源电力", desc: "" }, + { slug: "finance", name: "金融", desc: "" }, + ], + }, + events: { + key: "events", + title: "市场活动", + subtitle: "大会、公开课与合作巡展,全年活动一站查看。", + basePath: "/events", + detailPath: "/events/detail", + categoryPath: "/events/category", + unit: "场", + layout: "list", + searchable: false, + categories: [ + { slug: "conference", name: "行业大会", desc: "" }, + { slug: "online", name: "线上直播", desc: "" }, + { slug: "offline", name: "线下活动", desc: "" }, + ], + }, +}; + +/** 从路由路径推断栏目:/news/detail/xxx -> news */ +export function sectionFromPath(path: string): SectionConfig | undefined { + const first = path.split("/").filter(Boolean)[0]; + return first && first in sections ? sections[first as SectionKey] : undefined; +} + +/** 查询某个分类的展示名 */ +export function categoryName( + section: SectionKey, + slug: string | undefined +): string { + if (!slug) return "全部"; + return ( + sections[section].categories.find((item) => item.slug === slug)?.name ?? "全部" + ); +} diff --git a/website/src/config/site.ts b/website/src/config/site.ts new file mode 100644 index 0000000..bd34df3 --- /dev/null +++ b/website/src/config/site.ts @@ -0,0 +1,73 @@ +/** + * 站点级公共配置:品牌、导航、页脚 + * 后续接入后端 CMS 时,只需替换此处的数据来源即可。 + */ + +export interface NavItem { + label: string; + path: string; +} + +export interface FooterColumn { + title: string; + links: NavItem[]; +} + +export const siteInfo = { + brandMark: "YZ", + brandName: "云泽科技", + brandSub: "YUNZER TECH", + fullName: "云泽科技有限公司", + slogan: "欢迎访问云泽科技官方网站", + phone: "400-000-0000", + email: "contact@yunzer.com", + address: "北京市海淀区中关村软件园 25 号楼", + postalCode: "100193", + copyright: + "COPYRIGHT (C) 2026 YUNZER TECHNOLOGY CO., LTD. ALL RIGHTS RESERVED.", +}; + +/** 顶部工具条链接 */ +export const utilityLinks: NavItem[] = [ + { label: "加入我们", path: "/careers" }, + { label: "客户支持", path: "/support" }, + { label: "合作伙伴", path: "/partners" }, +]; + +/** 主导航 */ +export const navItems: NavItem[] = [ + { label: "关于我们", path: "/about" }, + { label: "产品中心", path: "/products" }, + { label: "解决方案", path: "/solutions" }, + { label: "客户案例", path: "/cases" }, + { label: "新闻中心", path: "/news" }, +]; + +/** 页脚链接分组 */ +export const footerColumns: FooterColumn[] = [ + { + title: "产品与方案", + links: [ + { label: "云原生平台", path: "/products/detail/cloud-native" }, + { label: "数据中台", path: "/products/detail/data-platform" }, + { label: "智能分析引擎", path: "/products/detail/analytics" }, + { label: "行业解决方案", path: "/solutions" }, + ], + }, + { + title: "服务与支持", + links: [ + { label: "产品文档", path: "/support/docs" }, + { label: "开发者中心", path: "/support/developer" }, + { label: "申请试用", path: "/support/trial" }, + { label: "服务保障", path: "/support/sla" }, + ], + }, +]; + +/** 页脚底部合规链接 */ +export const policyLinks: NavItem[] = [ + { label: "隐私政策", path: "/policy/privacy" }, + { label: "使用条款", path: "/policy/terms" }, + { label: "网站地图", path: "/policy/sitemap" }, +]; diff --git a/website/src/data/cases.ts b/website/src/data/cases.ts new file mode 100644 index 0000000..b246616 --- /dev/null +++ b/website/src/data/cases.ts @@ -0,0 +1,241 @@ +import type { ContentItem } from "@/types/content"; + +export const cases: ContentItem[] = [ + { + slug: "manufacturing-group", + section: "cases", + category: "manufacturing", + title: "某大型制造集团", + subtitle: "生产数据一体化改造", + summary: + "覆盖 6 个厂区、1200 余台设备,设备数据采集覆盖率从 41% 提升至 96%。", + tone: "navy", + tags: ["制造业", "设备联网", "生产可视化"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "客户是国内领先的精密制造集团,旗下 6 个厂区、1200 余台设备分属 20 多个品牌。此前生产数据依赖人工抄录,日报在次日中午才能汇总完成,异常发现普遍滞后半天以上。", + }, + { type: "heading", text: "业务挑战" }, + { + type: "list", + items: [ + "设备协议不统一,20 多个品牌难以用同一套方案采集", + "生产日报依赖人工,数据滞后且口径不一致", + "异常停机平均 4 小时才被发现,损失难以估量", + "各厂区系统独立建设,集团层面看不到整体产能", + ], + }, + { type: "heading", text: "解决方案" }, + { + type: "features", + items: [ + { icon: "plug", title: "边缘统一采集", desc: "按产线部署边缘网关,屏蔽协议差异,本地缓存保证不断数。" }, + { icon: "monitor", title: "集团产能看板", desc: "6 个厂区共用一套指标口径,产能与在制品实时上墙。" }, + { icon: "shield", title: "异常自动预警", desc: "停机、节拍偏离与质量异常自动推送至班组与设备科。" }, + ], + }, + { type: "heading", text: "项目成果", sub: "上线 6 个月后的实测数据" }, + { + type: "stats", + items: [ + { value: "96%", label: "设备数据采集覆盖率" }, + { value: "-60%", label: "生产异常响应时长" }, + { value: "+18%", label: "设备综合效率(OEE)" }, + { value: "4 小时", label: "日报缩短为实时看板" }, + ], + }, + { + type: "quote", + text: "以前我们每天上午都在开会核对昨天的产量,现在数据是实时的,会议变成了讨论怎么改进。", + author: "信息中心主任 · 赵敏", + }, + ], + }, + { + slug: "retail-chain", + section: "cases", + category: "retail", + title: "某全国连锁零售", + subtitle: "会员数据中台建设", + summary: + "打通 3 个线上渠道与 800 家门店的会员数据,活动 ROI 提升 24%。", + tone: "teal", + tags: ["零售", "会员运营", "OneID"], + blocks: [ + { + type: "paragraph", + text: "客户在全国拥有 800 余家门店,同时经营小程序、电商旗舰店与社群渠道。会员数据分散在四个系统,同一顾客在不同渠道被识别为不同的人,营销活动只能在单渠道内做。", + }, + { type: "heading", text: "业务挑战" }, + { + type: "list", + items: [ + "跨渠道会员无法识别为同一人,权益与积分无法合并", + "标签体系缺失,活动只能面向全量人群投放", + "门店选品依赖经验,滞销与缺货同时存在", + ], + }, + { + type: "features", + items: [ + { icon: "users", title: "OneID 归一", desc: "以手机号为主键合并四个渠道的身份数据。" }, + { icon: "target", title: "标签与人群包", desc: "沉淀 300 余个标签,人群包一键推送至短信与企微。" }, + { icon: "chart", title: "门店经营分析", desc: "按门店、时段拆解客流与转化,支撑排班与选品调整。" }, + ], + }, + { + type: "stats", + items: [ + { value: "+18%", label: "会员复购率" }, + { value: "+24%", label: "活动 ROI" }, + { value: "-30%", label: "滞销库存占比" }, + ], + }, + { + type: "quote", + text: "现在我们做一场活动,先选人群再定商品,而不是先把商品发下去再想卖给谁。", + author: "数字化总监 · 刘鹏", + }, + ], + }, + { + slug: "energy-group", + section: "cases", + category: "energy", + title: "某能源集团", + subtitle: "设备预测性维护平台", + summary: + "为 380 台关键机组建立健康度模型,非计划停机时长下降 32%。", + tone: "indigo", + tags: ["能源", "预测性维护", "状态监测"], + blocks: [ + { + type: "paragraph", + text: "客户的 380 台关键机组分布在全国 12 个基地,此前采用固定周期检修。突发故障带来的非计划停机,每年造成的直接损失超过千万元。", + }, + { + type: "features", + items: [ + { icon: "monitor", title: "高频状态采集", desc: "振动、温度、电流等测点毫秒级采集,边缘侧初筛异常。" }, + { icon: "chart", title: "健康度模型", desc: "机理与数据双模型输出健康度评分与剩余寿命预估。" }, + { icon: "clipboard", title: "检修工单闭环", desc: "预警自动派单,处理结果回流用于模型迭代。" }, + ], + }, + { + type: "stats", + items: [ + { value: "-32%", label: "非计划停机时长" }, + { value: "-21%", label: "年度检修成本" }, + { value: "92%", label: "故障预警准确率" }, + ], + }, + { + type: "quote", + text: "过去是坏了才修,现在是系统告诉我们哪台该修了,检修计划终于能提前半个月排。", + author: "设备管理部负责人 · 陈建国", + }, + ], + }, + { + slug: "bank-risk", + section: "cases", + category: "finance", + title: "某股份制银行", + subtitle: "数据合规与实时风控", + summary: + "经营日报从 T+1 提升到分钟级,监管报送人工核对工作量下降 90%。", + tone: "blue", + tags: ["金融", "数据合规", "实时风控"], + blocks: [ + { + type: "paragraph", + text: "客户同时承担监管报送、内部风控与经营分析三类数据需求。此前三套体系各自建设,口径不一致,审计时需要投入大量人力整理台账。", + }, + { + type: "features", + items: [ + { icon: "shield", title: "数据血缘", desc: "任一指标可追溯至源系统字段,审计留痕自动生成。" }, + { icon: "clock", title: "实时指标", desc: "核心经营指标分钟级更新,支撑日内经营决策。" }, + { icon: "target", title: "风险双引擎", desc: "规则引擎与模型引擎并行,覆盖名单、阈值与图谱识别。" }, + ], + }, + { + type: "table", + head: ["指标", "改造前", "改造后"], + rows: [ + ["经营日报时效", "T+1 上午", "当日分钟级"], + ["监管报送核对", "5 人日 / 期", "0.5 人日 / 期"], + ["风险识别方式", "名单规则为主", "规则 + 模型 + 图谱"], + ], + }, + ], + }, + { + slug: "logistics-company", + section: "cases", + category: "retail", + title: "某头部物流企业", + subtitle: "智能调度与在途可视化", + summary: + "每天 1.2 万单的动态排线,单均运输成本下降 14%,时效达成率 98.6%。", + tone: "teal", + tags: ["物流", "路径优化", "时效履约"], + blocks: [ + { + type: "paragraph", + text: "客户日均处理 1.2 万张运单,调度依赖资深调度员的经验。旺季运力紧张时,排线质量波动明显,时效投诉随之上升。", + }, + { + type: "features", + items: [ + { icon: "target", title: "分钟级排线", desc: "综合时效、成本与装载率,分钟级输出可用方案。" }, + { icon: "monitor", title: "在途可视化", desc: "位置与温控数据实时回传,偏离路线自动预警。" }, + { icon: "clipboard", title: "人机协同", desc: "调度员可微调方案,调整结果回流持续优化模型。" }, + ], + }, + { + type: "stats", + items: [ + { value: "-14%", label: "单均运输成本" }, + { value: "+9%", label: "车辆装载率" }, + { value: "98.6%", label: "承诺时效达成率" }, + ], + }, + ], + }, + { + slug: "gov-platform", + section: "cases", + category: "finance", + title: "某市级政务平台", + subtitle: "数据共享与一网通办", + summary: + "完成 42 个部门的数据编目,一件事办理材料精简 60%。", + tone: "navy", + tags: ["政务", "数据共享", "一网通办"], + blocks: [ + { + type: "paragraph", + text: "该市在推进一网通办过程中遇到数据壁垒:部门之间不清楚彼此有哪些数据,跨部门办事仍需群众重复提交材料。", + }, + { + type: "features", + items: [ + { icon: "file", title: "统一数据目录", desc: "完成 42 个部门、1800 余项数据的编目与责任登记。" }, + { icon: "plug", title: "共享交换", desc: "库表、文件、接口三种方式按需调用,全程留痕。" }, + { icon: "users", title: "一件事办理", desc: "以事项为主线串联多部门,材料一次提交多次复用。" }, + ], + }, + { + type: "stats", + items: [ + { value: "42 个", label: "已编目部门" }, + { value: "-60%", label: "办事提交材料" }, + { value: "+55%", label: "一次办结率" }, + ], + }, + ], + }, +]; diff --git a/website/src/data/events.ts b/website/src/data/events.ts new file mode 100644 index 0000000..41c39dc --- /dev/null +++ b/website/src/data/events.ts @@ -0,0 +1,154 @@ +import type { ContentItem } from "@/types/content"; + +export const events: ContentItem[] = [ + { + slug: "data-platform-v3-trial", + section: "events", + category: "online", + title: "数据中台 V3.0 全量开放试用", + subtitle: "线上 · 9 月 10 日 - 9 月 30 日", + summary: + "面向全部客户开放试用,体验流批一体内核、统一指标中心与数据质量中心。", + tone: "blue", + date: "09.10 ~ 09.30", + tags: ["线上", "免费试用"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "数据中台 V3.0 全量开放试用。试用账号开通后可直接体验流批一体内核、统一指标中心与数据质量中心三项核心能力,我们同时提供 20 个行业示例数据集供直接使用。", + }, + { type: "heading", text: "活动亮点" }, + { + type: "list", + items: [ + "开箱即用的行业示例数据集,无需自备数据即可验证", + "完整功能开放,无功能裁剪与调用次数限制", + "试用期内配备专属技术支持,工作日 2 小时内响应", + "提交试用反馈可获得 V3.0 官方实施手册", + ], + }, + { + type: "table", + head: ["项目", "说明"], + rows: [ + ["活动时间", "2026.09.10 09:00 ~ 2026.09.30 18:00"], + ["参与形式", "线上,随时开始"], + ["参与对象", "企业客户与合作伙伴"], + ["报名方式", "提交试用申请,1 个工作日内开通账号"], + ], + }, + ], + }, + { + slug: "summit-2026", + section: "events", + category: "conference", + title: "2026 云泽数智大会 · 上海站", + subtitle: "线下 · 10 月 18 日 - 10 月 19 日", + summary: + "一个主论坛 + 四个行业分论坛 + 800㎡ 产品体验区,30 余位客户现场分享。", + tone: "navy", + date: "10.18 ~ 10.19", + tags: ["大会", "上海"], + blocks: [ + { + type: "paragraph", + text: "本届大会以「数智驱动 产业升级」为主题,设主论坛一个、行业分论坛四个,并在现场设置 800 平方米产品体验区。", + }, + { type: "heading", text: "日程概览" }, + { + type: "steps", + items: [ + { title: "10.18 上午 · 主论坛", desc: "年度产品路线图发布,三项重大能力升级同步揭晓。" }, + { title: "10.18 下午 · 分论坛", desc: "制造业与零售消费两个行业分论坛平行开讲。" }, + { title: "10.19 上午 · 分论坛", desc: "能源电力与金融两个行业分论坛平行开讲。" }, + { title: "10.19 下午 · 体验区", desc: "产品实操体验与一对一方案咨询,需提前预约时段。" }, + ], + }, + { + type: "table", + head: ["信息", "内容"], + rows: [ + ["举办时间", "2026.10.18 ~ 2026.10.19"], + ["举办地点", "上海 · 国家会展中心 3 号馆"], + ["参会费用", "免费,需审核通过"], + ["报名方式", "官网在线报名,名额限 1200 人"], + ], + }, + ], + }, + { + slug: "partner-city-tour", + section: "events", + category: "offline", + title: "全国合作伙伴城市巡展", + subtitle: "线下 · 11 月 5 日 - 11 月 28 日", + summary: + "覆盖 12 座城市,面向合作伙伴开放产品路线、政策解读与联合方案研讨。", + tone: "indigo", + date: "11.05 ~ 11.28", + tags: ["合作伙伴", "巡展"], + blocks: [ + { + type: "paragraph", + text: "本次巡展覆盖华东、华南、西南共 12 座城市,每站半天,内容包含产品路线解读、渠道政策说明与联合方案研讨。", + }, + { + type: "list", + items: [ + "产品路线:未来一年的产品规划与能力开放节奏", + "渠道政策:伙伴分级标准、返点规则与项目保护机制", + "联合方案:围绕区域重点行业打磨可复制的方案包", + "现场答疑:原厂售前与交付团队面对面沟通", + ], + }, + { + type: "table", + head: ["日期", "城市", "形式"], + rows: [ + ["11.05", "杭州", "线下闭门会"], + ["11.12", "广州", "线下闭门会"], + ["11.19", "成都", "线下闭门会"], + ["11.28", "线上", "全国同步直播"], + ], + }, + ], + }, + { + slug: "data-platform-open-class-sept", + section: "events", + category: "online", + title: "数据中台实战公开课 · 第二期", + subtitle: "线上直播 · 9 月 25 日 20:00", + summary: + "主题:实时计算任务如何做到稳定可控。由云泽产品总监主讲,含 20 分钟答疑。", + tone: "teal", + date: "09.25", + tags: ["公开课", "直播"], + blocks: [ + { + type: "paragraph", + text: "第二期公开课聚焦实时计算任务的稳定性问题。我们将结合三个真实故障案例,拆解任务延迟、数据倾斜与状态膨胀三类典型问题的排查与治理方法。", + }, + { type: "heading", text: "课程大纲" }, + { + type: "list", + items: [ + "实时任务的稳定性到底由哪些因素决定", + "任务延迟的三种常见成因与定位路径", + "数据倾斜与状态膨胀的工程化治理手段", + "上线前的检查清单与线上监控指标建议", + ], + }, + { + type: "contact", + items: [ + { icon: "clock", label: "直播时间", value: "2026 年 9 月 25 日 20:00 - 21:30" }, + { icon: "monitor", label: "直播平台", value: "官网直播间 / 视频号同步" }, + { icon: "phone", label: "咨询电话", value: "400-000-0000" }, + ], + }, + ], + }, +]; diff --git a/website/src/data/news.ts b/website/src/data/news.ts new file mode 100644 index 0000000..916ab6b --- /dev/null +++ b/website/src/data/news.ts @@ -0,0 +1,308 @@ +import type { ContentItem } from "@/types/content"; + +export const news: ContentItem[] = [ + { + slug: "series-b-financing", + section: "news", + category: "company", + title: "云泽科技完成新一轮战略融资,加速数据智能产品研发", + subtitle: "公司公告", + summary: + "本轮融资将主要用于数据智能平台的产品迭代、行业解决方案深化以及海外市场拓展。", + tone: "navy", + date: "2025.08.20", + author: "品牌公关部", + tags: ["融资", "公司动态"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "云泽科技今日宣布完成新一轮战略融资,由产业资本与老股东共同参与。本轮融资将主要用于三个方向:数据智能平台的产品迭代、重点行业解决方案的深化,以及海外市场的初步布局。", + }, + { + type: "paragraph", + text: "公司创始人表示,过去两年客户需求已经从「要不要做数字化」转变为「怎么做得更快更稳」,这要求厂商不只是提供工具,还要能陪着客户把数据真正用起来。", + }, + { type: "heading", text: "资金用途" }, + { + type: "list", + items: [ + "数据中台与智能分析产品的持续研发投入", + "制造业、零售、能源三个重点行业的方案沉淀", + "东南亚与中东市场的团队组建与本地化适配", + "客户成功体系建设,提升交付后的长期价值", + ], + }, + { + type: "quote", + text: "我们不追求把产品线铺得最宽,而是希望在自己擅长的三个行业里做到客户愿意推荐给同行。", + author: "云泽科技 创始人兼 CEO", + }, + ], + }, + { + slug: "data-platform-v3", + section: "news", + category: "product", + title: "云泽数据中台 V3.0 正式发布:全链路实时计算能力升级", + subtitle: "产品发布", + summary: + "新版本在实时计算、指标管理与数据资产治理三个方向进行了系统性重构。", + tone: "blue", + date: "2025.08.20", + author: "产品中心", + tags: ["数据中台", "版本发布"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "云泽数据中台 V3.0 今日正式发布。本次版本重构了实时计算内核,将流式与批量任务的开发、调度与运维统一到一个引擎中,端到端延迟可稳定控制在秒级。", + }, + { type: "heading", text: "主要更新" }, + { + type: "features", + items: [ + { icon: "clock", title: "流批一体内核", desc: "同一套 SQL 同时支持流式与批量任务,减少重复开发。" }, + { icon: "chart", title: "统一指标中心", desc: "指标定义、计算逻辑与权限集中维护,一处修改全局生效。" }, + { icon: "shield", title: "数据质量中心", desc: "内置 30 余种质量规则,异常自动阻断下游任务。" }, + { icon: "plug", title: "数据源扩展", desc: "新增支持 12 种数据源,累计覆盖 40 余种主流系统。" }, + ], + }, + { + type: "paragraph", + text: "已有客户可在控制台一键升级,V2.x 版本的作业定义保持兼容。升级前建议先在测试环境验证自定义插件。", + }, + ], + }, + { + slug: "summit-2026-shanghai", + section: "news", + category: "event", + title: "2026 云泽数智大会将于 10 月在上海举办,报名通道开启", + subtitle: "市场活动", + summary: + "本届大会以「数智驱动 产业升级」为主题,将邀请 30 余位行业客户分享落地实践。", + tone: "indigo", + date: "2025.08.18", + author: "市场部", + tags: ["大会", "报名"], + blocks: [ + { + type: "paragraph", + text: "2026 云泽数智大会将于 10 月 18 日至 19 日在上海国家会展中心举办。大会设一个主论坛与四个行业分论坛,现场另设 800 平方米的产品体验区。", + }, + { type: "heading", text: "大会亮点" }, + { + type: "list", + items: [ + "主论坛发布年度产品路线图与三项重大能力升级", + "制造业、零售、能源、金融四个行业分论坛同步开讲", + "30 余位客户现场分享项目踩坑经验与真实收益数据", + "产品体验区提供数据中台与边缘网关的现场实操", + ], + }, + { + type: "table", + head: ["时间", "议程", "地点"], + rows: [ + ["10.18 09:30", "开幕式与主论坛", "主会场"], + ["10.18 14:00", "制造业 / 零售分论坛", "平行会场 A / B"], + ["10.19 09:30", "能源 / 金融分论坛", "平行会场 A / B"], + ["10.19 14:00", "产品体验与一对一咨询", "体验区"], + ], + }, + ], + }, + { + slug: "manufacturing-case-live", + section: "news", + category: "case", + title: "云泽科技助力某大型制造企业完成生产数据一体化改造", + subtitle: "客户案例", + summary: + "项目上线后,客户设备数据采集覆盖率提升至 96%,生产异常响应时长缩短 60%。", + tone: "teal", + date: "2025.08.15", + author: "客户成功部", + tags: ["制造业", "项目验收"], + blocks: [ + { + type: "paragraph", + text: "历时 6 个月,云泽科技为某大型精密制造集团完成 6 个厂区、1200 余台设备的数据一体化改造,项目已于近日通过终验。", + }, + { + type: "stats", + items: [ + { value: "96%", label: "设备数据采集覆盖率" }, + { value: "-60%", label: "生产异常响应时长" }, + { value: "+18%", label: "设备综合效率(OEE)" }, + ], + }, + { + type: "paragraph", + text: "项目采用边缘网关统一采集、中台统一建模的两层架构,集团层面首次实现了跨厂区的产能对比与瓶颈识别。", + }, + ], + }, + { + slug: "iso27001-certified", + section: "news", + category: "company", + title: "云泽科技通过 ISO 27001 信息安全管理体系认证", + subtitle: "公司公告", + summary: + "认证范围覆盖产品研发、项目实施与云端运维全流程,进一步满足金融与政务客户的合规要求。", + tone: "navy", + date: "2025.08.08", + author: "安全合规部", + tags: ["认证", "信息安全"], + blocks: [ + { + type: "paragraph", + text: "云泽科技近日正式通过 ISO/IEC 27001 信息安全管理体系认证,认证范围覆盖产品研发、项目实施与云端运维全流程。", + }, + { + type: "paragraph", + text: "配合本次认证,公司在数据分类分级、访问控制、供应商管理与应急响应四个方面完善了内部制度,并完成了全员安全意识培训。", + }, + { + type: "list", + items: [ + "建立数据分类分级标准与对应的访问控制策略", + "研发与生产环境网络隔离,变更须双人复核", + "与核心供应商签署数据处理协议并定期审计", + "制定安全事件响应预案,每半年组织一次演练", + ], + }, + ], + }, + { + slug: "analytics-3-5", + section: "news", + category: "product", + title: "智能分析引擎 3.5 版本上线:新增自然语言取数能力", + subtitle: "产品发布", + summary: + "业务人员可直接用一句话描述分析需求,系统自动生成查询并推荐可视化方式。", + tone: "blue", + date: "2025.07.30", + author: "产品中心", + tags: ["版本发布", "智能分析"], + blocks: [ + { + type: "paragraph", + text: "智能分析引擎 3.5 版本新增自然语言取数能力。业务人员只需用日常语言描述问题,系统即会结合指标中心生成查询语句,并推荐合适的图表形式。", + }, + { type: "heading", text: "本次更新" }, + { + type: "list", + items: [ + "自然语言取数:支持中文口语化提问与多轮追问", + "图表智能推荐:根据字段类型与分析意图自动选择图表", + "看板嵌入能力增强:支持免登录 Token 嵌入既有业务系统", + "移动端适配优化:复杂表格在小屏下自动切换为卡片视图", + ], + }, + { + type: "paragraph", + text: "自然语言取数默认开启审计日志,所有生成的查询语句均可回溯,便于数据团队掌握使用情况。", + }, + ], + }, + { + slug: "partner-program-2026", + section: "news", + category: "company", + title: "2026 年全国合作伙伴招募计划正式启动", + subtitle: "公司公告", + summary: + "面向华东、华南、西南三个区域招募解决方案与实施交付伙伴,提供产品培训与项目支持。", + tone: "indigo", + date: "2025.07.22", + author: "渠道合作部", + tags: ["合作伙伴", "招募"], + blocks: [ + { + type: "paragraph", + text: "云泽科技 2026 年全国合作伙伴招募计划正式启动,本轮重点面向华东、华南与西南三个区域,招募解决方案伙伴与实施交付伙伴。", + }, + { type: "heading", text: "伙伴权益" }, + { + type: "features", + items: [ + { icon: "book", title: "产品培训", desc: "每季度一次线下集训,配套线上课程与认证考试。" }, + { icon: "headset", title: "售前支持", desc: "重点项目提供原厂售前与方案架构师陪访。" }, + { icon: "shield", title: "交付保障", desc: "提供标准交付方法论与项目管理系统支持。" }, + ], + }, + { + type: "paragraph", + text: "有意向的伙伴可通过官网合作伙伴页面提交申请,我们会在 5 个工作日内完成初步沟通。", + }, + ], + }, + { + slug: "retail-case-acceptance", + section: "news", + category: "case", + title: "某全国连锁零售企业会员数据中台项目顺利验收", + subtitle: "客户案例", + summary: + "打通 3 个线上渠道与 800 家门店的会员数据,活动 ROI 提升 24%。", + tone: "teal", + date: "2025.07.15", + author: "客户成功部", + tags: ["零售", "项目验收"], + blocks: [ + { + type: "paragraph", + text: "该项目覆盖客户旗下 800 余家门店与小程序、电商旗舰店、社群三个线上渠道,完成了会员身份的跨渠道归一与标签体系建设。", + }, + { + type: "stats", + items: [ + { value: "+18%", label: "会员复购率" }, + { value: "+24%", label: "活动 ROI" }, + { value: "-30%", label: "滞销库存占比" }, + ], + }, + { + type: "quote", + text: "现在我们做一场活动,先选人群再定商品,而不是先把商品发下去再想卖给谁。", + author: "客户数字化总监", + }, + ], + }, + { + slug: "data-platform-open-class", + section: "news", + category: "event", + title: "数据中台实战公开课开播,首期聚焦指标管理", + subtitle: "市场活动", + summary: + "由云泽产品团队主讲的系列公开课,每期围绕一个真实项目难题展开拆解。", + tone: "blue", + date: "2025.07.08", + author: "市场部", + tags: ["公开课", "直播"], + blocks: [ + { + type: "paragraph", + text: "数据中台实战公开课正式开播,首期主题为「指标口径不统一,到底该从哪里下手」。课程以真实项目为背景,拆解指标混乱的常见成因与治理路径。", + }, + { + type: "list", + items: [ + "第一期:指标口径不统一的成因与治理路径", + "第二期:实时计算任务如何做到稳定可控", + "第三期:数据质量规则应该由谁来定", + "第四期:数据资产目录的落地与维护", + ], + }, + { + type: "paragraph", + text: "课程在官网与视频号同步直播,回放将在开播后三个工作日内上线。", + }, + ], + }, +]; diff --git a/website/src/data/pages.ts b/website/src/data/pages.ts new file mode 100644 index 0000000..065d72d --- /dev/null +++ b/website/src/data/pages.ts @@ -0,0 +1,564 @@ +import type { SinglePage } from "@/types/content"; + +/** + * 独立单页内容 + * key = 去掉前导斜杠的路由路径,例如 about、support/docs、policy/privacy + */ +export const singlePages: Record = { + about: { + title: "关于云泽", + subtitle: "用可靠的产品与长期的陪伴,帮企业把数据真正用起来。", + crumbs: ["关于云泽"], + tone: "navy", + blocks: [ + { + type: "paragraph", + text: "云泽科技成立于 2014 年,专注企业级云计算与数据智能领域。我们提供云原生平台、数据中台与智能分析产品,并为制造业、零售消费、能源电力与金融行业提供场景化解决方案。十二年里,我们服务了超过 1000 家企业客户,其中 300 余家为上市公司或集团型企业。", + }, + { + type: "stats", + items: [ + { value: "2014", label: "成立年份" }, + { value: "600+", label: "员工规模" }, + { value: "62%", label: "研发人员占比" }, + { value: "1000+", label: "服务企业客户" }, + ], + }, + { type: "heading", text: "发展历程", sub: "从一支 8 人团队到全国 6 个交付中心" }, + { + type: "timeline", + items: [ + { year: "2014", text: "公司成立,从企业级中间件与容器化咨询起步。" }, + { year: "2017", text: "发布自研云原生平台,服务首批 50 家制造业客户。" }, + { year: "2019", text: "数据中台 1.0 发布,进入零售与能源行业。" }, + { year: "2021", text: "完成 B 轮融资,成立上海、深圳、成都交付中心。" }, + { year: "2023", text: "智能分析引擎发布,累计服务客户突破 800 家。" }, + { year: "2026", text: "数据中台 V3.0 发布,启动海外市场布局。" }, + ], + }, + { type: "heading", text: "我们相信什么", sub: "这三条决定了我们怎么做产品、怎么做项目" }, + { + type: "features", + items: [ + { icon: "target", title: "先解决业务问题", desc: "不为了上系统而上系统,先弄清楚客户到底想改善哪个指标。" }, + { icon: "shield", title: "交付即运维起点", desc: "项目终验不是结束,我们要求交付团队对上线后半年的稳定负责。" }, + { icon: "users", title: "把能力留给客户", desc: "培训与文档与产品同等重要,客户能自主运转才算真正交付。" }, + ], + }, + { type: "heading", text: "资质与荣誉" }, + { + type: "list", + items: [ + "国家高新技术企业", + "ISO/IEC 27001 信息安全管理体系认证", + "CMMI 5 级软件成熟度认证", + "累计取得软件著作权 120 余项、发明专利 26 项", + "连续三年入选某行业研究机构「数据中台代表厂商」", + ], + }, + ], + }, + + careers: { + title: "加入我们", + subtitle: "和一群愿意把事情做扎实的人,一起做点有难度的事。", + crumbs: ["加入我们"], + tone: "blue", + blocks: [ + { + type: "paragraph", + text: "我们是一家技术驱动型公司,研发人员占比 62%。这里的项目大多有真实的业务难题,客户会在验收现场告诉你哪些地方还不好用——这既是压力,也是成长最快的地方。", + }, + { type: "heading", text: "为什么选择云泽" }, + { + type: "features", + items: [ + { icon: "target", title: "做有难度的项目", desc: "面向集团级客户,数据规模与业务复杂度都是真实的。" }, + { icon: "users", title: "扁平的技术氛围", desc: "技术方案在评审会上讨论,不按职级定对错。" }, + { icon: "clock", title: "尊重生活节奏", desc: "项目冲刺有调休,非必要不加班。" }, + { icon: "book", title: "持续学习投入", desc: "每年人均 8000 元学习预算,内部技术分享每周一次。" }, + ], + }, + { type: "heading", text: "热招岗位", sub: "以下岗位长期开放,欢迎自荐或推荐" }, + { + type: "table", + head: ["岗位", "方向", "经验要求", "工作地点"], + rows: [ + ["后端研发工程师", "数据中台", "3 年以上", "北京 / 成都"], + ["大数据开发工程师", "实时计算", "3 年以上", "北京 / 上海"], + ["前端研发工程师", "智能分析", "2 年以上", "北京"], + ["解决方案架构师", "制造业方向", "5 年以上", "上海 / 深圳"], + ["实施交付顾问", "零售方向", "3 年以上", "广州 / 成都"], + ["客户成功经理", "重点客户", "3 年以上", "北京 / 上海"], + ], + }, + { type: "heading", text: "福利待遇" }, + { + type: "list", + items: [ + "六险一金,补充商业医疗保险覆盖配偶与子女", + "年度体检、带薪年假 10 天起、司龄假", + "季度绩效奖金 + 项目奖金,核心岗位含股权激励", + "弹性工作制,每周可远程办公 1 天", + ], + }, + { + type: "links", + items: [ + { icon: "mail", title: "投递简历", desc: "发送至 hr@yunzer.com,标题注明岗位与城市", path: "/contact" }, + { icon: "users", title: "员工内推", desc: "内推成功可获得推荐奖金,详情咨询 HR", path: "/contact" }, + ], + }, + ], + }, + + partners: { + title: "合作伙伴", + subtitle: "与区域伙伴一起,把方案落到离客户最近的地方。", + crumbs: ["合作伙伴"], + tone: "indigo", + blocks: [ + { + type: "paragraph", + text: "我们采用「原厂产品 + 伙伴交付」的模式服务全国客户。原厂负责产品研发、售前支持与交付质量把关,伙伴负责区域客户经营与项目实施,双方在项目中共享收益。", + }, + { type: "heading", text: "合作类型" }, + { + type: "features", + items: [ + { icon: "target", title: "解决方案伙伴", desc: "在特定行业具备方案能力,可与原厂联合打磨行业方案包。" }, + { icon: "headset", title: "实施交付伙伴", desc: "具备项目实施与运维能力,承接区域项目的落地交付。" }, + { icon: "plug", title: "产品集成伙伴", desc: "产品可与云泽平台完成集成认证,进入联合解决方案目录。" }, + { icon: "book", title: "培训认证伙伴", desc: "面向区域客户提供产品培训与认证服务。" }, + ], + }, + { type: "heading", text: "伙伴权益" }, + { + type: "list", + items: [ + "区域项目保护,避免伙伴之间互相压价", + "重点项目原厂售前与架构师陪访支持", + "季度线下集训 + 线上课程 + 认证考试", + "标准交付方法论、项目管理系统与验收模板", + ], + }, + { type: "heading", text: "合作流程" }, + { + type: "steps", + items: [ + { title: "提交申请", desc: "在线提交公司资质、行业经验与团队规模信息。" }, + { title: "初步沟通", desc: "5 个工作日内完成首次沟通,明确合作类型。" }, + { title: "能力评估", desc: "评估方案或交付能力,必要时安排技术面谈。" }, + { title: "签约授权", desc: "签署合作协议并完成伙伴分级与授权。" }, + { title: "培训赋能", desc: "参加集训并通过认证,进入项目推荐池。" }, + ], + }, + { + type: "links", + items: [ + { icon: "mail", title: "提交合作申请", desc: "发送公司简介与意向合作类型至 partner@yunzer.com", path: "/contact" }, + { icon: "file", title: "查阅伙伴政策", desc: "分级标准、返点规则与项目保护机制说明", path: "/support/docs" }, + ], + }, + ], + }, + + contact: { + title: "联系我们", + subtitle: "无论是产品咨询、方案交流还是合作洽谈,我们都会在 1 个工作日内回复。", + crumbs: ["联系我们"], + tone: "blue", + blocks: [ + { + type: "contact", + items: [ + { icon: "phone", label: "服务热线", value: "400-000-0000(工作日 9:00 - 18:00)" }, + { icon: "mail", label: "商务合作", value: "contact@yunzer.com" }, + { icon: "mail", label: "渠道合作", value: "partner@yunzer.com" }, + { icon: "location", label: "总部地址", value: "北京市海淀区中关村软件园 25 号楼" }, + ], + }, + { type: "heading", text: "分支机构", sub: "就近联系我们的区域团队" }, + { + type: "table", + head: ["城市", "地址", "联系电话"], + rows: [ + ["北京(总部)", "海淀区中关村软件园 25 号楼", "010-0000-0000"], + ["上海", "浦东新区张江高科技园区 8 号楼", "021-0000-0000"], + ["深圳", "南山区科技园南区 12 栋", "0755-0000-0000"], + ["成都", "高新区天府大道中段 966 号", "028-0000-0000"], + ], + }, + { type: "heading", text: "按需求选择入口" }, + { + type: "links", + items: [ + { icon: "monitor", title: "预约产品演示", desc: "1 对 1 演示与答疑,通常 30 分钟", path: "/support/demo" }, + { icon: "clipboard", title: "申请免费试用", desc: "1 个工作日内开通试用账号", path: "/support/trial" }, + { icon: "book", title: "查阅产品文档", desc: "快速上手、接口说明与常见问题", path: "/support/docs" }, + { icon: "headset", title: "客户支持中心", desc: "已签约客户的服务入口与工单通道", path: "/support" }, + ], + }, + ], + }, + + support: { + title: "客户支持中心", + subtitle: "从上线到日常运维,遇到问题时有明确的路径可以走。", + crumbs: ["客户支持"], + tone: "navy", + blocks: [ + { + type: "paragraph", + text: "我们把支持体系分成「自助」与「人工」两层:常规问题通过文档与开发者中心自助解决,复杂问题通过工单进入原厂技术支持,并按合同约定的响应时效处理。", + }, + { type: "heading", text: "自助服务" }, + { + type: "links", + items: [ + { icon: "book", title: "产品文档", desc: "安装部署、功能说明与最佳实践", path: "/support/docs" }, + { icon: "code", title: "开发者中心", desc: "SDK、API 文档与示例代码", path: "/support/developer" }, + { icon: "clipboard", title: "申请试用", desc: "开通试用账号,含示例数据集", path: "/support/trial" }, + { icon: "monitor", title: "预约演示", desc: "由售前顾问进行 1 对 1 演示", path: "/support/demo" }, + ], + }, + { type: "heading", text: "支持体系" }, + { + type: "features", + items: [ + { icon: "headset", title: "专属支持群", desc: "每个项目建立专属群,原厂研发与交付人员都在群里。" }, + { icon: "clock", title: "分级响应", desc: "按问题等级约定响应与解决时效,超时自动升级。" }, + { icon: "shield", title: "版本与补丁", desc: "重大缺陷提供补丁包,安全漏洞 24 小时内响应。" }, + { icon: "file", title: "季度巡检", desc: "每季度输出一次系统健康报告与优化建议。" }, + ], + }, + { type: "heading", text: "服务承诺", sub: "详见服务保障条款" }, + { + type: "stats", + items: [ + { value: "2 小时", label: "紧急问题响应" }, + { value: "8 小时", label: "一般问题响应" }, + { value: "99.9%", label: "标准版服务可用性" }, + { value: "24 小时", label: "安全漏洞响应" }, + ], + }, + { type: "paragraph", text: "完整的服务等级与赔付条款请查阅服务保障页面。" }, + { + type: "links", + items: [ + { icon: "shield", title: "服务保障(SLA)", desc: "分级响应时效、可用性承诺与赔付规则", path: "/support/sla" }, + ], + }, + ], + }, + + "support/docs": { + title: "产品文档", + subtitle: "安装部署、功能说明、最佳实践与常见问题。", + crumbs: ["客户支持", "产品文档"], + tone: "blue", + blocks: [ + { + type: "paragraph", + text: "产品文档覆盖部署、配置、开发与运维四个阶段,所有文档随版本同步更新。建议在升级前先查阅对应版本的变更说明与兼容性提示。", + }, + { type: "heading", text: "文档目录" }, + { + type: "features", + items: [ + { icon: "monitor", title: "快速开始", desc: "环境要求、安装部署与初始化配置,30 分钟完成首次启动。" }, + { icon: "file", title: "功能说明", desc: "按模块说明功能入口、参数含义与使用限制。" }, + { icon: "book", title: "最佳实践", desc: "来自真实项目的建模规范、命名约定与调优建议。" }, + { icon: "shield", title: "运维手册", desc: "监控指标、备份恢复、扩容缩容与故障处理流程。" }, + ], + }, + { type: "heading", text: "按产品查阅" }, + { + type: "table", + head: ["产品", "当前版本", "文档入口"], + rows: [ + ["云原生平台", "v5.2", "部署指南 / 运维手册"], + ["数据中台", "v3.0", "快速开始 / 指标管理 / 数据质量"], + ["智能分析引擎", "v3.5", "建模指南 / 看板设计 / 移动端"], + ["边缘物联网关", "v2.4", "协议清单 / 边缘推理 / 远程升级"], + ], + }, + { type: "paragraph", text: "找不到需要的文档?可以在客户支持中心提交工单,我们会补充对应的说明。" }, + ], + }, + + "support/developer": { + title: "开发者中心", + subtitle: "SDK、开放 API、示例代码与集成认证。", + crumbs: ["客户支持", "开发者中心"], + tone: "indigo", + blocks: [ + { + type: "paragraph", + text: "开发者中心面向需要把云泽产品集成进既有系统的团队。平台提供 REST API、多语言 SDK 与 Webhook 回调,全部接口遵循统一的鉴权与错误码规范。", + }, + { + type: "features", + items: [ + { icon: "code", title: "开放 API", desc: "覆盖数据接入、任务调度、指标查询与权限管理。" }, + { icon: "plug", title: "多语言 SDK", desc: "提供 Java、Go、Python、TypeScript 四种语言 SDK。" }, + { icon: "monitor", title: "沙箱环境", desc: "独立沙箱与示例数据集,不影响生产环境。" }, + { icon: "shield", title: "集成认证", desc: "通过集成测试后可进入联合解决方案目录。" }, + ], + }, + { type: "heading", text: "接入流程" }, + { + type: "steps", + items: [ + { title: "创建应用", desc: "在控制台创建应用并获取 Client ID 与密钥。" }, + { title: "沙箱联调", desc: "在沙箱环境完成接口联调,验证鉴权与错误处理。" }, + { title: "提交审核", desc: "提交集成说明与技术联系人信息。" }, + { title: "正式上线", desc: "审核通过后切换生产环境,获得集成认证标识。" }, + ], + }, + { type: "paragraph", text: "接口限流默认按应用维度控制,如需提升配额请联系客户成功经理。" }, + ], + }, + + "support/trial": { + title: "申请免费试用", + subtitle: "1 个工作日内开通账号,含行业示例数据集,无需自备数据。", + crumbs: ["客户支持", "申请试用"], + tone: "teal", + blocks: [ + { + type: "paragraph", + text: "试用账号包含产品全部功能,不设调用次数限制。我们同时提供 20 个行业示例数据集,可以直接用于验证建模、指标与分析效果。", + }, + { type: "heading", text: "试用流程" }, + { + type: "steps", + items: [ + { title: "提交申请", desc: "填写企业与联系人信息,说明希望验证的场景。" }, + { title: "账号开通", desc: "1 个工作日内收到账号与初始密码,含入门指引。" }, + { title: "自助验证", desc: "使用示例数据或自备数据完成场景验证,可随时咨询。" }, + { title: "评估与选型", desc: "试用结束后我们提供选型建议与部署方案。" }, + ], + }, + { type: "heading", text: "试用版与正式版差异" }, + { + type: "table", + head: ["项目", "试用版", "正式版"], + rows: [ + ["功能范围", "全部功能", "全部功能"], + ["使用期限", "30 天", "按合同约定"], + ["部署方式", "云端共享环境", "私有化 / 专有云 / 公有云"], + ["技术支持", "工作日 2 小时内", "按 SLA 分级响应"], + ], + }, + { + type: "links", + items: [ + { icon: "clipboard", title: "提交试用申请", desc: "填写信息后 1 个工作日内开通", path: "/contact" }, + { icon: "monitor", title: "先预约一次演示", desc: "由售前顾问讲解并演示关键能力", path: "/support/demo" }, + ], + }, + ], + }, + + "support/sla": { + title: "服务保障", + subtitle: "分级响应时效、可用性承诺与赔付规则说明。", + crumbs: ["客户支持", "服务保障"], + tone: "navy", + blocks: [ + { + type: "paragraph", + text: "本页说明标准版服务等级协议(SLA)的主要内容。具体条款以双方签署的合同为准,企业版客户可在合同中约定更高等级的服务承诺。", + }, + { type: "heading", text: "问题分级与响应时效" }, + { + type: "table", + head: ["等级", "定义", "响应时效", "解决时效"], + rows: [ + ["P1 紧急", "生产环境不可用或核心数据丢失风险", "30 分钟", "4 小时"], + ["P2 严重", "核心功能不可用,业务受阻但有替代方案", "2 小时", "1 个工作日"], + ["P3 一般", "非核心功能异常或使用体验问题", "8 小时", "5 个工作日"], + ["P4 咨询", "使用咨询、配置指导与需求建议", "1 个工作日", "协商确定"], + ], + }, + { type: "heading", text: "可用性承诺" }, + { + type: "stats", + items: [ + { value: "99.9%", label: "标准版月可用性" }, + { value: "99.95%", label: "企业版月可用性" }, + { value: "24 小时", label: "安全漏洞响应" }, + ], + }, + { type: "heading", text: "赔付规则" }, + { + type: "list", + items: [ + "月度可用性低于承诺值时,按当季服务费的一定比例进行抵扣", + "P1 级问题响应超时,每次按合同约定金额赔付", + "因计划内维护导致的不可用不计入可用性统计,维护需提前 3 个工作日通知", + "不可抗力、客户自身环境变更或第三方系统故障不纳入赔付范围", + ], + }, + { type: "paragraph", text: "如需了解完整条款或申请更高的服务等级,请联系您的客户成功经理。" }, + ], + }, + + "support/demo": { + title: "预约产品演示", + subtitle: "由售前顾问进行 1 对 1 演示,围绕你的业务场景展开。", + crumbs: ["客户支持", "预约演示"], + tone: "blue", + blocks: [ + { + type: "paragraph", + text: "演示通常安排在 30 至 45 分钟,我们会在开始前先了解你的业务场景与关注点,演示内容围绕这些场景展开,而不是照着产品功能清单念一遍。", + }, + { type: "heading", text: "演示流程" }, + { + type: "steps", + items: [ + { title: "提交预约", desc: "填写企业信息、业务场景与期望的演示时间。" }, + { title: "需求确认", desc: "售前顾问在 1 个工作日内电话沟通,明确关注重点。" }, + { title: "在线演示", desc: "线上会议进行 30 - 45 分钟演示与答疑。" }, + { title: "方案建议", desc: "会后 2 个工作日内提供针对性的方案与选型建议。" }, + ], + }, + { type: "heading", text: "预约方式" }, + { + type: "contact", + items: [ + { icon: "phone", label: "预约热线", value: "400-000-0000(工作日 9:00 - 18:00)" }, + { icon: "mail", label: "预约邮箱", value: "demo@yunzer.com" }, + { icon: "clock", label: "可预约时段", value: "工作日 10:00 - 17:00" }, + ], + }, + ], + }, + + "policy/privacy": { + title: "隐私政策", + subtitle: "我们如何收集、使用和保护你的个人信息。", + crumbs: ["隐私政策"], + tone: "navy", + blocks: [ + { type: "paragraph", text: "生效日期:2026 年 1 月 1 日。本政策适用于云泽科技官方网站及我们提供的相关服务。" }, + { type: "heading", text: "一、我们收集的信息" }, + { + type: "list", + items: [ + "你主动提交的信息:姓名、公司名称、联系电话、邮箱等表单信息", + "自动收集的信息:IP 地址、浏览器类型、访问时间与访问页面", + "为你提供服务过程中产生的信息:账号信息、操作日志与工单记录", + ], + }, + { type: "heading", text: "二、信息的使用" }, + { + type: "paragraph", + text: "我们将收集到的信息用于:响应你的咨询与需求、向你发送你已同意的产品与活动信息、改进网站与产品体验、以及履行法律法规要求的义务。我们不会将你的个人信息用于与上述目的无关的用途。", + }, + { type: "heading", text: "三、信息的共享" }, + { + type: "list", + items: [ + "除法律法规要求或你明确授权外,我们不会向第三方共享你的个人信息", + "为完成服务而必须委托的供应商,我们会与其签署数据处理协议并限制其使用范围", + "涉及合并、分立等情形的,我们会要求承继方继续受本政策约束", + ], + }, + { type: "heading", text: "四、信息的保护" }, + { + type: "paragraph", + text: "我们通过了 ISO/IEC 27001 信息安全管理体系认证,采取数据分类分级、访问控制、传输与存储加密、操作审计等措施保护你的信息。", + }, + { type: "heading", text: "五、你的权利" }, + { + type: "paragraph", + text: "你有权查询、更正、删除你提交的个人信息,或撤回此前的授权同意。如需行使上述权利,请通过 contact@yunzer.com 与我们联系,我们将在 15 个工作日内处理。", + }, + ], + }, + + "policy/terms": { + title: "使用条款", + subtitle: "访问和使用本网站前,请仔细阅读以下条款。", + crumbs: ["使用条款"], + tone: "navy", + blocks: [ + { type: "paragraph", text: "欢迎访问云泽科技官方网站。你访问或使用本网站,即表示你已阅读、理解并同意接受本条款的约束。" }, + { type: "heading", text: "一、网站内容" }, + { + type: "paragraph", + text: "本网站上的文字、图片、图表、界面设计与程序代码等内容的著作权及相关权利归云泽科技或相应权利人所有。未经书面许可,任何人不得复制、修改、传播或用于商业用途。", + }, + { type: "heading", text: "二、使用规范" }, + { + type: "list", + items: [ + "不得利用本网站从事任何违反法律法规的活动", + "不得通过自动化程序批量抓取本站内容", + "不得尝试入侵、干扰或破坏本网站及其相关服务的正常运行", + "不得冒用云泽科技名义发布信息或从事商业活动", + ], + }, + { type: "heading", text: "三、免责声明" }, + { + type: "paragraph", + text: "本网站提供的信息仅供参考,不构成任何形式的承诺或保证。产品功能与规格以双方签署的合同及产品文档为准。我们不对因使用本站信息而产生的直接或间接损失承担责任。", + }, + { type: "heading", text: "四、条款变更" }, + { + type: "paragraph", + text: "我们可能根据业务或法律要求调整本条款,调整后的内容将在本页面公布并注明生效日期。继续使用本网站即视为接受调整后的条款。", + }, + { type: "heading", text: "五、适用法律" }, + { + type: "paragraph", + text: "本条款的订立、效力、解释与争议解决均适用中华人民共和国法律。因本条款产生的争议,双方应友好协商解决;协商不成的,提交北京市海淀区人民法院管辖。", + }, + ], + }, + + "policy/sitemap": { + title: "网站地图", + subtitle: "全站栏目与页面索引。", + crumbs: ["网站地图"], + tone: "blue", + blocks: [ + { type: "heading", text: "主要内容" }, + { + type: "links", + items: [ + { icon: "monitor", title: "新闻中心", desc: "公司公告、产品发布、市场活动与客户案例", path: "/news" }, + { icon: "plug", title: "产品中心", desc: "云原生平台、数据中台、智能分析等产品", path: "/products" }, + { icon: "target", title: "解决方案", desc: "制造业、零售、能源与金融行业的场景方案", path: "/solutions" }, + { icon: "ribbon", title: "客户案例", desc: "各行业客户的落地实践与项目成果", path: "/cases" }, + { icon: "calendar", title: "市场活动", desc: "大会、公开课与合作伙伴巡展安排", path: "/events" }, + ], + }, + { type: "heading", text: "关于与合作" }, + { + type: "links", + items: [ + { icon: "users", title: "关于云泽", desc: "公司简介、发展历程与资质荣誉", path: "/about" }, + { icon: "book", title: "加入我们", desc: "热招岗位、福利待遇与投递方式", path: "/careers" }, + { icon: "plug", title: "合作伙伴", desc: "合作类型、伙伴权益与申请流程", path: "/partners" }, + { icon: "mail", title: "联系我们", desc: "总部与分支机构联系方式", path: "/contact" }, + ], + }, + { type: "heading", text: "服务与支持" }, + { + type: "links", + items: [ + { icon: "headset", title: "客户支持中心", desc: "自助服务与人工支持入口", path: "/support" }, + { icon: "file", title: "产品文档", desc: "部署、功能说明与最佳实践", path: "/support/docs" }, + { icon: "code", title: "开发者中心", desc: "SDK、API 与集成认证", path: "/support/developer" }, + { icon: "clipboard", title: "申请试用", desc: "开通试用账号与示例数据集", path: "/support/trial" }, + { icon: "monitor", title: "预约演示", desc: "1 对 1 产品演示与答疑", path: "/support/demo" }, + { icon: "shield", title: "服务保障", desc: "分级响应时效与可用性承诺", path: "/support/sla" }, + ], + }, + ], + }, +}; diff --git a/website/src/data/products.ts b/website/src/data/products.ts new file mode 100644 index 0000000..e2447ec --- /dev/null +++ b/website/src/data/products.ts @@ -0,0 +1,238 @@ +import type { ContentItem } from "@/types/content"; + +export const products: ContentItem[] = [ + { + slug: "cloud-native", + section: "products", + category: "platform", + title: "云原生平台", + subtitle: "容器化与微服务治理", + summary: + "一站式容器编排、服务治理与 DevOps 流水线,帮助研发团队把交付周期从周压缩到天。", + tone: "navy", + tags: ["Kubernetes", "Service Mesh", "DevOps"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "云泽云原生平台面向中大型企业的多集群运维场景,统一纳管容器编排、服务网格、镜像仓库与 CI/CD 流水线。平台屏蔽底层复杂度,让业务团队专注于应用本身,运维团队则通过统一控制台完成资源交付、灰度发布与故障定位。", + }, + { + type: "features", + items: [ + { icon: "plug", title: "多集群统一纳管", desc: "跨公有云与自建机房统一编排,支持一键扩缩容与集群漂移。" }, + { icon: "shield", title: "服务网格治理", desc: "内置灰度、熔断、限流与全链路追踪,无需改造业务代码。" }, + { icon: "code", title: "流水线即代码", desc: "以 YAML 描述构建、测试、部署全流程,天然适配 GitOps。" }, + { icon: "chart", title: "可观测性", desc: "指标、日志、链路三合一,问题定位从小时级降到分钟级。" }, + ], + }, + { type: "heading", text: "适用场景", sub: "以下场景中收益最为明显" }, + { + type: "list", + items: [ + "业务系统正在从单体向微服务拆分,缺少统一治理手段", + "多环境、多集群并存,发布流程依赖人工、容易出错", + "需要满足等保与信创要求,要求资源可审计、可追溯", + "研发团队规模扩张,希望以平台化方式承载交付效率", + ], + }, + { + type: "table", + head: ["对比项", "传统模式", "使用云泽云原生平台"], + rows: [ + ["环境交付", "3 ~ 5 个工作日", "10 分钟以内"], + ["发布方式", "停机发布", "灰度发布并可一键回滚"], + ["资源利用率", "约 20%", "提升至 55% 以上"], + ["故障定位", "依赖人工排查", "全链路追踪自动定位"], + ], + }, + ], + }, + { + slug: "data-platform", + section: "products", + category: "data", + title: "数据中台", + subtitle: "采集 · 治理 · 资产化", + summary: + "从数据采集、治理到资产化与实时计算的一体化平台,让指标口径统一、数据随取随用。", + tone: "blue", + tags: ["实时计算", "数据治理", "指标管理"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "数据中台把散落在各业务系统中的数据统一采集入湖,经过清洗、建模与指标定义后,形成可复用的数据资产。业务人员不再需要向多个部门要数,口径不一致的问题也从机制上被消除。V3.0 版本重构了实时计算内核,任务延迟可稳定控制在秒级。", + }, + { + type: "features", + items: [ + { icon: "plug", title: "多源数据接入", desc: "支持数据库、消息队列、文件与 API 共 40 余种数据源。" }, + { icon: "shield", title: "数据质量监控", desc: "内置完整性、一致性、及时性规则,异常自动告警并阻断下游。" }, + { icon: "chart", title: "统一指标管理", desc: "指标定义、计算逻辑与权限统一维护,一处修改全局生效。" }, + { icon: "clock", title: "实时计算内核", desc: "流批一体,端到端延迟稳定在秒级,支撑实时决策场景。" }, + ], + }, + { type: "heading", text: "核心指标", sub: "基于已交付项目的统计数据" }, + { + type: "stats", + items: [ + { value: "40+", label: "支持的数据源类型" }, + { value: "秒级", label: "端到端处理延迟" }, + { value: "96%", label: "平均数据采集覆盖率" }, + { value: "60%", label: "问题响应时长下降" }, + ], + }, + { + type: "table", + head: ["版本", "核心能力", "适用规模"], + rows: [ + ["标准版", "离线数仓、指标管理", "10 个业务系统以内"], + ["专业版", "流批一体、数据质量", "50 个业务系统以内"], + ["企业版", "多租户、跨域数据交换", "集团级多法人架构"], + ], + }, + ], + }, + { + slug: "analytics", + section: "products", + category: "data", + title: "智能分析引擎", + subtitle: "自助式 BI 与智能洞察", + summary: + "面向业务人员的自助分析工具,支持拖拽建模与自然语言取数,让报表需求不再排队。", + tone: "teal", + tags: ["BI", "自助分析", "自然语言取数"], + blocks: [ + { + type: "paragraph", + text: "智能分析引擎把数据准备、可视化与智能洞察整合在一个工作台里。业务人员通过拖拽即可完成多维分析,借助自然语言取数能力,只需要用一句话描述问题,系统就会自动生成查询并给出图表建议。", + }, + { + type: "features", + items: [ + { icon: "chart", title: "拖拽式分析", desc: "无需 SQL 即可完成钻取、联动与同环比对比。" }, + { icon: "spark", title: "自然语言取数", desc: "用日常语言提问,自动生成查询语句与可视化结果。" }, + { icon: "target", title: "智能异常检测", desc: "自动识别指标突增突降并给出可能的影响因子。" }, + { icon: "users", title: "权限与分享", desc: "行级权限控制,看板可一键分享给指定成员或群组。" }, + ], + }, + { type: "heading", text: "为什么业务团队喜欢它" }, + { + type: "list", + items: [ + "报表需求从「提工单等排期」变为「自己动手五分钟出图」", + "指标口径与数据中台一致,避免同一张报表出现两个数字", + "移动端与钉钉、企业微信打通,管理层可随时查看", + "支持将看板嵌入既有业务系统,无需切换工作台", + ], + }, + ], + }, + { + slug: "iot-gateway", + section: "products", + category: "platform", + title: "边缘物联网关", + subtitle: "设备接入与边缘计算", + summary: + "支持 200 余种工业协议,在边缘侧完成数据采集、清洗与轻量推理,弱网环境依然稳定。", + tone: "indigo", + tags: ["工业协议", "边缘计算", "设备接入"], + blocks: [ + { + type: "paragraph", + text: "边缘物联网关部署在靠近设备的一侧,负责协议解析、数据缓存与边缘推理。即使与云端断链,网关仍可独立运行并在恢复后自动补传,保证数据不丢、生产不停。", + }, + { + type: "features", + items: [ + { icon: "plug", title: "协议广泛", desc: "内置 Modbus、OPC UA、Profinet 等 200 余种工业协议。" }, + { icon: "clock", title: "断网续传", desc: "本地可缓存 30 天数据,链路恢复后自动补传。" }, + { icon: "shield", title: "边缘推理", desc: "在本地运行轻量模型,满足低时延与数据不出厂的要求。" }, + { icon: "monitor", title: "远程运维", desc: "支持批量下发配置、远程升级与运行状态监控。" }, + ], + }, + { + type: "table", + head: ["规格", "标准型", "增强型"], + rows: [ + ["接入点数", "2000 点", "10000 点"], + ["本地存储", "64 GB", "512 GB"], + ["工作温度", "-10℃ ~ 60℃", "-30℃ ~ 70℃"], + ["典型部署", "车间级", "厂区级"], + ], + }, + ], + }, + { + slug: "lowcode", + section: "products", + category: "app", + title: "低代码应用平台", + subtitle: "拖拽搭建业务应用", + summary: + "表单、流程、报表一体化搭建,业务人员一周内即可上线一套内部管理系统。", + tone: "blue", + tags: ["低代码", "表单流程", "集成"], + blocks: [ + { + type: "paragraph", + text: "低代码应用平台把常见的审批、台账、巡检等场景沉淀为可复用模板。业务人员在可视化设计器中拖拽即可完成表单与流程配置,需要个性化逻辑时再通过脚本扩展,兼顾效率与灵活度。", + }, + { + type: "features", + items: [ + { icon: "file", title: "可视化设计器", desc: "表单、列表、详情页拖拽生成,支持多端自适应。" }, + { icon: "plug", title: "流程引擎", desc: "支持串行、并行、会签与条件分支,审批节点可视化配置。" }, + { icon: "code", title: "脚本扩展", desc: "需要复杂逻辑时可插入脚本,不牺牲灵活度。" }, + { icon: "shield", title: "权限体系", desc: "按组织、角色、数据范围三级控制,天然适配集团架构。" }, + ], + }, + { + type: "list", + items: [ + "内部审批流:请假、报销、采购、用章", + "业务台账:设备巡检、客户回访、安全检查", + "数据填报:周报、月报、专项统计", + "轻量门户:面向员工的一站式工作入口", + ], + }, + ], + }, + { + slug: "ai-copilot", + section: "products", + category: "app", + title: "智能运营助手", + subtitle: "基于大模型的业务助手", + summary: + "把企业知识与业务数据接入大模型,为客服、运营与销售提供随问随答的智能助手。", + tone: "teal", + tags: ["大模型", "知识库", "智能客服"], + blocks: [ + { + type: "paragraph", + text: "智能运营助手在私有化环境中接入企业知识库与业务数据,回答时附带来源出处,避免模型幻觉带来的风险。企业可以按部门配置不同的知识范围与数据权限,做到「答得准、管得住」。", + }, + { + type: "features", + items: [ + { icon: "book", title: "企业知识库", desc: "支持文档、工单、网页与数据库多类知识来源接入。" }, + { icon: "target", title: "答案可溯源", desc: "每条回答附带引用出处,便于核对与追责。" }, + { icon: "shield", title: "私有化部署", desc: "支持本地化部署,数据不出企业内网。" }, + { icon: "headset", title: "多渠道接入", desc: "可嵌入官网、企业微信、钉钉与工单系统。" }, + ], + }, + { + type: "stats", + items: [ + { value: "72%", label: "常见问题自动解决率" }, + { value: "45%", label: "客服首次响应耗时下降" }, + { value: "3 周", label: "平均上线周期" }, + ], + }, + ], + }, +]; diff --git a/website/src/data/solutions.ts b/website/src/data/solutions.ts new file mode 100644 index 0000000..0b91752 --- /dev/null +++ b/website/src/data/solutions.ts @@ -0,0 +1,235 @@ +import type { ContentItem } from "@/types/content"; + +export const solutions: ContentItem[] = [ + { + slug: "smart-factory", + section: "solutions", + category: "manufacturing", + title: "智能制造数字化工厂", + subtitle: "从设备联网到生产协同", + summary: + "打通设备层、执行层与管理层,让生产进度、设备状态与质量数据在同一套体系里流转。", + tone: "navy", + tags: ["设备联网", "MES 集成", "质量追溯"], + featured: true, + blocks: [ + { + type: "paragraph", + text: "多数制造企业的数字化难点不在于缺少系统,而在于设备、MES、ERP 各自为政,数据无法贯通。我们以边缘网关统一采集设备数据,在中台完成建模与指标定义,再向计划、质量与设备管理三个方向输出能力。", + }, + { type: "heading", text: "常见挑战" }, + { + type: "list", + items: [ + "设备品牌与协议繁杂,数据采集依赖人工抄表", + "生产进度靠电话与微信群同步,异常发现滞后", + "质量数据分散在纸质记录与 Excel 中,难以追溯", + "系统上线后缺乏运维能力,三个月后又回到原状", + ], + }, + { type: "heading", text: "方案构成", sub: "四个模块按需组合,可分阶段实施" }, + { + type: "features", + items: [ + { icon: "plug", title: "设备数据采集", desc: "边缘网关接入 200 余种工业协议,覆盖主流机床与产线。" }, + { icon: "monitor", title: "生产可视化", desc: "工单进度、节拍、在制品数量实时上墙,异常自动预警。" }, + { icon: "shield", title: "质量追溯", desc: "以批次为主线关联工艺参数与检验结果,问题可回溯到工序。" }, + { icon: "chart", title: "设备健康管理", desc: "基于振动与温度趋势做早期故障预警,降低非计划停机。" }, + ], + }, + { type: "heading", text: "实施路径" }, + { + type: "steps", + items: [ + { title: "现状诊断", desc: "2 周内完成产线走访、系统盘点与数据可用性评估。" }, + { title: "试点产线", desc: "选择 1 条代表性产线,8 周内完成采集与可视化上线。" }, + { title: "指标建模", desc: "与业务共同定义 OEE、良率等核心指标的计算口径。" }, + { title: "全面推广", desc: "按车间分批推广,同步移交运维文档与培训。" }, + ], + }, + { + type: "stats", + items: [ + { value: "96%", label: "设备数据采集覆盖率" }, + { value: "60%", label: "生产异常响应时长下降" }, + { value: "18%", label: "设备综合效率提升" }, + ], + }, + ], + }, + { + slug: "retail-ops", + section: "solutions", + category: "retail", + title: "零售全域数据运营", + subtitle: "会员 · 商品 · 门店", + summary: + "把线上与线下会员数据统一到一套标签体系,让活动投放从「拍脑袋」变成「按人群」。", + tone: "teal", + tags: ["会员运营", "标签体系", "门店分析"], + blocks: [ + { + type: "paragraph", + text: "零售企业的数据通常分散在 POS、小程序、电商平台与会员系统中。我们以手机号为主键完成 OneID 归一,建立统一标签体系,再把人群能力开放给营销与商品团队使用。", + }, + { type: "heading", text: "常见挑战" }, + { + type: "list", + items: [ + "同一会员在多个渠道有多个身份,无法识别为同一个人", + "活动效果无法归因,预算分配缺少依据", + "门店选品依赖店长经验,滞销与缺货同时存在", + "会员数据分散在服务商手里,企业无法自主运营", + ], + }, + { + type: "features", + items: [ + { icon: "users", title: "OneID 归一", desc: "跨渠道身份合并,形成唯一的会员视图。" }, + { icon: "target", title: "标签与人群", desc: "300+ 预设标签,支持自定义组合并一键推送到营销通道。" }, + { icon: "chart", title: "门店经营分析", desc: "客流、转化、连带率按门店与时段拆解,指导排班与选品。" }, + { icon: "spark", title: "效果归因", desc: "打通投放与成交数据,量化每场活动的增量收益。" }, + ], + }, + { + type: "stats", + items: [ + { value: "+18%", label: "会员复购率提升" }, + { value: "+24%", label: "活动 ROI 提升" }, + { value: "-30%", label: "滞销库存占比下降" }, + ], + }, + ], + }, + { + slug: "energy-maintenance", + section: "solutions", + category: "energy", + title: "能源设备预测性维护", + subtitle: "从定期检修到按需检修", + summary: + "基于设备运行数据建立健康度模型,在故障发生前给出检修建议,减少非计划停机。", + tone: "indigo", + tags: ["预测性维护", "设备健康度", "状态监测"], + blocks: [ + { + type: "paragraph", + text: "风电场、变电站与大型机组的检修长期依赖固定周期,既存在过度检修,也存在突发故障停机。我们通过高频采集振动、温度与电流数据,结合机理模型与机器学习,输出设备健康度评分与剩余可用寿命预估。", + }, + { + type: "features", + items: [ + { icon: "monitor", title: "状态实时监测", desc: "毫秒级采集关键测点,支持边缘侧异常初筛。" }, + { icon: "chart", title: "健康度建模", desc: "机理模型与数据模型结合,输出 0 ~ 100 健康度评分。" }, + { icon: "clock", title: "剩余寿命预估", desc: "预测关键部件剩余可用时间,辅助备件与检修排程。" }, + { icon: "shield", title: "检修闭环", desc: "预警自动生成检修工单,处理结果回流优化模型。" }, + ], + }, + { type: "heading", text: "典型收益" }, + { + type: "stats", + items: [ + { value: "-32%", label: "非计划停机时长" }, + { value: "-21%", label: "年度检修成本" }, + { value: "92%", label: "故障预警准确率" }, + ], + }, + ], + }, + { + slug: "finance-risk", + section: "solutions", + category: "finance", + title: "金融数据合规与风控", + subtitle: "报表时效与风险识别", + summary: + "在满足监管报送与数据合规要求的前提下,把报表时效从 T+1 提升到分钟级。", + tone: "blue", + tags: ["监管报送", "数据合规", "实时风控"], + blocks: [ + { + type: "paragraph", + text: "金融机构同时面对监管报送、内部风控与业务分析三类数据需求,口径与时效要求各不相同。我们以统一数据底座承载三类场景,通过数据血缘与权限体系满足合规审计要求。", + }, + { + type: "features", + items: [ + { icon: "shield", title: "数据血缘与审计", desc: "全链路血缘可视化,任一指标均可追溯到源系统字段。" }, + { icon: "clock", title: "实时指标计算", desc: "核心经营指标分钟级更新,支撑日内决策。" }, + { icon: "target", title: "风险规则引擎", desc: "规则与模型双引擎,支持名单、阈值与图谱三类识别。" }, + { icon: "file", title: "报送自动化", desc: "监管报表自动生成与校验,减少人工核对工作量。" }, + ], + }, + { + type: "table", + head: ["场景", "改造前", "改造后"], + rows: [ + ["经营日报", "T+1 上午出具", "当日分钟级更新"], + ["监管报送", "人工核对 5 人日", "自动生成 0.5 人日"], + ["风险识别", "名单规则为主", "规则 + 模型 + 图谱"], + ["合规审计", "人工整理台账", "血缘自动留痕"], + ], + }, + ], + }, + { + slug: "logistics", + section: "solutions", + category: "retail", + title: "智慧物流调度优化", + subtitle: "运力、路径与时效", + summary: + "结合订单结构、运力与路况做动态排线,在保证时效的前提下降低空驶率。", + tone: "teal", + tags: ["路径优化", "运力调度", "时效履约"], + blocks: [ + { + type: "paragraph", + text: "物流成本中占比最高的是运输环节。我们以订单、车辆、路况与时效承诺为输入,通过启发式算法在分钟级给出排线与配载方案,并支持调度员人工微调后回训练模型。", + }, + { + type: "features", + items: [ + { icon: "target", title: "动态排线", desc: "综合考虑时效、成本与装载率,分钟级输出方案。" }, + { icon: "monitor", title: "在途可视化", desc: "车辆位置与温控数据实时回传,异常自动预警。" }, + { icon: "chart", title: "成本分析", desc: "按线路、车型、客户维度拆解成本构成。" }, + { icon: "clipboard", title: "调度协同", desc: "调度员可在方案基础上调整,调整结果回流优化模型。" }, + ], + }, + { + type: "stats", + items: [ + { value: "-14%", label: "单均运输成本" }, + { value: "+9%", label: "车辆装载率提升" }, + { value: "98.6%", label: "承诺时效达成率" }, + ], + }, + ], + }, + { + slug: "gov-data", + section: "solutions", + category: "finance", + title: "政务数据一体化", + subtitle: "共享交换与一网通办", + summary: + "打通部门间的数据壁垒,支撑一网通办、一件事一次办等跨部门协同场景。", + tone: "navy", + tags: ["数据共享", "一网通办", "目录管理"], + blocks: [ + { + type: "paragraph", + text: "政务数据的难点在于目录不清、责任不明。我们以数据目录为抓手,先理清「有什么、在哪里、谁负责」,再通过共享交换平台提供按需调用能力,让跨部门办事流程真正跑起来。", + }, + { + type: "features", + items: [ + { icon: "file", title: "数据目录", desc: "统一编目与责任登记,解决数据找不到、认不清的问题。" }, + { icon: "plug", title: "共享交换", desc: "支持库表、文件、接口三种交换方式,全程留痕可审计。" }, + { icon: "shield", title: "安全管控", desc: "按事项授权,最小必要原则,敏感字段自动脱敏。" }, + { icon: "users", title: "协同办事", desc: "以一件事为主线串联多个部门,材料一次提交多次复用。" }, + ], + }, + ], + }, +]; diff --git a/website/src/layout/DefaultLayout.vue b/website/src/layout/DefaultLayout.vue new file mode 100644 index 0000000..8e15d6c --- /dev/null +++ b/website/src/layout/DefaultLayout.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/website/src/layout/SiteFooter.vue b/website/src/layout/SiteFooter.vue new file mode 100644 index 0000000..fe4b02f --- /dev/null +++ b/website/src/layout/SiteFooter.vue @@ -0,0 +1,397 @@ + + + + + diff --git a/website/src/layout/SiteHeader.vue b/website/src/layout/SiteHeader.vue new file mode 100644 index 0000000..a70d0a6 --- /dev/null +++ b/website/src/layout/SiteHeader.vue @@ -0,0 +1,373 @@ + + + + + diff --git a/website/src/main.ts b/website/src/main.ts new file mode 100644 index 0000000..3e4ca62 --- /dev/null +++ b/website/src/main.ts @@ -0,0 +1,9 @@ +import { createApp } from "vue"; +import App from "./App.vue"; +import router from "./router"; // 配置路由 +import store from "./store"; // 配置vuex +import "./styles/index.less"; + +const app = createApp(App); + +app.use(router).use(store).mount("#app"); diff --git a/website/src/router/index.ts b/website/src/router/index.ts new file mode 100644 index 0000000..10ab94f --- /dev/null +++ b/website/src/router/index.ts @@ -0,0 +1,201 @@ +//index.ts +import { createRouter, createWebHashHistory, type RouteRecordRaw } from "vue-router"; + +const DefaultLayout = () => import("../layout/DefaultLayout.vue"); +const HomeView = () => import("../views/home/index.vue"); +const ListView = () => import("../views/list.vue"); +const DetailView = () => import("../views/detail.vue"); +const SingleView = () => import("../views/single.vue"); +const NotFoundView = () => import("../views/not-found.vue"); + +/** + * 路由约定: + * - 列表页 /news、/products、/solutions、/cases、/events + * - 分类页 /news/category/:slug (其余栏目同理) + * - 详情页 /news/detail/:slug (其余栏目同理) + * - 单页 /about、/careers、/contact、/support、/support/:slug、/policy/:slug + * 列表页与详情页共用同一个组件,通过路由路径推导所属栏目。 + */ +const routes: RouteRecordRaw[] = [ + { + path: "/", + component: DefaultLayout, + children: [ + { + path: "", + name: "Home", + component: HomeView, + meta: { title: "官方网站" }, + }, + + // ---------------- 新闻中心 ---------------- + { + path: "news", + name: "News", + component: ListView, + meta: { title: "新闻中心" }, + }, + { + path: "news/category/:slug", + name: "NewsCategory", + component: ListView, + meta: { title: "新闻中心" }, + }, + { + path: "news/detail/:slug", + name: "NewsDetail", + component: DetailView, + meta: { title: "新闻详情" }, + }, + + // ---------------- 产品中心 ---------------- + { + path: "products", + name: "Products", + component: ListView, + meta: { title: "产品中心" }, + }, + { + path: "products/category/:slug", + name: "ProductCategory", + component: ListView, + meta: { title: "产品中心" }, + }, + { + path: "products/detail/:slug", + name: "ProductDetail", + component: DetailView, + meta: { title: "产品详情" }, + }, + + // ---------------- 解决方案 ---------------- + { + path: "solutions", + name: "Solutions", + component: ListView, + meta: { title: "解决方案" }, + }, + { + path: "solutions/category/:slug", + name: "SolutionCategory", + component: ListView, + meta: { title: "解决方案" }, + }, + { + path: "solutions/detail/:slug", + name: "SolutionDetail", + component: DetailView, + meta: { title: "方案详情" }, + }, + + // ---------------- 客户案例 ---------------- + { + path: "cases", + name: "Cases", + component: ListView, + meta: { title: "客户案例" }, + }, + { + path: "cases/category/:slug", + name: "CaseCategory", + component: ListView, + meta: { title: "客户案例" }, + }, + { + path: "cases/detail/:slug", + name: "CaseDetail", + component: DetailView, + meta: { title: "案例详情" }, + }, + + // ---------------- 市场活动 ---------------- + { + path: "events", + name: "Events", + component: ListView, + meta: { title: "市场活动" }, + }, + { + path: "events/category/:slug", + name: "EventCategory", + component: ListView, + meta: { title: "市场活动" }, + }, + { + path: "events/detail/:slug", + name: "EventDetail", + component: DetailView, + meta: { title: "活动详情" }, + }, + + // ---------------- 独立单页 ---------------- + { + path: "about", + name: "About", + component: SingleView, + meta: { title: "关于云泽" }, + }, + { + path: "careers", + name: "Careers", + component: SingleView, + meta: { title: "加入我们" }, + }, + { + path: "partners", + name: "Partners", + component: SingleView, + meta: { title: "合作伙伴" }, + }, + { + path: "contact", + name: "Contact", + component: SingleView, + meta: { title: "联系我们" }, + }, + { + path: "support", + name: "Support", + component: SingleView, + meta: { title: "客户支持中心" }, + }, + { + path: "support/:slug", + name: "SupportDetail", + component: SingleView, + meta: { title: "客户支持" }, + }, + { + path: "policy/:slug", + name: "Policy", + component: SingleView, + meta: { title: "政策条款" }, + }, + + // ---------------- 兜底 ---------------- + { + path: ":pathMatch(.*)*", + name: "NotFound", + component: NotFoundView, + meta: { title: "页面不存在" }, + }, + ], + }, +]; + +const router = createRouter({ + history: createWebHashHistory(), // 哈希模式 + routes, + scrollBehavior(_to, _from, savedPosition) { + if (savedPosition) return savedPosition; + return { top: 0 }; + }, +}); + +/** 根据路由 meta 同步浏览器标题 */ +router.afterEach((to) => { + const title = (to.meta.title as string | undefined) ?? ""; + document.title = title ? `${title} | 云泽科技` : "云泽科技 | 官方网站"; +}); + +export default router; diff --git a/website/src/store/actions.ts b/website/src/store/actions.ts new file mode 100644 index 0000000..fcc79a0 --- /dev/null +++ b/website/src/store/actions.ts @@ -0,0 +1,3 @@ +//actions.ts +const actions= {}; +export default actions; diff --git a/website/src/store/index.ts b/website/src/store/index.ts new file mode 100644 index 0000000..cabda5e --- /dev/null +++ b/website/src/store/index.ts @@ -0,0 +1,12 @@ +//index.ts +import { createStore } from "vuex"; +import state from "./state"; +import mutations from "./mutations"; +import actions from "./actions"; +const store = createStore({ + state, + mutations, + actions, + modules: {}, +}); +export default store; diff --git a/website/src/store/mutations.ts b/website/src/store/mutations.ts new file mode 100644 index 0000000..30ab601 --- /dev/null +++ b/website/src/store/mutations.ts @@ -0,0 +1,3 @@ +//mutations.ts +const mutations= {}; +export default mutations; diff --git a/website/src/store/state.ts b/website/src/store/state.ts new file mode 100644 index 0000000..c3d24c4 --- /dev/null +++ b/website/src/store/state.ts @@ -0,0 +1,3 @@ +//state.ts +const state= {}; +export default state; diff --git a/website/src/styles/base.less b/website/src/styles/base.less new file mode 100644 index 0000000..6e7d885 --- /dev/null +++ b/website/src/styles/base.less @@ -0,0 +1,148 @@ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; +} + +body { + font-family: "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", + "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; + font-size: 16px; + line-height: 1.6; + color: @ink-700; + background: @white; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +h1, +h2, +h3, +h4, +h5, +p, +figure { + margin: 0; + font-weight: inherit; +} + +ul, +ol { + margin: 0; + padding: 0; + list-style: none; +} + +a { + color: inherit; + text-decoration: none; +} + +img { + display: block; + max-width: 100%; +} + +button { + padding: 0; + border: 0; + background: none; + font: inherit; + color: inherit; + cursor: pointer; +} + +input, +textarea { + font: inherit; +} + +.container { + width: 100%; + max-width: @page-width; + margin: 0 auto; + padding: 0 @page-gutter; +} + +// 通用:横向滚动时隐藏滚动条 +.no-scrollbar { + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } +} + +// 通用圆形箭头按钮 +.circle-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 50%; + border: 1px solid @ink-300; + color: @ink-700; + background: @white; + transition: all 0.25s ease; + + svg { + width: 16px; + height: 16px; + } + + &:hover:not(:disabled) { + background: @navy-800; + border-color: @navy-800; + color: @white; + } + + &:disabled { + opacity: 0.35; + cursor: not-allowed; + } +} + +// 通用:封面配色(暂用渐变替代实拍图,后续可换成 img) +.tone-navy { + background: linear-gradient(140deg, #1b2f6e 0%, #0b1430 100%); +} + +.tone-blue { + background: linear-gradient(140deg, #3f7bff 0%, #2450d8 100%); +} + +.tone-teal { + background: linear-gradient(140deg, #22c2a0 0%, #17a88f 100%); +} + +.tone-indigo { + background: linear-gradient(140deg, #5b5ee8 0%, #3a3dbf 100%); +} + +// 通用:淡入上移动画 +.fade-up { + animation: fadeUp 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) both; +} + +@keyframes fadeUp { + from { + opacity: 0; + transform: translateY(28px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/website/src/styles/index.less b/website/src/styles/index.less new file mode 100644 index 0000000..a9feaa5 --- /dev/null +++ b/website/src/styles/index.less @@ -0,0 +1,2 @@ +@import "./variables.less"; +@import "./base.less"; diff --git a/website/src/styles/variables.less b/website/src/styles/variables.less new file mode 100644 index 0000000..d7e294f --- /dev/null +++ b/website/src/styles/variables.less @@ -0,0 +1,27 @@ +// ============ 品牌色 ============ +@navy-900: #0b1430; // 页脚 / 最深 +@navy-800: #142352; // 主色:深蓝区块 +@navy-700: #1b2f6e; +@navy-600: #24418f; +@blue-600: #2f6bf3; // 强调蓝 +@blue-500: #4b83ff; +@teal-600: #17a88f; // 右侧卡片 +@teal-500: #22c2a0; +@green-400: #2ec89b; // 小竖条 +@indigo-500: #4a4ddb; + +// ============ 中性色 ============ +@ink-900: #14161c; +@ink-800: #232733; +@ink-700: #3c4252; +@ink-600: #5b6376; +@ink-500: #838c9f; +@ink-400: #a9b1c1; +@ink-300: #ccd2dd; +@line: #e8ebf2; +@bg-soft: #f4f6fb; +@white: #ffffff; + +// ============ 布局 ============ +@page-width: 1680px; // 内容最大宽度 +@page-gutter: 40px; // 左右安全边距 diff --git a/website/src/types/content.ts b/website/src/types/content.ts new file mode 100644 index 0000000..45a3f6f --- /dev/null +++ b/website/src/types/content.ts @@ -0,0 +1,110 @@ +/** + * 内容模型:列表页 / 详情页 / 单页共用 + * 与后端 CMS(文章、产品、解决方案)字段保持一一对应的思路, + * 后续接入接口时只需替换 data 层的数据来源。 + */ + +/** 栏目标识 */ +export type SectionKey = "news" | "products" | "solutions" | "cases" | "events"; + +/** 分类 */ +export interface Category { + slug: string; + name: string; + desc?: string; +} + +/** 封面配色(暂用渐变替代实拍图) */ +export type CoverTone = "navy" | "blue" | "teal" | "indigo"; + +export interface Feature { + icon: string; + title: string; + desc: string; +} + +export interface Stat { + value: string; + label: string; +} + +export interface Step { + title: string; + desc: string; +} + +export interface TimelineNode { + year: string; + text: string; +} + +export interface ContactRow { + icon: string; + label: string; + value: string; +} + +export interface QuickLink { + icon: string; + title: string; + desc: string; + path: string; +} + +/** 正文区块:详情页与单页共用同一套渲染器 */ +export type Block = + | { type: "heading"; text: string; sub?: string } + | { type: "paragraph"; text: string } + | { type: "quote"; text: string; author?: string } + | { type: "list"; items: string[] } + | { type: "features"; items: Feature[] } + | { type: "stats"; items: Stat[] } + | { type: "steps"; items: Step[] } + | { type: "timeline"; items: TimelineNode[] } + | { type: "contact"; items: ContactRow[] } + | { type: "links"; items: QuickLink[] } + | { type: "table"; head: string[]; rows: string[][] }; + +/** 一条内容(新闻 / 产品 / 方案 / 案例 / 活动) */ +export interface ContentItem { + slug: string; + section: SectionKey; + /** 分类 slug */ + category: string; + title: string; + subtitle: string; + summary: string; + tone: CoverTone; + date?: string; + author?: string; + tags?: string[]; + featured?: boolean; + blocks: Block[]; +} + +/** 独立单页 */ +export interface SinglePage { + title: string; + subtitle: string; + /** 面包屑(不含"首页") */ + crumbs: string[]; + tone: CoverTone; + blocks: Block[]; +} + +/** 列表查询参数 */ +export interface ListQuery { + section: SectionKey; + category?: string; + keyword?: string; + page?: number; + pageSize?: number; +} + +export interface ListResult { + list: ContentItem[]; + total: number; + page: number; + pageSize: number; + totalPages: number; +} diff --git a/website/src/types/shims.d.ts b/website/src/types/shims.d.ts new file mode 100644 index 0000000..64c6577 --- /dev/null +++ b/website/src/types/shims.d.ts @@ -0,0 +1,8 @@ +// 补充第三方库缺失的类型声明 +declare module "vuex"; + +declare module "*.vue" { + import type { DefineComponent } from "vue"; + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/website/src/views/detail.vue b/website/src/views/detail.vue new file mode 100644 index 0000000..3818a7b --- /dev/null +++ b/website/src/views/detail.vue @@ -0,0 +1,540 @@ + + + + + diff --git a/website/src/views/home/components/HeroBanner.vue b/website/src/views/home/components/HeroBanner.vue new file mode 100644 index 0000000..eb5915b --- /dev/null +++ b/website/src/views/home/components/HeroBanner.vue @@ -0,0 +1,302 @@ + + + + + diff --git a/website/src/views/home/components/NewsSection.vue b/website/src/views/home/components/NewsSection.vue new file mode 100644 index 0000000..2813b10 --- /dev/null +++ b/website/src/views/home/components/NewsSection.vue @@ -0,0 +1,519 @@ + + + + + diff --git a/website/src/views/home/components/NoticeSection.vue b/website/src/views/home/components/NoticeSection.vue new file mode 100644 index 0000000..904cf04 --- /dev/null +++ b/website/src/views/home/components/NoticeSection.vue @@ -0,0 +1,637 @@ + + + + + diff --git a/website/src/views/home/components/QuickService.vue b/website/src/views/home/components/QuickService.vue new file mode 100644 index 0000000..3da4b84 --- /dev/null +++ b/website/src/views/home/components/QuickService.vue @@ -0,0 +1,268 @@ + + + + + diff --git a/website/src/views/home/components/ScheduleSection.vue b/website/src/views/home/components/ScheduleSection.vue new file mode 100644 index 0000000..a078dfa --- /dev/null +++ b/website/src/views/home/components/ScheduleSection.vue @@ -0,0 +1,436 @@ + + + + + diff --git a/website/src/views/home/index.vue b/website/src/views/home/index.vue new file mode 100644 index 0000000..9345e62 --- /dev/null +++ b/website/src/views/home/index.vue @@ -0,0 +1,23 @@ + + + + + diff --git a/website/src/views/list.vue b/website/src/views/list.vue new file mode 100644 index 0000000..7e69889 --- /dev/null +++ b/website/src/views/list.vue @@ -0,0 +1,297 @@ + + + + + diff --git a/website/src/views/not-found.vue b/website/src/views/not-found.vue new file mode 100644 index 0000000..b88042d --- /dev/null +++ b/website/src/views/not-found.vue @@ -0,0 +1,174 @@ + + + + + diff --git a/website/src/views/single.vue b/website/src/views/single.vue new file mode 100644 index 0000000..92ef824 --- /dev/null +++ b/website/src/views/single.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/website/tsconfig.app.json b/website/tsconfig.app.json new file mode 100644 index 0000000..f20b001 --- /dev/null +++ b/website/tsconfig.app.json @@ -0,0 +1,19 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "types": ["vite/client"], + "allowArbitraryExtensions": true, + "paths": { + "@/*": ["./src/*"], + "@c/*": ["./src/components/*"] + }, + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/website/tsconfig.json b/website/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/website/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/website/tsconfig.node.json b/website/tsconfig.node.json new file mode 100644 index 0000000..8455dcb --- /dev/null +++ b/website/tsconfig.node.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "es2023", + "lib": ["ES2023"], + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "module": "nodenext", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/website/vite.config.ts b/website/vite.config.ts new file mode 100644 index 0000000..1deb3d5 --- /dev/null +++ b/website/vite.config.ts @@ -0,0 +1,74 @@ +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' +import { defineConfig } from 'vite' + +// Less 全局变量文件(Windows 下需统一为 / 分隔符,否则 less 无法解析) +const lessVariables = resolve(import.meta.dirname, 'src/styles/variables.less').replace( + /\\/g, + '/', +) + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + "@": resolve(import.meta.dirname, "src"), + "@c": resolve(import.meta.dirname, "src/components"), + "/images": "src/assets/images/", + }, + }, + server: { + open: true, + host: '127.0.0.1', + port: 4002, + hmr: true, + proxy: { + '/api': { + target: 'http://127.0.0.1:9000', + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + } + } + }, + css: { + // 全局变量+全局引入less+配置主题色 + preprocessorOptions: { + less: { + javascriptEnabled: true, + // 全局注入设计变量,组件内无需重复 @import + additionalData: `@import "${lessVariables}";`, + // 全局变量使用:@primary-color + modifyVars: { + "primary-color": "#1890ff", // 全局主色 + "link-color": " #1890ff", // 链接色 + "success-color": " #52c41a", // 成功色 + "warning-color": " #faad14", // 警告色 + "error-color": " #ff4d4f", // 错误色 + "font-size-base": " 14px", // 主字号 + /*light浅色背景下*/ + "light-headline": "#262626", // 标题色 + "light-text": "#595959", // 主要文字 + "light-text-secondary": "#8c8c8c", // 次要文字 + "light-disabled": "#bfbfbf", // 禁用 + "light-border": " #d9d9d9", // 边框色 + "light-cut-off-rule": " #f0f0f0", // 分割线 + "light-bg": " #f5f5f5", // 背景 + "light-table-headline": " #fafafa", // 表格标题 + /*dark深色背景下*/ + "dark-headline": "#262626", // 标题色 + "dark-text": "#595959", // 主要文字 + "dark-text-secondary": "#8c8c8c", // 次要文字 + "dark-disabled": "#bfbfbf", // 禁用 + "dark-border": " #d9d9d9", // 边框色 + "dark-cut-off-rule": " #f0f0f0", // 分割线 + "dark-bg": " #f5f5f5", // 背景 + "dark-table-headline": " #fafafa", // 表格标题 + /*边框配置*/ + "border-radius-base": " 2px", // 组件/浮层圆角 + "box-shadow-base": " 0 2px 8px rgba(0, 0, 0, 0.15)", // 浮层阴影 + }, + }, + }, + }, +})