dark
7 months ago
12 changed files with 337 additions and 124 deletions
-
95src/locales/lang/en-US.ts
-
3src/locales/lang/pages/system/menus/en-US.ts
-
24src/locales/lang/pages/system/menus/zh-CN.ts
-
94src/locales/lang/zh-CN.ts
-
45src/pages/system/menus/index.tsx
-
13src/pages/system/menus/store.ts
-
102src/pages/system/roles/index.tsx
-
25src/pages/system/roles/store.ts
-
22src/pages/system/roles/style.ts
-
4src/service/base.ts
-
32src/service/system.ts
-
2vite.config.ts
@ -1,50 +1,63 @@ |
|||||
import antdEN from 'antd/locale/en_US' |
import antdEN from 'antd/locale/en_US' |
||||
|
import menus from './pages/system/menus/en-US' |
||||
|
|
||||
|
|
||||
export default { |
export default { |
||||
...antdEN, |
|
||||
|
...antdEN, |
||||
|
|
||||
error: { |
|
||||
'404': { |
|
||||
title: 'not fund', |
|
||||
message: 'Sorry, not found this page.' |
|
||||
|
error: { |
||||
|
'404': { |
||||
|
title: 'not fund', |
||||
|
message: 'Sorry, not found this page.' |
||||
|
}, |
||||
|
'403': { |
||||
|
title: 'not authorized', |
||||
|
message: 'Sorry, you are not authorized to access this page.' |
||||
|
}, |
||||
|
'error': { |
||||
|
title: 'error info', |
||||
|
}, |
||||
|
}, |
||||
|
route: { |
||||
|
goBack: 'Go Back', |
||||
|
}, |
||||
|
app: { |
||||
|
header: { |
||||
|
logout: 'logout', |
||||
|
} |
||||
}, |
}, |
||||
'403': { |
|
||||
title: 'not authorized', |
|
||||
message: 'Sorry, you are not authorized to access this page.' |
|
||||
|
login: { |
||||
|
title: 'Account Password Login', |
||||
|
username: 'Username', |
||||
|
usernameMsg: 'Please enter your username', |
||||
|
password: 'Password', |
||||
|
passwordMsg: 'Please enter your password', |
||||
|
code: 'Verification Code', |
||||
|
codeMsg: 'Please enter the verification code', |
||||
|
submit: 'Login', |
||||
|
success: 'Login success' |
||||
}, |
}, |
||||
'error': { |
|
||||
title: 'error info', |
|
||||
|
home: { |
||||
|
welcome: 'Welcome to' |
||||
}, |
}, |
||||
}, |
|
||||
route: { |
|
||||
goBack: 'Go Back', |
|
||||
}, |
|
||||
app: { |
|
||||
header: { |
|
||||
logout: 'logout', |
|
||||
|
system: { |
||||
|
menus, |
||||
|
}, |
||||
|
|
||||
|
errorTitle: 'Error', |
||||
|
successTitle: 'Success', |
||||
|
success: 'Submit Success', |
||||
|
fail: 'Submit Fail', |
||||
|
saveSuccess: 'Save Success', |
||||
|
saveFail: 'Save Fail', |
||||
|
|
||||
|
tabs: { |
||||
|
refresh: 'Refresh', |
||||
|
maximize: 'Maximize', |
||||
|
closeCurrent: 'Close current', |
||||
|
closeLeft: 'Close Left', |
||||
|
closeRight: 'Close Right', |
||||
|
closeOther: 'Close other', |
||||
|
closeAll: 'Close All' |
||||
} |
} |
||||
}, |
|
||||
login:{ |
|
||||
title: 'Account Password Login', |
|
||||
username: 'Username', |
|
||||
usernameMsg: 'Please enter your username', |
|
||||
password: 'Password', |
|
||||
passwordMsg: 'Please enter your password', |
|
||||
code: 'Verification Code', |
|
||||
codeMsg: 'Please enter the verification code', |
|
||||
submit: 'Login', |
|
||||
success: 'Login success' |
|
||||
}, |
|
||||
home: { |
|
||||
welcome: 'Welcome to' |
|
||||
}, |
|
||||
tabs: { |
|
||||
refresh: 'Refresh', |
|
||||
maximize: 'Maximize', |
|
||||
closeCurrent: 'Close current', |
|
||||
closeLeft: 'Close Left', |
|
||||
closeRight: 'Close Right', |
|
||||
closeOther: 'Close other', |
|
||||
closeAll: 'Close All' |
|
||||
} |
|
||||
} |
} |
@ -0,0 +1,3 @@ |
|||||
|
export default { |
||||
|
|
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
export default { |
||||
|
title: '菜单', |
||||
|
setting: '配置', |
||||
|
saveSuccess: '保存成功', |
||||
|
form:{ |
||||
|
title: '菜单名称', |
||||
|
parent: '上级菜单', |
||||
|
type:'类型', |
||||
|
typeOptions: { |
||||
|
menu: '菜单', |
||||
|
iframe: 'iframe', |
||||
|
link: '外链', |
||||
|
button: '按钮', |
||||
|
}, |
||||
|
name: '别名', |
||||
|
icon: '图标', |
||||
|
sort: '排序', |
||||
|
path: '路由', |
||||
|
component: '视图', |
||||
|
componentHelp: '视图路径,相对于src/pages,菜单组可以不填', |
||||
|
save: '保存', |
||||
|
}, |
||||
|
button: '按钮' |
||||
|
} |
@ -1,49 +1,61 @@ |
|||||
import antdZh from 'antd/locale/zh_CN' |
import antdZh from 'antd/locale/zh_CN' |
||||
|
import menus from './pages/system/menus/zh-CN.ts' |
||||
|
|
||||
|
|
||||
export default { |
export default { |
||||
...antdZh, |
|
||||
error: { |
|
||||
'404': { |
|
||||
title: '无法找到', |
|
||||
message: '找不到此页面' |
|
||||
|
...antdZh, |
||||
|
error: { |
||||
|
'404': { |
||||
|
title: '无法找到', |
||||
|
message: '找不到此页面' |
||||
|
}, |
||||
|
'403': { |
||||
|
title: '没有权限', |
||||
|
message: '对不起,您没有权限查看此页面。' |
||||
|
}, |
||||
|
'error': { |
||||
|
title: '错误信息', |
||||
|
}, |
||||
|
}, |
||||
|
route: { |
||||
|
goBack: '返回', |
||||
|
}, |
||||
|
app: { |
||||
|
header: { |
||||
|
logout: '退出登录', |
||||
|
} |
||||
}, |
}, |
||||
'403': { |
|
||||
title: '没有权限', |
|
||||
message: '对不起,您没有权限查看此页面。' |
|
||||
|
login: { |
||||
|
title: '账户密码登录', |
||||
|
username: '用户名', |
||||
|
usernameMsg: '请输入用户名', |
||||
|
password: '密码', |
||||
|
passwordMsg: '请输入密码', |
||||
|
code: '验证码', |
||||
|
codeMsg: '请输入验证码', |
||||
|
submit: '登录', |
||||
|
success: '登录成功' |
||||
}, |
}, |
||||
'error': { |
|
||||
title: '错误信息', |
|
||||
|
home: { |
||||
|
welcome: '欢迎使用' |
||||
|
}, |
||||
|
|
||||
|
system: { |
||||
|
menus, |
||||
}, |
}, |
||||
}, |
|
||||
route: { |
|
||||
goBack: '返回', |
|
||||
}, |
|
||||
app: { |
|
||||
header: { |
|
||||
logout: '退出登录', |
|
||||
|
errorTitle: '错误', |
||||
|
successTitle: '成功', |
||||
|
success: '提交成功', |
||||
|
fail: '提交失败', |
||||
|
saveSuccess: '保存成功', |
||||
|
saveFail: '保存失败', |
||||
|
tabs: { |
||||
|
refresh: '刷新', |
||||
|
maximize: '最大化', |
||||
|
closeCurrent: '关闭当前', |
||||
|
closeLeft: '关闭左侧', |
||||
|
closeRight: '关闭右侧', |
||||
|
closeOther: '关闭其它', |
||||
|
closeAll: '关闭所有' |
||||
} |
} |
||||
}, |
|
||||
login:{ |
|
||||
title: '账户密码登录', |
|
||||
username: '用户名', |
|
||||
usernameMsg: '请输入用户名', |
|
||||
password: '密码', |
|
||||
passwordMsg: '请输入密码', |
|
||||
code: '验证码', |
|
||||
codeMsg: '请输入验证码', |
|
||||
submit: '登录', |
|
||||
success: '登录成功' |
|
||||
}, |
|
||||
home: { |
|
||||
welcome: '欢迎使用' |
|
||||
}, |
|
||||
tabs: { |
|
||||
refresh: '刷新', |
|
||||
maximize: '最大化', |
|
||||
closeCurrent: '关闭当前', |
|
||||
closeLeft: '关闭左侧', |
|
||||
closeRight: '关闭右侧', |
|
||||
closeOther: '关闭其它', |
|
||||
closeAll: '关闭所有' |
|
||||
} |
|
||||
} |
} |
@ -1,15 +1,109 @@ |
|||||
import { PageContainer } from '@ant-design/pro-components' |
|
||||
import { createLazyFileRoute } from '@tanstack/react-router' |
|
||||
|
import { ActionType, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components' |
||||
|
import { createLazyFileRoute } from '@tanstack/react-router' |
||||
|
import { useStyle } from './style.ts' |
||||
|
import { useMemo, useRef } from 'react' |
||||
|
import { useAtomValue } from 'jotai' |
||||
|
import { rolesAtom } from './store.ts' |
||||
|
import { useTranslation } from '@/i18n.ts' |
||||
|
import { Button, Space, Table } from 'antd' |
||||
|
import { PlusOutlined } from '@ant-design/icons' |
||||
|
|
||||
const Roles = () => { |
const Roles = () => { |
||||
|
|
||||
|
const { t } = useTranslation() |
||||
|
const { styles } = useStyle() |
||||
|
const actionRef = useRef<ActionType>() |
||||
|
const { data, isLoading } = useAtomValue(rolesAtom) |
||||
|
|
||||
|
const columns = useMemo(() => { |
||||
|
|
||||
|
return [ |
||||
|
{ title: 'id', dataIndex: 'id', hideInTable: true, hideInSearch: true, }, |
||||
|
{ title: '名称', dataIndex: 'name' }, |
||||
|
{ title: '别名', dataIndex: 'code' }, |
||||
|
{ title: '状态', dataIndex: 'status' }, |
||||
|
{ title: '排序', dataIndex: 'sort', valueType: 'indexBorder', }, |
||||
|
{ title: '备注', dataIndex: 'remark' }, |
||||
|
{ |
||||
|
title: '操作', valueType: 'option', |
||||
|
key: 'option', |
||||
|
render: (text, record, _, action) => [ |
||||
|
<a |
||||
|
key="editable" |
||||
|
onClick={() => { |
||||
|
action?.startEditable?.(record.id) |
||||
|
}} |
||||
|
> |
||||
|
编辑 |
||||
|
</a>, |
||||
|
<a href={record.url} target="_blank" rel="noopener noreferrer" key="view"> |
||||
|
查看 |
||||
|
</a>, |
||||
|
<a href={record.url} target="_blank" rel="noopener noreferrer" key="del"> |
||||
|
删除 |
||||
|
</a>, |
||||
|
], |
||||
|
}, |
||||
|
] as ProColumns[] |
||||
|
}, []) |
||||
|
|
||||
return ( |
return ( |
||||
<PageContainer breadcrumbRender={false}> |
|
||||
|
<PageContainer breadcrumbRender={false} title={false} className={styles.container}> |
||||
|
<ProTable |
||||
|
rowKey={'id'} |
||||
|
actionRef={actionRef} |
||||
|
headerTitle={t('system.roles.title', '角色管理')} |
||||
|
columns={columns} |
||||
|
loading={isLoading} |
||||
|
dataSource={data?.rows} |
||||
|
search={false} |
||||
|
rowSelection={{ |
||||
|
selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT], |
||||
|
}} |
||||
|
tableAlertOptionRender={() => { |
||||
|
return ( |
||||
|
<Space size={16}> |
||||
|
<a>批量删除</a> |
||||
|
</Space> |
||||
|
); |
||||
|
}} |
||||
|
toolbar={{ |
||||
|
search: { |
||||
|
onSearch: (value: string) => { |
||||
|
alert(value) |
||||
|
}, |
||||
|
}, |
||||
|
onSearch: (value) => { |
||||
|
console.log('value', value) |
||||
|
}, |
||||
|
actions: [ |
||||
|
|
||||
|
<Button |
||||
|
key="button" |
||||
|
icon={<PlusOutlined/>} |
||||
|
onClick={() => { |
||||
|
actionRef.current?.reload() |
||||
|
}} |
||||
|
type="primary" |
||||
|
> |
||||
|
新建 |
||||
|
</Button>, |
||||
|
] |
||||
|
}} |
||||
|
pagination={{ |
||||
|
total: data?.total, |
||||
|
current: data?.page, |
||||
|
pageSize: data?.pageSize, |
||||
|
onChange: (page) => { |
||||
|
console.log('page', page) |
||||
|
} |
||||
|
}} |
||||
|
/> |
||||
</PageContainer> |
</PageContainer> |
||||
) |
) |
||||
} |
} |
||||
|
|
||||
export const Route = createLazyFileRoute("/system/roles")({ |
|
||||
|
export const Route = createLazyFileRoute('/system/roles')({ |
||||
component: Roles |
component: Roles |
||||
}) |
}) |
||||
|
|
@ -0,0 +1,25 @@ |
|||||
|
import { atom } from 'jotai/index' |
||||
|
import { IRole } from '@/types/roles' |
||||
|
import { atomWithQuery } from 'jotai-tanstack-query' |
||||
|
import { IPage, IPageResult } from '@/types' |
||||
|
import systemServ from '@/service/system.ts' |
||||
|
|
||||
|
type SearchParams = IPage & IRole |
||||
|
|
||||
|
export const idAtom = atom(0) |
||||
|
|
||||
|
export const IdsAtom = atom([]) |
||||
|
|
||||
|
export const roleAtom = atom<IRole>(undefined as unknown as IRole) |
||||
|
|
||||
|
export const searchAtom = atom<SearchParams>({} as SearchParams) |
||||
|
|
||||
|
|
||||
|
export const rolesAtom = atomWithQuery<any, IPageResult<IRole>>((get) => { |
||||
|
return { |
||||
|
queryKey: [ 'roles', get(searchAtom) ], |
||||
|
queryFn: async ({ queryKey: [ , params ] }) => { |
||||
|
return await systemServ.role.list(params as SearchParams) |
||||
|
}, |
||||
|
} |
||||
|
}) |
@ -0,0 +1,22 @@ |
|||||
|
import { createStyles } from '@/theme' |
||||
|
|
||||
|
export const useStyle = createStyles(({ token, css, cx, prefixCls }) => { |
||||
|
const prefix = `${prefixCls}-${token?.proPrefix}-role-page`; |
||||
|
|
||||
|
|
||||
|
const box = css`
|
||||
|
flex: 1; |
||||
|
background: ${token.colorBgContainer}; |
||||
|
`
|
||||
|
const form = css`
|
||||
|
display: flex; |
||||
|
flex-wrap: wrap; |
||||
|
min-width: 500px; |
||||
|
`
|
||||
|
|
||||
|
return { |
||||
|
container: cx(prefix), |
||||
|
box, |
||||
|
form, |
||||
|
} |
||||
|
}) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue