Browse Source

1、完善部门页面

2、优化页面级store的目录位置,使组件中使用更加简洁
main
dark 6 months ago
parent
commit
1abfdb00a4
  1. 2
      src/App.tsx
  2. 2
      src/Auth.tsx
  3. 2
      src/context.ts
  4. 0
      src/global.d.ts
  5. 2
      src/hooks/useFetch.ts
  6. 2
      src/i18n.ts
  7. 2
      src/layout/RootLayout.tsx
  8. 8
      src/pages/system/departments/components/DepartmentTree.tsx
  9. 8
      src/pages/system/departments/components/TreeNodeRender.tsx
  10. 255
      src/pages/system/departments/index.tsx
  11. 6
      src/pages/system/menus/components/BatchButton.tsx
  12. 2
      src/pages/system/menus/components/ButtonTable.tsx
  13. 10
      src/pages/system/menus/components/MenuTree.tsx
  14. 8
      src/pages/system/menus/components/TreeNodeRender.tsx
  15. 10
      src/pages/system/menus/index.tsx
  16. 16
      src/pages/system/roles/index.tsx
  17. 2
      src/request.ts
  18. 2
      src/routes.tsx
  19. 2
      src/service/base.ts
  20. 8
      src/service/system.ts
  21. 2
      src/store/department.ts
  22. 2
      src/store/menu.ts
  23. 2
      src/store/role.ts
  24. 2
      src/store/route.ts
  25. 2
      src/store/system.ts
  26. 86
      src/store/user.ts
  27. 5
      src/types/index.ts
  28. 3
      src/types/menus.d.ts
  29. 2
      src/utils/index.ts
  30. 2
      src/utils/uuid.ts

2
src/App.tsx

@ -2,7 +2,7 @@ import { AppContextProvider } from '@/context.ts'
import { initI18n } from '@/i18n.ts' import { initI18n } from '@/i18n.ts'
import { appAtom, appStore, changeLanguage } from '@/store/system.ts' import { appAtom, appStore, changeLanguage } from '@/store/system.ts'
import { userMenuDataAtom } from '@/store/user.ts' import { userMenuDataAtom } from '@/store/user.ts'
import { IAppData } from '@/types'
import { IAppData } from '@/global'
import { ConfigProvider } from '@/components/config-provider' import { ConfigProvider } from '@/components/config-provider'
import { Provider, useAtom, useAtomValue } from 'jotai' import { Provider, useAtom, useAtomValue } from 'jotai'
import './App.css' import './App.css'

2
src/Auth.tsx

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { Props } from './types'
import { Props } from './global'
import { useAtomValue } from 'jotai' import { useAtomValue } from 'jotai'
import { authAtom } from './store/user.ts' import { authAtom } from './store/user.ts'

2
src/context.ts

@ -1,4 +1,4 @@
import { IAppData } from '@/types'
import { IAppData } from '@/global'
import React, { createContext, ProviderProps, useContext } from 'react' import React, { createContext, ProviderProps, useContext } from 'react'
import { t } from 'i18next' import { t } from 'i18next'

0
src/types.d.ts → src/global.d.ts

2
src/hooks/useFetch.ts

@ -1,5 +1,5 @@
import { atomFamily } from 'jotai/utils' import { atomFamily } from 'jotai/utils'
import { IDataProps } from '@/types'
import { IDataProps } from '@/global'
import { useMemo, useRef } from 'react' import { useMemo, useRef } from 'react'
import { generateUUID } from '@/utils/uuid' import { generateUUID } from '@/utils/uuid'

2
src/i18n.ts

@ -35,7 +35,7 @@ export const initI18n = (options?: InitOptions) => {
}, },
}, },
fallbackLng: 'zh', fallbackLng: 'zh',
debug: true,
debug: false,
detection: detectionOptions, detection: detectionOptions,
interpolation: { interpolation: {
escapeValue: false, escapeValue: false,

2
src/layout/RootLayout.tsx

@ -4,7 +4,7 @@ import ErrorPage from '@/components/error/error.tsx'
import SelectLang from '@/components/select-lang' import SelectLang from '@/components/select-lang'
import { appAtom } from '@/store/system.ts' import { appAtom } from '@/store/system.ts'
import { userMenuDataAtom } from '@/store/user.ts' import { userMenuDataAtom } from '@/store/user.ts'
import { MenuItem } from '@/types'
import { MenuItem } from '@/global'
import { ProConfigProvider, ProLayout, } from '@ant-design/pro-components' import { ProConfigProvider, ProLayout, } from '@ant-design/pro-components'
import { zhCNIntl, enUSIntl } from '@ant-design/pro-provider/es/intl' import { zhCNIntl, enUSIntl } from '@ant-design/pro-provider/es/intl'
import { CatchBoundary, Link, Outlet } from '@tanstack/react-router' import { CatchBoundary, Link, Outlet } from '@tanstack/react-router'

8
src/pages/system/departments/components/DepartmentTree.tsx

@ -1,4 +1,4 @@
import { usePageStoreOptions } from '@/store'
import { Empty, Spin, Tree } from 'antd' import { Empty, Spin, Tree } from 'antd'
import { useStyle } from '../style.ts' import { useStyle } from '../style.ts'
import { useTranslation } from '@/i18n.ts' import { useTranslation } from '@/i18n.ts'
@ -16,9 +16,9 @@ export const DepartmentTree = ({ form }: { form: FormInstance }) => {
const { styles } = useStyle() const { styles } = useStyle()
const { t } = useTranslation() const { t } = useTranslation()
const setIds = useSetAtom(batchIdsAtom, usePageStoreOptions())
const setCurrent = useSetAtom(selectedDepartAtom, usePageStoreOptions())
const { data = [], isLoading } = useAtomValue(departTreeAtom, usePageStoreOptions())
const setIds = useSetAtom(batchIdsAtom)
const setCurrent = useSetAtom(selectedDepartAtom)
const { data = [], isLoading } = useAtomValue(departTreeAtom)
const flattenMenusRef = useRef<IDepartment[]>([]) const flattenMenusRef = useRef<IDepartment[]>([])
useDeepCompareEffect(() => { useDeepCompareEffect(() => {

8
src/pages/system/departments/components/TreeNodeRender.tsx

@ -1,6 +1,6 @@
import { usePageStoreOptions } from '@/store'
import { memo } from 'react' import { memo } from 'react'
import { MenuItem } from '@/types'
import { MenuItem } from '@/global'
import { Popconfirm, Space, TreeDataNode } from 'antd' import { Popconfirm, Space, TreeDataNode } from 'antd'
import { FormInstance } from 'antd/lib' import { FormInstance } from 'antd/lib'
import { useTranslation } from '@/i18n.ts' import { useTranslation } from '@/i18n.ts'
@ -14,9 +14,9 @@ export const TreeNodeRender = memo(({ node, form }: { node: MenuItem & TreeDataN
const { name } = node const { name } = node
const { t } = useTranslation() const { t } = useTranslation()
const { styles } = useStyle() const { styles } = useStyle()
const { mutate } = useAtomValue(deleteDepartAtom, usePageStoreOptions())
const { mutate } = useAtomValue(deleteDepartAtom)
const setCurrent = useSetAtom(selectedDepartAtom, usePageStoreOptions())
const setCurrent = useSetAtom(selectedDepartAtom)
return ( return (
<div className={styles.treeNode}> <div className={styles.treeNode}>

255
src/pages/system/departments/index.tsx

@ -1,4 +1,3 @@
import { usePageStoreOptions } from '@/store'
import { PageContainer, ProCard } from '@ant-design/pro-components' import { PageContainer, ProCard } from '@ant-design/pro-components'
import { Flexbox } from 'react-layout-kit' import { Flexbox } from 'react-layout-kit'
import { DraggablePanel } from '@/components/draggable-panel' import { DraggablePanel } from '@/components/draggable-panel'
@ -11,145 +10,147 @@ import { defaultDepart, selectedDepartAtom, departTreeAtom, saveOrUpdateDepartAt
import { useAtom, useAtomValue, } from 'jotai' import { useAtom, useAtomValue, } from 'jotai'
import Glass from '@/components/glass' import Glass from '@/components/glass'
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import UserPicker from '@/components/user-picker/UserPicker.tsx'
const Departments = () => { const Departments = () => {
const { t } = useTranslation()
const { styles, cx } = useStyle()
const [ form ] = Form.useForm()
const inputRef = useRef<InputRef>()
const { data } = useAtomValue(departTreeAtom, usePageStoreOptions())
const { mutate, isPending, isError, error } = useAtomValue(saveOrUpdateDepartAtom, usePageStoreOptions())
const [ current, setCurrent ] = useAtom(selectedDepartAtom, usePageStoreOptions())
const { t } = useTranslation()
const { styles, cx } = useStyle()
const [ form ] = Form.useForm()
const inputRef = useRef<InputRef>()
const { data } = useAtomValue(departTreeAtom)
const { mutate, isPending, isError, error } = useAtomValue(saveOrUpdateDepartAtom)
const [ current, setCurrent ] = useAtom(selectedDepartAtom)
useEffect(() => {
useEffect(() => {
if (isError) {
notification.error({
message: t('message.error', '错误'),
description: (error as any).message ?? t('message.saveFail', '保存失败'),
})
}
}, [ isError ])
if (isError) {
notification.error({
message: t('message.error', '错误'),
description: (error as any).message ?? t('message.saveFail', '保存失败'),
})
}
}, [ isError ])
useEffect(() => {
if (current.id === 0 && inputRef.current) {
inputRef.current.focus()
}
}, [ current ])
useEffect(() => {
if (current.id === 0 && inputRef.current) {
inputRef.current.focus()
}
}, [ current ])
return (
<PageContainer breadcrumbRender={false} title={false} className={styles.container}>
<Flexbox horizontal>
<DraggablePanel expandable={false}
placement="left"
defaultSize={{ width: 300 }}
maxWidth={500}
style={{ position: 'relative' }}
>
<ProCard title={t('system.departments.title', '部门')}>
<DepartmentTree form={form}/>
</ProCard>
<div className={styles.treeActions}>
<Divider style={{ flex: 1, margin: '8px 0' }}/>
<Button style={{ flex: 1 }} size={'small'}
block={true} type={'dashed'}
icon={<PlusOutlined/>}
onClick={() => {
const data = {
...defaultDepart,
parent_id: current.id ?? 0,
}
setCurrent(data)
form.setFieldsValue(data)
}}
>{t('actions.news')}</Button>
</div>
</DraggablePanel>
<Flexbox className={styles.box}>
<Glass
enabled={current.id === undefined}
description={<>
<Alert
message={t('message.infoTitle', '提示')}
description={t('system.departments.form.empty', '请从左侧选择一行数据操作')}
type="info"
/>
</>}
>
return (
<PageContainer breadcrumbRender={false} title={false} className={styles.container}>
<Flexbox horizontal>
<DraggablePanel expandable={false}
placement="left"
defaultSize={{ width: 300 }}
maxWidth={500}
style={{ position: 'relative' }}
>
<ProCard title={t('system.departments.title', '部门')}>
<DepartmentTree form={form}/>
</ProCard>
<div className={styles.treeActions}>
<Divider style={{ flex: 1, margin: '8px 0' }}/>
<Button style={{ flex: 1 }} size={'small'}
block={true} type={'dashed'}
icon={<PlusOutlined/>}
onClick={() => {
const data = {
...defaultDepart,
parent_id: current.id ?? 0,
}
setCurrent(data)
form.setFieldsValue(data)
}}
>{t('actions.news')}</Button>
</div>
</DraggablePanel>
<Flexbox className={styles.box}>
<Glass
enabled={current.id === undefined}
description={<>
<Alert
message={t('message.infoTitle', '提示')}
description={t('system.departments.form.empty', '请从左侧选择一行数据操作')}
type="info"
/>
</>}
>
<ProCard title={t('system.departments.setting', '编辑')}>
<Form form={form}
initialValues={current!}
labelAlign="left"
labelWrap
labelCol={{ span: 4 }}
wrapperCol={{ span: 12 }}
colon={false}
className={cx(styles.form, {
[styles.emptyForm]: current.id === undefined
})}
>
<Form.Item hidden={true} label={'id'} name={'id'}>
<Input disabled={true}/>
</Form.Item>
<Form.Item
rules={[
{ required: true, message: t('rules.required') }
]}
label={t('system.departments.form.name', '部门名称')} name={'name'}>
<Input ref={inputRef as any}
placeholder={t('system.departments.form.name', '部门名称')}/>
</Form.Item>
<Form.Item label={t('system.departments.form.parent', '上级部门')}
name={'parent_id'}>
<TreeSelect
treeData={[
{ id: 0, name: '顶级', children: data as any },
]}
treeDefaultExpandAll={true}
fieldNames={{
label: 'name',
value: 'id'
}}/>
</Form.Item>
<Form.Item label={t('system.departments.form.sort', '排序')} name={'sort'}>
<InputNumber/>
</Form.Item>
<Form.Item label={t('system.departments.form.manager_user_id', '负责人')}
name={'path'}>
<Input/>
</Form.Item>
<ProCard title={t('system.departments.setting', '编辑')}>
<Form form={form}
initialValues={current!}
labelAlign="left"
labelWrap
labelCol={{ span: 4 }}
wrapperCol={{ span: 12 }}
colon={false}
className={cx(styles.form, {
[styles.emptyForm]: current.id === undefined
})}
>
<Form.Item hidden={true} label={'id'} name={'id'}>
<Input disabled={true}/>
</Form.Item>
<Form.Item
rules={[
{ required: true, message: t('rules.required') }
]}
label={t('system.departments.form.name', '部门名称')} name={'name'}>
<Input ref={inputRef as any}
placeholder={t('system.departments.form.name', '部门名称')}/>
</Form.Item>
<Form.Item label={t('system.departments.form.parent', '上级部门')}
name={'parent_id'}>
<TreeSelect
treeData={[
{ id: 0, name: '顶级', children: data as any },
]}
treeDefaultExpandAll={true}
fieldNames={{
label: 'name',
value: 'id'
}}/>
</Form.Item>
<Form.Item label={t('system.departments.form.phone', '联系电话')}
name={'phone'}
>
<Input/>
</Form.Item>
<Form.Item label={' '}>
<Button type="primary"
htmlType={'submit'}
loading={isPending}
onClick={() => {
form.validateFields().then((values) => {
mutate(values)
})
}}
>
{t('system.departments.form.save', '保存')}
</Button>
</Form.Item>
<Form.Item label={t('system.departments.form.sort', '排序')} name={'sort'}>
<InputNumber/>
</Form.Item>
<Form.Item label={t('system.departments.form.manager_user_id', '负责人')}
name={'manager_user_id'}>
<UserPicker/>
</Form.Item>
</Form>
</ProCard>
<Form.Item label={t('system.departments.form.phone', '联系电话')}
name={'phone'}
>
<Input/>
</Form.Item>
<Form.Item label={' '}>
<Button type="primary"
htmlType={'submit'}
loading={isPending}
onClick={() => {
form.validateFields().then((values) => {
mutate(values)
})
}}
>
{t('system.departments.form.save', '保存')}
</Button>
</Form.Item>
</Glass>
</Flexbox>
</Flexbox>
</PageContainer>
)
</Form>
</ProCard>
</Glass>
</Flexbox>
</Flexbox>
</PageContainer>
)
} }

6
src/pages/system/menus/components/BatchButton.tsx

@ -1,4 +1,4 @@
import { usePageStoreOptions } from '@/store'
import { Button, Popconfirm } from 'antd' import { Button, Popconfirm } from 'antd'
import { useAtomValue } from 'jotai' import { useAtomValue } from 'jotai'
import { batchIdsAtom, deleteMenuAtom } from '@/store/menu.ts' import { batchIdsAtom, deleteMenuAtom } from '@/store/menu.ts'
@ -7,8 +7,8 @@ import { useTranslation } from '@/i18n.ts'
const BatchButton = () => { const BatchButton = () => {
const { t } = useTranslation() const { t } = useTranslation()
const { isPending, mutate, } = useAtomValue(deleteMenuAtom, usePageStoreOptions())
const ids = useAtomValue(batchIdsAtom, usePageStoreOptions())
const { isPending, mutate, } = useAtomValue(deleteMenuAtom)
const ids = useAtomValue(batchIdsAtom)
if (ids.length === 0) { if (ids.length === 0) {

2
src/pages/system/menus/components/ButtonTable.tsx

@ -1,7 +1,7 @@
import { useTranslation } from '@/i18n.ts' import { useTranslation } from '@/i18n.ts'
import { EditableFormInstance, EditableProTable } from '@ant-design/pro-components' import { EditableFormInstance, EditableProTable } from '@ant-design/pro-components'
import { useMemo, useRef, useState } from 'react' import { useMemo, useRef, useState } from 'react'
import { IDataProps } from '@/types'
import { IDataProps } from '@/global'
import { FormInstance } from 'antd/lib' import { FormInstance } from 'antd/lib'
type DataSourceType = { type DataSourceType = {

10
src/pages/system/menus/components/MenuTree.tsx

@ -1,6 +1,6 @@
import { usePageStoreOptions } from '@/store'
import { Empty, Spin, Tree } from 'antd' import { Empty, Spin, Tree } from 'antd'
import { MenuItem } from '@/types'
import { MenuItem } from '@/global'
import { useStyle } from '../style.ts' import { useStyle } from '../style.ts'
import { useTranslation } from '@/i18n.ts' import { useTranslation } from '@/i18n.ts'
import { useSetAtom } from 'jotai' import { useSetAtom } from 'jotai'
@ -17,9 +17,9 @@ const MenuTree = ({ form }: { form: FormInstance }) => {
const { styles } = useStyle() const { styles } = useStyle()
const { t } = useTranslation() const { t } = useTranslation()
const setCurrentMenu = useSetAtom(selectedMenuAtom, usePageStoreOptions())
const setIds = useSetAtom(batchIdsAtom, usePageStoreOptions())
const { data = [], isLoading } = useAtomValue(menuDataAtom, usePageStoreOptions())
const setCurrentMenu = useSetAtom(selectedMenuAtom)
const setIds = useSetAtom(batchIdsAtom)
const { data = [], isLoading } = useAtomValue(menuDataAtom)
const flattenMenusRef = useRef<MenuItem[]>([]) const flattenMenusRef = useRef<MenuItem[]>([])
useDeepCompareEffect(() => { useDeepCompareEffect(() => {

8
src/pages/system/menus/components/TreeNodeRender.tsx

@ -1,6 +1,6 @@
import { usePageStoreOptions } from '@/store'
import { memo } from 'react' import { memo } from 'react'
import { MenuItem } from '@/types'
import { MenuItem } from '@/global'
import { Popconfirm, Space, TreeDataNode } from 'antd' import { Popconfirm, Space, TreeDataNode } from 'antd'
import { FormInstance } from 'antd/lib' import { FormInstance } from 'antd/lib'
import { useTranslation } from '@/i18n.ts' import { useTranslation } from '@/i18n.ts'
@ -14,9 +14,9 @@ export const TreeNodeRender = memo(({ node, form }: { node: MenuItem & TreeDataN
const { title } = node const { title } = node
const { t } = useTranslation() const { t } = useTranslation()
const { styles } = useStyle() const { styles } = useStyle()
const { mutate } = useAtomValue(deleteMenuAtom, usePageStoreOptions())
const { mutate } = useAtomValue(deleteMenuAtom)
const setMenuData = useSetAtom(selectedMenuAtom, usePageStoreOptions())
const setMenuData = useSetAtom(selectedMenuAtom)
return ( return (
<div className={styles.treeNode}> <div className={styles.treeNode}>

10
src/pages/system/menus/index.tsx

@ -1,6 +1,6 @@
import Glass from '@/components/glass' import Glass from '@/components/glass'
import { useTranslation } from '@/i18n.ts' import { useTranslation } from '@/i18n.ts'
import { usePageStoreOptions } from '@/store'
import { PlusOutlined } from '@ant-design/icons' import { PlusOutlined } from '@ant-design/icons'
import { PageContainer, ProCard } from '@ant-design/pro-components' import { PageContainer, ProCard } from '@ant-design/pro-components'
import { Button, Form, Input, Radio, TreeSelect, InputNumber, notification, Alert, InputRef, Divider } from 'antd' import { Button, Form, Input, Radio, TreeSelect, InputNumber, notification, Alert, InputRef, Divider } from 'antd'
@ -11,7 +11,7 @@ import ButtonTable from './components/ButtonTable.tsx'
import { Flexbox } from 'react-layout-kit' import { Flexbox } from 'react-layout-kit'
import { DraggablePanel } from '@/components/draggable-panel' import { DraggablePanel } from '@/components/draggable-panel'
import { useStyle } from './style.ts' import { useStyle } from './style.ts'
import { MenuItem } from '@/types'
import { MenuItem } from '@/global'
import MenuTree from './components/MenuTree.tsx' import MenuTree from './components/MenuTree.tsx'
import BatchButton from '@/pages/system/menus/components/BatchButton.tsx' import BatchButton from '@/pages/system/menus/components/BatchButton.tsx'
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
@ -21,9 +21,9 @@ const Menus = () => {
const { styles, cx } = useStyle() const { styles, cx } = useStyle()
const { t } = useTranslation() const { t } = useTranslation()
const [ form ] = Form.useForm() const [ form ] = Form.useForm()
const { mutate, isPending, error, isError } = useAtomValue(saveOrUpdateMenuAtom, usePageStoreOptions())
const { data = [] } = useAtomValue(menuDataAtom, usePageStoreOptions())
const [ currentMenu, setMenuData ] = useAtom<MenuItem>(selectedMenuAtom, usePageStoreOptions()) ?? {}
const { mutate, isPending, error, isError } = useAtomValue(saveOrUpdateMenuAtom)
const { data = [] } = useAtomValue(menuDataAtom)
const [ currentMenu, setMenuData ] = useAtom<MenuItem>(selectedMenuAtom) ?? {}
const menuInputRef = useRef<InputRef | undefined>(undefined) const menuInputRef = useRef<InputRef | undefined>(undefined)
useEffect(() => { useEffect(() => {

16
src/pages/system/roles/index.tsx

@ -1,5 +1,5 @@
import Switch from '@/components/switch' import Switch from '@/components/switch'
import { usePageStoreOptions } from '@/store'
import { IMenu } from '@/types/menus' import { IMenu } from '@/types/menus'
import { import {
ActionType, ActionType,
@ -54,13 +54,13 @@ const Roles = memo(() => {
const { styles } = useStyle() const { styles } = useStyle()
const [ form ] = Form.useForm() const [ form ] = Form.useForm()
const actionRef = useRef<ActionType>() 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 [ page, setPage ] = useAtom(pageAtom)
const [ search, setSearch ] = useAtom(searchAtom)
const [ roleIds, setRoleIds ] = useAtom(roleIdsAtom)
const { data, isLoading, isFetching, refetch } = useAtomValue(rolesAtom)
const { isPending, mutate, isSuccess } = useAtomValue(saveOrUpdateRoleAtom)
const { mutate: deleteRole, isPending: isDeleting } = useAtomValue(deleteRoleAtom)
const [ , setRole ] = useAtom(roleAtom)
const [ open, setOpen ] = useState(false) const [ open, setOpen ] = useState(false)
const columns = useMemo(() => { const columns = useMemo(() => {

2
src/request.ts

@ -1,5 +1,5 @@
import { getToken, setToken } from '@/store/system.ts' import { getToken, setToken } from '@/store/system.ts'
import { IApiResult } from '@/types'
import { IApiResult } from '@/global'
import { Record } from '@icon-park/react' import { Record } from '@icon-park/react'
import { message } from 'antd' import { message } from 'antd'
import axios, { import axios, {

2
src/routes.tsx

@ -24,7 +24,7 @@ import {
import { TanStackRouterDevtools } from '@tanstack/router-devtools' import { TanStackRouterDevtools } from '@tanstack/router-devtools'
import { memo } from 'react' import { memo } from 'react'
import RootLayout from './layout/RootLayout' import RootLayout from './layout/RootLayout'
import { IRootContext, MenuItem } from './types'
import { IRootContext, MenuItem } from './global'
import { DevTools } from 'jotai-devtools' import { DevTools } from 'jotai-devtools'
const PageRootLayout = () => { const PageRootLayout = () => {

2
src/service/base.ts

@ -1,5 +1,5 @@
import { request, AxiosRequestConfig } from '@/request.ts' import { request, AxiosRequestConfig } from '@/request.ts'
import { IPage, IPageResult } from '@/types'
import { IPage, IPageResult } from '@/global'
export const createCURD = <TParams, TResult>(api: string, options?: AxiosRequestConfig) => { export const createCURD = <TParams, TResult>(api: string, options?: AxiosRequestConfig) => {

8
src/service/system.ts

@ -1,5 +1,5 @@
import { IPageResult } from '@/types'
import { IUserInfo } from '@/types/user'
import { IPageResult } from '@/global'
import { IUser, IUserInfo } from '@/types/user'
import request from '../request.ts' import request from '../request.ts'
import { LoginRequest, LoginResponse } from '@/types/login' import { LoginRequest, LoginResponse } from '@/types/login'
import { createCURD } from '@/service/base.ts' import { createCURD } from '@/service/base.ts'
@ -21,12 +21,14 @@ const systemServ = {
return request.post<LoginResponse>('/sys/login', data) return request.post<LoginResponse>('/sys/login', data)
}, },
user: { user: {
...createCURD<any, IUser>('/sys/user'),
current: () => { current: () => {
return request.get<IUserInfo>('/sys/user/info') return request.get<IUserInfo>('/sys/user/info')
}, },
menus: () => { menus: () => {
return request.get<IPageResult<IMenu[]>>('/sys/user/menus') return request.get<IPageResult<IMenu[]>>('/sys/user/menus')
}
},
}, },
role: { role: {

2
src/store/department.ts

@ -1,6 +1,6 @@
import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query' import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query'
import systemServ from '@/service/system.ts' import systemServ from '@/service/system.ts'
import { IApiResult, IPage } from '@/types'
import { IApiResult, IPage } from '@/global'
import { IDepartment } from '@/types/department' import { IDepartment } from '@/types/department'
import { atom, createStore } from 'jotai' import { atom, createStore } from 'jotai'
import { t } from 'i18next' import { t } from 'i18next'

2
src/store/menu.ts

@ -1,5 +1,5 @@
import systemServ from '@/service/system.ts' import systemServ from '@/service/system.ts'
import { IApiResult, IPage, MenuItem } from '@/types'
import { IApiResult, IPage, MenuItem } from '@/global'
import { IMenu } from '@/types/menus' import { IMenu } from '@/types/menus'
import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query' import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query'
import { atom, createStore } from 'jotai' import { atom, createStore } from 'jotai'

2
src/store/role.ts

@ -2,7 +2,7 @@ import { convertToBool } from '@/utils'
import { atom } from 'jotai/index' import { atom } from 'jotai/index'
import { IRole } from '@/types/roles' import { IRole } from '@/types/roles'
import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query' import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query'
import { IApiResult, IPage } from '@/types'
import { IApiResult, IPage } from '@/global'
import systemServ from '@/service/system.ts' import systemServ from '@/service/system.ts'
import { message } from 'antd' import { message } from 'antd'
import { t } from '@/i18n.ts' import { t } from '@/i18n.ts'

2
src/store/route.ts

@ -1,4 +1,4 @@
import { IRootContext } from '@/types'
import { IRootContext } from '@/global'
import { atom } from 'jotai' import { atom } from 'jotai'
export const routeContextAtom = atom<IRootContext>({}) export const routeContextAtom = atom<IRootContext>({})

2
src/store/system.ts

@ -1,4 +1,4 @@
import { IAppData } from '@/types'
import { IAppData } from '@/global'
import { createStore } from 'jotai' import { createStore } from 'jotai'
import { atomWithStorage } from 'jotai/utils' import { atomWithStorage } from 'jotai/utils'
import { changeLanguage as setLang } from 'i18next' import { changeLanguage as setLang } from 'i18next'

86
src/store/user.ts

@ -1,59 +1,77 @@
import { appAtom } from '@/store/system.ts' import { appAtom } from '@/store/system.ts'
import { IMenu } from '@/types/menus' import { IMenu } from '@/types/menus'
import { IUserInfo } from '@/types/user'
import { IUserInfo } from '@/types/user'
import { atom } from 'jotai/index' import { atom } from 'jotai/index'
import { IApiResult, IAuth, IPageResult, MenuItem } from '@/types'
import { IApiResult, IAuth, IPageResult, MenuItem } from '@/global'
import { LoginRequest } from '@/types/login' import { LoginRequest } from '@/types/login'
import { atomWithMutation, atomWithQuery } from 'jotai-tanstack-query' import { atomWithMutation, atomWithQuery } from 'jotai-tanstack-query'
import systemServ from '@/service/system.ts' import systemServ from '@/service/system.ts'
import { formatMenuData, isDev } from '@/utils' import { formatMenuData, isDev } from '@/utils'
export const authAtom = atom<IAuth>({ export const authAtom = atom<IAuth>({
isLogin: false,
authKey: []
isLogin: false,
authKey: []
}) })
const devLogin = { const devLogin = {
username: 'SupperAdmin',
password: 'kk123456',
code: '123456'
username: 'SupperAdmin',
password: 'kk123456',
code: '123456'
} }
export const loginFormAtom = atom<LoginRequest>({ export const loginFormAtom = atom<LoginRequest>({
...(isDev ? devLogin : {})
...(isDev ? devLogin : {})
} as LoginRequest) } as LoginRequest)
export const loginAtom = atomWithMutation<any, LoginRequest>(() => ({ export const loginAtom = atomWithMutation<any, LoginRequest>(() => ({
mutationKey: [ 'login' ],
mutationFn: async (params) => {
return await systemServ.login(params)
},
onSuccess: () => {
// console.log('login success', data)
},
retry: false,
mutationKey: [ 'login' ],
mutationFn: async (params) => {
return await systemServ.login(params)
},
onSuccess: () => {
// console.log('login success', data)
},
retry: false,
})) }))
export const currentUserAtom = atomWithQuery<IApiResult<IUserInfo>, any, IUserInfo>((get) => { export const currentUserAtom = atomWithQuery<IApiResult<IUserInfo>, any, IUserInfo>((get) => {
return {
queryKey: [ 'user_info', get(appAtom).token ],
queryFn: async () => {
return await systemServ.user.current()
},
select: (data) => {
return data.data
return {
queryKey: [ 'user_info', get(appAtom).token ],
queryFn: async () => {
return await systemServ.user.current()
},
select: (data) => {
return data.data
}
} }
}
}) })
export const userMenuDataAtom = atomWithQuery<IApiResult<IPageResult<IMenu[]>>, any, MenuItem[]>((get) => ({ export const userMenuDataAtom = atomWithQuery<IApiResult<IPageResult<IMenu[]>>, any, MenuItem[]>((get) => ({
enabled: false,
queryKey: [ 'user_menus', get(appAtom).token ],
queryFn: async () => {
return await systemServ.user.menus()
},
select: (data) => {
return formatMenuData(data.data.rows as any ?? [])
},
cacheTime: 1000 * 60,
retry: false,
enabled: false,
queryKey: [ 'user_menus', get(appAtom).token ],
queryFn: async () => {
return await systemServ.user.menus()
},
select: (data) => {
return formatMenuData(data.data.rows as any ?? [])
},
cacheTime: 1000 * 60,
retry: false,
})) }))
export const userSearchAtom = atom<{
dept_id: number,
key: string
} | unknown>({})
//user list
export const userListAtom = atomWithQuery((get) => {
return {
queryKey: [ 'user_list', get(userSearchAtom) ],
queryFn: async ({ queryKey: [ , params ] }) => {
return await systemServ.user.list(params)
},
select: (data) => {
return data.data
},
}
})

5
src/types/index.ts

@ -0,0 +1,5 @@
export * from './department'
export * from './user'
export * from './login'
export * from './roles'
export * from './menus'

3
src/types/menus.d.ts

@ -6,6 +6,9 @@ export interface MenuButton {
} }
interface Meta {
}
export interface IMenu { export interface IMenu {
id: number, id: number,
key: string, key: string,

2
src/utils/index.ts

@ -1,5 +1,5 @@
import { IMenu } from '@/types/menus' import { IMenu } from '@/types/menus'
import { FiledNames, FlattenData, MenuItem, TreeItem } from '@/types'
import { FiledNames, FlattenData, MenuItem, TreeItem } from '@/global'
import { getIcon } from '@/components/icon' import { getIcon } from '@/components/icon'
import { TreeDataNode } from 'antd' import { TreeDataNode } from 'antd'

2
src/utils/uuid.ts

@ -1,4 +1,4 @@
import { MenuItem } from '@/types'
import { MenuItem } from '@/global'
import { TreeDataNode } from 'antd' import { TreeDataNode } from 'antd'
export function generateUUID() { export function generateUUID() {

Loading…
Cancel
Save