|
|
import Switch from '@/components/switch' import { usePageStoreOptions } from '@/store' import { IMenu } from '@/types/menus' import { ActionType, PageContainer, ProColumns, ProTable, BetaSchemaForm, ProFormColumnsType, } from '@ant-design/pro-components' import { useStyle } from './style.ts' import { memo, useEffect, useMemo, useRef, useState } from 'react' import { useAtom, useAtomValue } from 'jotai' import { deleteRoleAtom, pageAtom, roleAtom, roleIdsAtom, rolesAtom, saveOrUpdateRoleAtom, searchAtom } from '@/store/role.ts' import { useTranslation } from '@/i18n.ts' import { Button, Form, Space, Spin, Table, Tree, Popconfirm } from 'antd' import { PlusOutlined } from '@ant-design/icons' import { menuDataAtom } from '@/store/menu.ts' import { getTreeCheckedStatus } from '@/utils/tree.ts'
const MenuTree = (props: any) => { const { data: menuList, isLoading: menuLoading } = useAtomValue(menuDataAtom) const { value, onChange, form, id, mode } = props
const onCheck = (checkedKeys: any, info: any) => { if (onChange) { onChange([ ...checkedKeys, ...info.halfCheckedKeys ]) } else { form.setFieldsValue({ [id]: [ ...checkedKeys, ...info.halfCheckedKeys ] }) } } if (menuLoading) { return <Spin spinning={true} size={'small'}/> } return <Tree treeData={menuList} fieldNames={{ title: 'title', key: 'id' }} disabled={mode !== 'edit'} checkable={true} onCheck={onCheck} checkedKeys={getTreeCheckedStatus<IMenu>(menuList!, value)}/>
}
const Roles = memo(() => {
const { t } = useTranslation() const { styles } = useStyle() const [ form ] = Form.useForm() const actionRef = useRef<ActionType>() const [ page, setPage ] = useAtom(pageAtom, usePageStoreOptions()) const [ search, setSearch ] = useAtom(searchAtom, usePageStoreOptions()) const [ roleIds, setRoleIds ] = useAtom(roleIdsAtom, usePageStoreOptions()) const { data, isLoading, isFetching, refetch } = useAtomValue(rolesAtom, usePageStoreOptions()) const { isPending, mutate, isSuccess } = useAtomValue(saveOrUpdateRoleAtom, usePageStoreOptions()) const { mutate: deleteRole, isPending: isDeleting } = useAtomValue(deleteRoleAtom, usePageStoreOptions()) const [ , setRole ] = useAtom(roleAtom, usePageStoreOptions()) const [ open, setOpen ] = useState(false)
const columns = useMemo(() => {
return [ { title: 'id', dataIndex: 'id', hideInTable: true, hideInSearch: true, formItemProps: { hidden: true } }, { title: t('system.roles.columns.name'), dataIndex: 'name', valueType: 'text', formItemProps: { rules: [ { required: true, message: t('message.required') } ] } }, { title: t('system.roles.columns.code'), dataIndex: 'code', valueType: 'text', formItemProps: { rules: [ { required: true, message: t('message.required') } ] } }, { title: t('system.roles.columns.status'), dataIndex: 'status', valueType: 'switch', render: (text) => { return <Switch value={!!text} size={'small'}/> } }, { title: t('system.roles.columns.sort'), dataIndex: 'sort', valueType: 'digit', }, { title: t('system.roles.columns.description'), dataIndex: 'description', valueType: 'textarea' }, { 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: t('system.roles.columns.option'), valueType: 'option', key: 'option', render: (_, record) => [ <a key="editable" onClick={() => { setRole(record) setOpen(true) form.setFieldsValue(record) }} > {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[] }, [])
useEffect(() => { if (isSuccess) { setOpen(false) } }, [ isSuccess ])
return ( <PageContainer breadcrumbRender={false} title={false} className={styles.container}> <ProTable rowKey={'id'} actionRef={actionRef} headerTitle={t('system.roles.title', '角色管理')} columns={columns} loading={isLoading || isFetching} 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}> <Popconfirm onConfirm={() => { deleteRole(roleIds) }} title={t('message.batchDelete')}> <Button type={'link'} loading={isDeleting}>{t('actions.batchDel')}</Button> </Popconfirm> </Space> ) }} options={{ reload: () => { refetch() }, }} toolbar={{ search: { loading: isFetching && !!search.key, onSearch: (value: string) => { setSearch({ key: value }) }, placeholder: t('system.roles.search.placeholder') }, actions: [ <Button key="button" icon={<PlusOutlined/>} onClick={() => { form.resetFields() form.setFieldsValue({ id: 0, }) setOpen(true) }} type="primary" > {t('actions.add', '添加')} </Button>, ] }} pagination={{ total: data?.total, current: page.page, pageSize: page.pageSize, onChange: (page) => {
setPage((prev) => { return { ...prev, page } }) } }} /> <BetaSchemaForm width={600} form={form} layout={'horizontal'} title={t('system.roles.edit.title', '角色编辑')} colProps={{ span: 24 }} labelCol={{ span: 6 }} wrapperCol={{ span: 16 }} layoutType={'ModalForm'} open={open} modalProps={{ maskClosable: false, }} onOpenChange={(open) => { setOpen(open) }} loading={isPending} onFinish={async (values) => { // console.log('values', values)
mutate(values) return true }} columns={columns as ProFormColumnsType[]}/> </PageContainer> ) })
export default Roles
|