可正常启用
This commit is contained in:
parent
fa31848e9f
commit
76eeeb4b8e
@ -1,5 +1,5 @@
|
|||||||
import {useState, useCallback, useEffect} from 'react';
|
import {useState, useCallback, useEffect} from 'react';
|
||||||
import {Modal} from 'antd';
|
import {message, Modal} from 'antd';
|
||||||
import type {TableState} from '@/types/table';
|
import type {TableState} from '@/types/table';
|
||||||
import {createInitialState} from '@/utils/table';
|
import {createInitialState} from '@/utils/table';
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
@ -38,8 +38,7 @@ export function useTableData<T extends { id: number }, P extends SortParams>({
|
|||||||
...params,
|
...params,
|
||||||
pageNum: state.pagination.current,
|
pageNum: state.pagination.current,
|
||||||
pageSize: state.pagination.pageSize,
|
pageSize: state.pagination.pageSize,
|
||||||
sortOrder: params?.sortOrder === 'ascend' ? 'asc' :
|
sortOrder: params?.sortOrder === 'ascend' ? 'asc' : params?.sortOrder === 'descend' ? 'desc' : undefined
|
||||||
params?.sortOrder === 'descend' ? 'desc' : undefined
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,10 +59,9 @@ export function useTableData<T extends { id: number }, P extends SortParams>({
|
|||||||
// CRUD操作
|
// CRUD操作
|
||||||
const handleCreate = useCallback(async (data: Partial<T>) => {
|
const handleCreate = useCallback(async (data: Partial<T>) => {
|
||||||
try {
|
try {
|
||||||
await request.post<T>(service.baseUrl, data, {
|
await request.post<T>(service.baseUrl, data);
|
||||||
successMessage: '创建成功'
|
message.success("创建成功")
|
||||||
});
|
await loadData();
|
||||||
loadData();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
@ -72,10 +70,9 @@ export function useTableData<T extends { id: number }, P extends SortParams>({
|
|||||||
|
|
||||||
const handleUpdate = useCallback(async (id: number, data: Partial<T>) => {
|
const handleUpdate = useCallback(async (id: number, data: Partial<T>) => {
|
||||||
try {
|
try {
|
||||||
await request.put<T>(`${service.baseUrl}/${id}`, data, {
|
await request.put<T>(`${service.baseUrl}/${id}`, data);
|
||||||
successMessage: '更新成功'
|
message.success("更新成功")
|
||||||
});
|
await loadData();
|
||||||
loadData();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
@ -92,9 +89,8 @@ export function useTableData<T extends { id: number }, P extends SortParams>({
|
|||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
await request.delete(`${service.baseUrl}/${id}`, {
|
await request.delete(`${service.baseUrl}/${id}`);
|
||||||
successMessage: '删除成功'
|
message.success("删除成功")
|
||||||
});
|
|
||||||
loadData();
|
loadData();
|
||||||
resolve(true);
|
resolve(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -51,19 +51,10 @@ const BasicLayout: React.FC = () => {
|
|||||||
const initializeUserData = async () => {
|
const initializeUserData = async () => {
|
||||||
// try {
|
// try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const menuData = await getCurrentUserMenus().then((response) => {
|
const menuData = await getCurrentUserMenus();
|
||||||
console.log(response)
|
console.log(menuData)
|
||||||
dispatch(setMenus(response));
|
dispatch(setMenus(menuData));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
})
|
|
||||||
// } catch (error) {
|
|
||||||
// console.log(error);
|
|
||||||
// message.error('初始化用户数据失败');
|
|
||||||
// dispatch(logout());
|
|
||||||
// navigate('/login', {replace: true});
|
|
||||||
// } finally {
|
|
||||||
// setLoading(false);
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!userInfo) {
|
if (!userInfo) {
|
||||||
|
|||||||
@ -6,8 +6,7 @@ import { useTableData } from '@/hooks/useTableData';
|
|||||||
import type {FixedType} from 'rc-table/lib/interface';
|
import type {FixedType} from 'rc-table/lib/interface';
|
||||||
import type {TablePaginationConfig} from 'antd/es/table';
|
import type {TablePaginationConfig} from 'antd/es/table';
|
||||||
import type {FilterValue, SorterResult} from 'antd/es/table/interface';
|
import type {FilterValue, SorterResult} from 'antd/es/table/interface';
|
||||||
import { assignTags, getAllTags } from './service';
|
import {assignTags, createRoleTag, deleteRoleTag, getAllTags, updateRoleTag} from './service';
|
||||||
import request from '@/utils/request';
|
|
||||||
|
|
||||||
const RolePage: React.FC = () => {
|
const RolePage: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
@ -42,9 +41,15 @@ const RolePage: React.FC = () => {
|
|||||||
const [tagForm] = Form.useForm();
|
const [tagForm] = Form.useForm();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getAllTags().then(response => {
|
const fetchTags = async () => { // 定义一个异步函数
|
||||||
setAllTags(response);
|
try {
|
||||||
});
|
const tags = await getAllTags(); // 在这里使用 await
|
||||||
|
setAllTags(tags);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取标签失败", error); // 处理错误
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchTags(); // 调用异步函数
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
@ -110,23 +115,18 @@ const RolePage: React.FC = () => {
|
|||||||
const handleTagManageSubmit = async () => {
|
const handleTagManageSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
const values = await tagForm.validateFields();
|
const values = await tagForm.validateFields();
|
||||||
const tagService = {
|
if (values.id) {
|
||||||
baseUrl: '/api/v1/role-tag'
|
await updateRoleTag(values.id, {
|
||||||
};
|
|
||||||
|
|
||||||
const formData = {
|
|
||||||
...values,
|
...values,
|
||||||
color: values.color.toHexString?.() || values.color
|
color: values.color.toHexString?.() || values.color
|
||||||
};
|
|
||||||
|
|
||||||
if (values.id) {
|
|
||||||
await request.put(`${tagService.baseUrl}/${values.id}`, formData, {
|
|
||||||
successMessage: '更新标签成功'
|
|
||||||
});
|
});
|
||||||
|
message.success("更新标签成功")
|
||||||
} else {
|
} else {
|
||||||
await request.post(tagService.baseUrl, formData, {
|
await createRoleTag({
|
||||||
successMessage: '创建标签成功'
|
...values,
|
||||||
|
color: values.color.toHexString?.() || values.color
|
||||||
});
|
});
|
||||||
|
message.success("标签添加成功")
|
||||||
}
|
}
|
||||||
setTagManageVisible(false);
|
setTagManageVisible(false);
|
||||||
const tags = await getAllTags();
|
const tags = await getAllTags();
|
||||||
@ -137,16 +137,25 @@ const RolePage: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleTagDelete = async (id: number) => {
|
const handleTagDelete = async (id: number) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除',
|
||||||
|
content: '确定要删除该记录吗?',
|
||||||
|
okText: '确定',
|
||||||
|
okType: 'danger',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: async () => {
|
||||||
try {
|
try {
|
||||||
await request.delete(`/api/v1/role-tag/${id}`, {
|
await deleteRoleTag(id);
|
||||||
successMessage: '删除标签成功'
|
message.success("删除成功");
|
||||||
});
|
|
||||||
// 刷新标签列表
|
// 刷新标签列表
|
||||||
const tags = await getAllTags();
|
const tags = await getAllTags();
|
||||||
setAllTags(tags);
|
setAllTags(tags);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('删除标签失败:', error);
|
console.error("角色标签删除失败", error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// onCancel: () => resolve(false)
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
|||||||
@ -1,52 +1,31 @@
|
|||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import type {Page} from '@/types/base/page';
|
import type {Page} from '@/types/base/page';
|
||||||
import type { RoleResponse, RoleRequest, RoleQuery, RoleTagResponse } from './types';
|
import {RoleResponse, RoleRequest, RoleQuery, RoleTagResponse, RoleTagRequest} from './types';
|
||||||
|
|
||||||
const BASE_URL = '/api/v1/role';
|
const BASE_URL = '/api/v1/role';
|
||||||
|
|
||||||
|
const ROLE_TAG_BASE_URL = '/api/v1/role-tag'
|
||||||
|
|
||||||
// 获取角色列表(分页)
|
// 获取角色列表(分页)
|
||||||
export const getRoles = (params?: RoleQuery) =>
|
export const getRoles = (params?: RoleQuery) => request.get<Page<RoleResponse>>(`${BASE_URL}/page`, {params});
|
||||||
request.get<Page<RoleResponse>>(`${BASE_URL}/page`, {
|
|
||||||
params
|
|
||||||
});
|
|
||||||
|
|
||||||
// 创建角色
|
// 创建角色
|
||||||
export const createRole = (data: RoleRequest) =>
|
export const createRole = (data: RoleRequest) => request.post<RoleResponse>(BASE_URL, data);
|
||||||
request.post<RoleResponse>(BASE_URL, data, {
|
|
||||||
successMessage: '创建角色成功'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 更新角色
|
// 更新角色
|
||||||
export const updateRole = (id: number, data: RoleRequest) =>
|
export const updateRole = (id: number, data: RoleRequest) => request.put<RoleResponse>(`${BASE_URL}/${id}`, data);
|
||||||
request.put<RoleResponse>(`${BASE_URL}/${id}`, data, {
|
|
||||||
successMessage: '更新角色成功'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 删除角色
|
// 删除角色
|
||||||
export const deleteRole = (id: number) =>
|
export const deleteRole = (id: number) => request.delete(`${BASE_URL}/${id}`);
|
||||||
request.delete(`${BASE_URL}/${id}`, {
|
|
||||||
successMessage: '删除角色成功'
|
|
||||||
});
|
|
||||||
|
|
||||||
export const assignMenus = async (roleId: number, menuIds: number[]) => {
|
|
||||||
return request.post(`/api/v1/role/${roleId}/menus`, menuIds, {
|
|
||||||
errorMessage: '分配菜单失败,请稍后重试'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getRoleMenus = async (roleId: number) => {
|
|
||||||
return request.get(`/api/v1/role/${roleId}/menus`, {
|
|
||||||
errorMessage: '获取角色菜单失败,请刷新重试'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 分配标签
|
// 分配标签
|
||||||
export const assignTags = (roleId: number, tagIds: number[]) =>
|
export const assignTags = (roleId: number, tagIds: number[]) => request.post(`${BASE_URL}/${roleId}/tags`, tagIds);
|
||||||
request.post(`${BASE_URL}/${roleId}/tags`, tagIds, {
|
|
||||||
successMessage: '分配标签成功'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取所有标签
|
// 获取所有标签
|
||||||
export const getAllTags = () =>
|
export const getAllTags = () => request.get<RoleTagResponse[]>(`${ROLE_TAG_BASE_URL}/list`);
|
||||||
request.get<RoleTagResponse[]>('/api/v1/role-tag/list');
|
|
||||||
|
|
||||||
|
export const deleteRoleTag = (id: number) => request.delete(`${ROLE_TAG_BASE_URL}/${id}`);
|
||||||
|
|
||||||
|
export const updateRoleTag = (id: number, data: RoleTagRequest) => request.put(`${ROLE_TAG_BASE_URL}/${id}`, data);
|
||||||
|
|
||||||
|
export const createRoleTag = (data: RoleRequest) => request.post<RoleResponse>(ROLE_TAG_BASE_URL, data);
|
||||||
@ -1,124 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { Table, Button, Modal, Form, Input, Space, ColorPicker } from 'antd';
|
|
||||||
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
|
||||||
import type { RoleTagResponse } from './types';
|
|
||||||
import { useTableData } from '@/hooks/useTableData';
|
|
||||||
import type { Color } from 'antd/es/color-picker';
|
|
||||||
|
|
||||||
const RoleTagPage: React.FC = () => {
|
|
||||||
const {
|
|
||||||
list: tags,
|
|
||||||
loading,
|
|
||||||
handleCreate,
|
|
||||||
handleUpdate,
|
|
||||||
handleDelete
|
|
||||||
} = useTableData({
|
|
||||||
service: {
|
|
||||||
baseUrl: '/api/v1/role-tag'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const [modalVisible, setModalVisible] = useState(false);
|
|
||||||
const [editingTag, setEditingTag] = useState<RoleTagResponse | null>(null);
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: '标签名称',
|
|
||||||
dataIndex: 'name',
|
|
||||||
key: 'name'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '颜色',
|
|
||||||
dataIndex: 'color',
|
|
||||||
key: 'color',
|
|
||||||
render: (color: string) => (
|
|
||||||
<div style={{
|
|
||||||
backgroundColor: color,
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
borderRadius: 4
|
|
||||||
}} />
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '描述',
|
|
||||||
dataIndex: 'description',
|
|
||||||
key: 'description'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
key: 'action',
|
|
||||||
render: (_: any, record: RoleTagResponse) => (
|
|
||||||
<Space>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
icon={<EditOutlined />}
|
|
||||||
onClick={() => handleEdit(record)}
|
|
||||||
>
|
|
||||||
编辑
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
danger
|
|
||||||
icon={<DeleteOutlined />}
|
|
||||||
onClick={() => handleDelete(record.id)}
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{ padding: '24px' }}>
|
|
||||||
<div style={{ marginBottom: 16 }}>
|
|
||||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
|
||||||
新增标签
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Table
|
|
||||||
loading={loading}
|
|
||||||
columns={columns}
|
|
||||||
dataSource={tags}
|
|
||||||
rowKey="id"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
title={editingTag ? '编辑标签' : '新增标签'}
|
|
||||||
open={modalVisible}
|
|
||||||
onOk={handleSubmit}
|
|
||||||
onCancel={() => setModalVisible(false)}
|
|
||||||
>
|
|
||||||
<Form form={form} layout="vertical">
|
|
||||||
<Form.Item
|
|
||||||
name="name"
|
|
||||||
label="标签名称"
|
|
||||||
rules={[{ required: true }]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
name="color"
|
|
||||||
label="标签颜色"
|
|
||||||
rules={[{ required: true }]}
|
|
||||||
>
|
|
||||||
<ColorPicker />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
name="description"
|
|
||||||
label="描述"
|
|
||||||
>
|
|
||||||
<Input.TextArea />
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RoleTagPage;
|
|
||||||
@ -9,8 +9,6 @@ export interface Response<T = any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface RequestOptions extends AxiosRequestConfig {
|
export interface RequestOptions extends AxiosRequestConfig {
|
||||||
successMessage?: string;
|
|
||||||
errorMessage?: string;
|
|
||||||
retryCount?: number;
|
retryCount?: number;
|
||||||
retryDelay?: number;
|
retryDelay?: number;
|
||||||
}
|
}
|
||||||
@ -32,6 +30,8 @@ const request = axios.create({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const defaultErrorMessage = '操作失败';
|
||||||
|
|
||||||
// 创建请求配置
|
// 创建请求配置
|
||||||
const createRequestConfig = (options?: Partial<RequestOptions>): RequestOptions => {
|
const createRequestConfig = (options?: Partial<RequestOptions>): RequestOptions => {
|
||||||
return {
|
return {
|
||||||
@ -41,52 +41,51 @@ const createRequestConfig = (options?: Partial<RequestOptions>): RequestOptions
|
|||||||
};
|
};
|
||||||
|
|
||||||
const responseHandler = (response: AxiosResponse<Response<any>>) => {
|
const responseHandler = (response: AxiosResponse<Response<any>>) => {
|
||||||
const data = response.data;
|
const result = response.data;
|
||||||
const config = response.config as RequestOptions;
|
if (result.success && result.code === 200) {
|
||||||
|
return result.data;
|
||||||
if (data.success && data.code === 200) {
|
|
||||||
config.successMessage && message.success(config.successMessage);
|
|
||||||
return data.data;
|
|
||||||
} else {
|
} else {
|
||||||
message.error(config.errorMessage || data.message);
|
if (result.message !== undefined) {
|
||||||
return Promise.reject(response); // 隐式返回 Promise
|
message.error(result.message || defaultErrorMessage);
|
||||||
|
return Promise.reject(response);
|
||||||
|
}
|
||||||
|
return Promise.reject(response);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const statusMessages: Record<number, string> = {
|
|
||||||
401: '未授权,请重新登录',
|
|
||||||
403: '拒绝访问',
|
|
||||||
404: '请求错误,未找到该资源',
|
|
||||||
500: '服务器错误'
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultErrorMessage = '服务器异常,请稍后再试!';
|
|
||||||
|
|
||||||
const errorHandler = (error: any) => {
|
const errorHandler = (error: any) => {
|
||||||
const config = error.config as RequestOptions;
|
|
||||||
|
|
||||||
// 检查是否有响应
|
|
||||||
if (!error.response) {
|
if (!error.response) {
|
||||||
message.error('网络连接异常,请检查网络');
|
message.error('网络连接异常,请检查网络');
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否为取消请求
|
|
||||||
if (axios.isCancel(error)) {
|
if (axios.isCancel(error)) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = error.response.status;
|
const status = error.response.status;
|
||||||
const msg = statusMessages[status] || defaultErrorMessage; // 获取相应的消息
|
let errorMessage = '';
|
||||||
|
switch (status) {
|
||||||
// 显示错误信息
|
case 401:
|
||||||
message.error(config.errorMessage || msg);
|
errorMessage = '未授权,请重新登录';
|
||||||
|
break;
|
||||||
return Promise.reject(error); // 拦截错误并返回
|
case 403:
|
||||||
|
errorMessage = '拒绝访问';
|
||||||
|
break;
|
||||||
|
case 404:
|
||||||
|
errorMessage = '请求错误,未找到该资源';
|
||||||
|
break;
|
||||||
|
case 500:
|
||||||
|
errorMessage = '服务异常,请稍后再试';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorMessage = '服务器异常,请稍后再试!';
|
||||||
|
}
|
||||||
|
message.error(errorMessage);
|
||||||
|
return Promise.reject(error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
request.interceptors.request.use(
|
request.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
@ -101,9 +100,8 @@ request.interceptors.request.use(
|
|||||||
request.interceptors.response.use(responseHandler, errorHandler);
|
request.interceptors.response.use(responseHandler, errorHandler);
|
||||||
|
|
||||||
const http = {
|
const http = {
|
||||||
get: <T = any>(url: string, config?: RequestOptions) => {
|
get: <T = any>(url: string, config?: RequestOptions) =>
|
||||||
return request.get<any, T>(url, createRequestConfig(config));
|
request.get<any, T>(url, createRequestConfig(config)),
|
||||||
},
|
|
||||||
|
|
||||||
post: <T = any>(url: string, data?: any, config?: RequestOptions) =>
|
post: <T = any>(url: string, data?: any, config?: RequestOptions) =>
|
||||||
request.post<any, Response<T>>(url, data, createRequestConfig(config)),
|
request.post<any, Response<T>>(url, data, createRequestConfig(config)),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user