提交前端代码
This commit is contained in:
parent
7b3ffc69c0
commit
8f6de47af3
@ -1,44 +0,0 @@
|
|||||||
import axios, { AxiosResponse } from 'axios';
|
|
||||||
import { message } from 'antd';
|
|
||||||
|
|
||||||
export interface ApiResponse<T> {
|
|
||||||
code: number;
|
|
||||||
message: string;
|
|
||||||
data: T;
|
|
||||||
success: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const request = axios.create({
|
|
||||||
baseURL: '/api',
|
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
|
|
||||||
request.interceptors.request.use(
|
|
||||||
(config) => {
|
|
||||||
const token = localStorage.getItem('token');
|
|
||||||
if (token) {
|
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
request.interceptors.response.use(
|
|
||||||
(response: AxiosResponse<ApiResponse<any>>) => {
|
|
||||||
const res = response.data;
|
|
||||||
if (res.code !== 200) {
|
|
||||||
message.error(res.message || '请求失败');
|
|
||||||
return Promise.reject(new Error(res.message || '请求失败'));
|
|
||||||
}
|
|
||||||
return res.data;
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
message.error(error.message || '请求失败');
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export default request;
|
|
||||||
@ -15,7 +15,7 @@ export interface LoginResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const login = async (data: LoginParams): Promise<LoginResult> => {
|
export const login = async (data: LoginParams): Promise<LoginResult> => {
|
||||||
return request.post('/api/auth/login', data);
|
return request.post('/api/v1/users/login', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const logout = async (): Promise<void> => {
|
export const logout = async (): Promise<void> => {
|
||||||
@ -23,7 +23,7 @@ export const logout = async (): Promise<void> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getUserMenus = async (): Promise<MenuDTO[]> => {
|
export const getUserMenus = async (): Promise<MenuDTO[]> => {
|
||||||
return request.get('/api/system/user/menus');
|
return request.get('/api/v1/menu/user');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getUsers = async (params: any) => {
|
export const getUsers = async (params: any) => {
|
||||||
|
|||||||
@ -1,120 +1,120 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import { Form, Input, Button, message, Select } from 'antd';
|
import {Form, Input, Button, message, Select} from 'antd';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import {useNavigate} from 'react-router-dom';
|
||||||
import { useDispatch } from 'react-redux';
|
import {useDispatch} from 'react-redux';
|
||||||
import { login } from '../../api/user';
|
import {login} from '../../api/user';
|
||||||
import { getEnabledTenants } from '../../pages/System/Tenant/service';
|
import {getEnabledTenants} from '../System/Tenant/service';
|
||||||
import { setToken, setUserInfo } from '../../store/userSlice';
|
import {setToken, setUserInfo} from '../../store/userSlice';
|
||||||
import type { LoginParams } from '../../types/user';
|
import type {LoginParams} from '../../types/user';
|
||||||
import type { TenantDTO } from '../../pages/System/Tenant/types';
|
import type {TenantDTO} from '../System/Tenant/types';
|
||||||
|
|
||||||
const Login: React.FC = () => {
|
const Login: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [tenants, setTenants] = useState<TenantDTO[]>([]);
|
const [tenants, setTenants] = useState<TenantDTO[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTenants();
|
fetchTenants();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const fetchTenants = async () => {
|
const fetchTenants = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await getEnabledTenants();
|
const data = await getEnabledTenants();
|
||||||
setTenants(data);
|
setTenants(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取租户列表失败:', error);
|
console.error('获取租户列表失败:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onFinish = async (values: LoginParams & { tenantId?: string }) => {
|
const onFinish = async (values: LoginParams & { tenantId?: string }) => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const { tenantId, ...loginParams } = values;
|
const {tenantId, ...loginParams} = values;
|
||||||
const result = await login(loginParams);
|
const result = await login(loginParams);
|
||||||
|
|
||||||
// 保存租户ID到localStorage
|
|
||||||
if (tenantId) {
|
|
||||||
localStorage.setItem('tenantId', tenantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(setToken(result.token));
|
// 保存租户ID到localStorage
|
||||||
dispatch(setUserInfo({
|
if (tenantId) {
|
||||||
id: result.id,
|
localStorage.setItem('tenantId', tenantId);
|
||||||
username: result.username,
|
}
|
||||||
nickname: result.nickname,
|
|
||||||
email: result.email,
|
|
||||||
phone: result.phone
|
|
||||||
}));
|
|
||||||
|
|
||||||
message.success('登录成功');
|
|
||||||
navigate('/dashboard', { replace: true });
|
|
||||||
} catch (error) {
|
|
||||||
console.error('登录失败:', error);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
dispatch(setToken(result.token));
|
||||||
<div style={{
|
dispatch(setUserInfo({
|
||||||
height: '100vh',
|
id: result.id,
|
||||||
display: 'flex',
|
username: result.username,
|
||||||
justifyContent: 'center',
|
nickname: result.nickname,
|
||||||
alignItems: 'center',
|
email: result.email,
|
||||||
background: '#f0f2f5'
|
phone: result.phone
|
||||||
}}>
|
}));
|
||||||
<div style={{
|
|
||||||
width: '400px',
|
|
||||||
padding: '40px',
|
|
||||||
background: '#fff',
|
|
||||||
borderRadius: '8px',
|
|
||||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
|
||||||
}}>
|
|
||||||
<h2 style={{ textAlign: 'center', marginBottom: '30px' }}>系统登录</h2>
|
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
name="login"
|
|
||||||
onFinish={onFinish}
|
|
||||||
autoComplete="off"
|
|
||||||
>
|
|
||||||
<Form.Item
|
|
||||||
name="tenantId"
|
|
||||||
rules={[{ required: true, message: '请选择租户!' }]}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
placeholder="请选择租户"
|
|
||||||
options={tenants.map(tenant => ({
|
|
||||||
label: tenant.name,
|
|
||||||
value: tenant.code
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
message.success('登录成功');
|
||||||
name="username"
|
navigate('/dashboard', {replace: true});
|
||||||
rules={[{ required: true, message: '请输入用户名!' }]}
|
} catch (error) {
|
||||||
>
|
console.error('登录失败:', error);
|
||||||
<Input placeholder="用户名" size="large" />
|
} finally {
|
||||||
</Form.Item>
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
<Form.Item
|
return (
|
||||||
name="password"
|
<div style={{
|
||||||
rules={[{ required: true, message: '请输入密码!' }]}
|
height: '100vh',
|
||||||
>
|
display: 'flex',
|
||||||
<Input.Password placeholder="密码" size="large" />
|
justifyContent: 'center',
|
||||||
</Form.Item>
|
alignItems: 'center',
|
||||||
|
background: '#f0f2f5'
|
||||||
|
}}>
|
||||||
|
<div style={{
|
||||||
|
width: '400px',
|
||||||
|
padding: '40px',
|
||||||
|
background: '#fff',
|
||||||
|
borderRadius: '8px',
|
||||||
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
||||||
|
}}>
|
||||||
|
<h2 style={{textAlign: 'center', marginBottom: '30px'}}>系统登录</h2>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
name="login"
|
||||||
|
onFinish={onFinish}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name="tenantId"
|
||||||
|
rules={[{required: true, message: '请选择租户!'}]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder="请选择租户"
|
||||||
|
options={tenants.map(tenant => ({
|
||||||
|
label: tenant.name,
|
||||||
|
value: tenant.code
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item>
|
<Form.Item
|
||||||
<Button type="primary" htmlType="submit" block size="large" loading={loading}>
|
name="username"
|
||||||
登录
|
rules={[{required: true, message: '请输入用户名!'}]}
|
||||||
</Button>
|
>
|
||||||
</Form.Item>
|
<Input placeholder="用户名" size="large"/>
|
||||||
</Form>
|
</Form.Item>
|
||||||
</div>
|
|
||||||
</div>
|
<Form.Item
|
||||||
);
|
name="password"
|
||||||
|
rules={[{required: true, message: '请输入密码!'}]}
|
||||||
|
>
|
||||||
|
<Input.Password placeholder="密码" size="large"/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item>
|
||||||
|
<Button type="primary" htmlType="submit" block size="large" loading={loading}>
|
||||||
|
登录
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Login;
|
export default Login;
|
||||||
@ -1,37 +1,37 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import type { TenantDTO, TenantQuery } from './types';
|
import type {TenantDTO, TenantQuery} from './types';
|
||||||
|
|
||||||
// 获取租户列表(分页)
|
// 获取租户列表(分页)
|
||||||
export const getTenants = async (params?: TenantQuery) => {
|
export const getTenants = async (params?: TenantQuery) => {
|
||||||
return request.get<TenantDTO[]>('/api/system/tenants', { params });
|
return request.get<TenantDTO[]>('/api/system/tenants', {params});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取所有启用的租户(用于登录页面)
|
// 获取所有启用的租户(用于登录页面)
|
||||||
export const getEnabledTenants = async () => {
|
export const getEnabledTenants = async () => {
|
||||||
return request.get<TenantDTO[]>('/api/system/tenants/list');
|
return request.get<TenantDTO[]>('/api/v1/tenant/list');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建租户
|
// 创建租户
|
||||||
export const createTenant = async (data: Partial<TenantDTO>) => {
|
export const createTenant = async (data: Partial<TenantDTO>) => {
|
||||||
return request.post<TenantDTO>('/api/system/tenants', data);
|
return request.post<TenantDTO>('/api/system/tenants', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新租户
|
// 更新租户
|
||||||
export const updateTenant = async (id: number, data: Partial<TenantDTO>) => {
|
export const updateTenant = async (id: number, data: Partial<TenantDTO>) => {
|
||||||
return request.put<TenantDTO>(`/api/system/tenants/${id}`, data);
|
return request.put<TenantDTO>(`/api/system/tenants/${id}`, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 删除租户
|
// 删除租户
|
||||||
export const deleteTenant = async (id: number) => {
|
export const deleteTenant = async (id: number) => {
|
||||||
return request.delete(`/api/system/tenants/${id}`);
|
return request.delete(`/api/system/tenants/${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 检查租户编码是否存在
|
// 检查租户编码是否存在
|
||||||
export const checkTenantCode = async (code: string) => {
|
export const checkTenantCode = async (code: string) => {
|
||||||
return request.get<boolean>(`/api/system/tenants/check-code`, { params: { code } });
|
return request.get<boolean>(`/api/system/tenants/check-code`, {params: {code}});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 检查租户名称是否存在
|
// 检查租户名称是否存在
|
||||||
export const checkTenantName = async (name: string) => {
|
export const checkTenantName = async (name: string) => {
|
||||||
return request.get<boolean>(`/api/system/tenants/check-name`, { params: { name } });
|
return request.get<boolean>(`/api/system/tenants/check-name`, {params: {name}});
|
||||||
};
|
};
|
||||||
@ -1,55 +1,53 @@
|
|||||||
import axios, { AxiosResponse } from 'axios';
|
import axios, {AxiosResponse} from 'axios';
|
||||||
import { message } from 'antd';
|
import {message} from 'antd';
|
||||||
|
|
||||||
export interface ApiResponse<T> {
|
export interface ApiResponse<T> {
|
||||||
code: number;
|
code: number;
|
||||||
message: string;
|
message: string;
|
||||||
data: T;
|
data: T;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const request = axios.create({
|
const request = axios.create({
|
||||||
baseURL: '',
|
baseURL: '',
|
||||||
timeout: 300000,
|
timeout: 300000,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
request.interceptors.request.use(
|
request.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
const tenantId = localStorage.getItem('tenantId');
|
const tenantId = localStorage.getItem('tenantId');
|
||||||
|
if (token) {
|
||||||
if (token) {
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
}
|
||||||
|
if (tenantId) {
|
||||||
|
config.headers['X-Devops-Tenant-Id'] = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tenantId) {
|
|
||||||
config.headers['X-Tenant-ID'] = tenantId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
request.interceptors.response.use(
|
request.interceptors.response.use(
|
||||||
(response: AxiosResponse<ApiResponse<any>>) => {
|
(response: AxiosResponse<ApiResponse<any>>) => {
|
||||||
const res = response.data;
|
const res = response.data;
|
||||||
if (res.code !== 200) {
|
if (res.code !== 200) {
|
||||||
message.error(res.message || '请求失败');
|
message.error(res.message || '请求失败');
|
||||||
return Promise.reject(new Error(res.message || '请求失败'));
|
return Promise.reject(new Error(res.message || '请求失败'));
|
||||||
|
}
|
||||||
|
return Promise.resolve(res.data);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
message.error(error.response?.data?.message || '请求失败');
|
||||||
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
return Promise.resolve(res.data);
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
message.error(error.response?.data?.message || '请求失败');
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export default request;
|
export default request;
|
||||||
Loading…
Reference in New Issue
Block a user