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);