diff --git a/package.json b/package.json
index 00ccda2..27bdb4e 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"license": "ISC",
"dependencies": {
"ant-design-vue": "^3.0.0",
- "axios": "^1.6.0",
+ "axios": "^1.8.2",
"vue": "^3.0.0",
"vue-router": "^4.0.0",
"vuex": "^4.0.0"
diff --git a/src/api/user.js b/src/api/user.js
new file mode 100644
index 0000000..f7703c1
--- /dev/null
+++ b/src/api/user.js
@@ -0,0 +1,22 @@
+import request from '../utils/request';
+import config from '../utils/config';
+
+/**
+ * 用户密码登录
+ * @param {Object} data - 登录参数
+ * @param {string} data.phone - 手机号
+ * @param {string} data.password - 密码
+ * @param {string} data.role - 角色,默认为 partner
+ * @returns {Promise} - 返回登录结果
+ */
+export function login(data) {
+ return request({
+ url: config.API.LOGIN,
+ method: 'post',
+ data: {
+ phone: data.phone,
+ password: data.password,
+ role: data.role || 'partner'
+ }
+ });
+}
\ No newline at end of file
diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue
index 7a8cf85..458da85 100644
--- a/src/layouts/AdminLayout.vue
+++ b/src/layouts/AdminLayout.vue
@@ -16,14 +16,6 @@
仪表盘
- $router.push('/user')">
-
- 用户管理
-
- $router.push('/settings')">
-
- 系统设置
-
@@ -34,7 +26,7 @@
- {{ userInfo?.name || '用户' }}
+ {{ userInfo?.nickname || userInfo?.name || '用户' }}
@@ -67,17 +59,13 @@ import { ref, computed, watch, onMounted } from 'vue';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import {
- DashboardOutlined,
- UserOutlined,
- SettingOutlined
+ DashboardOutlined
} from '@ant-design/icons-vue';
export default {
name: 'AdminLayout',
components: {
- DashboardOutlined,
- UserOutlined,
- SettingOutlined
+ DashboardOutlined
},
setup() {
const store = useStore();
diff --git a/src/router/index.js b/src/router/index.js
index 8c75e87..9db9c8e 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -12,18 +12,6 @@ const routes = [
name: 'Dashboard',
component: () => import('../views/Dashboard.vue'),
meta: { title: '仪表盘', icon: 'dashboard' }
- },
- {
- path: 'user',
- name: 'User',
- component: () => import('../views/User.vue'),
- meta: { title: '用户管理', icon: 'user' }
- },
- {
- path: 'settings',
- name: 'Settings',
- component: () => import('../views/Settings.vue'),
- meta: { title: '系统设置', icon: 'setting' }
}
]
},
diff --git a/src/store/index.js b/src/store/index.js
index e39807c..770c841 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,8 +1,9 @@
import { createStore } from 'vuex';
+import { login as userLogin } from '../api/user';
export default createStore({
state: {
- user: null,
+ user: JSON.parse(localStorage.getItem('user')) || null,
token: localStorage.getItem('token') || '',
sidebar: {
collapsed: false
@@ -19,29 +20,48 @@ export default createStore({
},
SET_USER(state, user) {
state.user = user;
+ localStorage.setItem('user', JSON.stringify(user));
+ },
+ CLEAR_USER(state) {
+ state.user = null;
+ localStorage.removeItem('user');
},
TOGGLE_SIDEBAR(state) {
state.sidebar.collapsed = !state.sidebar.collapsed;
}
},
actions: {
- login({ commit }, userInfo) {
- // 这里应该有实际的登录API调用
- return new Promise((resolve) => {
- // 模拟登录成功
- const token = 'mock-token-' + Date.now();
- commit('SET_TOKEN', token);
- commit('SET_USER', {
- name: userInfo.username,
- avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
- roles: ['admin']
+ // 登录
+ async login({ commit }, userInfo) {
+ try {
+ const response = await userLogin({
+ phone: userInfo.phone,
+ password: userInfo.password
});
- resolve();
- });
+
+ // 保存 token
+ commit('SET_TOKEN', response.access_token);
+
+ // 保存用户信息,确保包含 nickname
+ const userData = response.user || {};
+
+ // 如果没有头像,设置默认头像
+ if (!userData.avatar) {
+ userData.avatar = 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png';
+ }
+
+ commit('SET_USER', userData);
+
+ return response;
+ } catch (error) {
+ console.error('登录失败:', error);
+ throw error;
+ }
},
+ // 登出
logout({ commit }) {
commit('CLEAR_TOKEN');
- commit('SET_USER', null);
+ commit('CLEAR_USER');
}
},
getters: {
diff --git a/src/utils/config.js b/src/utils/config.js
new file mode 100644
index 0000000..31ffb2d
--- /dev/null
+++ b/src/utils/config.js
@@ -0,0 +1,19 @@
+// 环境配置
+const ENV = process.env.NODE_ENV || 'development';
+
+// API 基础地址配置
+const API_BASE_URL = {
+ development: 'http://localhost:8000',
+ test: 'https://api-dev.beefast.co',
+ production: 'https://api.beefast.co'
+};
+
+// 当前环境的 API 基础地址
+const BASE_URL = API_BASE_URL[ENV === 'production' ? 'production' : ENV === 'test' ? 'test' : 'development'];
+
+export default {
+ BASE_URL,
+ API: {
+ LOGIN: '/api/user/password-login'
+ }
+};
\ No newline at end of file
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..1be5675
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,77 @@
+import axios from 'axios';
+import { message } from 'ant-design-vue';
+import config from './config';
+import store from '../store';
+
+// 创建 axios 实例
+const service = axios.create({
+ baseURL: config.BASE_URL,
+ timeout: 15000
+});
+
+// 请求拦截器
+service.interceptors.request.use(
+ config => {
+ // 从 store 获取 token
+ const token = store.state.token;
+ // 如果有 token,添加到请求头
+ if (token) {
+ config.headers['Authorization'] = `Bearer ${token}`;
+ }
+ return config;
+ },
+ error => {
+ console.error('请求错误:', error);
+ return Promise.reject(error);
+ }
+);
+
+// 响应拦截器
+service.interceptors.response.use(
+ response => {
+ const res = response.data;
+
+ // 如果返回的状态码不是 200,则判断为错误
+ if (res.code !== 200) {
+ message.error(res.message || '请求失败');
+
+ // 401: 未授权,清除 token 并跳转到登录页
+ // 403: 禁止访问,清除 token 并跳转到登录页
+ if (res.code === 401 || res.code === 403) {
+ store.dispatch('logout');
+ window.location.href = '/login';
+ }
+
+ return Promise.reject(new Error(res.message || '请求失败'));
+ } else {
+ return res.data;
+ }
+ },
+ error => {
+ console.error('响应错误:', error);
+
+ // 处理 HTTP 状态码错误
+ if (error.response) {
+ const { status, data } = error.response;
+
+ // 处理 403 状态码
+ if (status === 403) {
+ message.error(data.message || '您没有权限访问此资源');
+ store.dispatch('logout');
+ window.location.href = '/login';
+ } else if (status === 401) {
+ message.error(data.message || '登录已过期,请重新登录');
+ store.dispatch('logout');
+ window.location.href = '/login';
+ } else {
+ message.error(data.message || `请求失败(${status})`);
+ }
+ } else {
+ message.error(error.message || '网络错误');
+ }
+
+ return Promise.reject(error);
+ }
+);
+
+export default service;
\ No newline at end of file
diff --git a/src/views/Login.vue b/src/views/Login.vue
index 52ba9de..58109bc 100644
--- a/src/views/Login.vue
+++ b/src/views/Login.vue
@@ -30,15 +30,17 @@
:model="formState"
name="login"
@finish="onFinish"
- autocomplete="off"
class="login-form"
>
{
+ const onFinish = async () => {
loading.value = true;
try {
- await store.dispatch('login', {
- username: formState.username,
+ const result = await store.dispatch('login', {
+ phone: formState.phone,
password: formState.password
});
- message.success('登录成功');
+
+ // 如果登录成功且有用户昵称,显示个性化欢迎信息
+ if (result && result.user && result.user.nickname) {
+ message.success(`欢迎回来,${result.user.nickname}!`);
+ } else {
+ message.success('登录成功');
+ }
+
router.push('/');
} catch (error) {
- message.error('登录失败: ' + error.message);
+ message.error('登录失败: ' + (error.message || '未知错误'));
} finally {
loading.value = false;
}
@@ -248,27 +257,30 @@ export default {
}
.login-footer {
+ margin-top: 40px;
text-align: center;
color: #999;
- font-size: 14px;
- margin-top: 20px;
+ font-size: 12px;
}
@media (max-width: 768px) {
.login-box {
- width: 90%;
- height: auto;
+ width: 100%;
+ height: 100%;
flex-direction: column;
+ border-radius: 0;
}
.login-left {
width: 100%;
- padding: 30px;
+ height: 30%;
+ padding: 20px;
}
.login-right {
width: 100%;
- padding: 30px;
+ height: 70%;
+ padding: 20px;
}
.logo-container {
@@ -276,7 +288,11 @@ export default {
}
.feature-list {
- margin-bottom: 30px;
+ margin-bottom: 20px;
+ }
+
+ .welcome-text {
+ margin-bottom: 20px;
}
}
\ No newline at end of file
diff --git a/src/views/Settings.vue b/src/views/Settings.vue
deleted file mode 100644
index bf6a5b0..0000000
--- a/src/views/Settings.vue
+++ /dev/null
@@ -1,354 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 保存设置
-
-
-
-
-
-
-
-
- 简单 (至少6位)
- 中等 (至少8位,包含字母和数字)
- 强 (至少10位,包含大小写字母、数字和特殊字符)
-
-
-
-
-
-
-
-
-
- 次
-
-
-
-
- 分钟
-
-
-
-
- 分钟
-
-
-
- 保存设置
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 保存设置
- 测试连接
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/views/User.vue b/src/views/User.vue
deleted file mode 100644
index a185ee7..0000000
--- a/src/views/User.vue
+++ /dev/null
@@ -1,501 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- 添加用户
-
-
-
-
-
-
-
-
-
-
- {{ record.status === 'active' ? '正常' : '禁用' }}
-
-
-
-
- 编辑
-
-
- 删除
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 管理员
- 普通用户
- 访客
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file