From 56ebfda34e98715104045778e90e50c2aabeb6ad Mon Sep 17 00:00:00 2001 From: fanfpy Date: Thu, 17 Jul 2025 17:48:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E6=A0=B8=E5=BF=83=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97=E4=B8=8E?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增多个功能页面包括AI投资、股票市场、收益预测等,并完成路由配置 添加登录注册页面及功能,实现全局错误处理 引入Element Plus UI库,优化移动端导航体验 创建仪表盘和主页布局,完善侧边栏和底部导航组件 --- services/frontend/package-lock.json | 235 ++++++++++++++- services/frontend/package.json | 9 +- services/frontend/src/App.vue | 197 ++---------- .../src/components/MobileBottomNav.vue | 52 ++++ services/frontend/src/components/Sidebar.vue | 98 ++++++ services/frontend/src/main.js | 28 +- services/frontend/src/router/index.js | 84 ++++++ services/frontend/src/views/Index.vue | 157 ++++++++++ .../src/views/private/AiInvestment.vue | 12 + .../frontend/src/views/private/Dashboard.vue | 88 ++++++ .../src/views/private/EarningsPrediction.vue | 12 + .../frontend/src/views/private/History.vue | 12 + services/frontend/src/views/private/Home.vue | 90 ++++++ .../src/views/private/StockMarket.vue | 12 + .../src/views/private/TradingNews.vue | 12 + services/frontend/src/views/public/Index.vue | 157 ++++++++++ services/frontend/src/views/public/Login.vue | 200 ++++++++++++ services/frontend/src/views/public/SignUp.vue | 285 ++++++++++++++++++ 18 files changed, 1566 insertions(+), 174 deletions(-) create mode 100644 services/frontend/src/components/MobileBottomNav.vue create mode 100644 services/frontend/src/components/Sidebar.vue create mode 100644 services/frontend/src/router/index.js create mode 100644 services/frontend/src/views/Index.vue create mode 100644 services/frontend/src/views/private/AiInvestment.vue create mode 100644 services/frontend/src/views/private/Dashboard.vue create mode 100644 services/frontend/src/views/private/EarningsPrediction.vue create mode 100644 services/frontend/src/views/private/History.vue create mode 100644 services/frontend/src/views/private/Home.vue create mode 100644 services/frontend/src/views/private/StockMarket.vue create mode 100644 services/frontend/src/views/private/TradingNews.vue create mode 100644 services/frontend/src/views/public/Index.vue create mode 100644 services/frontend/src/views/public/Login.vue create mode 100644 services/frontend/src/views/public/SignUp.vue diff --git a/services/frontend/package-lock.json b/services/frontend/package-lock.json index 6be00d0..38092ee 100644 --- a/services/frontend/package-lock.json +++ b/services/frontend/package-lock.json @@ -9,8 +9,9 @@ "version": "0.1.0", "dependencies": { "axios": "^1.3.4", + "element-plus": "^2.10.4", "vue": "^3.2.45", - "vue-router": "^4.1.6" + "vue-router": "^4.5.1" }, "devDependencies": { "@vue/cli-service": "~5.0.8", @@ -148,6 +149,15 @@ "node": ">=6.9.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -158,6 +168,15 @@ "node": ">=10.0.0" } }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", + "integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", @@ -221,6 +240,31 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.2.tgz", + "integrity": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.2.tgz", + "integrity": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.2", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -504,6 +548,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -705,6 +760,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -817,6 +887,12 @@ "@types/node": "*" } }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -1283,6 +1359,94 @@ "dev": true, "license": "MIT" }, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "license": "MIT", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", @@ -1739,6 +1903,12 @@ "dev": true, "license": "MIT" }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2890,6 +3060,12 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -3280,6 +3456,32 @@ "dev": true, "license": "ISC" }, + "node_modules/element-plus": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.10.4.tgz", + "integrity": "sha512-UD4elWHrCnp1xlPhbXmVcaKFLCRaRAY6WWRwemGfGW3ceIjXm9fSYc9RNH3AiOEA6Ds1p9ZvhCs76CR9J8Vd+A==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.1", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.14.182", + "@types/lodash-es": "^4.17.6", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.13", + "escape-html": "^1.0.3", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.2", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3429,7 +3631,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, "license": "MIT" }, "node_modules/escape-string-regexp": { @@ -5354,9 +5555,25 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, "node_modules/lodash.defaultsdeep": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", @@ -5620,6 +5837,12 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -6057,6 +6280,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, "node_modules/npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", diff --git a/services/frontend/package.json b/services/frontend/package.json index 201e658..dc28578 100644 --- a/services/frontend/package.json +++ b/services/frontend/package.json @@ -3,14 +3,15 @@ "version": "0.1.0", "private": true, "scripts": { - "serve": "vue-cli-service serve", - "build": "vue-cli-service build", - "lint": "vue-cli-service lint" + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint" }, "dependencies": { "axios": "^1.3.4", + "element-plus": "^2.10.4", "vue": "^3.2.45", - "vue-router": "^4.1.6" + "vue-router": "^4.5.1" }, "devDependencies": { "@vue/cli-service": "~5.0.8", diff --git a/services/frontend/src/App.vue b/services/frontend/src/App.vue index 0e50b89..714895c 100644 --- a/services/frontend/src/App.vue +++ b/services/frontend/src/App.vue @@ -1,7 +1,7 @@ - - - - \ No newline at end of file + }, + mounted() { + // 应用保存的主题 + document.documentElement.classList.toggle('dark', this.theme === 'dark'); + }, + methods: { + toggleTheme() { + this.theme = this.theme === 'dark' ? 'light' : 'dark'; + localStorage.setItem('theme', this.theme); + document.documentElement.classList.toggle('dark', this.theme === 'dark'); + } + } +} + + + \ No newline at end of file diff --git a/services/frontend/src/components/MobileBottomNav.vue b/services/frontend/src/components/MobileBottomNav.vue new file mode 100644 index 0000000..37b9864 --- /dev/null +++ b/services/frontend/src/components/MobileBottomNav.vue @@ -0,0 +1,52 @@ + + + + + \ No newline at end of file diff --git a/services/frontend/src/components/Sidebar.vue b/services/frontend/src/components/Sidebar.vue new file mode 100644 index 0000000..57e9323 --- /dev/null +++ b/services/frontend/src/components/Sidebar.vue @@ -0,0 +1,98 @@ + + + + + \ No newline at end of file diff --git a/services/frontend/src/main.js b/services/frontend/src/main.js index 160b96d..605bf0d 100644 --- a/services/frontend/src/main.js +++ b/services/frontend/src/main.js @@ -1,5 +1,31 @@ import './styles.css' import { createApp } from 'vue' import App from './App.vue' +import router from './router' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' -createApp(App).mount('#app') \ No newline at end of file +const app = createApp(App).use(router).use(ElementPlus) +// 添加全局错误处理 +app.config.errorHandler = (err, vm, info) => { + console.error('Vue全局错误捕获:', err, vm, info); + const errorDetails = err.message || err.toString(); + alert(`Vue错误: ${errorDetails}\n\n详细信息请查看控制台`); + } + + // 捕获window全局错误 + window.addEventListener('error', (event) => { + console.error('Window全局错误:', event.error); + const errorDetails = event.error?.message || event.error?.toString() || '未知错误'; + alert(`Window错误: ${errorDetails}\n\n详细信息请查看控制台`); + }); + + // 捕获未处理的Promise拒绝 + window.addEventListener('unhandledrejection', (event) => { + console.error('未处理的Promise拒绝:', event.reason); + const errorDetails = event.reason?.message || event.reason?.toString() || '未知Promise错误'; + alert(`Promise错误: ${errorDetails}\n\n详细信息请查看控制台`); + event.preventDefault(); + }); + +app.mount('#app') \ No newline at end of file diff --git a/services/frontend/src/router/index.js b/services/frontend/src/router/index.js new file mode 100644 index 0000000..710fabd --- /dev/null +++ b/services/frontend/src/router/index.js @@ -0,0 +1,84 @@ +import { createRouter, createWebHistory } from 'vue-router'; +import Home from '../views/private/Home.vue'; +import Dashboard from '../views/private/Dashboard.vue'; +import AiInvestment from '../views/private/AiInvestment.vue'; +import StockMarket from '../views/private/StockMarket.vue'; +import EarningsPrediction from '../views/private/EarningsPrediction.vue'; +import TradingNews from '../views/private/TradingNews.vue'; +import History from '../views/private/History.vue'; +import Login from '../views/public/Login.vue'; +import SignUp from '../views/public/SignUp.vue'; + +const routes = [ + { + path: '/', + name: 'Landing', + component: () => import('@/views/public/Index.vue') + }, + { + path: '/home', + name: 'Home', + component: Home, + meta: { requiresAuth: true }, + children: [ + { + path: '', + name: 'Dashboard', + component: Dashboard + }, + { + path: 'ai-investment', + name: 'AiInvestment', + component: AiInvestment + }, + { + path: 'stock-market', + name: 'StockMarket', + component: StockMarket + }, + { + path: 'earnings-prediction', + name: 'EarningsPrediction', + component: EarningsPrediction + }, + { + path: 'trading-news', + name: 'TradingNews', + component: TradingNews + }, + { + path: 'history', + name: 'History', + component: History + } + ] + }, + { + path: '/login', + name: 'Login', + component: Login + }, + { + path: '/sign-up', + name: 'SignUp', + component: SignUp + } +]; + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +// 路由守卫 +router.beforeEach((to, from, next) => { + const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true'; + // 需要登录的路由 + if (to.meta.requiresAuth && !isLoggedIn) { + next('/login'); + } else { + next(); + } +}) + +export default router; \ No newline at end of file diff --git a/services/frontend/src/views/Index.vue b/services/frontend/src/views/Index.vue new file mode 100644 index 0000000..85d7452 --- /dev/null +++ b/services/frontend/src/views/Index.vue @@ -0,0 +1,157 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/AiInvestment.vue b/services/frontend/src/views/private/AiInvestment.vue new file mode 100644 index 0000000..5119fe4 --- /dev/null +++ b/services/frontend/src/views/private/AiInvestment.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/Dashboard.vue b/services/frontend/src/views/private/Dashboard.vue new file mode 100644 index 0000000..3d4e438 --- /dev/null +++ b/services/frontend/src/views/private/Dashboard.vue @@ -0,0 +1,88 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/EarningsPrediction.vue b/services/frontend/src/views/private/EarningsPrediction.vue new file mode 100644 index 0000000..cf3303d --- /dev/null +++ b/services/frontend/src/views/private/EarningsPrediction.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/History.vue b/services/frontend/src/views/private/History.vue new file mode 100644 index 0000000..d1af0b0 --- /dev/null +++ b/services/frontend/src/views/private/History.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/Home.vue b/services/frontend/src/views/private/Home.vue new file mode 100644 index 0000000..2ad1418 --- /dev/null +++ b/services/frontend/src/views/private/Home.vue @@ -0,0 +1,90 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/StockMarket.vue b/services/frontend/src/views/private/StockMarket.vue new file mode 100644 index 0000000..bc3ada3 --- /dev/null +++ b/services/frontend/src/views/private/StockMarket.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/private/TradingNews.vue b/services/frontend/src/views/private/TradingNews.vue new file mode 100644 index 0000000..532c54a --- /dev/null +++ b/services/frontend/src/views/private/TradingNews.vue @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/public/Index.vue b/services/frontend/src/views/public/Index.vue new file mode 100644 index 0000000..85d7452 --- /dev/null +++ b/services/frontend/src/views/public/Index.vue @@ -0,0 +1,157 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/public/Login.vue b/services/frontend/src/views/public/Login.vue new file mode 100644 index 0000000..28ca028 --- /dev/null +++ b/services/frontend/src/views/public/Login.vue @@ -0,0 +1,200 @@ + + + \ No newline at end of file diff --git a/services/frontend/src/views/public/SignUp.vue b/services/frontend/src/views/public/SignUp.vue new file mode 100644 index 0000000..7ba03e6 --- /dev/null +++ b/services/frontend/src/views/public/SignUp.vue @@ -0,0 +1,285 @@ + + + \ No newline at end of file