diff --git a/.editorconfig b/.editorconfig
index 8065bf2..17e22af 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,4 +5,4 @@ indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
end_of_line = lf
-max_line_length = 100
+max_line_length = 260
diff --git a/package.json b/package.json
index cb65b76..f345c54 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,9 @@
"format": "prettier --write --experimental-cli src/"
},
"dependencies": {
+ "@element-plus/icons-vue": "^2.3.2",
"axios": "^1.13.2",
+ "element-plus": "^2.13.1",
"nprogress": "^0.2.0",
"pinia": "^3.0.4",
"vue": "^3.5.26",
diff --git a/src/assets/css/auth.css b/src/assets/css/auth.css
new file mode 100644
index 0000000..2bd4c04
--- /dev/null
+++ b/src/assets/css/auth.css
@@ -0,0 +1,154 @@
+/* 认证页面统一样式 */
+.auth-container {
+ min-height: 100vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ padding: 20px;
+ position: relative;
+ overflow: hidden;
+}
+
+.auth-container::before {
+ content: '';
+ position: absolute;
+ top: -50%;
+ left: -50%;
+ width: 200%;
+ height: 200%;
+ background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 50%);
+ animation: rotate 20s linear infinite;
+}
+
+@keyframes rotate {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.auth-card {
+ width: 100%;
+ max-width: 420px;
+ background: rgba(255, 255, 255, 0.95);
+ backdrop-filter: blur(10px);
+ border-radius: 16px;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+ padding: 40px;
+ position: relative;
+ z-index: 1;
+}
+
+.auth-header {
+ text-align: center;
+ margin-bottom: 32px;
+}
+
+.auth-header .logo {
+ font-size: 48px;
+ margin-bottom: 16px;
+ color: #667eea;
+}
+
+.auth-header h1 {
+ font-size: 28px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin: 0 0 8px 0;
+}
+
+.auth-header p {
+ font-size: 14px;
+ color: #7f8c8d;
+ margin: 0;
+}
+
+.auth-form {
+ margin-bottom: 24px;
+}
+
+.auth-actions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 24px;
+}
+
+.auth-actions .forgot-link {
+ color: #667eea;
+ text-decoration: none;
+ font-size: 14px;
+ transition: color 0.3s ease;
+}
+
+.auth-actions .forgot-link:hover {
+ color: #764ba2;
+}
+
+.auth-footer {
+ text-align: center;
+ padding-top: 24px;
+ border-top: 1px solid #eaeaea;
+}
+
+.auth-footer .link {
+ color: #667eea;
+ text-decoration: none;
+ font-size: 14px;
+ font-weight: 500;
+ transition: color 0.3s ease;
+}
+
+.auth-footer .link:hover {
+ color: #764ba2;
+}
+
+.auth-footer .text {
+ color: #7f8c8d;
+ font-size: 14px;
+ margin: 0 4px;
+}
+
+.code-button {
+ width: 100%;
+ height: 44px;
+ border-radius: 8px;
+ border: 1px solid #667eea;
+ background: transparent;
+ color: #667eea;
+ font-size: 14px;
+ transition: all 0.3s ease;
+}
+
+.code-button:hover:not(:disabled) {
+ background: rgba(102, 126, 234, 0.05);
+ color: #764ba2;
+ border-color: #764ba2;
+}
+
+.code-button:disabled {
+ border-color: #dcdfe6;
+ color: #c0c4cc;
+ cursor: not-allowed;
+}
+
+.language-switcher {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ z-index: 10;
+}
+
+/* 响应式设计 */
+@media (max-width: 768px) {
+ .auth-card {
+ padding: 30px 20px;
+ }
+
+ .auth-header h1 {
+ font-size: 24px;
+ }
+}
diff --git a/src/assets/css/nprogress.css b/src/assets/css/nprogress.css
new file mode 100644
index 0000000..26bcd47
--- /dev/null
+++ b/src/assets/css/nprogress.css
@@ -0,0 +1,76 @@
+/* 自定义 NProgress 样式 */
+#nprogress {
+ pointer-events: none;
+}
+
+#nprogress .bar {
+ background: linear-gradient(90deg, #00d4ff 0%, #7c4dff 100%);
+ position: fixed;
+ z-index: 9999;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 3px;
+ box-shadow: 0 0 10px rgba(0, 212, 255, 0.5);
+}
+
+/* 螺旋加载器样式 */
+#nprogress .peg {
+ display: block;
+ position: absolute;
+ right: 0;
+ width: 100px;
+ height: 100%;
+ box-shadow:
+ 0 0 10px #00d4ff,
+ 0 0 5px #7c4dff;
+ opacity: 1;
+ transform: rotate(3deg) translate(0px, -4px);
+}
+
+/* 进度条动画 */
+@keyframes nprogress-spinner {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+/* 如果启用加载器时的样式 */
+#nprogress .spinner {
+ display: block;
+ position: fixed;
+ z-index: 9999;
+ top: 15px;
+ right: 15px;
+}
+
+#nprogress .spinner-icon {
+ width: 18px;
+ height: 18px;
+ box-sizing: border-box;
+ border: solid 2px transparent;
+ border-top-color: #00d4ff;
+ border-left-color: #7c4dff;
+ border-radius: 50%;
+ animation: nprogress-spinner 400ms linear infinite;
+}
+
+/* 进度条闪烁效果 */
+@keyframes nprogress-flicker {
+ 0% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+#nprogress .bar {
+ animation: nprogress-flicker 0.5s ease-in-out;
+}
diff --git a/src/config/index.js b/src/config/index.js
index 3ad4b5f..003977f 100644
--- a/src/config/index.js
+++ b/src/config/index.js
@@ -1,4 +1,5 @@
export default {
app_title: 'vueadmin',
+ DASHBOARD_URL: '/home',
baseURL: ''
}
diff --git a/src/config/routes.js b/src/config/routes.js
new file mode 100644
index 0000000..cf2bb94
--- /dev/null
+++ b/src/config/routes.js
@@ -0,0 +1,18 @@
+/**
+ * 用户静态路由配置
+ * 这些路由会根据用户角色进行过滤后添加到路由中
+ */
+const userRoutes = [
+ {
+ path: '/home',
+ name: 'home',
+ component: 'home',
+ meta: {
+ title: 'dashboard',
+ icon: 'el-icon-odometer',
+ role: ['admin']
+ }
+ }
+]
+
+export default userRoutes
diff --git a/src/i18n/locales/en-US.js b/src/i18n/locales/en-US.js
index 0a1ef77..7e25d76 100644
--- a/src/i18n/locales/en-US.js
+++ b/src/i18n/locales/en-US.js
@@ -70,7 +70,47 @@ export default {
usernamePlaceholder: 'Please enter username',
passwordPlaceholder: 'Please enter password',
noAccount: "Don't have an account?",
- registerNow: 'Register Now'
+ registerNow: 'Register Now',
+ forgotPassword: 'Forgot Password?',
+ rememberMe: 'Remember Me'
+ },
+ register: {
+ title: 'User Registration',
+ subtitle: 'Create your account and get started',
+ registerButton: 'Register',
+ registerSuccess: 'Registration Successful',
+ registerFailed: 'Registration Failed',
+ usernamePlaceholder: 'Please enter username',
+ emailPlaceholder: 'Please enter email address',
+ passwordPlaceholder: 'Please enter password',
+ confirmPasswordPlaceholder: 'Please enter password again',
+ usernameRule: 'Username length between 3 to 20 characters',
+ emailRule: 'Please enter a valid email address',
+ passwordRule: 'Password length between 6 to 20 characters',
+ agreeRule: 'Please agree to the user agreement',
+ agreeTerms: 'I have read and agree to the',
+ terms: 'User Agreement',
+ hasAccount: 'Already have an account?',
+ loginNow: 'Login Now'
+ },
+ resetPassword: {
+ title: 'Reset Password',
+ subtitle: 'Reset your password via email verification code',
+ resetButton: 'Reset Password',
+ resetSuccess: 'Password reset successful',
+ resetFailed: 'Reset failed',
+ emailPlaceholder: 'Please enter email address',
+ codePlaceholder: 'Please enter verification code',
+ newPasswordPlaceholder: 'Please enter new password',
+ confirmPasswordPlaceholder: 'Please enter new password again',
+ emailRule: 'Please enter a valid email address',
+ codeRule: 'Verification code must be 6 characters',
+ passwordRule: 'Password length between 6 to 20 characters',
+ sendCode: 'Send Code',
+ codeSent: 'Verification code has been sent to your email',
+ resendCode: 'Resend in {seconds} seconds',
+ sendCodeFirst: 'Please enter email address first',
+ backToLogin: 'Back to Login'
},
layout: {
toggleSidebar: 'Toggle Sidebar',
diff --git a/src/i18n/locales/zh-CN.js b/src/i18n/locales/zh-CN.js
index c86871d..3e21999 100644
--- a/src/i18n/locales/zh-CN.js
+++ b/src/i18n/locales/zh-CN.js
@@ -70,7 +70,47 @@ export default {
usernamePlaceholder: '请输入用户名',
passwordPlaceholder: '请输入密码',
noAccount: '还没有账户?',
- registerNow: '立即注册'
+ registerNow: '立即注册',
+ forgotPassword: '忘记密码?',
+ rememberMe: '记住我'
+ },
+ register: {
+ title: '用户注册',
+ subtitle: '创建您的账户,开始使用',
+ registerButton: '注册',
+ registerSuccess: '注册成功',
+ registerFailed: '注册失败',
+ usernamePlaceholder: '请输入用户名',
+ emailPlaceholder: '请输入邮箱地址',
+ passwordPlaceholder: '请输入密码',
+ confirmPasswordPlaceholder: '请再次输入密码',
+ usernameRule: '用户名长度在 3 到 20 个字符',
+ emailRule: '请输入正确的邮箱地址',
+ passwordRule: '密码长度在 6 到 20 个字符',
+ agreeRule: '请同意用户协议',
+ agreeTerms: '我已阅读并同意',
+ terms: '用户协议',
+ hasAccount: '已有账户?',
+ loginNow: '立即登录'
+ },
+ resetPassword: {
+ title: '重置密码',
+ subtitle: '通过邮箱验证码重置您的密码',
+ resetButton: '重置密码',
+ resetSuccess: '密码重置成功',
+ resetFailed: '重置失败',
+ emailPlaceholder: '请输入邮箱地址',
+ codePlaceholder: '请输入验证码',
+ newPasswordPlaceholder: '请输入新密码',
+ confirmPasswordPlaceholder: '请再次输入新密码',
+ emailRule: '请输入正确的邮箱地址',
+ codeRule: '验证码长度为6位',
+ passwordRule: '密码长度在 6 到 20 个字符',
+ sendCode: '发送验证码',
+ codeSent: '验证码已发送到您的邮箱',
+ resendCode: '{seconds}秒后重新发送',
+ sendCodeFirst: '请先输入邮箱地址',
+ backToLogin: '返回登录'
},
layout: {
toggleSidebar: '切换侧边栏',
diff --git a/src/layouts/other/404.vue b/src/layouts/other/404.vue
new file mode 100644
index 0000000..e076afb
--- /dev/null
+++ b/src/layouts/other/404.vue
@@ -0,0 +1,401 @@
+
+
+
+
+
+
404
+
+
页面未找到
+
抱歉,您访问的页面不存在或已被移除
+
+
+
+
+
+
+
+
diff --git a/src/layouts/other/empty.vue b/src/layouts/other/empty.vue
new file mode 100644
index 0000000..bdf1bc8
--- /dev/null
+++ b/src/layouts/other/empty.vue
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ title }}
+
{{ description }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main.js b/src/main.js
index 1082a3a..c2ddecf 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,5 +1,7 @@
import { createApp } from 'vue'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
import pinia from './stores'
@@ -8,6 +10,7 @@ import { useI18nStore } from './stores/modules/i18n'
const app = createApp(App)
+app.use(ElementPlus)
app.use(router)
app.use(pinia)
app.use(i18n)
diff --git a/src/pages/home/Dashboard.vue b/src/pages/home/index.vue
similarity index 100%
rename from src/pages/home/Dashboard.vue
rename to src/pages/home/index.vue
diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue
index 6fdef84..e817032 100644
--- a/src/pages/login/index.vue
+++ b/src/pages/login/index.vue
@@ -1,399 +1,147 @@
-