feat(component): 添加组件协作功能和权限控制

master
钟良源 2 weeks ago
parent a9419c92f8
commit 40c54170ec

@ -0,0 +1,28 @@
import axios from 'axios';
// 公共路径
const urlPrefix = '/api/v1/bpms-workbench';
// 添加协作用户
export function addCollaborator(params: {
componentBaseId: string|number,
collaboratorId: string,
permission: string
}) {
return axios.post(`${urlPrefix}/componentCollaborator/submit`, params);
}
// 删除协作用户
export function deleteCollaborator(params: { id: string }) {
return axios.post(`${urlPrefix}/componentCollaborator/delete`, params);
}
// 组件协作 同步gitea协作者数据到本地
export function synchronizeCollaborator(componentBaseId: string | number) {
return axios.get(`${urlPrefix}/componentCollaborator/synchronize`, { params: { componentBaseId } });
}
// 获取该组件下的协作者列表
export function getCollaboratorList(componentBaseId: string | number) {
return axios.get(`${urlPrefix}/componentCollaborator/list`, { params: { componentBaseId } });
}

@ -42,4 +42,9 @@ export function logout() {
export function getUserToken() {
return axios.get<LoginRes>(`${urlPrefix}/sessions/validate`, {});
}
// 获取用户列表
export function getUserList() {
return axios.get(`${urlPrefix}/users/list`);
}

@ -38,7 +38,7 @@ const Option = Select.Option;
// 定义组件模式类型
type ComponentMode = 'create' | 'edit' | 'copy';
const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'create' }) => {
const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'create', permission = 'write' }) => {
const [selectedImage, setSelectedImage] = useState('');
const [description, setDescription] = useState('');
const [classifyList, setClassifyList] = useState([]);
@ -73,6 +73,8 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
const isEditMode = mode === 'edit';
// 判断是否为创建模式
const isCreateMode = mode === 'create';
// 判断是否为只读模式read权限
const isReadOnly = permission === 'read';
const columns: TableColumnProps[] = [
{
@ -112,14 +114,14 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
setSelectedApiData(record);
setShowApiModal(true);
}}
disabled={isCopyMode || (componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus))}
disabled={isReadOnly || isCopyMode || (componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus))}
>
</Button>
<Button
type="text"
status="danger"
disabled={isCopyMode || (componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus))}
disabled={isReadOnly || isCopyMode || (componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus))}
onClick={async () => {
// 显示删除确认框
Modal.confirm({
@ -463,34 +465,40 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
const modalFooter = () => {
return (
<Space size={30}>
<Button size="small" type="outline" style={{ borderRadius: 5 }} onClick={() => setVisible(false)}></Button>
{isCopyMode ? (
<Button size="small" type="outline" style={{ borderRadius: 5 }} onClick={() => setVisible(false)}>
{isReadOnly ? '关闭' : '取消'}
</Button>
{!isReadOnly && (
<>
<Button
size="small"
type="primary"
style={{ borderRadius: 5 }}
onClick={handleCopyDesign}
>
</Button>
<Button
size="small"
type="primary"
style={{ borderRadius: 5 }}
onClick={handleCopyAll}
>
</Button>
{isCopyMode ? (
<>
<Button
size="small"
type="primary"
style={{ borderRadius: 5 }}
onClick={handleCopyDesign}
>
</Button>
<Button
size="small"
type="primary"
style={{ borderRadius: 5 }}
onClick={handleCopyAll}
>
</Button>
</>
) : showSaveBtn ? (
<Button size="small" type="primary" style={{ borderRadius: 5 }} onClick={() => onSubmit()}>
{isEditMode ? '更新' : '保存'}
</Button>
) : (
<Button size="small" type="primary" style={{ borderRadius: 5 }} onClick={() => onSubmit()}>
{isEditMode ? '更新组件信息' : '提交组件信息'}
</Button>
)}
</>
) : showSaveBtn ? (
<Button size="small" type="primary" style={{ borderRadius: 5 }} onClick={() => onSubmit()}>
{isEditMode ? '更新' : '保存'}
</Button>
) : (
<Button size="small" type="primary" style={{ borderRadius: 5 }} onClick={() => onSubmit()}>
{isEditMode ? '更新组件信息' : '提交组件信息'}
</Button>
)}
</Space>
);
@ -506,6 +514,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
headers={{ Authorization: getToken() }}
fileList={file ? [file] : initialImageUrl ? [{ url: initialImageUrl, status: 'done' }] : []}
showUploadList={false}
disabled={isReadOnly}
onChange={(_, currentFile: any) => {
setFile({
...currentFile,
@ -601,7 +610,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
}
}
]}>
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" />
<Input style={{ width: '90%' }} allowClear placeholder="请输入名称" disabled={isReadOnly} />
</FormItem>
</Grid.Col>
<Grid.Col span={14}>
@ -620,7 +629,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
style={{ width: '90%' }}
allowClear
placeholder="请输入代码标识"
disabled={created || isEditMode}
disabled={isReadOnly || created || isEditMode}
onChange={(e) => debouncedValidateProjectId(e)}
/>
</FormItem>
@ -642,6 +651,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
<Select
placeholder="请选择分类"
style={{ width: '90%' }}
disabled={isReadOnly}
>
{classifyList.map((option, index) => (
<Option key={option.id} value={option.label}>
@ -666,7 +676,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
<Select
placeholder="请选择组件语言"
style={{ width: '90%' }}
disabled={created || isEditMode || isCopyMode}
disabled={isReadOnly || created || isEditMode || isCopyMode}
>
{codeLanguageOptions.map((option) => (
<Option key={option.value} value={option.value}>
@ -685,6 +695,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
allowCreate
mode="multiple"
style={{ width: '90%' }}
disabled={isReadOnly}
>
{tagsList.map((option, index) => (
<Option key={option.value} value={option.value}>
@ -709,7 +720,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
<Select
placeholder="请选择组件类型"
style={{ width: '90%' }}
disabled={created || isEditMode}
disabled={isReadOnly || created || isEditMode}
>
{componentTypeOptions.map((option) => (
<Option key={option.value} value={option.value}>
@ -726,6 +737,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
<EditorSection
visible={visible}
initialContent={description}
disabled={isReadOnly}
/>
</div>
</div>
@ -740,7 +752,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
type="secondary"
style={{ borderRadius: 5 }}
loading={codeInitLoading}
disabled={(!componentDesignData || componentDesignData.length === 0) || componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus)}
disabled={isReadOnly || (!componentDesignData || componentDesignData.length === 0) || componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus)}
onClick={() => handleCodeInit()}
>
@ -753,7 +765,7 @@ const AddComponentModal = ({ visible, baseInfo, setVisible, onReFresh, mode = 'c
setSelectedApiData(null); // 确保新增时清空选中的API数据
setShowApiModal(true);
}}
disabled={componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus)}
disabled={isReadOnly || componentInfo && !['DEFAULT', 'DESIGN'].includes(componentInfo.componentStatus)}
>
+
</Button>

@ -10,6 +10,8 @@ import {
interface HandleButtonGroupProps {
row: ComponentItem;
index: number;
permission?: string; // 协作权限admin, write, read
isCollaborator?: boolean; // 是否为协作组件
onHandlePublishComponent: (row: ComponentItem) => void;
onGoToReview: (row: ComponentItem) => void;
onPublishOrRevokeComponent: (action: 'publish' | 'revoke', identifier: string, version: string) => void;
@ -26,6 +28,8 @@ interface HandleButtonGroupProps {
const HandleButtonGroup: React.FC<HandleButtonGroupProps> = ({
row,
index,
permission = 'write',
isCollaborator = false,
onHandlePublishComponent,
onGoToReview,
onPublishOrRevokeComponent,
@ -44,60 +48,72 @@ const HandleButtonGroup: React.FC<HandleButtonGroupProps> = ({
return eligibleStatuses.includes(currentStatus.toLowerCase());
};
// 权限检查函数 - 只在协作组件时才应用权限控制
const canWrite = !isCollaborator || permission === 'write' || permission === 'admin';
const canAdmin = !isCollaborator || permission === 'admin';
const isReadOnly = isCollaborator && permission === 'read';
// 构建更多操作菜单
const renderDropdownMenu = () => {
const items = [];
// 组件复制
if (!isEligible([componentStatusConstant.DEFAULT, componentStatusConstant.DESIGN], row.componentStatus)) {
items.push(
<Menu.Item key="copy">
<Button type="text" onClick={() => onCopyHandler(row)}></Button>
</Menu.Item>
);
}
// 分享协作
// 分享协作 - 我的组件中所有人都可以分享协同组件中只有admin权限可以分享
if (!isEligible([componentStatusConstant.DESIGN, componentStatusConstant.DEFAULT], row.componentStatus)) {
items.push(
<Menu.Item key="share">
<Button type="text" onClick={() => onShareCollaboration(row)}></Button>
</Menu.Item>
);
}
// 导出组件
items.push(
<Menu.Item key="export">
<Button type="text" onClick={() => onExportComponent(row)}></Button>
</Menu.Item>
);
// 取消发布
if (row.publicStatus === publicStatus.PUBLISHED && onCancelPublish) {
items.push(
<Menu.Item key="cancelPublish">
<Button type="text" onClick={() => onCancelPublish(row)}></Button>
</Menu.Item>
);
// 我的组件:显示分享协作
// 协同组件只有admin权限才显示
if (!isCollaborator || canAdmin) {
items.push(
<Menu.Item key="share">
<Button type="text" onClick={() => onShareCollaboration(row)}></Button>
</Menu.Item>
);
}
}
// 下架组件
if (isEligible([componentStatusConstant.DEPLOYED], row.componentStatus)) {
// 以下操作只在"我的组件"tab显示
if (!isCollaborator) {
// 组件复制 - 所有权限都可以复制
if (!isEligible([componentStatusConstant.DEFAULT, componentStatusConstant.DESIGN], row.componentStatus)) {
items.push(
<Menu.Item key="copy">
<Button type="text" onClick={() => onCopyHandler(row)}></Button>
</Menu.Item>
);
}
// 导出组件 - 所有权限都可以导出
items.push(
<Menu.Item key="stop">
<Button type="text" onClick={() => onStopComponentShow(row)}></Button>
<Menu.Item key="export">
<Button type="text" onClick={() => onExportComponent(row)}></Button>
</Menu.Item>
);
}
// 删除组件
if (!isEligible([componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED], row.componentStatus)) {
items.push(
<Menu.Item key="delete">
<Button type="text" onClick={() => onRowDel(row)}></Button>
</Menu.Item>
);
// 取消发布
if (row.publicStatus === publicStatus.PUBLISHED && onCancelPublish) {
items.push(
<Menu.Item key="cancelPublish">
<Button type="text" onClick={() => onCancelPublish(row)}></Button>
</Menu.Item>
);
}
// 下架组件
if (isEligible([componentStatusConstant.DEPLOYED], row.componentStatus)) {
items.push(
<Menu.Item key="stop">
<Button type="text" onClick={() => onStopComponentShow(row)}></Button>
</Menu.Item>
);
}
// 删除组件
if (!isEligible([componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED], row.componentStatus)) {
items.push(
<Menu.Item key="delete">
<Button type="text" onClick={() => onRowDel(row)}></Button>
</Menu.Item>
);
}
}
return <Menu>{items}</Menu>;
@ -105,44 +121,50 @@ const HandleButtonGroup: React.FC<HandleButtonGroupProps> = ({
return (
<>
{/* 发布组件*/}
{row.publicStatus !== publicStatus.REVIEW && isEligible([componentStatusConstant.CODING, componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED], row.componentStatus) && (
<Button
type="text"
onClick={() => onHandlePublishComponent(row)}
>
{row.publicStatus === publicStatus.PUBLISHED ? '更新版本' : '发布组件'}
</Button>
)}
{(row.publicStatus === publicStatus.REVIEW || row.publicStatus === publicStatus.REJECTED) && (
<Button
type="text"
onClick={() => onGoToReview(row)}
>
</Button>
)}
{/* 公开组件/取消公开 */}
{row.publishStatus !== publishStatusConstant.PUBLISHED ? (
<Button
type="text"
onClick={() => onPublishOrRevokeComponent('publish', row.identifier, row.version)}
>
</Button>
) : (
<Button
type="text"
onClick={() => onPublishOrRevokeComponent('revoke', row.identifier, row.version)}
>
</Button>
{/* 协同组件tab下不显示发布相关操作 */}
{!isCollaborator && (
<>
{/* 发布组件 */}
{row.publicStatus !== publicStatus.REVIEW && isEligible([componentStatusConstant.CODING, componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED], row.componentStatus) && (
<Button
type="text"
onClick={() => onHandlePublishComponent(row)}
>
{row.publicStatus === publicStatus.PUBLISHED ? '更新版本' : '发布组件'}
</Button>
)}
{/* 查看审核 */}
{(row.publicStatus === publicStatus.REVIEW || row.publicStatus === publicStatus.REJECTED) && (
<Button
type="text"
onClick={() => onGoToReview(row)}
>
</Button>
)}
{/* 公开组件/取消公开 */}
{row.publishStatus !== publishStatusConstant.PUBLISHED ? (
<Button
type="text"
onClick={() => onPublishOrRevokeComponent('publish', row.identifier, row.version)}
>
</Button>
) : (
<Button
type="text"
onClick={() => onPublishOrRevokeComponent('revoke', row.identifier, row.version)}
>
</Button>
)}
</>
)}
{/* 查看源码 */}
{isEligible(
{/* 查看源码 - admin和write权限可以查看源码 */}
{canWrite && isEligible(
[componentStatusConstant.CODING, componentStatusConstant.DEPLOYED, componentStatusConstant.PUBLISHED],
row.componentStatus
) ? (
@ -154,7 +176,7 @@ const HandleButtonGroup: React.FC<HandleButtonGroupProps> = ({
</Button>
) : null}
{/* 编辑组件 */}
{/* 编辑组件 - 所有权限都可以点击但read权限会是只读模式 */}
<Button
type="text"
onClick={() => onShowEdit(row, index)}

@ -31,6 +31,7 @@ import { getComponentClassify } from '@/api/componentClassify';
import AddComponentModal from '@/pages/componentDevelopment/componentList/addComponentModal';
import PublishComponentModal from '@/pages/componentDevelopment/componentList/publishComponentModal';
import ImportComponentModal from '@/pages/componentDevelopment/componentList/importComponentModal';
import ShareCollaborationModal from '@/pages/componentDevelopment/componentList/shareCollaborationModal';
import HandleButtonGroup from '@/pages/componentDevelopment/componentList/handleButtonGroup';
import CompAudit from '@/pages/componentDevelopment/componentList/compAudit';
import {
@ -93,6 +94,10 @@ const GlobalVarContainer = () => {
const [historyData, setHistoryData] = useState([]);
const [currentReviewComponent, setCurrentReviewComponent] = useState(null);
// 分享协作弹窗状态
const [shareModalVisible, setShareModalVisible] = useState(false);
const [shareComponent, setShareComponent] = useState<ComponentItem | null>(null);
const dispatch = useDispatch();
const skipNextFetchRef = useRef(false); // 用于跳过下一次由分页变化触发的请求
@ -139,6 +144,19 @@ const GlobalVarContainer = () => {
title: '创建人',
dataIndex: 'createUserName'
},
// 协同组件列表显示权限
...(selectedItem === '协同组件' ? [{
title: '协作权限',
dataIndex: 'permission',
render: (_, record) => {
const permissionMap = {
read: '读',
write: '写',
admin: '管理'
};
return <span>{permissionMap[record.permission] || record.permission || '-'}</span>;
}
}] : []),
{
title: '代码语言',
dataIndex: 'codeLanguage'
@ -200,6 +218,8 @@ const GlobalVarContainer = () => {
<HandleButtonGroup
row={record}
index={index}
permission={selectedItem === '协同组件' ? record.permission : undefined}
isCollaborator={selectedItem === '协同组件'}
onHandlePublishComponent={(row) => {
setSelectedPublishComponent(row);
setPublishModalVisible(true);
@ -257,8 +277,8 @@ const GlobalVarContainer = () => {
setMode('copy'); // 设置模式为复制
}}
onShareCollaboration={(row) => {
// TODO: 实现分享协作逻辑
console.log('Share collaboration', row);
setShareComponent(row);
setShareModalVisible(true);
}}
onExportComponent={(row) => {
// 实现导出组件逻辑
@ -845,6 +865,7 @@ const GlobalVarContainer = () => {
}}
onReFresh={fetchComponentData}
mode={mode} // 传递模式
permission={selectedItem === '协同组件' && selectComponent ? selectComponent.permission : 'write'} // 传递权限
/>
{/*发布组件弹窗*/}
@ -870,6 +891,21 @@ const GlobalVarContainer = () => {
loading={importLoading}
/>
{/*分享协作弹窗*/}
<ShareCollaborationModal
visible={shareModalVisible}
componentInfo={shareComponent}
isReadOnly={selectedItem === '协同组件'} // 协同组件tab下为只读模式
currentPermission={selectedItem === '协同组件' && shareComponent ? shareComponent.permission : undefined} // 传递当前用户权限
onCancel={() => {
setShareModalVisible(false);
setShareComponent(null);
}}
onSuccess={() => {
// 协作者变更后可以选择刷新列表或其他操作
}}
/>
{/* 审核历史弹窗 */}
<Modal
title={`审核历史 - ${currentReviewComponent?.name || ''}`}

@ -0,0 +1,355 @@
import React, { useState, useEffect } from 'react';
import { Modal, Select, Button, Message, Table, Space } from '@arco-design/web-react';
import { IconDelete } from '@arco-design/web-react/icon';
import { getUserList } from '@/api/user';
import {
getCollaboratorList,
addCollaborator,
deleteCollaborator
} from '@/api/componentCollaborator';
import { ComponentItem } from '@/api/interface';
interface ShareCollaborationModalProps {
visible: boolean;
componentInfo: ComponentItem | null;
onCancel: () => void;
onSuccess?: () => void;
isReadOnly?: boolean; // 是否为只读模式协同组件tab下
currentPermission?: string; // 当前用户的权限在协同组件tab下使用
}
interface User {
id: string;
username: string;
account?: string;
}
interface Collaborator {
id: string;
collaboratorId: string;
collaboratorName: string;
permission: string;
createTime?: string;
}
const ShareCollaborationModal: React.FC<ShareCollaborationModalProps> = ({
visible,
componentInfo,
onCancel,
onSuccess,
isReadOnly = false,
currentPermission = 'write'
}) => {
const [userList, setUserList] = useState<User[]>([]);
const [collaboratorList, setCollaboratorList] = useState<Collaborator[]>([]);
const [selectedUserId, setSelectedUserId] = useState<string>('');
const [selectedPermission, setSelectedPermission] = useState<string>('write');
const [loading, setLoading] = useState(false);
const [tableLoading, setTableLoading] = useState(false);
// 判断是否可以添加协作者(我的组件 或 协同组件中的admin权限
const canAdd = !isReadOnly || currentPermission === 'admin';
// 判断是否可以编辑/删除(只有我的组件可以)
const canEdit = !isReadOnly;
// 权限选项
const permissionOptions = [
{ label: '管理', value: 'admin' },
{ label: '读', value: 'read' },
{ label: '写', value: 'write' }
];
// 获取用户列表
const fetchUserList = async () => {
try {
const res: any = await getUserList();
if (res.code === 200 && res.data) {
setUserList(res.data.records);
}
} catch (error) {
console.error('获取用户列表失败:', error);
Message.error('获取用户列表失败');
}
};
// 获取协作者列表
const fetchCollaboratorList = async () => {
if (!componentInfo?.id) return;
try {
setTableLoading(true);
const res: any = await getCollaboratorList(componentInfo.id);
if (res.code === 200 && res.data) {
setCollaboratorList(res.data);
}
} catch (error) {
console.error('获取协作者列表失败:', error);
Message.error('获取协作者列表失败');
} finally {
setTableLoading(false);
}
};
// 添加协作者
const handleAddCollaborator = async () => {
if (!selectedUserId) {
Message.warning('请选择协作者');
return;
}
if (!componentInfo?.id) {
Message.error('组件信息不完整');
return;
}
// 检查是否已经添加过该用户
const existingCollaborator = collaboratorList.find(
c => c.collaboratorId === selectedUserId
);
if (existingCollaborator) {
Message.warning('该用户已经是协作者');
return;
}
try {
setLoading(true);
const res: any = await addCollaborator({
componentBaseId: componentInfo.id,
collaboratorId: selectedUserId,
permission: selectedPermission
});
if (res.code === 200) {
Message.success('添加协作者成功');
setSelectedUserId('');
setSelectedPermission('write');
fetchCollaboratorList();
onSuccess?.();
}
else {
Message.error(res.msg || '添加协作者失败');
}
} catch (error) {
console.error('添加协作者失败:', error);
Message.error('添加协作者失败');
} finally {
setLoading(false);
}
};
// 删除协作者
const handleDeleteCollaborator = async (collaboratorId: string) => {
Modal.confirm({
title: '确认移除',
content: '确定要移除该协作者吗?',
okButtonProps: { status: 'danger' },
onOk: async () => {
try {
const res: any = await deleteCollaborator({ id: collaboratorId });
if (res.code === 200) {
Message.success('移除协作者成功');
fetchCollaboratorList();
onSuccess?.();
}
else {
Message.error(res.msg || '移除协作者失败');
}
} catch (error) {
console.error('移除协作者失败:', error);
Message.error('移除协作者失败');
}
}
});
};
// 更新协作者权限
const handleUpdatePermission = async (collaborator: Collaborator, newPermission: string) => {
if (!componentInfo?.id) {
Message.error('组件信息不完整');
return;
}
try {
const res: any = await addCollaborator({
componentBaseId: componentInfo.id,
collaboratorId: collaborator.collaboratorId,
permission: newPermission
});
if (res.code === 200) {
Message.success('权限更新成功');
fetchCollaboratorList();
onSuccess?.();
} else {
Message.error(res.msg || '权限更新失败');
}
} catch (error) {
console.error('权限更新失败:', error);
Message.error('权限更新失败');
}
};
// 表格列定义
const columns = [
{
title: '用户账号',
dataIndex: 'collaboratorAccount',
width: 200
},
{
title: '操作权限',
dataIndex: 'permission',
width: 150,
render: (permission: string, record: Collaborator) => {
const permissionMap = {
read: '读',
write: '写',
admin: '管理'
};
// 不可编辑时只显示文本
if (!canEdit) {
return <span>{permissionMap[permission] || permission}</span>;
}
// 可编辑时显示下拉框
return (
<Select
placeholder="操作权限"
value={permission}
onChange={(newPermission) => handleUpdatePermission(record, newPermission)}
style={{ width: 120 }}
>
{permissionOptions.map(option => (
<Select.Option key={option.value} value={option.value}>
{option.label}
</Select.Option>
))}
</Select>
);
}
},
{
title: '操作',
dataIndex: 'operations',
width: 100,
render: (_: any, record: Collaborator) => {
// 不可编辑时不显示删除按钮
if (!canEdit) {
return null;
}
return (
<Button
type="text"
status="danger"
icon={<IconDelete />}
onClick={() => handleDeleteCollaborator(record.id)}
>
</Button>
);
}
}
];
// 当弹窗打开时,获取数据
useEffect(() => {
if (visible) {
fetchUserList();
fetchCollaboratorList();
}
else {
// 关闭时重置状态
setSelectedUserId('');
setSelectedPermission('write');
}
}, [visible, componentInfo?.id]);
return (
<Modal
title="选择协作者"
visible={visible}
onCancel={onCancel}
footer={null}
style={{ width: 700 }}
>
<div style={{ marginBottom: 20 }}>
<div style={{
marginBottom: 16,
padding: '12px 16px',
background: '#f7f8fa',
borderRadius: 4
}}>
<div style={{ fontWeight: 500, marginBottom: 4 }}>
({collaboratorList.length})
</div>
</div>
{/* 添加协作者表单 - 我的组件或协同组件admin权限可以添加 */}
{canAdd && (
<Space style={{ width: '100%', marginBottom: 16 }}>
<Select
placeholder="请选择协作者"
value={selectedUserId}
onChange={setSelectedUserId}
style={{ width: 300 }}
showSearch
filterOption={(inputValue, option) => {
const children = option.props?.children;
if (!children || typeof children !== 'string') return false;
return children.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0;
}}
>
{userList.map(user => (
<Select.Option key={user.id} value={user.id}>
{user.account || user.username}
</Select.Option>
))}
</Select>
<Select
placeholder="操作权限"
value={selectedPermission}
onChange={setSelectedPermission}
style={{ width: 150 }}
>
{permissionOptions.map(option => (
<Select.Option key={option.value} value={option.value}>
{option.label}
</Select.Option>
))}
</Select>
<Button
type="primary"
onClick={handleAddCollaborator}
loading={loading}
>
</Button>
</Space>
)}
{/* 协作者列表 */}
<Table
columns={columns}
data={collaboratorList}
loading={tableLoading}
pagination={false}
border={{
wrapper: true,
cell: true
}}
noDataElement={
<div style={{ padding: '40px 0', textAlign: 'center', color: '#999' }}>
</div>
}
/>
</div>
</Modal>
);
};
export default ShareCollaborationModal;
Loading…
Cancel
Save