|
|
@ -9,9 +9,17 @@ import { createLazyFileRoute } from '@tanstack/react-router' |
|
|
|
import { useStyle } from './style.ts' |
|
|
|
import { memo, useEffect, useMemo, useRef, useState } from 'react' |
|
|
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai' |
|
|
|
import { pageAtom, roleAtom, rolesAtom, saveOrUpdateRoleAtom, searchAtom } from './store.ts' |
|
|
|
import { |
|
|
|
deleteRoleAtom, |
|
|
|
pageAtom, |
|
|
|
roleAtom, |
|
|
|
roleIdsAtom, |
|
|
|
rolesAtom, |
|
|
|
saveOrUpdateRoleAtom, |
|
|
|
searchAtom |
|
|
|
} from './store.ts' |
|
|
|
import { useTranslation } from '@/i18n.ts' |
|
|
|
import { Button, Form, Space, Spin, Table, Tree } from 'antd' |
|
|
|
import { Button, Form, Space, Spin, Table, Tree, Popconfirm } from 'antd' |
|
|
|
import { PlusOutlined } from '@ant-design/icons' |
|
|
|
import { menuDataAtom } from '@/pages/system/menus/store.ts' |
|
|
|
import { getTreeCheckedStatus } from '@/utils/tree.ts' |
|
|
@ -46,8 +54,10 @@ const Roles = memo(() => { |
|
|
|
const actionRef = useRef<ActionType>() |
|
|
|
const [ page, setPage ] = useAtom(pageAtom) |
|
|
|
const setSearch = useSetAtom(searchAtom) |
|
|
|
const [ roleIds, setRoleIds ] = useAtom(roleIdsAtom) |
|
|
|
const { data, isLoading, isFetching, refetch } = useAtomValue(rolesAtom) |
|
|
|
const { isPending, mutate, isSuccess } = useAtomValue(saveOrUpdateRoleAtom) |
|
|
|
const { mutate: deleteRole, isPending: isDeleteing } = useAtomValue(deleteRoleAtom) |
|
|
|
const [ , setRole ] = useAtom(roleAtom) |
|
|
|
const [ open, setOpen ] = useState(false) |
|
|
|
|
|
|
@ -58,49 +68,61 @@ const Roles = memo(() => { |
|
|
|
title: 'id', dataIndex: 'id', |
|
|
|
hideInTable: true, |
|
|
|
hideInSearch: true, |
|
|
|
// hideInForm: true,
|
|
|
|
formItemProps: { |
|
|
|
hidden: true |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '名称', dataIndex: 'name', valueType: 'text', |
|
|
|
title: t('system.roles.columns.name'), dataIndex: 'name', valueType: 'text', |
|
|
|
formItemProps: { |
|
|
|
rules: [ { required: true, message: '请输入角色名称' } ] |
|
|
|
rules: [ { required: true, message: t('message.required') } ] |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '别名', dataIndex: 'code', valueType: 'text', |
|
|
|
title: t('system.roles.columns.code'), dataIndex: 'code', valueType: 'text', |
|
|
|
formItemProps: { |
|
|
|
rules: [ { required: true, message: '请输入别名' } ] |
|
|
|
rules: [ { required: true, message: t('message.required') } ] |
|
|
|
} |
|
|
|
}, |
|
|
|
{ title: '状态', dataIndex: 'status', valueType: 'switch', }, |
|
|
|
{ title: t('system.roles.columns.status'), dataIndex: 'status', valueType: 'switch', }, |
|
|
|
{ |
|
|
|
title: '排序', dataIndex: 'sort', valueType: 'digit', |
|
|
|
title: t('system.roles.columns.sort'), dataIndex: 'sort', valueType: 'digit', |
|
|
|
}, |
|
|
|
{ title: '备注', dataIndex: 'description', valueType: 'textarea' }, |
|
|
|
{ title: t('system.roles.columns.description'), dataIndex: 'description', valueType: 'textarea' }, |
|
|
|
{ |
|
|
|
title: '权限', dataIndex: 'menu_ids', |
|
|
|
title: t('system.roles.columns.menu_ids'), |
|
|
|
hideInTable: true, |
|
|
|
hideInSearch: true, |
|
|
|
dataIndex: 'menu_ids', |
|
|
|
valueType: 'text', |
|
|
|
renderFormItem: (item, config, form) => { |
|
|
|
return <MenuTree {...config} form={form} {...item.fieldProps} /> |
|
|
|
} |
|
|
|
}, |
|
|
|
{ |
|
|
|
title: '操作', valueType: 'option', |
|
|
|
title: t('system.roles.columns.option'), valueType: 'option', |
|
|
|
key: 'option', |
|
|
|
render: (text, record, _, action) => [ |
|
|
|
<a |
|
|
|
key="editable" |
|
|
|
onClick={() => { |
|
|
|
setRole(record) |
|
|
|
setOpen(true) |
|
|
|
form.setFieldsValue(record) |
|
|
|
}} |
|
|
|
<a key="editable" |
|
|
|
onClick={() => { |
|
|
|
setRole(record) |
|
|
|
setOpen(true) |
|
|
|
form.setFieldsValue(record) |
|
|
|
}} |
|
|
|
> |
|
|
|
编辑 |
|
|
|
</a>, |
|
|
|
<a href={record.url} target="_blank" rel="noopener noreferrer" key="del"> |
|
|
|
删除 |
|
|
|
{t('actions.edit', '编辑')} |
|
|
|
</a>, |
|
|
|
<Popconfirm |
|
|
|
key={'del_confirm'} |
|
|
|
onConfirm={()=>{ |
|
|
|
deleteRole([ record.id ]) |
|
|
|
}} |
|
|
|
title={t('message.deleteConfirm')}> |
|
|
|
<a key="del" > |
|
|
|
{t('actions.delete', '删除')} |
|
|
|
</a> |
|
|
|
</Popconfirm> |
|
|
|
, |
|
|
|
], |
|
|
|
}, |
|
|
|
] as ProColumns[] |
|
|
@ -112,6 +134,7 @@ const Roles = memo(() => { |
|
|
|
} |
|
|
|
}, [ isSuccess ]) |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
<PageContainer breadcrumbRender={false} title={false} className={styles.container}> |
|
|
|
<ProTable |
|
|
@ -123,12 +146,22 @@ const Roles = memo(() => { |
|
|
|
dataSource={data?.rows} |
|
|
|
search={false} |
|
|
|
rowSelection={{ |
|
|
|
onChange: (selectedRowKeys) => { |
|
|
|
setRoleIds(selectedRowKeys as number[]) |
|
|
|
}, |
|
|
|
selectedRowKeys: roleIds, |
|
|
|
selections: [ Table.SELECTION_ALL, Table.SELECTION_INVERT ], |
|
|
|
}} |
|
|
|
tableAlertOptionRender={() => { |
|
|
|
return ( |
|
|
|
<Space size={16}> |
|
|
|
<a>批量删除</a> |
|
|
|
<Popconfirm |
|
|
|
onConfirm={() => { |
|
|
|
deleteRole(roleIds) |
|
|
|
}} |
|
|
|
title={t('message.batchDelete')}> |
|
|
|
<Button type={'link'} loading={isDeleteing}>{t('actions.batchDel')}</Button> |
|
|
|
</Popconfirm> |
|
|
|
</Space> |
|
|
|
) |
|
|
|
}} |
|
|
@ -140,7 +173,7 @@ const Roles = memo(() => { |
|
|
|
toolbar={{ |
|
|
|
search: { |
|
|
|
onSearch: (value: string) => { |
|
|
|
setSearch({ name: value }) |
|
|
|
setSearch({ key: value }) |
|
|
|
}, |
|
|
|
}, |
|
|
|
actions: [ |
|
|
@ -156,7 +189,7 @@ const Roles = memo(() => { |
|
|
|
}} |
|
|
|
type="primary" |
|
|
|
> |
|
|
|
新建 |
|
|
|
{t('actions.add', '添加')} |
|
|
|
</Button>, |
|
|
|
] |
|
|
|
}} |
|
|
|