From be8c526a454aa9081000d15f26bebdef8c183aea Mon Sep 17 00:00:00 2001
From: wsj <593216709@qq.com>
Date: Mon, 26 Oct 2026 23:34:23 +0800
Subject: [PATCH] feat: 提交
---
src/pages/system/roles/index.tsx | 125 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/src/pages/system/roles/index.tsx b/src/pages/system/roles/index.tsx
new file mode 100644
index 0000000..1d6f6ac
--- /dev/null
+++ b/src/pages/system/roles/index.tsx
@@ -0,0 +1,125 @@
+import { useCallback, useMemo, useRef, useState } from 'react';
+import { ProTable } from '@ant-design/pro-components';
+import type { ActionType } from '@ant-design/pro-components';
+import { App as AntdApp, Descriptions, Drawer, Tag } from 'antd';
+import { createRoleColumns, getRoleStatusMeta, getRoleTypeMeta } from './columns';
+import { getRoleDetail, getRoleList, toggleRoleStatus } from './server';
+import type { RoleListQuery, RoleVO } from './types';
+
+const Roles = () => {
+ const actionRef = useRef<ActionType>();
+ const { message, modal } = AntdApp.useApp();
+ const [detail, setDetail] = useState<RoleVO | null>(null);
+ const [detailOpen, setDetailOpen] = useState(false);
+ const [detailLoading, setDetailLoading] = useState(false);
+
+ const handleDetail = useCallback(async (record: RoleVO) => {
+ setDetailOpen(true);
+ setDetailLoading(true);
+
+ try {
+ const data = await getRoleDetail({ id: record.id });
+ setDetail(data);
+ } catch {
+ // 错误已由 request 统一提示
+ setDetailOpen(false);
+ } finally {
+ setDetailLoading(false);
+ }
+ }, []);
+
+ const handleToggle = useCallback(
+ (record: RoleVO) => {
+ const nextAction = record.status === 'ENABLED' ? '禁用' : '启用';
+ modal.confirm({
+ title: `${nextAction}角色`,
+ content: `确定要${nextAction}角色「${record.roleName}」吗?`,
+ okText: nextAction,
+ cancelText: '取消',
+ okButtonProps: { danger: record.status === 'ENABLED' },
+ onOk: async () => {
+ await toggleRoleStatus({ id: record.id });
+ message.success(`角色已${nextAction}`);
+ actionRef.current?.reload();
+ },
+ });
+ },
+ [message, modal],
+ );
+
+ const columns = useMemo(
+ () => createRoleColumns({ onDetail: handleDetail, onToggle: handleToggle }),
+ [handleDetail, handleToggle],
+ );
+
+ return (
+ <div className="role-page">
+ <ProTable<RoleVO, RoleListQuery>
+ rowKey="id"
+ actionRef={actionRef}
+ columns={columns}
+ cardProps={{ className: 'table-card' }}
+ search={{ labelWidth: 'auto', defaultCollapsed: false }}
+ scroll={{ x: 960 }}
+ options={false}
+ pagination={{
+ defaultPageSize: 10,
+ showSizeChanger: true,
+ hideOnSinglePage: false,
+ showTotal: (total) => `共 ${total} 条`,
+ }}
+ request={async (params) => {
+ const { current = 1, pageSize = 10, roleName, status } = params;
+ const keyword = roleName?.trim().toLowerCase();
+ const list = await getRoleList();
+ const filtered = list.filter((role) => {
+ const matchesKeyword =
+ !keyword ||
+ role.roleName.toLowerCase().includes(keyword) ||
+ role.roleCode.toLowerCase().includes(keyword);
+ const matchesStatus = !status || role.status === status;
+ return matchesKeyword && matchesStatus;
+ });
+ const start = (current - 1) * pageSize;
+
+ return {
+ data: filtered.slice(start, start + pageSize),
+ total: filtered.length,
+ success: true,
+ };
+ }}
+ />
+
+ <Drawer
+ title="角色详情"
+ width={460}
+ open={detailOpen}
+ loading={detailLoading}
+ onClose={() => {
+ setDetailOpen(false);
+ setDetail(null);
+ }}
+ >
+ {detail && (
+ <Descriptions column={1} bordered size="small">
+ <Descriptions.Item label="角色名称">{detail.roleName}</Descriptions.Item>
+ <Descriptions.Item label="角色编码">{detail.roleCode}</Descriptions.Item>
+ <Descriptions.Item label="角色类型">
+ <Tag color={getRoleTypeMeta(detail.roleType).color} bordered={false}>
+ {getRoleTypeMeta(detail.roleType).text}
+ </Tag>
+ </Descriptions.Item>
+ <Descriptions.Item label="状态">
+ <Tag color={getRoleStatusMeta(detail.status).color} bordered={false}>
+ {getRoleStatusMeta(detail.status).text}
+ </Tag>
+ </Descriptions.Item>
+ <Descriptions.Item label="描述">{detail.description || '-'}</Descriptions.Item>
+ </Descriptions>
+ )}
+ </Drawer>
+ </div>
+ );
+};
+
+export default Roles;
--
Gitblit v1.9.3