Files
helix-web-react/src/page/role/index.tsx
T
2025-12-29 14:20:38 +08:00

321 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect, useState } from "react"
import axios, { type AxiosError } from "axios"
import { App, Button, Form, Input, Select, Space, Switch, Table } from "antd"
import type { Role } from "@/types/entity"
import { RoleApi } from "@/api"
import type { QueryRoleRequest } from "@/types/web/request"
import type { GeneralErrorResponse } from "@/types/web/response"
import {
DeleteOutlined,
ExportOutlined,
ImportOutlined,
PlusOutlined,
SearchOutlined,
UndoOutlined,
} from "@ant-design/icons"
import type { QueryRoleForm } from "@/types/form"
import type { Status } from "@/types/constant"
import AddRoleDialogue from "@/components/add-role-dialogue"
import type { RoleFormValues } from "@/components/role-display-form"
import EditRoleDialogue from "@/components/edit-role-dialogue"
export default function RolePage() {
const { message, modal } = App.useApp()
const [queryForm] = Form.useForm<QueryRoleForm>()
const [addRoleForm] = Form.useForm<RoleFormValues>()
const [editRoleForm] = Form.useForm<RoleFormValues>()
const [roles, setRoles] = useState<Role[]>([])
const [pageNum, setPageNum] = useState<number>(1)
const [pageSize, setPageSize] = useState<number>(10)
const [totalElementCount, setTotalElementCount] = useState<number>(0)
const [isLastPage, setIsLastPage] = useState<boolean>(false)
const [isFirstPage, setIsFirstPage] = useState<boolean>(false)
const queryRoles = (pageNum: number, pageSize: number, queryRoleForm: QueryRoleForm | null) => {
const queryRoleRequest: QueryRoleRequest = {
code: queryRoleForm?.qCode ?? null,
name: queryRoleForm?.qName ?? null,
status: queryRoleForm?.qStatus ?? null,
pageNum,
pageSize,
}
RoleApi.fetchRoles(queryRoleRequest)
.then((response) => {
setPageNum(response.pageable.pageNumber + 1)
setPageSize(response.pageable.pageSize)
setTotalElementCount(response.totalElements)
setRoles(response.content.sort((role1, role2) => role1.sort - role2.sort))
setIsLastPage(response.last)
setIsFirstPage(response.first)
})
.catch((error) => {
const err = error as AxiosError<GeneralErrorResponse>
void message.error(err.response?.data.message ?? "获取角色失败")
})
}
const changeRoleStatus = (roleId: number | string, checked: boolean) => {
const status: Status = checked ? "ACTIVE" : "INACTIVE"
setRoles((prevRoles) =>
prevRoles.map((role) => (role.id === roleId ? { ...role, status } : role))
)
}
const onAddRoleFinish = async () => {
try {
const values = await addRoleForm.validateFields()
console.log(values)
await RoleApi.addRole(values)
void message.success(`角色 ${values.name} 创建成功`)
return true
} catch (error: unknown) {
if (axios.isAxiosError<GeneralErrorResponse>(error)) {
// 处理 Axios 请求错误
const serverMsg = error.response?.data?.message
void message.error(serverMsg ?? "服务异常,请稍后再试")
} else {
// 处理其他预期外的错误(如代码逻辑 Bug)
console.error("未知错误:", error)
void message.error("发生系统错误,请联系管理员")
}
return false
}
}
const handleAddRole = () => {
modal
.confirm({
title: "添加用户",
content: <AddRoleDialogue form={addRoleForm} />,
width: 600,
onOk: onAddRoleFinish,
})
.then(
() => {
const formValues = queryForm.getFieldsValue()
queryRoles(pageNum, pageSize, formValues)
},
() => {
console.error("用户取消添加角色")
}
)
.finally(() => {
addRoleForm.resetFields()
})
}
const onEditRoleFinish = async () => {
try {
const values = await editRoleForm.validateFields()
console.log(values)
await RoleApi.editRole(values)
void message.success(`角色 ${values.name} 更新成功`)
return true
} catch (error: unknown) {
if (axios.isAxiosError<GeneralErrorResponse>(error)) {
const serverMsg = error.response?.data?.message
void message.error(serverMsg ?? "后端服务异常,请稍后再试")
} else {
console.error("未知错误:", error)
void message.error("发生系统错误,请联系管理员")
}
return false
}
}
const handleEditRole = (role: Role) => {
modal
.confirm({
title: "修改用户",
content: <EditRoleDialogue form={editRoleForm} initialValues={role} />,
width: 600,
onOk: onEditRoleFinish,
})
.then(
() => {
const formValues = queryForm.getFieldsValue()
queryRoles(pageNum, pageSize, formValues)
},
() => {
console.error("用户取消添加角色")
}
)
.finally(() => {
editRoleForm.resetFields()
})
}
const onDeleteRoleFinish = async (role: Role) => {
try {
await RoleApi.deleteRole(role.id)
void message.info(`角色 ${role.name} 删除成功`)
// Refresh roles
if (roles.length == 1 && isLastPage && !isFirstPage) {
setPageNum(pageNum - 1)
} else {
// Execute refresh manually
const searchParams = queryForm.getFieldsValue()
queryRoles(pageNum, pageSize, searchParams)
}
return true
} catch (error: unknown) {
if (axios.isAxiosError<GeneralErrorResponse>(error)) {
const serverMsg = error.response?.data?.message
void message.error(serverMsg ?? "服务异常,请稍后再试")
} else {
console.error("未知错误:", error)
void message.error("发生系统错误,请联系管理员")
}
return false
}
}
const handleDeleteRole = async (role: Role) => {
modal
.confirm({
title: "删除角色确认",
content: <></>,
onOk: () => onDeleteRoleFinish(role),
})
}
useEffect(() => {
queryRoles(pageNum, pageSize, null)
}, [pageNum, pageSize])
return (
<div className="flex gap-6 flex-col">
<Form<QueryRoleForm>
form={queryForm}
className="mt-0 mb-6"
layout="inline"
labelAlign="right"
onFinish={(values) => {
queryRoles(pageNum, pageSize, values)
}}
onReset={() => {
queryRoles(pageNum, pageSize, null)
}}>
<Form.Item<QueryRoleForm> label="角色名称" name="qName">
<Input />
</Form.Item>
<Form.Item<QueryRoleForm> label="角色编码" name="qCode">
<Input />
</Form.Item>
<Form.Item<QueryRoleForm> label="角色状态" name="qStatus">
<Select<Status>
className="w-26"
options={[
{
label: "已启用",
value: "ACTIVE",
},
{
label: "未启用",
value: "INACTIVE",
},
]}
/>
</Form.Item>
<Form.Item<QueryRoleForm>>
<Space>
<Button color="primary" variant="solid" htmlType="submit" icon={<SearchOutlined />}>
</Button>
<Button color="orange" variant="solid" htmlType="reset" icon={<UndoOutlined />}>
</Button>
</Space>
</Form.Item>
</Form>
<Space size={8}>
<Button variant="solid" type="primary" icon={<PlusOutlined />} onClick={handleAddRole}>
</Button>
<Button variant="solid" danger icon={<DeleteOutlined />}>
</Button>
<Button variant="solid" color="green" icon={<ImportOutlined />}>
</Button>
<Button variant="solid" color="green" icon={<ExportOutlined />}>
</Button>
</Space>
<Table<Role>
columns={[
{ title: "角色编号", dataIndex: "id" },
{ title: "角色名称", dataIndex: "name" },
{ title: "角色编码", dataIndex: "code" },
{ title: "显示顺序", dataIndex: "sort" },
{
title: "状态",
key: "status",
render: (role: Role) => (
<>
<Switch
value={role.status == "ACTIVE"}
onChange={(checked) => changeRoleStatus(role.id, checked)}
/>
</>
),
},
{
title: "默认角色",
key: "defaultValue",
render: (role: Role) => (
<>
<Switch value={role.defaultValue} disabled />
</>
),
},
{ title: "创建时间", dataIndex: "createdAt" },
{
title: "操作",
render: (role: Role) => (
<>
<Space.Compact>
<Button variant="solid" onClick={() => handleEditRole(role)}>
</Button>
<Button variant="solid" danger onClick={() => handleDeleteRole(role)}>
</Button>
</Space.Compact>
</>
),
key: "operations",
},
]}
dataSource={roles}
rowKey="id"
pagination={{
current: pageNum,
total: totalElementCount,
pageSize: pageSize,
defaultCurrent: 1,
defaultPageSize: 10,
pageSizeOptions: [10, 25, 50],
showSizeChanger: true,
onShowSizeChange: (pageNum, pageSize) => {
console.log(`onSizeChange ==> pageNum = ${pageNum}, pageSize = ${pageSize}`)
setPageNum(pageNum)
setPageSize(pageSize)
},
onChange: (pageNum, pageSize) => {
console.log(`onChange ==> pageNum = ${pageNum}, pageSize = ${pageSize}`)
setPageNum(pageNum)
setPageSize(pageSize)
},
}}
/>
</div>
)
}