From aada97ed2281b8b108a933ebae6ba61326690eb9 Mon Sep 17 00:00:00 2001 From: wuxichen <17301714657@163.com> Date: Wed, 17 Sep 2025 10:41:00 +0800 Subject: [PATCH] feat: menu --- .github/workflows/ci.yml | 1 + config/config.ts | 13 +- src/app.tsx | 38 +++- src/components/DrawerForm/index.tsx | 122 +++++++++++ src/components/EnhancedProTable/index.tsx | 249 ++++++---------------- src/components/EnhancedProTable/types.ts | 3 +- src/constants/{ => antd}/icons.tsx | 0 src/constants/index.ts | 1 + src/hooks/antd/useEnhancedTable.ts | 116 ---------- src/hooks/antd/useModal.ts | 131 ++++++++++++ src/hooks/antd/useRequest.ts | 51 +++++ src/locales/zh-CN/pages.ts | 138 ++++++------ src/locales/zh-TW/pages.ts | 138 ++++++------ src/pages/system/dept/index.tsx | 5 + src/pages/system/dict/index.tsx | 5 + src/pages/system/log/login/index.tsx | 5 + src/pages/system/log/operate/index.tsx | 5 + src/pages/system/menu/index.tsx | 5 + src/pages/system/post/index.tsx | 5 + src/pages/system/role/index.tsx | 5 + src/pages/system/tenant/list/config.tsx | 223 +++++++++++++++++++ src/pages/system/tenant/list/index.tsx | 171 +++++++++------ src/pages/system/user/index.tsx | 5 + src/requestErrorConfig.ts | 2 + src/services/system/tenant/list.ts | 2 +- src/utils/antd/commonRules.ts | 43 ++++ src/utils/antd/tableConfigFactory.tsx | 18 +- 27 files changed, 973 insertions(+), 527 deletions(-) create mode 100644 src/components/DrawerForm/index.tsx rename src/constants/{ => antd}/icons.tsx (100%) create mode 100644 src/constants/index.ts delete mode 100644 src/hooks/antd/useEnhancedTable.ts create mode 100644 src/hooks/antd/useModal.ts create mode 100644 src/hooks/antd/useRequest.ts create mode 100644 src/pages/system/dept/index.tsx create mode 100644 src/pages/system/dict/index.tsx create mode 100644 src/pages/system/log/login/index.tsx create mode 100644 src/pages/system/log/operate/index.tsx create mode 100644 src/pages/system/menu/index.tsx create mode 100644 src/pages/system/post/index.tsx create mode 100644 src/pages/system/role/index.tsx create mode 100644 src/pages/system/tenant/list/config.tsx create mode 100644 src/pages/system/user/index.tsx create mode 100644 src/utils/antd/commonRules.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61bf586..024d91d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,7 @@ permissions: jobs: build: + if: false runs-on: ${{ matrix.os }} strategy: matrix: diff --git a/config/config.ts b/config/config.ts index b68bf91..7562f8b 100644 --- a/config/config.ts +++ b/config/config.ts @@ -152,13 +152,12 @@ export default defineConfig({ * @doc https://pro.ant.design/zh-cn/docs/openapi/ */ openAPI: [ - { - requestLibPath: "import { request } from '@umijs/max'", - - schemaPath: join(__dirname, "oneapi/prodapi.json"), - mock: false, - projectName: "prodApi", - }, + // { + // requestLibPath: "import { request } from '@umijs/max'", + // schemaPath: join(__dirname, "oneapi/prodapi.json"), + // mock: false, + // projectName: "prodApi", + // }, // {schemaPath: "./docs/apifox-api.json", // requestLibPath: "import { request } from '@umijs/max'", // schemaPath: join(__dirname, "oneapi.json"), diff --git a/src/app.tsx b/src/app.tsx index 8d964fd..6d3dd3a 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,5 +1,11 @@ -import React, { Children, Component, JSX, Suspense } from "react"; -import { Spin } from "antd"; +import React, { + Children, + Component, + createContext, + JSX, + Suspense, +} from "react"; +import { Modal, Spin } from "antd"; import type { Settings as LayoutSettings } from "@ant-design/pro-components"; import { SettingDrawer } from "@ant-design/pro-components"; import type { RequestConfig, RunTimeLayoutConfig } from "@umijs/max"; @@ -197,6 +203,34 @@ export const request: RequestConfig = { return { url, options: { ...options, headers } }; }, ], + // 添加参数序列化配置 + paramsSerializer: (params) => { + const searchParams = new URLSearchParams(); + + const appendParams = (key: string, value: any) => { + if (Array.isArray(value)) { + // 特殊处理 createTime 数组,转换为 createTime[0] 和 createTime[1] 格式 + if (key === "createTime") { + value.forEach((val, index) => { + searchParams.append(`${key}[${index}]`, val); + }); + } else { + // 其他数组参数保持默认行为 + value.forEach((val) => { + searchParams.append(`${key}[]`, val); + }); + } + } else if (value !== null && value !== undefined) { + searchParams.append(key, String(value)); + } + }; + + Object.keys(params).forEach((key) => { + appendParams(key, params[key]); + }); + + return searchParams.toString(); + }, }; // umi 4 使用 modifyRoutes export function patchClientRoutes({ routes }: { routes: any }) { diff --git a/src/components/DrawerForm/index.tsx b/src/components/DrawerForm/index.tsx new file mode 100644 index 0000000..2c31598 --- /dev/null +++ b/src/components/DrawerForm/index.tsx @@ -0,0 +1,122 @@ +import React, { useImperativeHandle, forwardRef } from "react"; +import { DrawerForm } from "@ant-design/pro-components"; +import type { ProFormColumnsType } from "@ant-design/pro-components"; +import { BetaSchemaForm } from "@ant-design/pro-components"; +import { Button, Drawer, Space, Typography } from "antd"; +import { CloseOutlined } from "@ant-design/icons"; +const { Title } = Typography; +interface ConfigurableDrawerFormProps { + title?: string; + columns: ProFormColumnsType[]; + onSubmit?: (values: any) => Promise; + initialValues?: Record; + width?: number; +} + +export interface ConfigurableDrawerFormRef { + open: (data?: Record) => void; + close: () => void; +} + +const ConfigurableDrawerForm = forwardRef< + ConfigurableDrawerFormRef, + ConfigurableDrawerFormProps +>(({ title = "表单", columns, onSubmit, initialValues, width = 600 }, ref) => { + const [open, setOpen] = React.useState(false); + const [formData, setFormData] = React.useState(initialValues || {}); + const [loading, setLoading] = React.useState(false); + // 添加表单实例引用 + const formRef = React.useRef(null); + useImperativeHandle(ref, () => ({ + open: (data) => { + if (data) { + setFormData(data); + } + console.log("open"); + setOpen(true); + }, + close: () => setOpen(false), + })); + + const handleSubmit = async () => { + try { + if (onSubmit) { + await formRef.current?.validateFields(); + setLoading(true); + const values = formRef.current?.getFieldsValue(); + const success = await onSubmit(values); + if (success) { + setOpen(false); + return true; + } + return false; + } + return true; + } finally { + setLoading(false); + } + }; + const customHeader = ( +
+ + {title} + +
+ ); + return ( + setOpen(false)} + width={width} + footer={ + + + + + } + > + {/* {customHeader} */} + + + ); +}); + +export default ConfigurableDrawerForm; diff --git a/src/components/EnhancedProTable/index.tsx b/src/components/EnhancedProTable/index.tsx index 9637a33..81d7787 100644 --- a/src/components/EnhancedProTable/index.tsx +++ b/src/components/EnhancedProTable/index.tsx @@ -1,5 +1,12 @@ // components/EnhancedProTable/EnhancedProTable.tsx -import React, { useRef, useState, useCallback, useMemo } from "react"; +import React, { + useRef, + useState, + useCallback, + useMemo, + act, + forwardRef, +} from "react"; import { ProTable, ProColumns, @@ -19,17 +26,19 @@ import { handleTableDropdownSelect, formatPaginationTotal, } from "@/utils/antd/tableHelpers"; +import { PlusOutlined } from "@ant-design/icons"; function EnhancedProTable( - props: EnhancedProTableProps + props: EnhancedProTableProps, + ref: React.Ref | undefined ) { const { - columns: originalColumns, + columns, request, actions = [], - toolbarActions = [], permissions = [], checkPermission = () => true, + toolbarActions, showIndex = true, showSelection = true, showActions = true, @@ -44,160 +53,8 @@ function EnhancedProTable( ...restProps } = props; - const actionRef = useRef(null); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [selectedRows, setSelectedRows] = useState([]); - - // 权限检查 - const hasPermission = useCallback( - (permission?: string) => { - if (!permission) return true; - return checkPermission(permission); - }, - [checkPermission] - ); - - // 过滤有权限的操作 - const filteredActions = useMemo(() => { - return actions.filter((action) => hasPermission(action.permission)); - }, [actions, hasPermission]); - - const filteredToolbarActions = useMemo(() => { - return toolbarActions.filter((action) => hasPermission(action.permission)); - }, [toolbarActions, hasPermission]); - - // 构建操作列 - const buildActionColumn = useCallback((): ProColumns => { - if (!showActions || filteredActions.length === 0) { - return {} as ProColumns; - } - - return { - title: "操作", - valueType: "option", - key: "actions", - fixed: "right", - width: Math.min(filteredActions.length * 60 + 50, 200), - render: (_, record, index, action) => { - // 过滤可见的操作 - const visibleActions = filteredActions.filter( - (actionItem) => !actionItem.visible || actionItem.visible(record) - ); - - if (visibleActions.length === 0) return null; - - // 显示的操作按钮 - const displayActions = visibleActions.slice(0, maxActionCount); - // 更多操作 - const moreActions = visibleActions.slice(maxActionCount); - - const actionElements: React.ReactNode[] = displayActions.map( - (actionItem) => ( - actionItem.onClick(record, action)} - style={{ - color: actionItem.danger ? "#ff4d4f" : undefined, - }} - > - {actionItem.icon} {actionItem.label} - - ) - ); - - // 如果有更多操作,添加下拉菜单 - if (moreActions.length > 0) { - const menuItems = buildTableDropdownMenuItems( - moreActions.map((actionItem) => ({ - key: actionItem.key, - label: actionItem.label, - icon: actionItem.icon, - danger: actionItem.danger, - disabled: actionItem.disabled?.(record) || false, - })) - ); - - actionElements.push( - { - handleTableDropdownSelect(key, moreActions, record, action); - action?.reload(); - }} - menus={menuItems} - /> - ); - } - - // 自定义操作渲染 - if (customActionRender) { - return customActionRender(record, actionElements); - } - - return actionElements; - }, - }; - }, [showActions, filteredActions, maxActionCount, customActionRender]); - - // 构建列配置 - const enhancedColumns = useMemo(() => { - const columns: ProColumns[] = []; - - // 添加序号列 - if (showIndex) { - columns.push({ - title: "序号", - dataIndex: "index", - valueType: "indexBorder", - width: 48, - fixed: "left", - }); - } - - // 添加原始列 - columns.push(...originalColumns); - - // 添加操作列 - const actionColumn = buildActionColumn(); - if (actionColumn.title) { - columns.push(actionColumn); - } - - return columns; - }, [originalColumns, showIndex, buildActionColumn]); - - // 工具栏渲染 - const toolBarRender = useCallback(() => { - const defaultActions = filteredToolbarActions.map((action) => ( - - )); - - if (customToolbarRender) { - return customToolbarRender(defaultActions); - } - - return defaultActions; - }, [ - filteredToolbarActions, - selectedRowKeys, - selectedRows, - customToolbarRender, - ]); - // 行选择配置 const rowSelection = useMemo(() => { if (!showSelection) return undefined; @@ -233,45 +90,60 @@ function EnhancedProTable( [showSelection] ); - // 表格提醒操作渲染 - const tableAlertOptionRender = useCallback(() => { - if (!showSelection || selectedRowKeys.length === 0) return false; - - const batchActions = filteredToolbarActions.filter( - (action) => action.needSelection - ); - - if (batchActions.length === 0) return false; - - return ( - - {batchActions.map((action) => ( - - action.onClick(selectedRowKeys as number[], selectedRows) - } - > - {action.label} - - ))} - - ); - }, [showSelection, selectedRowKeys, selectedRows, filteredToolbarActions]); - + const toolBarRender = useCallback( + ( + action: ActionType | undefined, + rows: { + selectedRowKeys?: (string | number)[] | undefined; + selectedRows?: T[] | undefined; + } + ) => { + const toolbarElements = + toolbarActions?.map((action) => { + return ( + + ); + }) || []; + // return [ + // , + // ]; + return toolbarElements; + }, + [toolbarActions] + ); return ( {...restProps} - columns={enhancedColumns} - actionRef={actionRef} + columns={columns} + actionRef={ref} request={request} rowKey="id" rowSelection={rowSelection} toolBarRender={toolBarRender} + manualRequest={false} + showSorterTooltip tableAlertRender={tableAlertRender} - tableAlertOptionRender={tableAlertOptionRender} + // tableAlertOptionRender={tableAlertOptionRender} + scroll={{ x: "max-content" }} search={{ labelWidth: "auto", + defaultCollapsed: false, ...restProps.search, }} options={{ @@ -291,4 +163,9 @@ function EnhancedProTable( ); } -export default EnhancedProTable; +export default forwardRef(EnhancedProTable) as < + T extends BaseRecord, + U extends ParamsType = any +>( + props: EnhancedProTableProps & { ref?: React.Ref } +) => React.ReactElement; diff --git a/src/components/EnhancedProTable/types.ts b/src/components/EnhancedProTable/types.ts index d10f5a8..99fc9a0 100644 --- a/src/components/EnhancedProTable/types.ts +++ b/src/components/EnhancedProTable/types.ts @@ -47,7 +47,7 @@ export interface ToolbarAction { type?: ButtonProps["type"]; danger?: boolean; disabled?: boolean; - onClick: (selectedKeys: React.Key[], selectedRows: any[]) => void; + onClick: (selectedKeys?: React.Key[], selectedRows?: any[]) => void; permission?: string; needSelection?: boolean; } @@ -58,6 +58,7 @@ export interface EnhancedProTableProps request?: ( params: U & { current?: number; pageSize?: number } ) => Promise>; + loading?: boolean; // 添加 loading 属性 actions?: TableAction[]; toolbarActions?: ToolbarAction[]; permissions?: string[]; diff --git a/src/constants/icons.tsx b/src/constants/antd/icons.tsx similarity index 100% rename from src/constants/icons.tsx rename to src/constants/antd/icons.tsx diff --git a/src/constants/index.ts b/src/constants/index.ts new file mode 100644 index 0000000..043f68d --- /dev/null +++ b/src/constants/index.ts @@ -0,0 +1 @@ +export const formStatusType = { create: "创建", update: "编辑" }; diff --git a/src/hooks/antd/useEnhancedTable.ts b/src/hooks/antd/useEnhancedTable.ts deleted file mode 100644 index a456f4c..0000000 --- a/src/hooks/antd/useEnhancedTable.ts +++ /dev/null @@ -1,116 +0,0 @@ -// hooks/useEnhancedTable.ts -import { useRef, useState, useCallback } from "react"; -import { ActionType } from "@ant-design/pro-components"; -import { message } from "antd"; -import { - UseEnhancedTableOptions, - UseEnhancedTableReturn, -} from "@/components/EnhancedProTable/types"; - -export function useEnhancedTable( - options: UseEnhancedTableOptions = {} -): UseEnhancedTableReturn { - const actionRef = useRef(undefined); - const [selectedRowKeys, setSelectedRowKeys] = useState([]); - const [selectedRows, setSelectedRows] = useState([]); - const [loading, setLoading] = useState(false); - - const { onAdd, onEdit, onDelete, onView, onExport, onBatchDelete } = options; - - // 刷新表格 - const reload = useCallback(() => { - actionRef.current?.reload(); - }, []); - - // 重置表格 - const reset = useCallback(() => { - actionRef.current?.reset?.(); - setSelectedRowKeys([]); - setSelectedRows([]); - }, []); - - // 清空选择 - const clearSelection = useCallback(() => { - setSelectedRowKeys([]); - setSelectedRows([]); - }, []); - - // 处理删除 - const handleDelete = useCallback( - async (record: T) => { - if (!onDelete) return; - - setLoading(true); - try { - const success = await onDelete(record); - if (success) { - message.success("删除成功"); - reload(); - } - } finally { - setLoading(false); - } - }, - [onDelete, reload] - ); - - // 处理批量删除 - const handleBatchDelete = useCallback( - async (keys: React.Key[]) => { - if (!onBatchDelete || keys.length === 0) return; - - setLoading(true); - try { - const success = await onBatchDelete(keys); - if (success) { - message.success("批量删除成功"); - clearSelection(); - reload(); - } - } catch (error) { - message.error("批量删除失败"); - } finally { - setLoading(false); - } - }, - [onBatchDelete, clearSelection, reload] - ); - - // 处理导出 - const handleExport = useCallback( - (rows: T[]) => { - if (!onExport) return; - if (rows.length === 0) { - message.warning("请选择要导出的数据"); - return; - } - onExport(rows); - }, - [onExport] - ); - - return { - actionRef, - selectedRowKeys, - selectedRows, - loading, - setSelectedRowKeys, - setSelectedRows, - reload, - reset, - clearSelection, - handleDelete, - handleBatchDelete, - handleExport, - actions: { - add: onAdd, - edit: onEdit, - delete: handleDelete, - view: onView, - export: handleExport, - batchDelete: handleBatchDelete, - }, - }; -} - -export type { UseEnhancedTableOptions, UseEnhancedTableReturn }; diff --git a/src/hooks/antd/useModal.ts b/src/hooks/antd/useModal.ts new file mode 100644 index 0000000..3b46e74 --- /dev/null +++ b/src/hooks/antd/useModal.ts @@ -0,0 +1,131 @@ +import { App } from "antd"; +import { useCallback } from "react"; + +export interface ConfirmOptions { + title: string; + content?: string; + okText?: string; + cancelText?: string; + onOk?: () => Promise | void; + onCancel?: () => void; + type?: "confirm" | "info" | "success" | "error" | "warning"; +} + +export const useModal = () => { + const { modal, message } = App.useApp(); + + // 通用确认对话框 + const showConfirm = useCallback( + (options: ConfirmOptions) => { + const { + title, + content, + okText = "确定", + cancelText = "取消", + onOk, + onCancel, + type = "confirm", + } = options; + + const modalMethod = modal[type]; + + return modalMethod({ + title, + content, + okText, + cancelText, + onOk, + onCancel, + }); + }, + [modal] + ); + + // 删除确认对话框 + const showDeleteConfirm = useCallback( + ( + onConfirm: () => Promise | void, + title: string = "删除确认", + content: string = "确定要删除吗?此操作不可恢复。" + ) => { + return modal.confirm({ + title, + content, + okText: "删除", + cancelText: "取消", + okType: "danger", + onOk: async () => { + try { + await onConfirm(); + message.success("删除成功"); + } catch (error) { + message.error("删除失败"); + throw error; + } + }, + }); + }, + [modal, message] + ); + + // 编辑确认对话框 + const showEditConfirm = useCallback( + ( + onConfirm: () => Promise | void, + title: string = "编辑确认", + content: string = "确定要保存修改吗?" + ) => { + return modal.confirm({ + title, + content, + okText: "保存", + cancelText: "取消", + onOk: async () => { + try { + await onConfirm(); + message.success("保存成功"); + } catch (error) { + message.error("保存失败"); + throw error; + } + }, + }); + }, + [modal, message] + ); + + // 状态切换确认对话框 + const showStatusConfirm = useCallback( + ( + onConfirm: () => Promise | void, + action: string, + itemName: string = "该项" + ) => { + return modal.confirm({ + title: `${action}确认`, + content: `确定要${action}${itemName}吗?`, + okText: action, + cancelText: "取消", + onOk: async () => { + try { + await onConfirm(); + message.success(`${action}成功`); + } catch (error) { + message.error(`${action}失败`); + throw error; + } + }, + }); + }, + [modal, message] + ); + + return { + modal, + message, + showConfirm, + showDeleteConfirm, + showEditConfirm, + showStatusConfirm, + }; +}; diff --git a/src/hooks/antd/useRequest.ts b/src/hooks/antd/useRequest.ts new file mode 100644 index 0000000..d44e18c --- /dev/null +++ b/src/hooks/antd/useRequest.ts @@ -0,0 +1,51 @@ +// hooks/useRequest.ts +import { useState, useCallback } from "react"; +import { message } from "antd"; + +export interface UseRequestOptions { + onSuccess?: (data: T) => void; + onError?: (error: any) => void; + showErrorMessage?: boolean; +} + +export function useRequest( + requestFn: (params: P) => Promise, + options: UseRequestOptions = {} +) { + const [loading, setLoading] = useState(false); + const [data, setData] = useState(null); + const [error, setError] = useState(null); + + const { onSuccess, onError, showErrorMessage = true } = options; + + const run = useCallback( + async (params: P) => { + setLoading(true); + setError(null); + + try { + const result = await requestFn(params); + setData(result); + onSuccess?.(result); + return result; + } catch (err) { + setError(err); + onError?.(err); + if (showErrorMessage) { + message.error("请求失败"); + } + throw err; + } finally { + setLoading(false); + } + }, + [requestFn, onSuccess, onError, showErrorMessage] + ); + + return { + loading, + data, + error, + run, + }; +} diff --git a/src/locales/zh-CN/pages.ts b/src/locales/zh-CN/pages.ts index 22ac97a..b08b246 100644 --- a/src/locales/zh-CN/pages.ts +++ b/src/locales/zh-CN/pages.ts @@ -1,71 +1,71 @@ export default { - 'pages.layouts.userLayout.title': - 'Ant Design 是西湖区最具影响力的 Web 设计规范', - 'pages.login.accountLogin.tab': '账户密码登录', - 'pages.login.accountLogin.errorMessage': - '错误的用户名和密码(admin/ant.design)', - 'pages.login.failure': '登录失败,请重试!', - 'pages.login.success': '登录成功!', - 'pages.login.username.placeholder': '用户名: admin or user', - 'pages.login.username.required': '用户名是必填项!', - 'pages.login.password.placeholder': '密码: ant.design', - 'pages.login.password.required': '密码是必填项!', - 'pages.login.phoneLogin.tab': '手机号登录', - 'pages.login.phoneLogin.errorMessage': '验证码错误', - 'pages.login.phoneNumber.placeholder': '请输入手机号!', - 'pages.login.phoneNumber.required': '手机号是必填项!', - 'pages.login.phoneNumber.invalid': '不合法的手机号!', - 'pages.login.captcha.placeholder': '请输入验证码!', - 'pages.login.captcha.required': '验证码是必填项!', - 'pages.login.phoneLogin.getVerificationCode': '获取验证码', - 'pages.getCaptchaSecondText': '秒后重新获取', - 'pages.login.rememberMe': '自动登录', - 'pages.login.forgotPassword': '忘记密码 ?', - 'pages.login.submit': '登录', - 'pages.login.loginWith': '其他登录方式 :', - 'pages.login.registerAccount': '注册账户', - 'pages.welcome.link': '欢迎使用', - 'pages.welcome.alertMessage': '更快更强的重型组件,已经发布。', - 'pages.404.subTitle': '抱歉,您访问的页面不存在。', - 'pages.404.buttonText': '返回首页', - 'pages.admin.subPage.title': ' 这个页面只有 admin 权限才能查看', - 'pages.admin.subPage.alertMessage': - 'umi ui 现已发布,欢迎使用 npm run ui 启动体验。', - 'pages.searchTable.createForm.newRule': '新建规则', - 'pages.searchTable.updateForm.ruleConfig': '规则配置', - 'pages.searchTable.updateForm.basicConfig': '基本信息', - 'pages.searchTable.updateForm.ruleName.nameLabel': '规则名称', - 'pages.searchTable.updateForm.ruleName.nameRules': '请输入规则名称!', - 'pages.searchTable.updateForm.ruleDesc.descLabel': '规则描述', - 'pages.searchTable.updateForm.ruleDesc.descPlaceholder': '请输入至少五个字符', - 'pages.searchTable.updateForm.ruleDesc.descRules': - '请输入至少五个字符的规则描述!', - 'pages.searchTable.updateForm.ruleProps.title': '配置规则属性', - 'pages.searchTable.updateForm.object': '监控对象', - 'pages.searchTable.updateForm.ruleProps.templateLabel': '规则模板', - 'pages.searchTable.updateForm.ruleProps.typeLabel': '规则类型', - 'pages.searchTable.updateForm.schedulingPeriod.title': '设定调度周期', - 'pages.searchTable.updateForm.schedulingPeriod.timeLabel': '开始时间', - 'pages.searchTable.updateForm.schedulingPeriod.timeRules': '请选择开始时间!', - 'pages.searchTable.titleDesc': '描述', - 'pages.searchTable.ruleName': '规则名称为必填项', - 'pages.searchTable.titleCallNo': '服务调用次数', - 'pages.searchTable.titleStatus': '状态', - 'pages.searchTable.nameStatus.default': '关闭', - 'pages.searchTable.nameStatus.running': '运行中', - 'pages.searchTable.nameStatus.online': '已上线', - 'pages.searchTable.nameStatus.abnormal': '异常', - 'pages.searchTable.titleUpdatedAt': '上次调度时间', - 'pages.searchTable.exception': '请输入异常原因!', - 'pages.searchTable.titleOption': '操作', - 'pages.searchTable.config': '配置', - 'pages.searchTable.subscribeAlert': '订阅警报', - 'pages.searchTable.title': '查询表格', - 'pages.searchTable.new': '新建', - 'pages.searchTable.chosen': '已选择', - 'pages.searchTable.item': '项', - 'pages.searchTable.totalServiceCalls': '服务调用次数总计', - 'pages.searchTable.tenThousand': '万', - 'pages.searchTable.batchDeletion': '批量删除', - 'pages.searchTable.batchApproval': '批量审批', + "pages.layouts.userLayout.title": + "Ant Design 是西湖区最具影响力的 Web 设计规范", + "pages.login.accountLogin.tab": "账户密码登录", + "pages.login.accountLogin.errorMessage": + "错误的用户名和密码(admin/ant.design)", + "pages.login.failure": "登录失败,请重试!", + "pages.login.success": "登录成功!", + "pages.login.username.placeholder": "用户名: admin or user", + "pages.login.username.required": "用户名是必填项!", + "pages.login.password.placeholder": "密码: ant.design", + "pages.login.password.required": "密码是必填项!", + "pages.login.phoneLogin.tab": "手机号登录", + "pages.login.phoneLogin.errorMessage": "验证码错误", + "pages.login.phoneNumber.placeholder": "请输入手机号!", + "pages.login.phoneNumber.required": "手机号是必填项!", + "pages.login.phoneNumber.invalid": "不合法的手机号!", + "pages.login.captcha.placeholder": "请输入验证码!", + "pages.login.captcha.required": "验证码是必填项!", + "pages.login.phoneLogin.getVerificationCode": "获取验证码", + "pages.getCaptchaSecondText": "秒后重新获取", + "pages.login.rememberMe": "自动登录", + "pages.login.forgotPassword": "忘记密码 ?", + "pages.login.submit": "登录", + "pages.login.loginWith": "其他登录方式 :", + "pages.login.registerAccount": "注册账户", + "pages.welcome.link": "欢迎使用", + "pages.welcome.alertMessage": "更快更强的重型组件,已经发布。", + "pages.404.subTitle": "抱歉,您访问的页面不存在。", + "pages.404.buttonText": "返回首页", + "pages.admin.subPage.title": " 这个页面只有 admin 权限才能查看", + "pages.admin.subPage.alertMessage": + "umi ui 现已发布,欢迎使用 npm run ui 启动体验。", + "pages.searchTable.createForm.newRule": "新建规则", + "pages.searchTable.updateForm.ruleConfig": "规则配置", + "pages.searchTable.updateForm.basicConfig": "基本信息", + "pages.searchTable.updateForm.ruleName.nameLabel": "规则名称", + "pages.searchTable.updateForm.ruleName.nameRules": "请输入规则名称!", + "pages.searchTable.updateForm.ruleDesc.descLabel": "规则描述", + "pages.searchTable.updateForm.ruleDesc.descPlaceholder": "请输入至少五个字符", + "pages.searchTable.updateForm.ruleDesc.descRules": + "请输入至少五个字符的规则描述!", + "pages.searchTable.updateForm.ruleProps.title": "配置规则属性", + "pages.searchTable.updateForm.object": "监控对象", + "pages.searchTable.updateForm.ruleProps.templateLabel": "规则模板", + "pages.searchTable.updateForm.ruleProps.typeLabel": "规则类型", + "pages.searchTable.updateForm.schedulingPeriod.title": "设定调度周期", + "pages.searchTable.updateForm.schedulingPeriod.timeLabel": "开始时间", + "pages.searchTable.updateForm.schedulingPeriod.timeRules": "请选择开始时间!", + "pages.searchTable.titleDesc": "描述", + "pages.searchTable.ruleName": "规则名称为必填项", + "pages.searchTable.titleCallNo": "服务调用次数", + "pages.searchTable.titleStatus": "状态", + "pages.searchTable.nameStatus.default": "关闭", + "pages.searchTable.nameStatus.running": "运行中", + "pages.searchTable.nameStatus.online": "已上线", + "pages.searchTable.nameStatus.abnormal": "异常", + "pages.searchTable.titleUpdatedAt": "上次调度时间", + "pages.searchTable.exception": "请输入异常原因!", + "pages.searchTable.titleOption": "操作", + "pages.searchTable.config": "配置", + "pages.searchTable.subscribeAlert": "订阅警报", + "pages.searchTable.title": "查询表格", + "pages.searchTable.new": "新增", + "pages.searchTable.chosen": "已选择", + "pages.searchTable.item": "项", + "pages.searchTable.totalServiceCalls": "服务调用次数总计", + "pages.searchTable.tenThousand": "万", + "pages.searchTable.batchDeletion": "批量删除", + "pages.searchTable.batchApproval": "批量审批", }; diff --git a/src/locales/zh-TW/pages.ts b/src/locales/zh-TW/pages.ts index 17aa25f..3a5a1cf 100644 --- a/src/locales/zh-TW/pages.ts +++ b/src/locales/zh-TW/pages.ts @@ -1,71 +1,71 @@ export default { - 'pages.layouts.userLayout.title': - 'Ant Design 是西湖區最具影響力的 Web 設計規範', - 'pages.login.accountLogin.tab': '賬戶密碼登錄', - 'pages.login.accountLogin.errorMessage': - '錯誤的用戶名和密碼(admin/ant.design)', - 'pages.login.failure': '登錄失敗,請重試!', - 'pages.login.success': '登錄成功!', - 'pages.login.username.placeholder': '用戶名: admin or user', - 'pages.login.username.required': '用戶名是必填項!', - 'pages.login.password.placeholder': '密碼: ant.design', - 'pages.login.password.required': '密碼是必填項!', - 'pages.login.phoneLogin.tab': '手機號登錄', - 'pages.login.phoneLogin.errorMessage': '驗證碼錯誤', - 'pages.login.phoneNumber.placeholder': '請輸入手機號!', - 'pages.login.phoneNumber.required': '手機號是必填項!', - 'pages.login.phoneNumber.invalid': '不合法的手機號!', - 'pages.login.captcha.placeholder': '請輸入驗證碼!', - 'pages.login.captcha.required': '驗證碼是必填項!', - 'pages.login.phoneLogin.getVerificationCode': '獲取驗證碼', - 'pages.getCaptchaSecondText': '秒後重新獲取', - 'pages.login.rememberMe': '自動登錄', - 'pages.login.forgotPassword': '忘記密碼 ?', - 'pages.login.submit': '登錄', - 'pages.login.loginWith': '其他登錄方式 :', - 'pages.login.registerAccount': '註冊賬戶', - 'pages.welcome.link': '歡迎使用', - 'pages.welcome.alertMessage': '更快更強的重型組件,已經發布。', - 'pages.404.subTitle': '抱歉,您訪問的頁面不存在。', - 'pages.404.buttonText': '返回首頁', - 'pages.admin.subPage.title': '這個頁面只有 admin 權限才能查看', - 'pages.admin.subPage.alertMessage': - 'umi ui 現已發佈,歡迎使用 npm run ui 啓動體驗。', - 'pages.searchTable.createForm.newRule': '新建規則', - 'pages.searchTable.updateForm.ruleConfig': '規則配置', - 'pages.searchTable.updateForm.basicConfig': '基本信息', - 'pages.searchTable.updateForm.ruleName.nameLabel': '規則名稱', - 'pages.searchTable.updateForm.ruleName.nameRules': '請輸入規則名稱!', - 'pages.searchTable.updateForm.ruleDesc.descLabel': '規則描述', - 'pages.searchTable.updateForm.ruleDesc.descPlaceholder': '請輸入至少五個字符', - 'pages.searchTable.updateForm.ruleDesc.descRules': - '請輸入至少五個字符的規則描述!', - 'pages.searchTable.updateForm.ruleProps.title': '配置規則屬性', - 'pages.searchTable.updateForm.object': '監控對象', - 'pages.searchTable.updateForm.ruleProps.templateLabel': '規則模板', - 'pages.searchTable.updateForm.ruleProps.typeLabel': '規則類型', - 'pages.searchTable.updateForm.schedulingPeriod.title': '設定調度週期', - 'pages.searchTable.updateForm.schedulingPeriod.timeLabel': '開始時間', - 'pages.searchTable.updateForm.schedulingPeriod.timeRules': '請選擇開始時間!', - 'pages.searchTable.titleDesc': '描述', - 'pages.searchTable.ruleName': '規則名稱爲必填項', - 'pages.searchTable.titleCallNo': '服務調用次數', - 'pages.searchTable.titleStatus': '狀態', - 'pages.searchTable.nameStatus.default': '關閉', - 'pages.searchTable.nameStatus.running': '運行中', - 'pages.searchTable.nameStatus.online': '已上線', - 'pages.searchTable.nameStatus.abnormal': '異常', - 'pages.searchTable.titleUpdatedAt': '上次調度時間', - 'pages.searchTable.exception': '請輸入異常原因!', - 'pages.searchTable.titleOption': '操作', - 'pages.searchTable.config': '配置', - 'pages.searchTable.subscribeAlert': '訂閱警報', - 'pages.searchTable.title': '查詢表格', - 'pages.searchTable.new': '新建', - 'pages.searchTable.chosen': '已選擇', - 'pages.searchTable.item': '項', - 'pages.searchTable.totalServiceCalls': '服務調用次數總計', - 'pages.searchTable.tenThousand': '萬', - 'pages.searchTable.batchDeletion': '批量刪除', - 'pages.searchTable.batchApproval': '批量審批', + "pages.layouts.userLayout.title": + "Ant Design 是西湖區最具影響力的 Web 設計規範", + "pages.login.accountLogin.tab": "賬戶密碼登錄", + "pages.login.accountLogin.errorMessage": + "錯誤的用戶名和密碼(admin/ant.design)", + "pages.login.failure": "登錄失敗,請重試!", + "pages.login.success": "登錄成功!", + "pages.login.username.placeholder": "用戶名: admin or user", + "pages.login.username.required": "用戶名是必填項!", + "pages.login.password.placeholder": "密碼: ant.design", + "pages.login.password.required": "密碼是必填項!", + "pages.login.phoneLogin.tab": "手機號登錄", + "pages.login.phoneLogin.errorMessage": "驗證碼錯誤", + "pages.login.phoneNumber.placeholder": "請輸入手機號!", + "pages.login.phoneNumber.required": "手機號是必填項!", + "pages.login.phoneNumber.invalid": "不合法的手機號!", + "pages.login.captcha.placeholder": "請輸入驗證碼!", + "pages.login.captcha.required": "驗證碼是必填項!", + "pages.login.phoneLogin.getVerificationCode": "獲取驗證碼", + "pages.getCaptchaSecondText": "秒後重新獲取", + "pages.login.rememberMe": "自動登錄", + "pages.login.forgotPassword": "忘記密碼 ?", + "pages.login.submit": "登錄", + "pages.login.loginWith": "其他登錄方式 :", + "pages.login.registerAccount": "註冊賬戶", + "pages.welcome.link": "歡迎使用", + "pages.welcome.alertMessage": "更快更強的重型組件,已經發布。", + "pages.404.subTitle": "抱歉,您訪問的頁面不存在。", + "pages.404.buttonText": "返回首頁", + "pages.admin.subPage.title": "這個頁面只有 admin 權限才能查看", + "pages.admin.subPage.alertMessage": + "umi ui 現已發佈,歡迎使用 npm run ui 啓動體驗。", + "pages.searchTable.createForm.newRule": "新建規則", + "pages.searchTable.updateForm.ruleConfig": "規則配置", + "pages.searchTable.updateForm.basicConfig": "基本信息", + "pages.searchTable.updateForm.ruleName.nameLabel": "規則名稱", + "pages.searchTable.updateForm.ruleName.nameRules": "請輸入規則名稱!", + "pages.searchTable.updateForm.ruleDesc.descLabel": "規則描述", + "pages.searchTable.updateForm.ruleDesc.descPlaceholder": "請輸入至少五個字符", + "pages.searchTable.updateForm.ruleDesc.descRules": + "請輸入至少五個字符的規則描述!", + "pages.searchTable.updateForm.ruleProps.title": "配置規則屬性", + "pages.searchTable.updateForm.object": "監控對象", + "pages.searchTable.updateForm.ruleProps.templateLabel": "規則模板", + "pages.searchTable.updateForm.ruleProps.typeLabel": "規則類型", + "pages.searchTable.updateForm.schedulingPeriod.title": "設定調度週期", + "pages.searchTable.updateForm.schedulingPeriod.timeLabel": "開始時間", + "pages.searchTable.updateForm.schedulingPeriod.timeRules": "請選擇開始時間!", + "pages.searchTable.titleDesc": "描述", + "pages.searchTable.ruleName": "規則名稱爲必填項", + "pages.searchTable.titleCallNo": "服務調用次數", + "pages.searchTable.titleStatus": "狀態", + "pages.searchTable.nameStatus.default": "關閉", + "pages.searchTable.nameStatus.running": "運行中", + "pages.searchTable.nameStatus.online": "已上線", + "pages.searchTable.nameStatus.abnormal": "異常", + "pages.searchTable.titleUpdatedAt": "上次調度時間", + "pages.searchTable.exception": "請輸入異常原因!", + "pages.searchTable.titleOption": "操作", + "pages.searchTable.config": "配置", + "pages.searchTable.subscribeAlert": "訂閱警報", + "pages.searchTable.title": "查詢表格", + "pages.searchTable.new": "新增", + "pages.searchTable.chosen": "已選擇", + "pages.searchTable.item": "項", + "pages.searchTable.totalServiceCalls": "服務調用次數總計", + "pages.searchTable.tenThousand": "萬", + "pages.searchTable.batchDeletion": "批量刪除", + "pages.searchTable.batchApproval": "批量審批", }; diff --git a/src/pages/system/dept/index.tsx b/src/pages/system/dept/index.tsx new file mode 100644 index 0000000..6aa7795 --- /dev/null +++ b/src/pages/system/dept/index.tsx @@ -0,0 +1,5 @@ +const SyStemDept = () => { + return <>SyStemDept; +}; + +export default SyStemDept; diff --git a/src/pages/system/dict/index.tsx b/src/pages/system/dict/index.tsx new file mode 100644 index 0000000..1fa62c3 --- /dev/null +++ b/src/pages/system/dict/index.tsx @@ -0,0 +1,5 @@ +const SyStemDict = () => { + return <>SyStemDict; +}; + +export default SyStemDict; diff --git a/src/pages/system/log/login/index.tsx b/src/pages/system/log/login/index.tsx new file mode 100644 index 0000000..e47f9fb --- /dev/null +++ b/src/pages/system/log/login/index.tsx @@ -0,0 +1,5 @@ +const SyStemLogLogin = () => { + return <>SyStemLogLogin; +}; + +export default SyStemLogLogin; diff --git a/src/pages/system/log/operate/index.tsx b/src/pages/system/log/operate/index.tsx new file mode 100644 index 0000000..45fe9f8 --- /dev/null +++ b/src/pages/system/log/operate/index.tsx @@ -0,0 +1,5 @@ +const SyStemLogOperate = () => { + return <>SyStemLogOperate; +}; + +export default SyStemLogOperate; diff --git a/src/pages/system/menu/index.tsx b/src/pages/system/menu/index.tsx new file mode 100644 index 0000000..d0c7045 --- /dev/null +++ b/src/pages/system/menu/index.tsx @@ -0,0 +1,5 @@ +const SyStemMenu = () => { + return <>SyStemMenu; +}; + +export default SyStemMenu; diff --git a/src/pages/system/post/index.tsx b/src/pages/system/post/index.tsx new file mode 100644 index 0000000..195d9a8 --- /dev/null +++ b/src/pages/system/post/index.tsx @@ -0,0 +1,5 @@ +const SyStemPost = () => { + return <>SyStemPost; +}; + +export default SyStemPost; diff --git a/src/pages/system/role/index.tsx b/src/pages/system/role/index.tsx new file mode 100644 index 0000000..cc9b280 --- /dev/null +++ b/src/pages/system/role/index.tsx @@ -0,0 +1,5 @@ +const SyStemRole = () => { + return <>SyStemRole; +}; + +export default SyStemRole; diff --git a/src/pages/system/tenant/list/config.tsx b/src/pages/system/tenant/list/config.tsx new file mode 100644 index 0000000..03d1192 --- /dev/null +++ b/src/pages/system/tenant/list/config.tsx @@ -0,0 +1,223 @@ +import { type TenantVO, deleteTenant } from "@/services/system/tenant/list"; +import { ProColumns } from "@ant-design/pro-components"; +import { DatePicker, Modal, Popconfirm } from "antd"; +import { FormInstance } from "antd/lib"; +import dayjs from "dayjs"; + +export const baseTenantColumns: ProColumns[] = [ + { + title: "租户编号", + dataIndex: "id", + tip: "租户编号", + width: 100, + hideInSearch: true, // 在搜索表单中隐藏 + }, + { + title: "租户名", + dataIndex: "name", + tip: "租户名", // 提示信息 + }, + { + title: "租户套餐", + dataIndex: "packageId", + valueType: "select", + request: async () => { + return [ + { + label: "默认套餐", + value: 1, + }, + ]; + }, + // valueEnum: { + // all: { text: "全部", status: "Default" }, + // open: { text: "未解决", status: "Error" }, + // closed: { text: "已解决", status: "Success" }, + // }, + }, + { + title: "联系人", + dataIndex: "contactName", + }, + { + title: "联系手机", + dataIndex: "contactMobile", + }, + { + title: "账号额度", + dataIndex: "accountCount", + hideInSearch: true, // 在搜索表单中隐藏 + }, + { + title: "过期时间", + dataIndex: "expireTime", + valueType: "dateTime", + + hideInSearch: true, // 在搜索表单中隐藏 + }, + { title: "绑定域名", dataIndex: "website", width: 100 }, + { + title: "租户状态", + dataIndex: "status", + valueType: "select", + valueEnum: { + all: { text: "全部", status: "Default" }, + open: { text: "未解决", status: "Error" }, + closed: { text: "已解决", status: "Success" }, + }, + }, + { + title: "创建时间", + dataIndex: "createTime", + valueType: "dateRange", + search: { + transform: (value) => { + return [`${value[0]} 00:00:00`, `${value[1]} 00:00:00`]; + }, + }, + render: (_, record: TenantVO) => + dayjs(record.createTime).format("YYYY-MM-DD HH:mm:ss"), + }, +]; + +export const formColumns: any = [ + { + title: "租户名", + dataIndex: "name", + tip: "租户名", // 提示信息 + formItemProps: { + rules: [ + { + required: true, + message: "请输入用户名", + }, + // { + // min: 2, + // max: 20, + // message: "用户名长度为2-20个字符", + // }, + ], + }, + }, + { + title: "租户套餐", + dataIndex: "packageId", + valueType: "select", + formItemProps: { + rules: [ + { + required: true, + message: "请选择租户套餐", + }, + ], + }, + fieldProps: { + placeholder: "请选择套餐类型", + options: [ + { + label: "普通套餐", + value: 111, + }, + ], + }, + }, + { + title: "联系人", + dataIndex: "contactName", + }, + { + title: "联系手机", + dataIndex: "contactMobile", + formItemProps: { + rules: [ + { + required: true, + message: "请输入联系手机", + }, + ], + }, + }, + { + title: "用户名称", + dataIndex: "username", + hideInForm: true, + formItemProps: { + rules: [ + { + required: true, + message: "请输入用户名称", + }, + { + pattern: /^[a-zA-Z0-9]+$/, + message: "用户账号由 0-9、a-z、A-Z 组成", + }, + // 用户账号由 数字、字母组成 + ], + }, + }, + { + title: "用户密码", + dataIndex: "password", + valueType: "password", + hideInForm: true, + fieldProps: { + placeholder: "请输入用户密码", + autoComplete: "new-password", + }, + formItemProps: { + rules: [ + { + required: true, + message: "请输入用户密码", + }, + { + min: 4, + max: 16, + message: "密码长度为4-16个字符", + }, + ], + }, + }, + { + title: "账号额度", + dataIndex: "accountCount", + valueType: "digit", + }, + { + title: "过期时间", + dataIndex: "expireTime", + valueType: "date", + + fieldProps: { + placeholder: "请选择过期时间", + format: "YYYY-MM-DD", + }, + }, + { title: "绑定域名", dataIndex: "website" }, + { + title: "租户状态", + dataIndex: "status", + valueType: "radio", + formItemProps: { + rules: [ + { + required: true, + message: "请选择租户状态", + }, + ], + }, + fieldProps: { + placeholder: "请选择套餐类型", + options: [ + { + label: "启用", + value: 1, + }, + { + label: "禁用", + value: 0, + }, + ], + }, + }, +]; diff --git a/src/pages/system/tenant/list/index.tsx b/src/pages/system/tenant/list/index.tsx index a306334..b82d531 100644 --- a/src/pages/system/tenant/list/index.tsx +++ b/src/pages/system/tenant/list/index.tsx @@ -1,68 +1,49 @@ import EnhancedProTable from "@/components/EnhancedProTable"; import { getTenantPage, - deleteTenant, + createTenant, type TenantPageReqVO, type TenantVO, + deleteTenant, + updateTenant, } from "@/services/system/tenant/list"; +import React, { createContext, useCallback } from "react"; +import ConfigurableDrawerForm, { + ConfigurableDrawerFormRef, +} from "@/components/DrawerForm"; +import { useRef, useState } from "react"; +import { formColumns, baseTenantColumns } from "./config"; import { PlusOutlined } from "@ant-design/icons"; -import { - ProCoreActionType, - ProTable, - TableDropdown, - type ProColumns, -} from "@ant-design/pro-components"; -import { Button, Space } from "antd"; - -import { - createOrderTableConfig, - createCommonActions, - createCommonToolbarActions, -} from "@/utils/antd/tableConfigFactory"; -import { useEnhancedTable } from "@/hooks/antd/useEnhancedTable"; +import { ref } from "process"; +import { ActionType, ProColumns } from "@ant-design/pro-components"; +import { ToolbarAction } from "@/components/EnhancedProTable/types"; +import { Modal, Popconfirm } from "antd"; +import { formStatusType } from "@/constants"; +import dayjs from "dayjs"; +export const waitTimePromise = async (time: number = 90) => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(true); + }, time); + }); +}; const TenantList = () => { - const columns: ProColumns[] = [ - { - title: "租户编号", - dataIndex: "id", - tip: "租户编号", - }, - { - title: "租户名", - dataIndex: "name", - - ellipsis: true, // 超长省略 - tip: "租户名", // 提示信息 - }, - { - title: "状态", - dataIndex: "status", - valueType: "select", - valueEnum: { - all: { text: "全部", status: "Default" }, - open: { text: "未解决", status: "Error" }, - closed: { text: "已解决", status: "Success" }, - }, - }, - { - title: "创建时间", - dataIndex: "created_at", - valueType: "dateTime", - hideInSearch: true, // 在搜索表单中隐藏 - }, - ]; - + const configurableDrawerRef = useRef(null); + const tableRef = useRef(null); + const [type, setType] = useState<"create" | "update">("create"); + const [id, setId] = useState(0); const onFetch = async ( params: TenantPageReqVO & { pageSize?: number; current?: number; } ) => { + await waitTimePromise(); const data = await getTenantPage({ + ...params, pageNo: params.current, pageSize: params.pageSize, }); - console.log(data); return { data: data.list, success: true, @@ -70,39 +51,89 @@ const TenantList = () => { }; }; - const { actionRef, selectedRowKeys, selectedRows, actions } = - useEnhancedTable({ - onEdit: (record) => { - console.log("编辑订单:", record); - }, - onDelete: async (record) => { - await deleteTenant(record.id); - return true; - }, - }); - const tableActions = createCommonActions({ - onView: actions.view, - onEdit: actions.edit, - onDelete: actions.delete, - }); + const handleSubmit = useCallback( + async (values: TenantVO) => { + if (type === "create") { + await createTenant(values); + } else { + await updateTenant({ + ...values, + id, + expireTime: dayjs(values.expireTime).valueOf(), + }); + } + tableRef.current?.reload(); + return true; + }, + [type] + ); - const toolbarActions = createCommonToolbarActions({ - onExport: actions.export, - }); + const handleAdd = () => { + setType("create"); + configurableDrawerRef.current?.open({}); + }; + const handleEdit = (record: TenantVO) => { + setType("update"); + setId(record.id); + + configurableDrawerRef.current?.open(record); + }; + const toolbarActions: ToolbarAction[] = [ + { + key: "add", + label: "新建", + type: "primary", + icon: , + onClick: handleAdd, + }, + ]; + + const actionColumns: ProColumns = { + title: "操作", + dataIndex: "option", + valueType: "option", + fixed: "right", + width: 120, + render: (text: React.ReactNode, record: TenantVO, _: any, action: any) => [ + handleEdit(record)}> + 编辑 + , + { + await deleteTenant(record.id); + action?.reload(); + }} + okText="是" + cancelText="否" + > + 删除 + , + ], + }; + const columns = [...baseTenantColumns, actionColumns]; return ( -
+ <> + ref={tableRef} columns={columns} request={onFetch} - actions={tableActions} toolbarActions={toolbarActions} - headerTitle="订单管理" + headerTitle="租户列表" showIndex={false} - // showSelection + showSelection={false} showActions maxActionCount={3} /> -
+ + + ); }; diff --git a/src/pages/system/user/index.tsx b/src/pages/system/user/index.tsx new file mode 100644 index 0000000..5b0441b --- /dev/null +++ b/src/pages/system/user/index.tsx @@ -0,0 +1,5 @@ +const SyStemUser = () => { + return <>SyStemUser; +}; + +export default SyStemUser; diff --git a/src/requestErrorConfig.ts b/src/requestErrorConfig.ts index 7b7a273..d2342ee 100644 --- a/src/requestErrorConfig.ts +++ b/src/requestErrorConfig.ts @@ -137,6 +137,7 @@ export const errorConfig: RequestConfig = { setToken(refreshTokenRes); console.log(getAccessToken()); config.headers!.Authorization = "Bearer " + getAccessToken(); + console.log(requestList); requestList.forEach((cb: any) => { cb(); }); @@ -154,6 +155,7 @@ export const errorConfig: RequestConfig = { } return; } else { + console.log("刷新令牌失败"); //添加到队列,等待刷新获取到新的令牌 return new Promise((resolve) => { requestList.push(() => { diff --git a/src/services/system/tenant/list.ts b/src/services/system/tenant/list.ts index ae80d44..ed40044 100644 --- a/src/services/system/tenant/list.ts +++ b/src/services/system/tenant/list.ts @@ -10,7 +10,7 @@ export interface TenantVO { packageId: number; username: string; password: string; - expireTime: Date; + expireTime: Date | number; accountCount: number; createTime: Date; } diff --git a/src/utils/antd/commonRules.ts b/src/utils/antd/commonRules.ts new file mode 100644 index 0000000..c537cdf --- /dev/null +++ b/src/utils/antd/commonRules.ts @@ -0,0 +1,43 @@ +// 常用的校验规则配置 +// rules: [ +// { required: true, message: '请输入用户名' }, +// { min: 3, max: 20, message: '用户名长度为3-20个字符' }, +// { pattern: /^[a-zA-Z0-9_]+$/, message: '用户名只能包含字母、数字和下划线' }, +// ], +const commonRules = { + // 必填 + required: { required: true, message: "此项为必填项" }, + + // 邮箱 + email: { type: "email", message: "请输入正确的邮箱格式" }, + + // 手机号 + phone: { pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号格式" }, + + // 身份证 + idCard: { + pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, + message: "请输入正确的身份证号", + }, + + // 密码强度 + strongPassword: { + pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/, + message: "密码必须包含大小写字母、数字,至少8位", + }, + + // 数字范围 + numberRange: (min: number, max: number) => ({ + type: "number", + min, + max, + message: `请输入${min}-${max}之间的数字`, + }), + + // 字符长度 + lengthRange: (min: number, max: number) => ({ + min, + max, + message: `长度为${min}-${max}个字符`, + }), +}; diff --git a/src/utils/antd/tableConfigFactory.tsx b/src/utils/antd/tableConfigFactory.tsx index c2236be..92cce91 100644 --- a/src/utils/antd/tableConfigFactory.tsx +++ b/src/utils/antd/tableConfigFactory.tsx @@ -2,7 +2,8 @@ import React from "react"; import { ProColumns } from "@ant-design/pro-components"; import { Tag } from "antd"; -import { ICONS, IconType } from "@/constants/icons"; +import { history, useIntl } from "@umijs/max"; +import { ICONS, IconType } from "@/constants/antd/icons"; import { TableAction, ToolbarAction, @@ -129,13 +130,18 @@ export const createCommonToolbarActions = (handlers: { onImport?: () => void; }): ToolbarAction[] => { const actions: ToolbarAction[] = []; - if (handlers.onAdd) { actions.push( - createToolbarAction("add", "新建", "add", handlers.onAdd, { - type: "primary", - permission: "add", - }) + createToolbarAction( + "add", + useIntl().formatMessage({ id: "pages.searchTable.new" }), + "add", + handlers.onAdd, + { + type: "primary", + permission: "add", + } + ) ); }