import { StepsForm } from '@ant-design/pro-form'; import type { ProFormInstance } from '@ant-design/pro-form'; import { Drawer, Space } from 'antd'; import { Children, cloneElement, isValidElement, memo, useEffect, useRef, useState } from 'react'; import { FormattedMessage, useDispatch, useIntl } from 'umi'; import { useBindFeature } from '../BindFeature/hooks'; import { useBindData } from '../BindData/hooks'; import { useBindRoleOrPolicy } from '../BindRole/hooks'; import _ from 'lodash'; import FeatureStep from './FeatureStep'; import FlagStep from './FlagStep'; import PolicyStep from './PolicyStep'; import RoleStep from './RoleStep'; interface CopyPermissionPrpos { /** * @description feature 绑定的类型,目前支持如下两种。 * @type 'feature' | 'option' | 'policy' | 'user' */ type: 'feature' | 'option' | 'policy' | 'user' | 'role'; // 选择类型 /** * @description 绑定的类型的id,如type选了user,就要传入userId。 */ id?: number; // 默认参数 /** * @description 标题 */ title?: string; /** * @description 自定义标题 */ titleRender?: () => any; /** * @description 自定义底部说明整体内容 */ footerRender?: () => any; /** * @description 自定义按钮 */ linkRender?: () => any; /** * @description 名称 */ name?: string; /** * @description 需要复制的权限 */ copyList?: ('feature' | 'flag' | 'policy' | 'role')[]; /** * @description 是否有有效期。 */ isHaveDate?: boolean; /** * @description 可以自定义触发内容,默认是角色 */ children?: React.ReactChildren | React.ReactElement; /** * @description 结束需要做的事 */ onFinish?: (values, ref: ProFormInstance, setOpen, cb: () => void) => void; /** * @description 点击复制按钮以后的回调函数 */ onClick?: () => void; } const CopyPermission = ({ children, onClick, id, type = 'user', isHaveDate = false, title = '', titleRender, footerRender, linkRender, name = '', copyList = ['feature', 'flag', 'policy', 'role'], onFinish, }: CopyPermissionPrpos) => { const { formatMessage } = useIntl(); const dispatch = useDispatch(); const [open, setOpen] = useState(false); const baseFormRef = useRef(); const featureFormRef = useRef(); const dataFormRef = useRef(); const roleFormRef = useRef(); const policyFormRef = useRef(); const { featureTreeData, initFetch, updateFn: featureUpdateFn, loading, title: featureTitle, list, } = useBindFeature({ name: 'features', id, type, isHaveDate, form: featureFormRef, }); const { initFetch: dataInitFetch, updateFn: dataUpdateFn, loading: dataLoading, // activeKey: dataActiveKey, // setActiveKey: dataSetActiveKey, flagList: dataFlagList, getSelectOptions: dataGetSelectOptions, selectMap: dataSelectMap, title: dataTitle, appId, } = useBindData({ name: 'flags', type, id, isHaveDate, form: dataFormRef }); const { allData: roleAllData, loading: roleLoading, initFetch: roleInitFetch, updateFn: roleUpdateFn, title: roleTitle, list: roleList, } = useBindRoleOrPolicy({ name: 'roles', comType: 'role', type, id, form: roleFormRef, isHaveDate, }); const { allData: policyAllData, loading: policyLoading, initFetch: policyInitFetch, updateFn: policyUpdateFn, title: policyTitle, list: policyList, } = useBindRoleOrPolicy({ name: 'policies', comType: 'policy', type, id, form: policyFormRef, isHaveDate, }); const [values, setValues] = useState({}); // 使用 React.cloneElement 来给 children 添加属性 const childrenWithProps = Children.map(children, (child) => { // 检查元素类型以防止添加属性到非元素节点 if (isValidElement(child)) { // @ts-ignore return cloneElement(child, { formRef: baseFormRef }); // 添加特定的属性 } return child; }); useEffect(() => { if (open) { baseFormRef?.current?.setFieldsValue(values); } }, [open, values, baseFormRef, copyList]); useEffect(() => { if (open && isHaveDate) { dispatch({ type: 'public/fetchAppDetail', payload: appId, }); } }, [open, appId, isHaveDate, dispatch]); const items = [ { title: `${title}${formatMessage({ id: 'component.copy.steps.title' })}`, }, ]; if (copyList?.includes('feature')) { items.push({ title: featureTitle }); } if (copyList?.includes('flag')) { items.push({ title: dataTitle }); } if (copyList?.includes('role')) { items.push({ title: roleTitle }); } if (copyList?.includes('policy')) { items.push({ title: policyTitle }); } return ( <> { return ( setOpen(false)} footer={ footerRender ? ( footerRender?.() ) : ( <>
) } extra={{submitter}} > {dom}
); }} onFinish={async (val) => { const { features, flags, policies, roles, ...base } = val; let options: number[] = []; _.keys(flags).forEach((key) => { options = [ ...options, ...flags[key]?.data?.map((item: any) => ({ ...item, flagId: parseInt(key?.replace('data', ''), 10), })), ]; }); await onFinish?.( { base, features: features?.data, options, policies: policies?.data, roles: roles?.data, }, baseFormRef, setOpen, async (createId) => { await [ copyList?.includes('feature') && featureUpdateFn(features?.data, [], (item: number, map: {}) => ({ featureId: item, appId, [`${type}Id`]: createId, expiredAt: (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) || undefined, })), copyList?.includes('flag') && dataUpdateFn(flags, {}, (item, map) => ({ appId, flagId: map?.[item]?.flagId, optionId: item, [`${type}Id`]: createId, expiredAt: (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) || undefined, })), copyList?.includes('role') && roleUpdateFn(roles?.data, [], (item: number, map: {}) => ({ [`roleId`]: item, appId, [`${type}Id`]: createId, expiredAt: (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) || undefined, })), copyList?.includes('policy') && policyUpdateFn(policies?.data, [], (item: number, map: {}) => ({ [`policyId`]: item, appId, [`${type}Id`]: createId, expiredAt: (isHaveDate ? Math.round(map?.[item]?.expiredAt / 1000) : undefined) || undefined, })), ]; }, ); setValues({}); return true; }} > setValues(val)} onFinish={async () => { return true; }} > {childrenWithProps} {copyList?.includes('feature') ? ( { return true; }} > ) : null} {copyList?.includes('flag') ? ( { return true; }} > ) : null} {copyList?.includes('role') ? ( { return true; }} > ) : null} {copyList?.includes('policy') ? ( { return true; }} > ) : null}
{ onClick?.(); setOpen(true); }} > {linkRender ? ( linkRender?.() ) : ( )} ); }; export default memo(CopyPermission);