|
|
@ -1,16 +1,17 @@
|
|
|
|
import { openReconfirmModalP } from '@/components/Modal';
|
|
|
|
import { openReconfirmModalP } from '@/components/Modal';
|
|
|
|
import type { MenuProps } from 'antd';
|
|
|
|
import type { MenuProps } from 'antd';
|
|
|
|
import { useCallback } from 'react';
|
|
|
|
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
formatFullTime,
|
|
|
|
formatFullTime,
|
|
|
|
humanizeMsDuration,
|
|
|
|
humanizeMsDuration,
|
|
|
|
model,
|
|
|
|
model,
|
|
|
|
|
|
|
|
PERMISSION,
|
|
|
|
showSuccessToasts,
|
|
|
|
showSuccessToasts,
|
|
|
|
t,
|
|
|
|
t,
|
|
|
|
useAsyncRequest,
|
|
|
|
useAsyncRequest,
|
|
|
|
|
|
|
|
useEvent,
|
|
|
|
useGroupInfo,
|
|
|
|
useGroupInfo,
|
|
|
|
useGroupMemberInfos,
|
|
|
|
useGroupMemberInfos,
|
|
|
|
useMemoizedFn,
|
|
|
|
useHasGroupPermission,
|
|
|
|
UserBaseInfo,
|
|
|
|
UserBaseInfo,
|
|
|
|
useSearch,
|
|
|
|
useSearch,
|
|
|
|
} from 'tailchat-shared';
|
|
|
|
} from 'tailchat-shared';
|
|
|
@ -23,8 +24,13 @@ import { useFriendNicknameMap } from 'tailchat-shared/redux/hooks/useFriendNickn
|
|
|
|
export function useGroupMemberAction(groupId: string) {
|
|
|
|
export function useGroupMemberAction(groupId: string) {
|
|
|
|
const groupInfo = useGroupInfo(groupId);
|
|
|
|
const groupInfo = useGroupInfo(groupId);
|
|
|
|
const members = groupInfo?.members ?? [];
|
|
|
|
const members = groupInfo?.members ?? [];
|
|
|
|
|
|
|
|
const roles = groupInfo?.roles ?? [];
|
|
|
|
const userInfos = useGroupMemberInfos(groupId);
|
|
|
|
const userInfos = useGroupMemberInfos(groupId);
|
|
|
|
const friendNicknameMap = useFriendNicknameMap();
|
|
|
|
const friendNicknameMap = useFriendNicknameMap();
|
|
|
|
|
|
|
|
const [allowManageUser, allowManageRoles] = useHasGroupPermission(groupId, [
|
|
|
|
|
|
|
|
PERMISSION.core.manageUser,
|
|
|
|
|
|
|
|
PERMISSION.core.manageRoles,
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
const { handleMuteMember, handleUnmuteMember } = useMemberMuteAction(
|
|
|
|
const { handleMuteMember, handleUnmuteMember } = useMemberMuteAction(
|
|
|
|
groupId,
|
|
|
|
groupId,
|
|
|
@ -64,26 +70,31 @@ export function useGroupMemberAction(groupId: string) {
|
|
|
|
[groupId]
|
|
|
|
[groupId]
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const getMemberHasMute = useCallback(
|
|
|
|
const getMemberHasMute = useEvent((userId: string): boolean => {
|
|
|
|
(userId: string): boolean => {
|
|
|
|
const member = members.find((m) => m.userId === userId);
|
|
|
|
const member = members.find((m) => m.userId === userId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!member || !member.muteUntil) {
|
|
|
|
if (!member || !member.muteUntil) {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const muteUntil = member.muteUntil;
|
|
|
|
const muteUntil = member.muteUntil;
|
|
|
|
|
|
|
|
|
|
|
|
return new Date(muteUntil).valueOf() > new Date().valueOf();
|
|
|
|
return new Date(muteUntil).valueOf() > new Date().valueOf();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
[members]
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const generateActionMenu = useMemoizedFn(
|
|
|
|
const getMemberRoles = useEvent((userId: string): string[] => {
|
|
|
|
(member: UserBaseInfo): MenuProps => {
|
|
|
|
return members.find((m) => m.userId === userId)?.roles ?? [];
|
|
|
|
const hasMute = getMemberHasMute(member._id);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const muteItems: MenuProps['items'] = hasMute
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 生成群组成员操作菜单
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
const generateActionMenu = useEvent((member: UserBaseInfo): MenuProps => {
|
|
|
|
|
|
|
|
const hasMute = getMemberHasMute(member._id);
|
|
|
|
|
|
|
|
const memberRoles = getMemberRoles(member._id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const muteItems: MenuProps['items'] = allowManageUser
|
|
|
|
|
|
|
|
? hasMute
|
|
|
|
? [
|
|
|
|
? [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
key: 'unmute',
|
|
|
|
key: 'unmute',
|
|
|
@ -136,23 +147,71 @@ export function useGroupMemberAction(groupId: string) {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
];
|
|
|
|
]
|
|
|
|
|
|
|
|
: [];
|
|
|
|
const menu: MenuProps = {
|
|
|
|
|
|
|
|
items: _compact([
|
|
|
|
const roleItems: MenuProps['items'] =
|
|
|
|
...muteItems,
|
|
|
|
allowManageRoles && roles.length > 0
|
|
|
|
{
|
|
|
|
? [
|
|
|
|
key: 'delete',
|
|
|
|
{
|
|
|
|
label: t('移出群组'),
|
|
|
|
key: 'manageRole',
|
|
|
|
danger: true,
|
|
|
|
label: t('分配身份组'),
|
|
|
|
onClick: () => handleRemoveGroupMember(member._id),
|
|
|
|
children: roles.map((role) => ({
|
|
|
|
},
|
|
|
|
key: role._id,
|
|
|
|
] as MenuProps['items']),
|
|
|
|
label: role.name,
|
|
|
|
};
|
|
|
|
className: memberRoles.includes(role._id)
|
|
|
|
|
|
|
|
? 'underline'
|
|
|
|
return menu;
|
|
|
|
: undefined,
|
|
|
|
}
|
|
|
|
onClick: async () => {
|
|
|
|
);
|
|
|
|
// switch member role
|
|
|
|
|
|
|
|
if (memberRoles.includes(role._id)) {
|
|
|
|
|
|
|
|
// 已拥有该身份
|
|
|
|
|
|
|
|
await model.group.removeGroupMemberRoles(
|
|
|
|
|
|
|
|
groupId,
|
|
|
|
|
|
|
|
[member._id],
|
|
|
|
|
|
|
|
[role._id]
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
showSuccessToasts(
|
|
|
|
|
|
|
|
t('移除用户 [{{name}}] 身份组 [{{roleName}}] 成功', {
|
|
|
|
|
|
|
|
name: member.nickname,
|
|
|
|
|
|
|
|
roleName: role.name,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// 没有该身份
|
|
|
|
|
|
|
|
await model.group.appendGroupMemberRoles(
|
|
|
|
|
|
|
|
groupId,
|
|
|
|
|
|
|
|
[member._id],
|
|
|
|
|
|
|
|
[role._id]
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
showSuccessToasts(
|
|
|
|
|
|
|
|
t('授予用户 [{{name}}] 身份组 [{{roleName}}] 成功', {
|
|
|
|
|
|
|
|
name: member.nickname,
|
|
|
|
|
|
|
|
roleName: role.name,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
})),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
: [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const menu: MenuProps = {
|
|
|
|
|
|
|
|
items: _compact([
|
|
|
|
|
|
|
|
...muteItems,
|
|
|
|
|
|
|
|
...roleItems,
|
|
|
|
|
|
|
|
allowManageUser && {
|
|
|
|
|
|
|
|
key: 'delete',
|
|
|
|
|
|
|
|
label: t('移出群组'),
|
|
|
|
|
|
|
|
danger: true,
|
|
|
|
|
|
|
|
onClick: () => handleRemoveGroupMember(member._id),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
] as MenuProps['items']),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return menu;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
userInfos,
|
|
|
|
userInfos,
|
|
|
|