diff --git a/src/components/table/Table.tsx b/src/components/table/Table.tsx new file mode 100644 index 0000000..f32f1a0 --- /dev/null +++ b/src/components/table/Table.tsx @@ -0,0 +1,95 @@ +import { ProTable, ProTableProps, ProCard } from '@ant-design/pro-components' +import React, { useEffect, useRef, useState } from 'react' +import { useStyle } from './style' + +export interface TableProps extends ProTableProps { + +} + +export const Table = = any, D = any>(props: TableProps) => { + + const { styles } = useStyle() + const toolbarRef = useRef(undefined) + const alterRef = useRef(undefined) + const [ toolbarHeight, setHeight ] = useState(65) + const [ alterHeight, setAlterHeight ] = useState(0) + + const scroll = props.scroll ? { + ...props.scroll, + y: props.scroll.y ?? ` calc(100vh - ${toolbarHeight + 200}px)` + } : undefined + + useEffect(() => { + + if (!toolbarRef.current) return + + setHeight(toolbarRef.current?.offsetHeight ?? 65) + + //监听toolbarRef offsetHeight + const observer = new ResizeObserver(entries => { + for (const entry of entries) { + if (entry.target === toolbarRef.current) { + setHeight(entry.contentRect.height) + } + } + }) + + observer.observe(toolbarRef.current!) + + return () => { + observer.disconnect() + } + + }, [ toolbarRef.current ]) + + useEffect(() => { + + if (!alterRef.current) return + + setHeight(alterRef.current?.offsetHeight ?? 65) + + //监听toolbarRef offsetHeight + const observer = new ResizeObserver(entries => { + for (const entry of entries) { + if (entry.target === alterRef.current && entry.contentRect.height > 0) { + setAlterHeight(entry.contentRect.height + 16) + } + } + }) + + observer.observe(alterRef.current!) + + return () => { + observer.disconnect() + } + + }, [ alterRef.current ]) + + const style = { + '--toolbar-height': `${toolbarHeight}px`, + '--alter-height': `${alterHeight}px`, + } as React.CSSProperties + + // @ts-ignore fix dataItem + return + {...props} + className={styles.container} + style={style} + tableRender={(props, _dom, domList) => { + return +
{domList.toolbar}
+
{domList.alert}
+ <>{domList.table} +
+ }} + scroll={scroll} + > +} + +export default Table \ No newline at end of file diff --git a/src/components/table/index.ts b/src/components/table/index.ts new file mode 100644 index 0000000..3908464 --- /dev/null +++ b/src/components/table/index.ts @@ -0,0 +1 @@ +export * from './Table.tsx' \ No newline at end of file diff --git a/src/components/table/style.ts b/src/components/table/style.ts new file mode 100644 index 0000000..c27fd12 --- /dev/null +++ b/src/components/table/style.ts @@ -0,0 +1,23 @@ +import { createStyles } from '@/theme' + +export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) => { + const prefix = `${prefixCls}-${token?.proPrefix}-my-table` + + const container = css` + + --toolbar-height: 65px; + --alter-height: 0px; + --padding: 37px; + --table-body-height: calc(var(--toolbar-height, 65px) + var(--alter-height, 0px) + var(--header-height, 56px) + var(--padding, 20px) * 4); + + .ant-table-body { + overflow: auto scroll; + max-height: calc(100vh - var(--table-body-height)) !important; + height: calc(100vh - var(--table-body-height)) !important; + } + ` + + return { + container: cx(prefix, props?.className, container), + } +}) \ No newline at end of file diff --git a/src/hooks/useScrollStyle.ts b/src/hooks/useScrollStyle.ts index 3694ff6..812b629 100644 --- a/src/hooks/useScrollStyle.ts +++ b/src/hooks/useScrollStyle.ts @@ -64,11 +64,9 @@ export const useScrollStyle = () => { background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px; background-attachment: local, local, scroll, scroll; - ${scrollbar.toString()} - + ${scrollbar} ` - return { scrollbarBackground, scrollbar, diff --git a/src/layout/ListPageLayout.tsx b/src/layout/ListPageLayout.tsx index 58afe25..f0cc0de 100644 --- a/src/layout/ListPageLayout.tsx +++ b/src/layout/ListPageLayout.tsx @@ -18,8 +18,9 @@ const ListPageLayout: React.FC = ( <>
= (props) => { - const { styles } = useStyle({ className: 'two-col' }) - return ( - - - - {props.leftPanel} - - - {props.children} - - - - ) + const { styles, cx } = useStyle({ className: 'two-col' }) + return ( + + + + {props.leftPanel} + + + {props.children} + + + + ) } export default TwoColPageLayout \ No newline at end of file diff --git a/src/layout/style.ts b/src/layout/style.ts index f61fcd8..b715707 100644 --- a/src/layout/style.ts +++ b/src/layout/style.ts @@ -7,8 +7,6 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) const { scrollbar } = useScrollStyle() - console.log(scrollbar) - const container = { [prefix]: css` @@ -33,9 +31,36 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) ${scrollbar} } + + .ant-pro-layout-content{ + padding: 20px; + + } + .ant-pro-layout .ant-pro-layout-content-has-page-container{ + padding: 0; + } + .ant-pro-page-container-children-container{ + + padding-inline: 20px; + padding-block-end: 20px; + + } + .ant-page-header-no-children { + height: 20px; + } + + .ant-pro-card{ + height: calc(100vh - 100px)!important; + min-height: calc(100vh - 100px)!important; + } + `, } + const pageCard = css` + + ` + const pageContext = css` box-shadow: ${token.boxShadowSecondary}; ` @@ -91,8 +116,12 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) background: ${token.colorBgContainer}; ` const authHeight = css` - min-height: calc(100vh - 122px); background-color: ${token.colorBgContainer}; + + .ant-pro-draggable-panel-fixed{ + height: calc(100vh - 100px)!important; + min-height: calc(100vh - 100px)!important; + } ` return { @@ -103,6 +132,7 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) sideMenu, mySider, mySiderMenu, + pageCard, } }) \ No newline at end of file diff --git a/src/pages/cms/collect/index.tsx b/src/pages/cms/collect/index.tsx index 8ecb8b8..264a837 100644 --- a/src/pages/cms/collect/index.tsx +++ b/src/pages/cms/collect/index.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useState } from 'react' -import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import { BetaSchemaForm, ProColumns, ProFormColumnsType } from '@ant-design/pro-components' import { useTranslation } from '@/i18n.ts' import { useAtom, useAtomValue } from 'jotai' import { @@ -14,6 +14,7 @@ import { Button, Form, Popconfirm } from 'antd' import ListPageLayout from '@/layout/ListPageLayout.tsx' import Switch from '@/components/switch' import Action from '@/components/action/Action.tsx' +import { Table as ProTable } from '@/components/table' const i18nPrefix = 'cms.collect' @@ -269,7 +270,7 @@ const Collect = () => { ] }} scroll={{ - x: 2000, + x: 2000, y: 'calc(100vh - 265px)' }} loading={isLoading || isFetching} dataSource={data?.rows ?? []} @@ -284,6 +285,13 @@ const Collect = () => { total: data?.total, pageSize: search.pageSize, current: search.page, + onShowSizeChange: (current: number, size: number) => { + setSearch({ + ...search, + pageSize: size, + page: current + }) + }, onChange: (current, pageSize) => { setSearch(prev => { return { diff --git a/src/pages/cms/video/index.tsx b/src/pages/cms/video/index.tsx index 934d8ba..401904e 100644 --- a/src/pages/cms/video/index.tsx +++ b/src/pages/cms/video/index.tsx @@ -8,7 +8,7 @@ import { import { useEffect, useMemo, useState } from 'react' import Switch from '@/components/switch' import Action from '@/components/action/Action.tsx' -import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import { BetaSchemaForm, ProColumns, ProFormColumnsType } from '@ant-design/pro-components' import ListPageLayout from '@/layout/ListPageLayout.tsx' import TagPro from '@/components/tag-pro/TagPro.tsx' import { categoriesAtom, categoryByIdAtom, categoryIdAtom } from '@/store/cms/category.ts' @@ -17,6 +17,7 @@ import { FilterOutlined } from '@ant-design/icons' import TagValue from '@/components/tag-value/TagValue.tsx' import dayjs from 'dayjs' import { useStyle } from './style.ts' +import { Table as ProTable } from '@/components/table' const i18nPrefix = 'cms.video' @@ -677,7 +678,7 @@ const Video = () => { ] }} scroll={{ - x: 3800, y: 'calc(100vh - 290px)' + x: 3800, y: 'calc(100vh - 265px)' }} onRow={(record) => { return { @@ -703,6 +704,13 @@ const Video = () => { total: data?.total, pageSize: search.pageSize, current: search.page, + onShowSizeChange: (current: number, size: number) => { + setSearch({ + ...search, + pageSize: size, + page: current + }) + }, onChange: (current, pageSize) => { setSearch(prev => { return { diff --git a/src/pages/cms/video_cloud/index.tsx b/src/pages/cms/video_cloud/index.tsx index 0e19f4c..b55b0e5 100644 --- a/src/pages/cms/video_cloud/index.tsx +++ b/src/pages/cms/video_cloud/index.tsx @@ -4,7 +4,7 @@ import { useAtom, useAtomValue } from 'jotai' import { useEffect, useMemo, useState } from 'react' import Switch from '@/components/switch' import Action from '@/components/action/Action.tsx' -import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import { BetaSchemaForm, ProColumns, ProFormColumnsType } from '@ant-design/pro-components' import ListPageLayout from '@/layout/ListPageLayout.tsx' import { deleteVideoCloudAtom, @@ -22,6 +22,7 @@ import { videoTypes } from '@/store/cms/video.ts' import { useStyle} from './style' import { getValueCount } from '@/utils' import { FilterOutlined } from '@ant-design/icons' +import { Table as ProTable } from '@/components/table' const i18nPrefix = 'cms.videoCloud' @@ -682,7 +683,7 @@ const VideoCloud = () => { }} scroll={{ - x: 3800, y: 'calc(100vh - 290px)' + x: 3800, y: 'calc(100vh - 265px)' }} onRow={(record) => { return { @@ -708,6 +709,13 @@ const VideoCloud = () => { total: data?.total, pageSize: search.pageSize, current: search.page, + onShowSizeChange: (current: number, size: number) => { + setSearch({ + ...search, + pageSize: size, + page: current + }) + }, onChange: (current, pageSize) => { setSearch(prev => { return { diff --git a/src/pages/cms/video_magnet/index.tsx b/src/pages/cms/video_magnet/index.tsx index 6ae38f5..01a1947 100644 --- a/src/pages/cms/video_magnet/index.tsx +++ b/src/pages/cms/video_magnet/index.tsx @@ -4,7 +4,7 @@ import { useAtom, useAtomValue } from 'jotai' import { useEffect, useMemo, useState } from 'react' import Switch from '@/components/switch' import Action from '@/components/action/Action.tsx' -import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import { BetaSchemaForm, ProColumns, ProFormColumnsType } from '@ant-design/pro-components' import ListPageLayout from '@/layout/ListPageLayout.tsx' import { videoTypes } from '@/store/cms/video.ts' import { @@ -21,6 +21,7 @@ import TagValue from '@/components/tag-value/TagValue.tsx' import dayjs from 'dayjs' import TagPro from '@/components/tag-pro/TagPro.tsx' import { useStyle } from './style' +import { Table as ProTable } from '@/components/table' const i18nPrefix = 'cms.videoMagnet' @@ -681,7 +682,7 @@ const VideoMagnet = () => { ] }} scroll={{ - x: 3800, y: 'calc(100vh - 290px)' + x: 3800, y: 'calc(100vh - 265px)' }} onRow={(record) => { return { @@ -707,6 +708,13 @@ const VideoMagnet = () => { total: data?.total, pageSize: search.pageSize, current: search.page, + onShowSizeChange: (current: number, size: number) => { + setSearch({ + ...search, + pageSize: size, + page: current + }) + }, onChange: (current, pageSize) => { setSearch(prev => { return { diff --git a/src/pages/system/logs/login/index.tsx b/src/pages/system/logs/login/index.tsx index 43feaeb..30b8fe1 100644 --- a/src/pages/system/logs/login/index.tsx +++ b/src/pages/system/logs/login/index.tsx @@ -1,144 +1,156 @@ import Switch from '@/components/switch' import { - ActionType, - PageContainer, - ProColumns, - ProTable, + ActionType, + ProColumns, } from '@ant-design/pro-components' import { useStyle } from './style.ts' import { memo, useMemo, useRef, useState } from 'react' import { useAtom, useAtomValue } from 'jotai' +import { Table as ProTable } from '@/components/table' import { useTranslation } from '@/i18n.ts' import { Button, Space, Table, Popconfirm } from 'antd' import { deleteLoginLogAtom, loginLogPageAtom, loginLogsAtom, loginLogSearchAtom } from '@/store/system/logs.ts' +import ListPageLayout from '@/layout/ListPageLayout.tsx' const LoginLog = memo(() => { - const { t } = useTranslation() - const { styles } = useStyle() - const actionRef = useRef() - const [ page, setPage ] = useAtom(loginLogPageAtom) - const [ search, setSearch ] = useAtom(loginLogSearchAtom) - const { data, isLoading, isFetching, refetch } = useAtomValue(loginLogsAtom) - const { mutate: deleteLog, isPending: isDeleting } = useAtomValue(deleteLoginLogAtom) - const [ ids, setIds ] = useState([]) + const { t } = useTranslation() + const { styles } = useStyle() + const actionRef = useRef() + const [ page, setPage ] = useAtom(loginLogPageAtom) + const [ search, setSearch ] = useAtom(loginLogSearchAtom) + const { data, isLoading, isFetching, refetch } = useAtomValue(loginLogsAtom) + const { mutate: deleteLog, isPending: isDeleting } = useAtomValue(deleteLoginLogAtom) + const [ ids, setIds ] = useState([]) - const columns = useMemo(() => { + const columns = useMemo(() => { - return [ - { - title: 'id', dataIndex: 'id', - hideInTable: true, - hideInSearch: true, - formItemProps: { - hidden: true - } - }, - { - title: t('system.logs.login.columns.username', '登录帐号'), dataIndex: 'username', valueType: 'text', - }, - { - title: t('system.logs.login.columns.ip', '登录IP'), dataIndex: 'ip', valueType: 'text', - }, - { - title: t('system.logs.login.columns.user_agent', '浏览器'), dataIndex: 'user_agent', valueType: 'text', - }, - { - title: t('system.logs.login.columns.status', '状态'), dataIndex: 'status', valueType: 'switch', - render: (_, record) => { - return - }, - }, - { - title: t('system.logs.login.columns.created_at', '登录时间'), - dataIndex: 'created_at', - valueType: 'dateTime', - }, - { - title: t('system.logs.login.columns.option','操作'), valueType: 'option', - key: 'option', - render: (_, record) => [ - { - deleteLog([ record.id ]) - }} - title={t('message.deleteConfirm')}> - - {t('actions.delete', '删除')} - - - , - ], - }, - ] as ProColumns[] - }, []) + return [ + { + title: 'id', dataIndex: 'id', + hideInTable: true, + hideInSearch: true, + formItemProps: { + hidden: true + } + }, + { + title: t('system.logs.login.columns.username', '登录帐号'), dataIndex: 'username', valueType: 'text', + }, + { + title: t('system.logs.login.columns.ip', '登录IP'), dataIndex: 'ip', valueType: 'text', + }, + { + title: t('system.logs.login.columns.user_agent', '浏览器'), dataIndex: 'user_agent', valueType: 'text', + width: 500, + ellipsis: true, + }, + { + title: t('system.logs.login.columns.status', '状态'), dataIndex: 'status', valueType: 'switch', + width: 80, + render: (_, record) => { + return + }, + }, + { + title: t('system.logs.login.columns.created_at', '登录时间'), + dataIndex: 'created_at', + valueType: 'dateTime', + width: 180, + }, + { + title: t('system.logs.login.columns.option', '操作'), valueType: 'option', + key: 'option', + render: (_, record) => [ + { + deleteLog([ record.id ]) + }} + title={t('message.deleteConfirm')}> + + {t('actions.delete', '删除')} + + + , + ], + }, + ] as ProColumns[] + }, []) - return ( - -
- { - setIds(selectedRowKeys as number[]) - }, - selectedRowKeys: ids, - selections: [ Table.SELECTION_ALL, Table.SELECTION_INVERT ], - }} - tableAlertOptionRender={() => { - return ( - - { - deleteLog(ids) - }} - title={t('message.batchDelete')}> - - - - ) - }} - options={{ - reload: () => { - refetch() - }, - }} - toolbar={{ - search: { - loading: isFetching && !!search.key, - onSearch: (value: string) => { - setSearch({ key: value }) - }, - placeholder: t('system.logs.login.search.placeholder','请输入用户名查询') - }, - actions: [] - }} - pagination={{ - total: data?.total, - current: page.page, - pageSize: page.pageSize, - onChange: (page) => { + return ( + + <> + { + setIds(selectedRowKeys as number[]) + }, + selectedRowKeys: ids, + selections: [ Table.SELECTION_ALL, Table.SELECTION_INVERT ], + }} + scroll={{ - setPage((prev) => { - return { ...prev, page } - }) - } - }} - /> -
+ }} + tableAlertOptionRender={() => { + return ( + + { + deleteLog(ids) + }} + title={t('message.batchDelete')}> + + + + ) + }} + options={{ + reload: () => { + refetch() + }, + }} + toolbar={{ + search: { + loading: isFetching && !!search.key, + onSearch: (value: string) => { + setSearch({ key: value }) + }, + placeholder: t('system.logs.login.search.placeholder', '请输入用户名查询') + }, + actions: [] + }} + pagination={{ + total: data?.total, + current: page.page, + pageSize: page.pageSize, + onShowSizeChange: (current: number, size: number) => { + setPage({ + ...page, + pageSize: size, + page: current + }) + }, + onChange: (page) => { - -
- ) + setPage((prev) => { + return { ...prev, page } + }) + } + }} + /> + + + ) }) export default LoginLog \ No newline at end of file diff --git a/src/pages/system/menus/index.tsx b/src/pages/system/menus/index.tsx index 2ee36b5..3765efc 100644 --- a/src/pages/system/menus/index.tsx +++ b/src/pages/system/menus/index.tsx @@ -16,192 +16,192 @@ import TwoColPageLayout from '@/layout/TwoColPageLayout.tsx' const Menus = () => { - const { styles, cx } = useStyle() - const { t } = useTranslation() - const [ form ] = Form.useForm() - const { mutate, isPending, error, isError } = useAtomValue(saveOrUpdateMenuAtom) - const { data = [] } = useAtomValue(menuDataAtom) - const [ currentMenu, setMenuData ] = useAtom(selectedMenuAtom) ?? {} - const menuInputRef = useRef(undefined) - - useEffect(() => { - - if (isError) { - notification.error({ - message: t('message.error', '错误'), - description: (error as any).message ?? t('message.saveFail', '保存失败'), - }) - } - }, [ isError ]) - - useEffect(() => { - if (currentMenu.id === 0 && menuInputRef.current) { - menuInputRef.current.focus() - } - }, [ currentMenu ]) - - return ( - - - - - } - > - - - -
- - -
+ const { styles, cx } = useStyle() + const { t } = useTranslation() + const [ form ] = Form.useForm() + const { mutate, isPending, error, isError } = useAtomValue(saveOrUpdateMenuAtom) + const { data = [] } = useAtomValue(menuDataAtom) + const [ currentMenu, setMenuData ] = useAtom(selectedMenuAtom) ?? {} + const menuInputRef = useRef(undefined) + + useEffect(() => { + + if (isError) { + notification.error({ + message: t('message.error', '错误'), + description: (error as any).message ?? t('message.saveFail', '保存失败'), + }) + } + }, [ isError ]) + + useEffect(() => { + if (currentMenu.id === 0 && menuInputRef.current) { + menuInputRef.current.focus() + } + }, [ currentMenu ]) + + return ( + + + + + } + > + + + +
+ + +
+ } + > + + + + } > - - - - - } +
+ + - + + + + + + + + + + + + + + { + return prev.icon !== next.icon + }}> + + + + + + + + + + - - - - - - - - - - - - - - - - - { - return prev.icon !== next.icon - }}> - - - - - - - - - - - - - - - - - - - - { - return prevValues.id !== curValues.id - }}> - - - - - -
- -
- ) + + + + + +
+ + + + { + return prevValues.id !== curValues.id + }}> + + + + + + + + + ) } export default Menus \ No newline at end of file diff --git a/src/pages/system/menus/style.ts b/src/pages/system/menus/style.ts index a5834b1..01e5133 100644 --- a/src/pages/system/menus/style.ts +++ b/src/pages/system/menus/style.ts @@ -1,7 +1,9 @@ import { createStyles } from '@/theme' +import { useScrollStyle } from '@/hooks/useScrollStyle' export const useStyle = createStyles(({ token, css, cx, prefixCls }) => { const prefix = `${prefixCls}-${token?.proPrefix}-menu-page` + const { scrollbarBackground } = useScrollStyle() const box = css` flex: 1; @@ -18,12 +20,21 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }) => { const formSetting = css` flex: 1; - + + .ant-pro-card-body { + overflow: auto; + ${scrollbarBackground} + .ant-pro-card-body-content { + padding-inline: 10px 0; + } + } ` const formButtons = css` width: 500px; - + .ant-pro-card-body { + overflow: hidden; + } ` const tree = css` diff --git a/src/pages/system/roles/index.tsx b/src/pages/system/roles/index.tsx index 0ded53b..1874c8b 100644 --- a/src/pages/system/roles/index.tsx +++ b/src/pages/system/roles/index.tsx @@ -203,6 +203,13 @@ const Roles = memo(() => { total: data?.total, current: page.page, pageSize: page.pageSize, + onShowSizeChange: (current: number, size: number) => { + setPage({ + ...page, + pageSize: size, + page: current + }) + }, onChange: (page) => { setPage((prev) => { diff --git a/src/pages/system/users/index.tsx b/src/pages/system/users/index.tsx index 699137e..493c3c8 100644 --- a/src/pages/system/users/index.tsx +++ b/src/pages/system/users/index.tsx @@ -1,11 +1,11 @@ import TwoColPageLayout from '@/layout/TwoColPageLayout.tsx' import { - ActionType, - BetaSchemaForm, - ProCard, - ProColumns, - ProFormColumnsType, - ProTable + ActionType, + BetaSchemaForm, + ProCard, + ProColumns, + ProFormColumnsType, + ProTable } from '@ant-design/pro-components' import { Button, Form, Popconfirm } from 'antd' import { PlusOutlined } from '@ant-design/icons' @@ -13,12 +13,12 @@ import { useTranslation } from '@/i18n.ts' import DepartmentTree from '@/components/department-tree/DepartmentTree.tsx' import { useAtom, useAtomValue } from 'jotai' import { - deleteUserAtom, resetPasswordAtom, - saveOrUpdateUserAtom, - userListAtom, - userPageAtom, - userSearchAtom, - userSelectedAtom + deleteUserAtom, resetPasswordAtom, + saveOrUpdateUserAtom, + userListAtom, + userPageAtom, + userSearchAtom, + userSelectedAtom } from '@/store/system/user.ts' import { useMemo, useRef, useState } from 'react' import Switch from '@/components/switch' @@ -27,220 +27,227 @@ import RolePicker from '@/components/role-picker/RolePicker.tsx' const Users = () => { - const { t } = useTranslation() - const [ page, setPage ] = useAtom(userPageAtom) - const [ search, setSearch ] = useAtom(userSearchAtom) - const [ , setCurrent ] = useAtom(userSelectedAtom) - const { mutate: saveOrUpdate, isSuccess, isPending: isSubmitting } = useAtomValue(saveOrUpdateUserAtom) - const { data, isFetching, isLoading, refetch } = useAtomValue(userListAtom) - const { mutate: deleteUser, isPending, } = useAtomValue(deleteUserAtom) - const { mutate: resetPass, isPending: isResetting } = useAtomValue(resetPasswordAtom) - const [ form ] = Form.useForm() - const actionRef = useRef() - const [ open, setOpen ] = useState(false) + const { t } = useTranslation() + const [ page, setPage ] = useAtom(userPageAtom) + const [ search, setSearch ] = useAtom(userSearchAtom) + const [ , setCurrent ] = useAtom(userSelectedAtom) + const { mutate: saveOrUpdate, isSuccess, isPending: isSubmitting } = useAtomValue(saveOrUpdateUserAtom) + const { data, isFetching, isLoading, refetch } = useAtomValue(userListAtom) + const { mutate: deleteUser, isPending, } = useAtomValue(deleteUserAtom) + const { mutate: resetPass, isPending: isResetting } = useAtomValue(resetPasswordAtom) + const [ form ] = Form.useForm() + const actionRef = useRef() + const [ open, setOpen ] = useState(false) - const columns = useMemo(() => { + const columns = useMemo(() => { - return [ - { - title: 'id', dataIndex: 'id', - hideInTable: true, - hideInSearch: true, - formItemProps: { - hidden: true - } - }, - { - title: t('system.users.columns.name', '姓名'), dataIndex: 'name', valueType: 'text', - formItemProps: { - rules: [ { required: true, message: t('message.required') } ] - } - }, - { - title: t('system.users.columns.username', '用户名'), dataIndex: 'username', valueType: 'text', - formItemProps: { - rules: [ { required: true, message: t('message.required') } ] - } - }, - { - title: t('system.users.columns.roles', '角色'), dataIndex: 'roles', valueType: 'select', - render: (_, record) => { - return record.roles?.map(role => role.name).join(',') || '' - }, - renderFormItem: (item, config) => { - const { mode, ...other } = config as any - return - }, + return [ + { + title: 'id', dataIndex: 'id', + hideInTable: true, + hideInSearch: true, + formItemProps: { + hidden: true + } + }, + { + title: t('system.users.columns.name', '姓名'), dataIndex: 'name', valueType: 'text', + formItemProps: { + rules: [ { required: true, message: t('message.required') } ] + } + }, + { + title: t('system.users.columns.username', '用户名'), dataIndex: 'username', valueType: 'text', + formItemProps: { + rules: [ { required: true, message: t('message.required') } ] + } + }, + { + title: t('system.users.columns.roles', '角色'), dataIndex: 'roles', valueType: 'select', + render: (_, record) => { + return record.roles?.map(role => role.name).join(',') || '' + }, + renderFormItem: (item, config) => { + const { mode, ...other } = config as any + return + }, - }, - { - title: t('system.users.columns.dept_id', '所属部门'), dataIndex: 'dept_id', - render: (_, record) => { - return record.dept_name || '' - }, - renderFormItem: (item, config) => { - return - } - }, - { - title: t('system.users.columns.status', '状态'), dataIndex: 'status', valueType: 'switch', - render: (_, record) => { - return - }, - renderFormItem: (item, config) => { - return - }, - }, - { - title: t('system.users.columns.update_at', '更新时间'), - hideInTable: true, - hideInSearch: true, - hideInForm: true, - dataIndex: 'update_at', - valueType: 'dateTime', - }, - { - title: t('system.users.columns.option', '操作'), valueType: 'option', - key: 'option', - render: (_, record) => [ - { - setCurrent(record) - setOpen(true) - form.setFieldsValue(record) - }} - > - {t('actions.edit', '编辑')} - , - { - resetPass(record.id) - }} - title={ - kk123456' - }) - }}> - }> - - {t('actions.resetPass', '重置密码')} - - , - { - deleteUser([ record.id ]) - }} - title={t('message.deleteConfirm')}> - - {t('actions.delete', '删除')} - - - , - ], - }, - ] as ProColumns[] - }, []) + }, + { + title: t('system.users.columns.dept_id', '所属部门'), dataIndex: 'dept_id', + render: (_, record) => { + return record.dept_name || '' + }, + renderFormItem: (item, config) => { + return + } + }, + { + title: t('system.users.columns.status', '状态'), dataIndex: 'status', valueType: 'switch', + render: (_, record) => { + return + }, + renderFormItem: (item, config) => { + return + }, + }, + { + title: t('system.users.columns.update_at', '更新时间'), + hideInTable: true, + hideInSearch: true, + hideInForm: true, + dataIndex: 'update_at', + valueType: 'dateTime', + }, + { + title: t('system.users.columns.option', '操作'), valueType: 'option', + key: 'option', + render: (_, record) => [ + { + setCurrent(record) + setOpen(true) + form.setFieldsValue(record) + }} + > + {t('actions.edit', '编辑')} + , + { + resetPass(record.id) + }} + title={ + kk123456' + }) + }}> + }> + + {t('actions.resetPass', '重置密码')} + + , + { + deleteUser([ record.id ]) + }} + title={t('message.deleteConfirm')}> + + {t('actions.delete', '删除')} + + + , + ], + }, + ] as ProColumns[] + }, []) - return ( - - - { - setSearch({ - dept_id: item.id, - }) - }} - /> - - - }> - { - refetch() - }, + return ( + + + { - setSearch({ key: value }) - }, - placeholder: t('system.users.search.placeholder', '输入用户名') - }, - actions: [ - , - ] - }} - pagination={{ - total: data?.total, - current: page.page, - pageSize: page.pageSize, - onChange: (page) => { - setPage((prev) => { - return { ...prev, page } - }) - } + onItemClick={(item) => { + setSearch({ + dept_id: item.id, + }) }} /> - { - setOpen(open) - }} - loading={isSubmitting} - onFinish={async (values) => { - // console.log('values', values) - saveOrUpdate(values) - return isSuccess - }} - columns={columns as ProFormColumnsType[]}/> - - ) + + + }> + { + refetch() + }, + }} + toolbar={{ + search: { + loading: isFetching && !!search.key, + onSearch: (value: string) => { + setSearch({ key: value }) + }, + placeholder: t('system.users.search.placeholder', '输入用户名') + }, + actions: [ + , + ] + }} + pagination={{ + total: data?.total, + current: page.page, + pageSize: page.pageSize, + onShowSizeChange: (current: number, size: number) => { + setPage({ + ...page, + pageSize: size, + page: current + }) + }, + onChange: (page) => { + setPage((prev) => { + return { ...prev, page } + }) + } + }} + /> + { + setOpen(open) + }} + loading={isSubmitting} + onFinish={async (values) => { + // console.log('values', values) + saveOrUpdate(values) + return isSuccess + }} + columns={columns as ProFormColumnsType[]}/> + + ) } diff --git a/src/pages/videos/list/index.tsx b/src/pages/videos/list/index.tsx index 7aeb20d..635edf5 100644 --- a/src/pages/videos/list/index.tsx +++ b/src/pages/videos/list/index.tsx @@ -14,7 +14,6 @@ import { ProColumns, ProFormColumnsType, ProFormUploadButton, - ProTable } from '@ant-design/pro-components' import ListPageLayout from '@/layout/ListPageLayout.tsx' import { categoryByIdAtom, categoryIdAtom } from '@/store/videos/category.ts' @@ -23,6 +22,7 @@ import TagValue from '@/components/tag-value/TagValue.tsx' import { useStyle } from './style' import { ExportOutlined, FilterOutlined } from '@ant-design/icons' import { getValueCount } from '@/utils' +import { Table as ProTable } from '@/components/table' const i18nPrefix = 'videos.list' @@ -694,6 +694,13 @@ const Video = () => { total: data?.total, pageSize: search.pageSize, current: search.page, + onShowSizeChange: (current: number, size: number) => { + setSearch({ + ...search, + pageSize: size, + page: current + }) + }, onChange: (current, pageSize) => { setSearch(prev => { return { diff --git a/src/pages/websites/ssl/index.tsx b/src/pages/websites/ssl/index.tsx index cc766a0..063f080 100644 --- a/src/pages/websites/ssl/index.tsx +++ b/src/pages/websites/ssl/index.tsx @@ -10,7 +10,7 @@ import { sslSearchAtom, uploadSslAtom } from '@/store/websites/ssl.ts' import ListPageLayout from '@/layout/ListPageLayout.tsx' -import { BetaSchemaForm, ProColumns, ProFormColumnsType, ProTable } from '@ant-design/pro-components' +import { BetaSchemaForm, ProColumns, ProFormColumnsType } from '@ant-design/pro-components' import { memo, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from '@/i18n.ts' import { Button, Form, Popconfirm, Space } from 'antd' @@ -31,6 +31,7 @@ import { detailAtom } from './components/store.ts' import Upload from './components/Upload.tsx' import { FormInstance } from 'antd/lib' import Download from '@/components/download/Download.tsx' +import { Table as ProTable } from '@/components/table' const SSL = () => { @@ -371,10 +372,18 @@ const SSL = () => { , ] }} + scroll={{}} pagination={{ pageSize: page?.pageSize ?? 10, total: data?.total ?? 0, current: page?.page ?? 1, + onShowSizeChange: (current: number, size: number) => { + setPage({ + ...page, + pageSize: size, + page: current + }) + }, onChange: (page, pageSize) => { setPage(prev => ({ ...prev, diff --git a/src/utils/dom.ts b/src/utils/dom.ts new file mode 100644 index 0000000..312bb6d --- /dev/null +++ b/src/utils/dom.ts @@ -0,0 +1,12 @@ +export function getElementRealHeight(el: Element) { + const style = window.getComputedStyle(el) + + const paddingTop = parseInt(style.paddingTop) + const paddingBottom = parseInt(style.paddingBottom) + const marginTop = parseInt(style.marginTop) + const marginBottom = parseInt(style.marginBottom) + + const clientHeight = el.clientHeight + + return clientHeight + paddingTop + paddingBottom + marginTop + marginBottom +} \ No newline at end of file