feat: 实现前端核心功能模块与路由配置

新增多个功能页面包括AI投资、股票市场、收益预测等,并完成路由配置
添加登录注册页面及功能,实现全局错误处理
引入Element Plus UI库,优化移动端导航体验
创建仪表盘和主页布局,完善侧边栏和底部导航组件
This commit is contained in:
fanfpy 2025-07-17 17:48:14 +08:00
parent f13a25c40e
commit 56ebfda34e
18 changed files with 1566 additions and 174 deletions

View File

@ -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",

View File

@ -9,8 +9,9 @@
},
"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",

View File

@ -1,7 +1,7 @@
<template>
<div id="app" :class="[theme === 'dark' ? 'bg-gray-900 text-white' : 'bg-gray-50 text-gray-900', 'min-h-screen flex flex-col']">
<!-- 导航栏 -->
<header class="sticky top-0 z-50" :class="theme === 'dark' ? 'bg-gray-900/80 backdrop-blur-md border-b border-gray-800' : 'bg-white/80 backdrop-blur-md border-b border-gray-200'">
<header v-if="['Landing', 'Login', 'SignUp'].includes($route.name)" class="sticky top-0 z-50" :class="theme === 'dark' ? 'bg-gray-900/80 backdrop-blur-md border-b border-gray-800' : 'bg-white/80 backdrop-blur-md border-b border-gray-200'">
<div class="container mx-auto px-4 py-4 flex justify-between items-center">
<div class="flex items-center space-x-2">
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center">
@ -22,148 +22,13 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
</button>
<button class="hidden md:block px-4 py-2 rounded-lg" :class="theme === 'dark' ? 'border border-gray-700 hover:bg-gray-800' : 'border border-gray-300 hover:bg-gray-100'">登录</button>
<button class="px-4 py-2 rounded-lg bg-gradient-to-r from-green-500 to-blue-600 hover:opacity-90 transition-opacity">开始使用</button>
<button @click="$router.push('/sign-up')" class="px-4 py-2 rounded-lg bg-gradient-to-r from-green-500 to-blue-600 hover:opacity-90 transition-opacity">开始使用</button>
</div>
</div>
</header>
<!-- 主页区域 -->
<section class="relative py-20 overflow-hidden">
<div class="absolute inset-0" :class="theme === 'dark' ? 'bg-[radial-gradient(circle_at_top_right,_rgba(79,70,229,0.15),_transparent_70%)]' : 'bg-[radial-gradient(circle_at_top_right,_rgba(79,70,229,0.05),_transparent_70%)]'"></div>
<div class="container mx-auto px-4 relative z-10">
<div class="max-w-3xl mx-auto text-center">
<div class="inline-block px-3 py-1 rounded-full" :class="theme === 'dark' ? 'bg-gray-800 text-green-400' : 'bg-gray-200 text-green-600'">
由AI驱动的智能投资平台
</div>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 leading-tight">
The Most Powerful AI Platform for <span class="text-transparent bg-clip-text bg-gradient-to-r from-green-400 to-blue-500">Smarter Investment</span>
</h1>
<p class="text-xl mb-10 max-w-2xl mx-auto" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
利用人工智能技术分析市场趋势提供精准选股建议帮助投资者做出更明智的决策
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4">
<button class="px-8 py-4 rounded-xl bg-gradient-to-r from-green-500 to-blue-600 hover:opacity-90 transition-opacity text-lg font-medium">
免费试用 14
</button>
<button class="px-8 py-4 rounded-xl" :class="theme === 'dark' ? 'bg-gray-800 hover:bg-gray-700' : 'bg-gray-200 hover:bg-gray-300'">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
观看演示
</button>
</div>
</div>
</div>
</section>
<!-- 核心功能模块 -->
<section id="features" class="py-20" :class="theme === 'dark' ? 'bg-gray-900 border-t border-gray-800' : 'bg-white border-t border-gray-200'">
<div class="container mx-auto px-4">
<div class="text-center mb-16">
<div class="inline-block px-3 py-1 rounded-full" :class="theme === 'dark' ? 'bg-gray-800 text-blue-400' : 'bg-gray-200 text-blue-600'">
核心功能
</div>
<h2 class="text-3xl md:text-4xl font-bold mb-6">AI驱动的智能股票分析与投资决策平台</h2>
<p class="text-xl max-w-3xl mx-auto" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
集成五大核心功能模块提供全方位的股票数据分析与投资决策支持
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- 每日股票推荐 -->
<div :class="theme === 'dark' ? 'bg-gray-800/50 border border-gray-800' : 'bg-white border border-gray-200'" class="rounded-2xl p-6 hover:border-blue-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-blue-500/20 flex items-center justify-center mb-6 group-hover:bg-blue-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">每日股票推荐</h3>
<p :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'" class="mb-4">
基于机器学习算法每日推送潜力股票推荐列表结合市场趋势与历史数据分析助您把握投资机会
</p>
<ul class="space-y-2 text-sm" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多因子模型评估</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 风险收益比分析</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 行业分布均衡推荐</li>
</ul>
</div>
<!-- 技术分析 -->
<div :class="theme === 'dark' ? 'bg-gray-800/50 border border-gray-800' : 'bg-white border border-gray-200'" class="rounded-2xl p-6 hover:border-green-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-green-500/20 flex items-center justify-center mb-6 group-hover:bg-green-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2v-6a2 2 0 00-2-2h-2a2 2 0 00-2 2v6z" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">技术分析</h3>
<p :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'" class="mb-4">
提供专业级股票技术分析图表支持多种技术指标与周期切换帮助您深入分析股票走势与市场情绪
</p>
<ul class="space-y-2 text-sm" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 实时K线图与指标</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多周期技术分析</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 技术形态识别</li>
</ul>
</div>
<!-- 用户设置股票 -->
<div :class="theme === 'dark' ? 'bg-gray-800/50 border border-gray-800' : 'bg-white border border-gray-200'" class="rounded-2xl p-6 hover:border-purple-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-purple-500/20 flex items-center justify-center mb-6 group-hover:bg-purple-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">用户设置股票</h3>
<p :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'" class="mb-4">
个性化股票关注列表管理支持添加删除和分组管理关注股票实时追踪您关心的市场动态
</p>
<ul class="space-y-2 text-sm" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义关注列表</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 股票分组管理</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 快速访问与排序</li>
</ul>
</div>
<!-- 添加指标 -->
<div :class="theme === 'dark' ? 'bg-gray-800/50 border border-gray-800' : 'bg-white border border-gray-200'" class="rounded-2xl p-6 hover:border-yellow-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-yellow-500/20 flex items-center justify-center mb-6 group-hover:bg-yellow-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">添加指标</h3>
<p :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'" class="mb-4">
灵活的技术指标自定义功能支持添加MACDRSIKDJ等多种技术指标自定义参数与显示样式
</p>
<ul class="space-y-2 text-sm" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 30+技术指标支持</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义指标参数</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多指标组合分析</li>
</ul>
</div>
<!-- 订阅股票的技术信号提醒 -->
<div :class="theme === 'dark' ? 'bg-gray-800/50 border border-gray-800' : 'bg-white border border-gray-200'" class="rounded-2xl p-6 hover:border-red-500/50 transition-all group md:col-span-2 lg:col-span-1">
<div class="w-14 h-14 rounded-xl bg-red-500/20 flex items-center justify-center mb-6 group-hover:bg-red-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">技术信号提醒</h3>
<p :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'" class="mb-4">
智能技术信号监测系统支持自定义股票信号条件实时推送买卖点提醒不错过任何投资机会
</p>
<ul class="space-y-2 text-sm" :class="theme === 'dark' ? 'text-gray-400' : 'text-gray-600'">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义信号条件</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 实时推送提醒</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 历史信号回溯</li>
</ul>
</div>
</div>
</div>
</section>
<!-- 路由视图 -->
<router-view />
<!-- 页脚 -->
<footer class="mt-auto" :class="theme === 'dark' ? 'bg-gray-900 border-t border-gray-800' : 'bg-white border-t border-gray-200'">
@ -173,31 +38,31 @@
</div>
</div>
</footer>
</div>
</template>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
theme: localStorage.getItem('theme') || 'dark'
}
},
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');
}
}
<script>
export default {
name: 'App',
data() {
return {
theme: localStorage.getItem('theme') || 'dark'
}
</script>
},
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');
}
}
}
</script>
<style scoped>
/* 移除默认样式使用Tailwind工具类 */
</style>
<style scoped>
/* 移除默认样式使用Tailwind工具类 */
</style>

View File

@ -0,0 +1,52 @@
<template>
<div class="fixed bottom-0 left-0 right-0 bg-gray-900 border-t border-gray-800 z-40 px-4 py-2 md:hidden">
<div class="flex justify-around items-center">
<router-link to="/home" class="flex flex-col items-center py-1 px-3 rounded-md" active-class="text-green-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h12a1 1 0 001-1v-4a1 1 0 00-1-1h-2a1 1 0 00-1 1v4a1 1 0 01-1 1m-6 0a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1m-6 0h12a1 1 0 001-1v-2a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 01-1 1"/>
</svg>
<span class="text-xs mt-1">我的主页</span>
</router-link>
<router-link to="/home/ai-investment" class="flex flex-col items-center py-1 px-3 rounded-md" active-class="text-green-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
</svg>
<span class="text-xs mt-1">AI投资</span>
</router-link>
<router-link to="/home/stock-market" class="flex flex-col items-center py-1 px-3 rounded-md" active-class="text-green-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2"/>
</svg>
<span class="text-xs mt-1">股票市场</span>
</router-link>
<router-link to="/home/earnings-prediction" class="flex flex-col items-center py-1 px-3 rounded-md" active-class="text-green-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
<span class="text-xs mt-1">收益预测</span>
</router-link>
<router-link to="/home/trading-news" class="flex flex-col items-center py-1 px-3 rounded-md" active-class="text-green-500">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10l4 4h-6a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
<span class="text-xs mt-1">交易新闻</span>
</router-link>
</div>
</div>
</template>
<script>
export default {
name: 'MobileBottomNav'
}
</script>
<style scoped>
.router-link-active {
color: #10b981;
}
</style>

View File

@ -0,0 +1,98 @@
<template>
<div class="bg-gray-900 text-gray-100 h-screen w-64 fixed left-0 top-0 p-4 shadow-lg z-10">
<div class="flex items-center mb-8">
<div class="w-8 h-8 bg-gradient-to-r from-green-500 to-blue-600 rounded-md flex items-center justify-center mr-2">
<span class="font-bold text-white">A</span>
</div>
<h1 class="text-xl font-bold">AriStockAI</h1>
</div>
<nav>
<ul class="space-y-1">
<li>
<router-link to="/home" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-800 transition-colors" active-class="bg-gray-800 text-white">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h12a1 1 0 001-1v-4a1 1 0 00-1-1h-2a1 1 0 00-1 1v4a1 1 0 01-1 1m-6 0a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1m-6 0h12a1 1 0 001-1v-2a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 01-1 1"/>
</svg>
<span>首页</span>
</router-link>
</li>
<li>
<router-link to="/home/ai-investment" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-800 transition-colors" active-class="bg-gray-800 text-white">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
</svg>
<span>AI投资</span>
</router-link>
</li>
<li>
<router-link to="/home/stock-market" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-800 transition-colors" active-class="bg-gray-800 text-white">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2"/>
</svg>
<span>股票市场</span>
</router-link>
</li>
<li>
<router-link to="/home/earnings-prediction" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-800 transition-colors" active-class="bg-gray-800 text-white">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
</svg>
<span>收益预测</span>
</router-link>
</li>
<li>
<router-link to="/home/trading-news" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-800 transition-colors" active-class="bg-gray-800 text-white">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10l4 4h-6a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
<span>交易新闻</span>
</router-link>
</li>
<li>
<router-link to="/home/history" class="flex items-center px-4 py-3 rounded-lg hover:bg-gray-800 transition-colors" active-class="bg-gray-800 text-white">
<svg class="w-5 h-5 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span>历史记录</span>
</router-link>
</li>
</ul>
</nav>
<div class="absolute bottom-8 left-0 right-0 px-4">
<div class="bg-gray-800 rounded-lg p-4">
<div class="flex items-center mb-2">
<div class="w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center mr-3">
<span class="text-sm font-medium">F</span>
</div>
<div>
<p class="text-sm font-medium">fanfpy@qq.com</p>
<p class="text-xs text-gray-400">高级会员</p>
</div>
</div>
<button @click="handleLogout" class="w-full py-2 text-sm text-gray-300 hover:text-white bg-gray-700 rounded-lg transition-colors">
退出登录
</button>
</div>
</div>
</div>
</template>
<script>
import { ElMessage } from 'element-plus';
export default {
name: 'Sidebar',
methods: {
handleLogout() {
localStorage.removeItem('isLoggedIn');
this.$router.push('/');
ElMessage.success('已成功退出登录');
}
}
}
</script>
<style scoped>
/* 侧边栏样式已通过Tailwind实现 */
</style>

View File

@ -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')
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')

View File

@ -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;

View File

@ -0,0 +1,157 @@
<template>
<div class="min-h-screen bg-gray-900 text-white">
<!-- 英雄区域 -->
<section class="relative py-20 overflow-hidden">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_top_right,_rgba(79,70,229,0.15),_transparent_70%)]"></div>
<div class="container mx-auto px-4 relative z-10">
<div class="max-w-3xl mx-auto text-center">
<div class="inline-block px-3 py-1 rounded-full bg-gray-800 text-green-400 mb-6">
由AI驱动的智能投资平台
</div>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 leading-tight">
The Most Powerful AI Platform for <span class="text-transparent bg-clip-text bg-gradient-to-r from-green-400 to-blue-500">Smarter Investment</span>
</h1>
<p class="text-xl mb-10 max-w-2xl mx-auto text-gray-400">
利用人工智能技术分析市场趋势提供精准选股建议帮助投资者做出更明智的决策
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4">
<button class="px-8 py-4 rounded-xl bg-gradient-to-r from-green-500 to-blue-600 hover:opacity-90 transition-opacity text-lg font-medium" @click="handleStartUsing">
开始使用
</button>
<button class="px-8 py-4 rounded-xl bg-gray-800 hover:bg-gray-700 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
观看演示
</button>
</div>
</div>
</div>
</section>
<!-- 核心功能模块 -->
<section id="features" class="py-20 bg-gray-900 border-t border-gray-800">
<div class="container mx-auto px-4">
<div class="text-center mb-16">
<div class="inline-block px-3 py-1 rounded-full bg-gray-800 text-blue-400 mb-4">
核心功能
</div>
<h2 class="text-3xl md:text-4xl font-bold mb-6">AI驱动的智能股票分析与投资决策平台</h2>
<p class="text-xl max-w-3xl mx-auto text-gray-400">
集成五大核心功能模块提供全方位的股票数据分析与投资决策支持
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- 每日股票推荐 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-blue-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-blue-500/20 flex items-center justify-center mb-6 group-hover:bg-blue-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">每日股票推荐</h3>
<p class="text-gray-400 mb-4">
基于机器学习算法每日推送潜力股票推荐列表结合市场趋势与历史数据分析助您把握投资机会
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多因子模型评估</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 风险收益比分析</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 行业分布均衡推荐</li>
</ul>
</div>
<!-- 技术分析 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-green-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-green-500/20 flex items-center justify-center mb-6 group-hover:bg-green-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2v-6a2 2 0 00-2-2h-2a2 2 0 00-2 2v6z" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">技术分析</h3>
<p class="text-gray-400 mb-4">
提供专业级股票技术分析图表支持多种技术指标与周期切换帮助您深入分析股票走势与市场情绪
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 实时K线图与指标</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多周期技术分析</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 技术形态识别</li>
</ul>
</div>
<!-- 用户设置股票 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-purple-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-purple-500/20 flex items-center justify-center mb-6 group-hover:bg-purple-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">用户设置股票</h3>
<p class="text-gray-400 mb-4">
个性化股票关注列表管理支持添加删除和分组管理关注股票实时追踪您关心的市场动态
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义关注列表</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 股票分组管理</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 快速访问与排序</li>
</ul>
</div>
<!-- 添加指标 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-yellow-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-yellow-500/20 flex items-center justify-center mb-6 group-hover:bg-yellow-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">添加指标</h3>
<p class="text-gray-400 mb-4">
灵活的技术指标自定义功能支持添加MACDRSIKDJ等多种技术指标自定义参数与显示样式
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 30+技术指标支持</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义指标参数</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多指标组合分析</li>
</ul>
</div>
<!-- 订阅股票的技术信号提醒 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-red-500/50 transition-all group md:col-span-2 lg:col-span-1">
<div class="w-14 h-14 rounded-xl bg-red-500/20 flex items-center justify-center mb-6 group-hover:bg-red-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">技术信号提醒</h3>
<p class="text-gray-400 mb-4">
智能技术信号监测系统支持自定义股票信号条件实时推送买卖点提醒不错过任何投资机会
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义信号条件</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 实时推送提醒</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 历史信号回溯</li>
</ul>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
export default {
name: 'LandingPage',
methods: {
handleStartUsing() {
//
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
if (isLoggedIn) {
this.$router.push('/home');
} else {
this.$router.push('/sign-up');
}
}
}
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<div class="p-6">
<h1 class="text-2xl font-bold text-white mb-6">AI投资</h1>
<!-- AI投资内容将在后续开发中添加 -->
</div>
</template>
<script>
export default {
name: 'AiInvestment'
}
</script>

View File

@ -0,0 +1,88 @@
<template>
<div class="p-4 md:p-6">
<!-- 搜索栏 -->
<div class="relative mb-6">
<input type="text" placeholder="Search symbols or ask a question" class="w-full bg-gray-800 rounded-full py-3 pl-10 pr-4 text-sm focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-400">
<svg xmlns="http://www.w3.org/2000/svg" class="absolute left-3 top-3 h-5 w-5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<button class="absolute right-3 top-2.5 bg-green-500 p-1.5 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
</button>
</div>
<!-- 市场指标 -->
<div class="grid grid-cols-3 gap-3 mb-6">
<div class="bg-gray-800 rounded-lg p-3 text-center">
<div class="text-xs text-gray-400">IWM</div>
<div class="text-white font-medium">+1.01%</div>
</div>
<div class="bg-gray-800 rounded-lg p-3 text-center">
<div class="text-xs text-gray-400">DIA</div>
<div class="text-white font-medium">+0.5%</div>
</div>
<div class="bg-gray-800 rounded-lg p-3 text-center">
<div class="text-xs text-gray-400">BTC</div>
<div class="text-white font-medium">-0.2%</div>
</div>
</div>
<!-- 交易策略 -->
<h2 class="text-lg font-semibold text-white mb-4">Trading Strategies</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div class="bg-gray-800 rounded-xl p-4 border border-gray-700">
<div class="text-green-400 text-sm font-medium mb-2">AI Investment</div>
<h3 class="text-white font-bold mb-3">AI Stock Picker</h3>
<div class="flex justify-between items-end">
<div class="text-xs text-gray-400">Top 3 stocks daily</div>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</div>
</div>
<div class="bg-gray-800 rounded-xl p-4 border border-gray-700">
<div class="text-green-400 text-sm font-medium mb-2">Stock & Crypto</div>
<h3 class="text-white font-bold mb-3">Swing Trades</h3>
<div class="flex justify-between items-end">
<div class="text-xs text-gray-400">Trade signals daily</div>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</div>
</div>
</div>
<!-- AI分析 -->
<h2 class="text-lg font-semibold text-white mb-4">AI Analysis</h2>
<div class="grid grid-cols-2 gap-3">
<button class="bg-gray-800 hover:bg-gray-700 transition-colors rounded-lg p-3 border border-gray-700 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
<span class="text-white text-sm">Quick Insights</span>
</button>
<button class="bg-gray-800 hover:bg-gray-700 transition-colors rounded-lg p-3 border border-gray-700 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" />
</svg>
<span class="text-white text-sm">Technical Expert</span>
</button>
</div>
</div>
</template>
<script>
export default {
name: 'Dashboard',
data() {
return {
//
}
},
methods: {
//
}
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<div class="p-6">
<h1 class="text-2xl font-bold text-white mb-6">收益预测</h1>
<!-- 收益预测内容将在后续开发中添加 -->
</div>
</template>
<script>
export default {
name: 'EarningsPrediction'
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<div class="p-6">
<h1 class="text-2xl font-bold text-white mb-6">历史记录</h1>
<!-- 历史记录内容将在后续开发中添加 -->
</div>
</template>
<script>
export default {
name: 'History'
}
</script>

View File

@ -0,0 +1,90 @@
<template>
<div class="flex min-h-screen relative">
<!-- 移动端侧边栏遮罩层 -->
<div v-if="isMobile && isSidebarOpen" @click="isSidebarOpen = false" class="fixed inset-0 bg-black bg-opacity-50 z-40 lg:hidden"></div>
<div :class="['fixed inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out', isSidebarOpen ? 'translate-x-0' : '-translate-x-full', 'w-64', isMobile ? 'w-4/5' : 'w-64']">
<Sidebar />
</div>
<!-- 移动端遮罩层已移除侧边栏在移动端不再显示 -->
<div :class="['flex-1 flex flex-col h-screen overflow-hidden transition-all duration-300', (!isMobile || isSidebarOpen) ? 'ml-64' : 'ml-0', isMobile && isSidebarOpen ? 'ml-4/5' : '']">
<!-- 顶部导航栏 -->
<header class="bg-gray-800 border-b border-gray-700 py-3 px-6">
<div class="flex items-center justify-between">
<button @click="isSidebarOpen = !isSidebarOpen" class="lg:hidden">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<div class="flex items-center justify-between">
<div class="relative w-1/3">
<input type="text" placeholder="搜索资产、策略或指标..." class="w-full bg-gray-700 rounded-lg py-2 pl-10 pr-4 text-sm focus:outline-none focus:ring-2 focus:ring-green-500"
:class="theme === 'dark' ? 'text-gray-200 placeholder-gray-400' : 'text-gray-800 placeholder-gray-500'">
<svg xmlns="http://www.w3.org/2000/svg" class="absolute left-3 top-2.5 h-5 w-5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
<div class="flex items-center space-x-4">
<button class="p-2 rounded-lg hover:bg-gray-700 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-300" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
<div class="h-8 w-8 rounded-full bg-gradient-to-r from-green-500 to-blue-600 flex items-center justify-center text-white font-medium">JD</div>
</div>
</div>
</header>
<!-- 主内容区域 -->
<main class="flex-1 overflow-y-auto p-6 bg-gray-900 pb-20"> <!-- 添加底部内边距避免被导航栏遮挡 -->
<router-view />
</main>
<MobileBottomNav v-if="isMobile" />
</div>
</div>
</template>
<script>
import Sidebar from '@/components/Sidebar.vue'
import MobileBottomNav from '@/components/MobileBottomNav.vue'
export default {
name: 'Home',
components: {
Sidebar,
MobileBottomNav
},
data() {
return {
theme: localStorage.getItem('theme') || 'dark',
isMobile: false,
isSidebarOpen: true //
}
},
methods: {
checkScreenSize() {
this.isMobile = window.innerWidth < 768;
}
},
mounted() {
this.checkScreenSize();
//
if (this.isMobile) {
this.isSidebarOpen = false;
}
window.addEventListener('resize', this.checkScreenSize);
document.documentElement.classList.toggle('dark', this.theme === 'dark');
},
beforeUnmount() {
window.removeEventListener('resize', this.checkScreenSize);
},
computed: {
backgroundClass() {
return this.theme === 'dark'
? 'bg-[radial-gradient(circle_at_top_right,_rgba(79,70,229,0.15),_transparent_70%)]'
: 'bg-[radial-gradient(circle_at_top_right,_rgba(79,70,229,0.05),_transparent_70%)]';
}
}
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<div class="p-6">
<h1 class="text-2xl font-bold text-white mb-6">股票市场</h1>
<!-- 股票市场内容将在后续开发中添加 -->
</div>
</template>
<script>
export default {
name: 'StockMarket'
}
</script>

View File

@ -0,0 +1,12 @@
<template>
<div class="p-6">
<h1 class="text-2xl font-bold text-white mb-6">交易新闻</h1>
<!-- 交易新闻内容将在后续开发中添加 -->
</div>
</template>
<script>
export default {
name: 'TradingNews'
}
</script>

View File

@ -0,0 +1,157 @@
<template>
<div class="min-h-screen bg-gray-900 text-white">
<!-- 英雄区域 -->
<section class="relative py-20 overflow-hidden">
<div class="absolute inset-0 bg-[radial-gradient(circle_at_top_right,_rgba(79,70,229,0.15),_transparent_70%)]"></div>
<div class="container mx-auto px-4 relative z-10">
<div class="max-w-3xl mx-auto text-center">
<div class="inline-block px-3 py-1 rounded-full bg-gray-800 text-green-400 mb-6">
由AI驱动的智能投资平台
</div>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 leading-tight">
The Most Powerful AI Platform for <span class="text-transparent bg-clip-text bg-gradient-to-r from-green-400 to-blue-500">Smarter Investment</span>
</h1>
<p class="text-xl mb-10 max-w-2xl mx-auto text-gray-400">
利用人工智能技术分析市场趋势提供精准选股建议帮助投资者做出更明智的决策
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4">
<button class="px-8 py-4 rounded-xl bg-gradient-to-r from-green-500 to-blue-600 hover:opacity-90 transition-opacity text-lg font-medium" @click="handleStartUsing">
开始使用
</button>
<button class="px-8 py-4 rounded-xl bg-gray-800 hover:bg-gray-700 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 inline mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
观看演示
</button>
</div>
</div>
</div>
</section>
<!-- 核心功能模块 -->
<section id="features" class="py-20 bg-gray-900 border-t border-gray-800">
<div class="container mx-auto px-4">
<div class="text-center mb-16">
<div class="inline-block px-3 py-1 rounded-full bg-gray-800 text-blue-400 mb-4">
核心功能
</div>
<h2 class="text-3xl md:text-4xl font-bold mb-6">AI驱动的智能股票分析与投资决策平台</h2>
<p class="text-xl max-w-3xl mx-auto text-gray-400">
集成五大核心功能模块提供全方位的股票数据分析与投资决策支持
</p>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- 每日股票推荐 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-blue-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-blue-500/20 flex items-center justify-center mb-6 group-hover:bg-blue-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">每日股票推荐</h3>
<p class="text-gray-400 mb-4">
基于机器学习算法每日推送潜力股票推荐列表结合市场趋势与历史数据分析助您把握投资机会
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多因子模型评估</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 风险收益比分析</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 行业分布均衡推荐</li>
</ul>
</div>
<!-- 技术分析 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-green-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-green-500/20 flex items-center justify-center mb-6 group-hover:bg-green-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2v-6a2 2 0 00-2-2h-2a2 2 0 00-2 2v6z" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">技术分析</h3>
<p class="text-gray-400 mb-4">
提供专业级股票技术分析图表支持多种技术指标与周期切换帮助您深入分析股票走势与市场情绪
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 实时K线图与指标</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多周期技术分析</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 技术形态识别</li>
</ul>
</div>
<!-- 用户设置股票 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-purple-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-purple-500/20 flex items-center justify-center mb-6 group-hover:bg-purple-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">用户设置股票</h3>
<p class="text-gray-400 mb-4">
个性化股票关注列表管理支持添加删除和分组管理关注股票实时追踪您关心的市场动态
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义关注列表</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 股票分组管理</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 快速访问与排序</li>
</ul>
</div>
<!-- 添加指标 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-yellow-500/50 transition-all group">
<div class="w-14 h-14 rounded-xl bg-yellow-500/20 flex items-center justify-center mb-6 group-hover:bg-yellow-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">添加指标</h3>
<p class="text-gray-400 mb-4">
灵活的技术指标自定义功能支持添加MACDRSIKDJ等多种技术指标自定义参数与显示样式
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 30+技术指标支持</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义指标参数</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 多指标组合分析</li>
</ul>
</div>
<!-- 订阅股票的技术信号提醒 -->
<div class="bg-gray-800/50 border border-gray-800 rounded-2xl p-6 hover:border-red-500/50 transition-all group md:col-span-2 lg:col-span-1">
<div class="w-14 h-14 rounded-xl bg-red-500/20 flex items-center justify-center mb-6 group-hover:bg-red-500/30 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-7 w-7 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</div>
<h3 class="text-xl font-bold mb-3">技术信号提醒</h3>
<p class="text-gray-400 mb-4">
智能技术信号监测系统支持自定义股票信号条件实时推送买卖点提醒不错过任何投资机会
</p>
<ul class="space-y-2 text-sm text-gray-400">
<li class="flex items-center gap-2"><span class="text-green-400"></span> 自定义信号条件</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 实时推送提醒</li>
<li class="flex items-center gap-2"><span class="text-green-400"></span> 历史信号回溯</li>
</ul>
</div>
</div>
</div>
</section>
</div>
</template>
<script>
export default {
name: 'LandingPage',
methods: {
handleStartUsing() {
//
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
if (isLoggedIn) {
this.$router.push('/home');
} else {
this.$router.push('/sign-up');
}
}
}
}
</script>

View File

@ -0,0 +1,200 @@
<template>
<div class="min-h-screen flex items-center justify-center bg-gray-900 text-white p-4">
<div class="w-full max-w-md">
<div class="text-center mb-8">
<div class="flex items-center justify-center space-x-2 mb-2">
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center">
<span class="font-bold text-xl">A</span>
</div>
<span class="font-bold text-xl">AriStockAI</span>
</div>
<p class="text-gray-400">
没有账号
<a href="#" class="text-green-400 hover:underline" @click.prevent="$router.push('/sign-up')">注册</a>
</p>
</div>
<div class="bg-gray-800 rounded-2xl p-8 shadow-lg">
<div class="grid grid-cols-2 gap-4 mb-4">
<button @click="handleGoogleLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 22q-2.05 0-3.875-.788t-3.188-2.15-2.15-3.187T2 12q0-2.05.788-3.875t2.15-3.188 3.187-2.15T12 2q2.05 0 3.875.788t3.188 2.15 2.15 3.187T22 12q0 2.05-.788 3.875t-2.15 3.188-3.187 2.15T12 22zm0-2q3.333 0 5.667-2.333T20 12q0-3.333-2.333-5.667T12 4Q8.667 4 6.333 6.333T4 12q0 3.333 2.333 5.667T12 20zm0-8q1.657 0 2.828-.828T16 8q0-1.657-.828-2.828T12 4Q10.343 4 9.172 5.172T8 8q0 1.657.828 2.828T12 12zm-6 4h12q-.667-1.333-2.333-2T12 12t-3.667.667T6 14z"/>
</svg>
Google
</button>
<button @click="handleTwitterLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M22.46 6c-.77.35-1.6.58-2.46.69.88-.53 1.56-1.37 1.88-2.38-.83.5-1.75.85-2.72 1.05C18.37 4.5 17.26 4 16 4c-2.35 0-4.27 1.92-4.27 4.29 0 .34.04.67.11.98C8.28 9.09 4.11 7.38 1.67 4.79c-.4.69-.64 1.52-.64 2.46 0 1.71.87 3.21 2.18 4.09-.81-.02-1.56-.25-2.22-.64v.06c0 2.08 1.48 3.82 3.44 4.21a4.22 4.22 0 0 1-1.88.07 4.28 4.28 0 0 0 4 2.98 8.521 8.521 0 0 1-5.33 1.84c-.34 0-.68-.02-1.02-.06C1.88 20.29 4.49 21 7.34 21c8.45 0 13.17-6.98 13.17-13.17 0-.2-.01-.4-.02-.6.9-.63 1.65-1.43 2.25-2.34z"/>
</svg>
Twitter
</button>
<button @click="handleFacebookLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
</svg>
Facebook
</button>
<button @click="handleMicrosoftLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2.25c-5.38 0-9.75 4.37-9.75 9.75s4.37 9.75 9.75 9.75 9.75-4.37 9.75-9.75S17.38 2.25 12 2.25zm3.75 11.62c0 2.9-2.35 5.25-5.25 5.25s-5.25-2.35-5.25-5.25 2.35-5.25 5.25-5.25h1.5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5H12c-3.86 0-7 3.14-7 7s3.14 7 7 7 7-3.14 7-7v-1.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z"/>
</svg>
Microsoft
</button>
</div>
<div class="flex items-center justify-between my-6">
<div class="h-px bg-gray-700 flex-grow"></div>
<span class="px-4 text-gray-400">OR</span>
<div class="h-px bg-gray-700 flex-grow"></div>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-400 mb-1">邮箱</label>
<div class="relative">
<input type="email" v-model="email" placeholder="输入您的邮箱" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-500"/>
<svg class="absolute right-3 top-3.5 w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
</div>
<p v-if="emailError" class="text-red-400 text-xs mt-1">{{ emailError }}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-400 mb-1">密码</label>
<div class="relative">
<input :type="showPassword ? 'text' : 'password'" v-model="password" placeholder="输入您的密码" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-500"/>
<button type="button" class="absolute right-3 top-3.5 text-gray-500" @click="showPassword = !showPassword">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
</button>
</div>
<p v-if="passwordError" class="text-red-400 text-xs mt-1">{{ passwordError }}</p>
</div>
<div class="text-right mb-6">
<a href="#" class="text-sm text-gray-400 hover:underline">Forgot Password</a>
</div>
<button class="w-full py-3 px-4 bg-gradient-to-r from-green-500 to-blue-600 rounded-lg font-medium hover:opacity-90 transition-opacity" @click="handleLogin()">
登录
</button>
<p class="text-xs text-gray-500 text-center mt-6">
By using AriStockAI, you agree to the <a href="#" class="text-gray-400 hover:underline">使用条款</a> and <a href="#" class="text-gray-400 hover:underline">隐私政策</a>
</p>
</div>
</div>
</div>
<el-dialog
v-model="showSuccessModal"
title="登录成功"
:closable="false"
:show-close="false"
:modal-append-to-body="false"
:append-to-body="true"
>
<div class="text-center py-4">
<div class="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<p class="text-gray-400 mb-6">您已成功登录即将跳转到主页</p>
</div>
<template #footer>
<div class="flex justify-center">
<el-button
type="primary"
@click="handleModalClose"
class="px-6 py-2 bg-gradient-to-r from-green-500 to-blue-600 rounded-lg"
>
确定
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Login',
data() {
return {
email: '',
password: '',
showPassword: false,
emailError: '',
passwordError: '',
showSuccessModal: false
}
},
methods: {
validateForm() {
let isValid = true;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
//
if (!this.email) {
this.emailError = '请输入邮箱';
isValid = false;
} else if (!emailRegex.test(this.email)) {
this.emailError = '请输入有效的邮箱地址';
isValid = false;
} else {
this.emailError = '';
}
//
if (!this.password) {
this.passwordError = '请输入密码';
isValid = false;
} else {
this.passwordError = '';
}
return isValid;
},
handleLogin() {
if (!this.validateForm()) return;
//
localStorage.setItem('isLoggedIn', 'true');
this.showSuccessModal = true;
},
handleGoogleLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.showSuccessModal = true;
},
handleTwitterLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.showSuccessModal = true;
},
handleFacebookLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.showSuccessModal = true;
},
handleMicrosoftLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.showSuccessModal = true;
},
handleModalClose() {
this.showSuccessModal = false;
this.$router.push('/home');
}
}
}
</script>

View File

@ -0,0 +1,285 @@
<template>
<div class="min-h-screen flex items-center justify-center bg-gray-900 text-white p-4">
<div class="w-full max-w-md">
<div class="text-center mb-8">
<div class="flex items-center justify-center space-x-2 mb-2">
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-green-500 to-blue-600 flex items-center justify-center">
<span class="font-bold text-xl">A</span>
</div>
<span class="font-bold text-xl">AriStockAI</span>
</div>
<p class="text-gray-400">
已有账号
<a href="#" class="text-green-400 hover:underline" @click.prevent="$router.push('/login')">登录</a>
</p>
</div>
<div class="bg-gray-800 rounded-2xl p-8 shadow-lg">
<div class="grid grid-cols-2 gap-4 mb-4">
<button @click="handleGoogleLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 22q-2.05 0-3.875-.788t-3.188-2.15-2.15-3.187T2 12q0-2.05.788-3.875t2.15-3.188 3.187-2.15T12 2q2.05 0 3.875.788t3.188 2.15 2.15 3.187T22 12q0 2.05-.788 3.875t-2.15 3.188-3.187 2.15T12 22zm0-2q3.333 0 5.667-2.333T20 12q0-3.333-2.333-5.667T12 4Q8.667 4 6.333 6.333T4 12q0 3.333 2.333 5.667T12 20zm0-8q1.657 0 2.828-.828T16 8q0-1.657-.828-2.828T12 4Q10.343 4 9.172 5.172T8 8q0 1.657.828 2.828T12 12zm-6 4h12q-.667-1.333-2.333-2T12 12t-3.667.667T6 14z"/>
</svg>
Google
</button>
<button @click="handleTwitterLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M22.46 6c-.77.35-1.6.58-2.46.69.88-.53 1.56-1.37 1.88-2.38-.83.5-1.75.85-2.72 1.05C18.37 4.5 17.26 4 16 4c-2.35 0-4.27 1.92-4.27 4.29 0 .34.04.67.11.98C8.28 9.09 4.11 7.38 1.67 4.79c-.4.69-.64 1.52-.64 2.46 0 1.71.87 3.21 2.18 4.09-.81-.02-1.56-.25-2.22-.64v.06c0 2.08 1.48 3.82 3.44 4.21a4.22 4.22 0 0 1-1.88.07 4.28 4.28 0 0 0 4 2.98 8.521 8.521 0 0 1-5.33 1.84c-.34 0-.68-.02-1.02-.06C1.88 20.29 4.49 21 7.34 21c8.45 0 13.17-6.98 13.17-13.17 0-.2-.01-.4-.02-.6.9-.63 1.65-1.43 2.25-2.34z"/>
</svg>
Twitter
</button>
<button @click="handleFacebookLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z"/>
</svg>
Facebook
</button>
<button @click="handleMicrosoftLogin" class="py-3 px-4 bg-white text-gray-900 rounded-lg font-medium flex items-center justify-center hover:bg-gray-100 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2.25c-5.38 0-9.75 4.37-9.75 9.75s4.37 9.75 9.75 9.75 9.75-4.37 9.75-9.75S17.38 2.25 12 2.25zm3.75 11.62c0 2.9-2.35 5.25-5.25 5.25s-5.25-2.35-5.25-5.25 2.35-5.25 5.25-5.25h1.5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5H12c-3.86 0-7 3.14-7 7s3.14 7 7 7 7-3.14 7-7v-1.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z"/>
</svg>
Microsoft
</button>
</div>
<div class="flex items-center justify-between my-6">
<div class="h-px bg-gray-700 flex-grow"></div>
<span class="px-4 text-gray-400">OR</span>
<div class="h-px bg-gray-700 flex-grow"></div>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-400 mb-1">邮箱</label>
<div class="relative">
<input type="email" v-model="email" placeholder="输入您的邮箱" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-500"/>
<svg class="absolute right-3 top-3.5 w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
</svg>
</div>
<p v-if="emailError" class="text-red-400 text-xs mt-1">{{ emailError }}</p>
</div>
<div class="grid grid-cols-3 gap-4">
<div class="col-span-2">
<label class="block text-sm font-medium text-gray-400 mb-1">验证码</label>
<div class="relative">
<input type="text" v-model="verificationCode" placeholder="输入验证码" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-500"/>
</div>
<p v-if="verificationCodeError" class="text-red-400 text-xs mt-1">{{ verificationCodeError }}</p>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium text-gray-400 mb-1">&nbsp;</label>
<button :disabled="countdown > 0" @click="handleSendCode" class="w-full bg-gray-700 hover:bg-gray-600 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white transition-colors">
{{ countdown > 0 ? `${countdown}s` : '获取验证码' }}
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-400 mb-1">密码</label>
<div class="relative">
<input :type="showPassword ? 'text' : 'password'" v-model="password" placeholder="设置密码" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-500"/>
<button type="button" class="absolute right-3 top-3.5 text-gray-500" @click="showPassword = !showPassword">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
</button>
</div>
<p v-if="passwordError" class="text-red-400 text-xs mt-1">{{ passwordError }}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-400 mb-1">确认密码</label>
<div class="relative">
<input :type="showPassword ? 'text' : 'password'" v-model="confirmPassword" placeholder="再次输入密码" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 text-white placeholder-gray-500"/>
</div>
<p v-if="confirmPasswordError" class="text-red-400 text-xs mt-1">{{ confirmPasswordError }}</p>
</div>
<button class="w-full py-3 px-4 bg-gradient-to-r from-green-500 to-blue-600 rounded-lg font-medium hover:opacity-90 transition-opacity" @click="handleRegister()">
注册
</button>
<p class="text-xs text-gray-500 text-center mt-6">
By using AriStockAI, you agree to the <a href="#" class="text-gray-400 hover:underline">使用条款</a> and <a href="#" class="text-gray-400 hover:underline">隐私政策</a>
</p>
</div>
</div>
</div>
<el-dialog
v-model="showSuccessModal"
:title="modalTitle"
:closable="false"
:show-close="false"
:modal-append-to-body="false"
:append-to-body="true"
>
<div class="text-center py-4">
<div class="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
</div>
<p class="text-gray-400 mb-6">{{ modalMessage }}</p>
</div>
<template #footer>
<div class="flex justify-center">
<el-button
type="primary"
@click="handleModalClose"
class="px-6 py-2 bg-gradient-to-r from-green-500 to-blue-600 rounded-lg"
>
确定
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'SignUp',
data() {
return {
email: '',
password: '',
confirmPassword: '',
verificationCode: '',
showPassword: false,
countdown: 0,
emailError: '',
passwordError: '',
confirmPasswordError: '',
verificationCodeError: '',
showSuccessModal: false,
modalTitle: '',
modalMessage: ''
}
},
methods: {
validateForm() {
let isValid = true;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
//
if (!this.email) {
this.emailError = '请输入邮箱';
isValid = false;
} else if (!emailRegex.test(this.email)) {
this.emailError = '请输入有效的邮箱地址';
isValid = false;
} else {
this.emailError = '';
}
//
if (!this.verificationCode) {
this.verificationCodeError = '请输入验证码';
isValid = false;
} else {
this.verificationCodeError = '';
}
//
if (!this.password) {
this.passwordError = '请设置密码';
isValid = false;
} else if (!passwordRegex.test(this.password)) {
this.passwordError = '密码至少8位包含字母和数字';
isValid = false;
} else {
this.passwordError = '';
}
//
if (!this.confirmPassword) {
this.confirmPasswordError = '请确认密码';
isValid = false;
} else if (this.password !== this.confirmPassword) {
this.confirmPasswordError = '两次密码输入不一致';
isValid = false;
} else {
this.confirmPasswordError = '';
}
return isValid;
},
handleRegister() {
if (!this.validateForm()) return;
//
localStorage.setItem('isLoggedIn', 'true');
this.modalTitle = '注册成功';
this.modalMessage = '您已成功注册,即将跳转到主页';
this.showSuccessModal = true;
},
handleSendCode() {
//
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!this.email || !emailRegex.test(this.email)) {
this.emailError = '请输入有效的邮箱地址';
return;
}
this.emailError = '';
//
this.countdown = 60;
const timer = setInterval(() => {
this.countdown--;
if (this.countdown <= 0) {
clearInterval(timer);
}
}, 1000);
this.modalTitle = '发送成功';
this.modalMessage = '验证码已发送至您的邮箱';
this.showSuccessModal = true;
},
handleGoogleLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.modalTitle = '注册成功';
this.modalMessage = '通过Google账号注册成功即将跳转到主页';
this.showSuccessModal = true;
},
handleTwitterLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.modalTitle = '注册成功';
this.modalMessage = '通过Twitter账号注册成功即将跳转到主页';
this.showSuccessModal = true;
},
handleFacebookLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.modalTitle = '注册成功';
this.modalMessage = '通过Facebook账号注册成功即将跳转到主页';
this.showSuccessModal = true;
},
handleMicrosoftLogin() {
//
localStorage.setItem('isLoggedIn', 'true');
this.modalTitle = '注册成功';
this.modalMessage = '通过Microsoft账号注册成功即将跳转到主页';
this.showSuccessModal = true;
},
handleModalClose() {
this.showSuccessModal = false;
//
if (this.modalTitle === '注册成功') {
this.$router.push('/home');
}
}
}
}
</script>