2026-03-09 21:29:03 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 群组服务
|
|
|
|
|
|
* 处理群组管理、成员管理、群设置、群公告等功能
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* 使用 RESTful API: /api/v1/groups
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
2026-04-13 01:30:37 +08:00
|
|
|
|
import { api } from '../core/api';
|
2026-03-09 21:29:03 +08:00
|
|
|
|
import {
|
|
|
|
|
|
GroupResponse,
|
|
|
|
|
|
GroupMemberResponse,
|
|
|
|
|
|
GroupAnnouncementResponse,
|
|
|
|
|
|
GroupListResponse,
|
|
|
|
|
|
GroupMemberListResponse,
|
|
|
|
|
|
GroupAnnouncementListResponse,
|
|
|
|
|
|
CreateGroupRequest,
|
|
|
|
|
|
InviteMembersRequest,
|
|
|
|
|
|
TransferOwnerRequest,
|
|
|
|
|
|
SetRoleRequest,
|
|
|
|
|
|
SetNicknameRequest,
|
|
|
|
|
|
SetMuteAllRequest,
|
|
|
|
|
|
SetJoinTypeRequest,
|
|
|
|
|
|
CreateAnnouncementRequest,
|
|
|
|
|
|
MyMemberInfoResponse,
|
|
|
|
|
|
SetGroupAvatarRequest,
|
|
|
|
|
|
HandleGroupRequestAction,
|
2026-03-20 23:00:27 +08:00
|
|
|
|
CursorPaginationRequest,
|
|
|
|
|
|
CursorPaginationResponse,
|
2026-04-13 01:30:37 +08:00
|
|
|
|
} from '@/types/dto';
|
2026-03-09 21:29:03 +08:00
|
|
|
|
|
2026-03-24 14:21:31 +08:00
|
|
|
|
function asGroupId(raw: unknown): string {
|
|
|
|
|
|
return String(raw);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeGroup(g: GroupResponse): GroupResponse {
|
|
|
|
|
|
return { ...g, id: asGroupId(g.id) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeMember(m: GroupMemberResponse): GroupMemberResponse {
|
|
|
|
|
|
return { ...m, group_id: asGroupId(m.group_id) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeAnnouncement(a: GroupAnnouncementResponse): GroupAnnouncementResponse {
|
|
|
|
|
|
return { ...a, group_id: asGroupId(a.group_id) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeGroupListResponse(r: GroupListResponse): GroupListResponse {
|
|
|
|
|
|
return { ...r, list: r.list.map(normalizeGroup) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeMemberListResponse(r: GroupMemberListResponse): GroupMemberListResponse {
|
|
|
|
|
|
return { ...r, list: r.list.map(normalizeMember) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeAnnouncementListResponse(
|
|
|
|
|
|
r: GroupAnnouncementListResponse
|
|
|
|
|
|
): GroupAnnouncementListResponse {
|
|
|
|
|
|
return { ...r, list: r.list.map(normalizeAnnouncement) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeGroupCursor(
|
|
|
|
|
|
r: CursorPaginationResponse<GroupResponse>
|
|
|
|
|
|
): CursorPaginationResponse<GroupResponse> {
|
|
|
|
|
|
return { ...r, list: r.list.map(normalizeGroup) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeMemberCursor(
|
|
|
|
|
|
r: CursorPaginationResponse<GroupMemberResponse>
|
|
|
|
|
|
): CursorPaginationResponse<GroupMemberResponse> {
|
|
|
|
|
|
return { ...r, list: r.list.map(normalizeMember) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeAnnouncementCursor(
|
|
|
|
|
|
r: CursorPaginationResponse<GroupAnnouncementResponse>
|
|
|
|
|
|
): CursorPaginationResponse<GroupAnnouncementResponse> {
|
|
|
|
|
|
return { ...r, list: r.list.map(normalizeAnnouncement) };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 21:29:03 +08:00
|
|
|
|
// 群组服务类(纯 API 层)
|
|
|
|
|
|
// SQLite/内存缓存编排由 groupManager 统一处理
|
|
|
|
|
|
class GroupService {
|
2026-03-26 16:46:22 +08:00
|
|
|
|
// ==================== 群组管理 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取群组列表
|
|
|
|
|
|
* GET /api/v1/groups
|
|
|
|
|
|
*/
|
|
|
|
|
|
async getGroups(page = 1, pageSize = 20): Promise<GroupListResponse> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
const response = await api.get<GroupListResponse>('/groups', {
|
2026-03-09 21:29:03 +08:00
|
|
|
|
page,
|
|
|
|
|
|
page_size: pageSize,
|
|
|
|
|
|
});
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeGroupListResponse(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-26 16:46:22 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取群组详情
|
|
|
|
|
|
* GET /api/v1/groups/:id
|
|
|
|
|
|
*/
|
|
|
|
|
|
async getGroup(id: string): Promise<GroupResponse> {
|
2026-03-24 14:21:31 +08:00
|
|
|
|
const response = await api.get<GroupResponse>(`/groups/${encodeURIComponent(id)}`);
|
|
|
|
|
|
return normalizeGroup(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-26 16:46:22 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取群组成员列表
|
|
|
|
|
|
* GET /api/v1/groups/:id/members
|
|
|
|
|
|
*/
|
|
|
|
|
|
async getMembers(groupId: string, page = 1, pageSize = 50): Promise<GroupMemberListResponse> {
|
2026-03-09 21:29:03 +08:00
|
|
|
|
const response = await api.get<GroupMemberListResponse>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/members`,
|
2026-03-09 21:29:03 +08:00
|
|
|
|
{
|
|
|
|
|
|
page,
|
|
|
|
|
|
page_size: pageSize,
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeMemberListResponse(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建群组
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async createGroup(data: CreateGroupRequest): Promise<GroupResponse> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
const response = await api.post<GroupResponse>('/groups', data);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeGroup(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前用户在群组中的成员信息
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* GET /api/v1/groups/:id/me
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async getMyMemberInfo(groupId: string): Promise<MyMemberInfoResponse> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
const response = await api.get<MyMemberInfoResponse>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/me`
|
2026-03-10 20:52:50 +08:00
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return {
|
|
|
|
|
|
...response.data,
|
|
|
|
|
|
member: normalizeMember(response.data.member),
|
|
|
|
|
|
};
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 解散群组
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* DELETE /api/v1/groups/:id
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async dissolveGroup(id: string): Promise<void> {
|
|
|
|
|
|
await api.delete(`/groups/${encodeURIComponent(id)}`);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 转让群主
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/transfer
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async transferOwner(id: string, data: TransferOwnerRequest): Promise<void> {
|
|
|
|
|
|
await api.post(`/groups/${encodeURIComponent(id)}/transfer`, data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 成员管理 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 邀请成员加入群组
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/invitations
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async inviteMembers(groupId: string, data: InviteMembersRequest): Promise<void> {
|
|
|
|
|
|
await api.post(`/groups/${encodeURIComponent(groupId)}/invitations`, data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 申请加入群组
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/join-requests
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async joinGroup(groupId: string): Promise<void> {
|
|
|
|
|
|
await api.post(`/groups/${encodeURIComponent(groupId)}/join-requests`);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* 响应群邀请/申请
|
|
|
|
|
|
* POST /api/v1/groups/:id/join-requests/respond
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async respondInvite(groupId: string, data: HandleGroupRequestAction): Promise<void> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
await api.post(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/join-requests/respond`,
|
2026-03-10 20:52:50 +08:00
|
|
|
|
data
|
|
|
|
|
|
);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 审批主动加群申请
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/join-requests/handle
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async reviewJoinRequest(groupId: string, data: HandleGroupRequestAction): Promise<void> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
await api.post(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/join-requests/handle`,
|
2026-03-10 20:52:50 +08:00
|
|
|
|
data
|
|
|
|
|
|
);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 退出群组
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/leave
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async leaveGroup(groupId: string): Promise<void> {
|
|
|
|
|
|
await api.post(`/groups/${encodeURIComponent(groupId)}/leave`);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移除群成员(踢人)
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/members/kick
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async removeMember(groupId: string, userId: string): Promise<void> {
|
|
|
|
|
|
await api.post(`/groups/${encodeURIComponent(groupId)}/members/kick`, {
|
2026-03-09 21:29:03 +08:00
|
|
|
|
user_id: userId,
|
|
|
|
|
|
reject_add_request: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置成员角色(设置/取消管理员)
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* PUT /api/v1/groups/:id/members/:user_id/admin
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async setMemberRole(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
groupId: string,
|
2026-03-09 21:29:03 +08:00
|
|
|
|
userId: string,
|
|
|
|
|
|
data: SetRoleRequest
|
|
|
|
|
|
): Promise<void> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
await api.put(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/members/${encodeURIComponent(userId)}/admin`,
|
2026-03-10 20:52:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
enable: data.role === 'admin',
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置群昵称
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* PUT /api/v1/groups/:id/members/me/nickname
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async setNickname(groupId: string, data: SetNicknameRequest): Promise<void> {
|
|
|
|
|
|
await api.put(`/groups/${encodeURIComponent(groupId)}/members/me/nickname`, data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 禁言/解禁成员
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/members/ban
|
2026-03-09 21:29:03 +08:00
|
|
|
|
* @param groupId 群组ID
|
|
|
|
|
|
* @param userId 用户ID
|
|
|
|
|
|
* @param duration 禁言时长(秒),0表示解除禁言
|
|
|
|
|
|
*/
|
|
|
|
|
|
async muteMember(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
groupId: string,
|
2026-03-09 21:29:03 +08:00
|
|
|
|
userId: string,
|
|
|
|
|
|
duration: number = 0
|
|
|
|
|
|
): Promise<void> {
|
2026-03-24 14:21:31 +08:00
|
|
|
|
await api.post(`/groups/${encodeURIComponent(groupId)}/members/ban`, {
|
2026-03-09 21:29:03 +08:00
|
|
|
|
user_id: userId,
|
|
|
|
|
|
duration: duration,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 群设置 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置全员禁言
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* PUT /api/v1/groups/:id/ban
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async setMuteAll(groupId: string, data: SetMuteAllRequest): Promise<void> {
|
|
|
|
|
|
await api.put(`/groups/${encodeURIComponent(groupId)}/ban`, {
|
2026-03-09 21:29:03 +08:00
|
|
|
|
enable: data.mute_all,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置加群方式
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* PUT /api/v1/groups/:id/join-type
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async setJoinType(groupId: string, data: SetJoinTypeRequest): Promise<void> {
|
|
|
|
|
|
await api.put(`/groups/${encodeURIComponent(groupId)}/join-type`, data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置群名称
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* PUT /api/v1/groups/:id/name
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async setGroupName(groupId: string, groupName: string): Promise<void> {
|
|
|
|
|
|
await api.put(`/groups/${encodeURIComponent(groupId)}/name`, {
|
2026-03-09 21:29:03 +08:00
|
|
|
|
group_name: groupName,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置群头像
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* PUT /api/v1/groups/:id/avatar
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async setGroupAvatar(groupId: string, avatarUrl: string): Promise<GroupResponse> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
const response = await api.put<GroupResponse>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/avatar`,
|
2026-03-10 20:52:50 +08:00
|
|
|
|
{
|
|
|
|
|
|
avatar: avatarUrl,
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeGroup(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 群公告 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建群公告
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* POST /api/v1/groups/:id/announcements
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async createAnnouncement(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
groupId: string,
|
2026-03-09 21:29:03 +08:00
|
|
|
|
data: CreateAnnouncementRequest
|
|
|
|
|
|
): Promise<GroupAnnouncementResponse> {
|
|
|
|
|
|
const response = await api.post<GroupAnnouncementResponse>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/announcements`,
|
2026-03-10 20:52:50 +08:00
|
|
|
|
data
|
2026-03-09 21:29:03 +08:00
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeAnnouncement(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取群公告列表
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* GET /api/v1/groups/:id/announcements
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async getAnnouncements(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
groupId: string,
|
2026-03-09 21:29:03 +08:00
|
|
|
|
page = 1,
|
|
|
|
|
|
pageSize = 20
|
|
|
|
|
|
): Promise<GroupAnnouncementListResponse> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await api.get<GroupAnnouncementListResponse>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/announcements`,
|
2026-03-09 21:29:03 +08:00
|
|
|
|
{
|
|
|
|
|
|
page,
|
|
|
|
|
|
page_size: pageSize,
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeAnnouncementListResponse(response.data);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取群公告列表失败:', error);
|
|
|
|
|
|
return {
|
|
|
|
|
|
list: [],
|
|
|
|
|
|
total: 0,
|
|
|
|
|
|
page: 1,
|
|
|
|
|
|
page_size: pageSize,
|
|
|
|
|
|
total_pages: 0,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除群公告
|
2026-03-10 20:52:50 +08:00
|
|
|
|
* DELETE /api/v1/groups/:id/announcements/:announcement_id
|
2026-03-09 21:29:03 +08:00
|
|
|
|
*/
|
2026-03-24 14:21:31 +08:00
|
|
|
|
async deleteAnnouncement(groupId: string, announcementId: number): Promise<void> {
|
2026-03-10 20:52:50 +08:00
|
|
|
|
await api.delete(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/announcements/${encodeURIComponent(String(announcementId))}`
|
2026-03-10 20:52:50 +08:00
|
|
|
|
);
|
2026-03-09 21:29:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-20 23:00:27 +08:00
|
|
|
|
// ==================== 游标分页方法 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取群组列表(游标分页)
|
|
|
|
|
|
* GET /api/v1/groups/cursor
|
|
|
|
|
|
* @param params 游标分页请求参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
async getGroupsCursor(
|
|
|
|
|
|
params: CursorPaginationRequest = {}
|
|
|
|
|
|
): Promise<CursorPaginationResponse<GroupResponse>> {
|
|
|
|
|
|
try {
|
2026-03-23 23:38:53 +08:00
|
|
|
|
const response = await api.get<CursorPaginationResponse<GroupResponse>>('/groups/cursor', params);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeGroupCursor(response.data);
|
2026-03-20 23:00:27 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取群组列表失败:', error);
|
|
|
|
|
|
return {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
list: [],
|
2026-03-20 23:00:27 +08:00
|
|
|
|
next_cursor: null,
|
|
|
|
|
|
prev_cursor: null,
|
|
|
|
|
|
has_more: false,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取群组成员列表(游标分页)
|
|
|
|
|
|
* GET /api/v1/groups/:id/members/cursor
|
|
|
|
|
|
* @param groupId 群组ID
|
|
|
|
|
|
* @param params 游标分页请求参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
async getGroupMembersCursor(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
groupId: string,
|
2026-03-20 23:00:27 +08:00
|
|
|
|
params: CursorPaginationRequest = {}
|
|
|
|
|
|
): Promise<CursorPaginationResponse<GroupMemberResponse>> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await api.get<CursorPaginationResponse<GroupMemberResponse>>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/members/cursor`,
|
2026-03-23 23:38:53 +08:00
|
|
|
|
params
|
2026-03-20 23:00:27 +08:00
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeMemberCursor(response.data);
|
2026-03-20 23:00:27 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取群组成员列表失败:', error);
|
|
|
|
|
|
return {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
list: [],
|
2026-03-20 23:00:27 +08:00
|
|
|
|
next_cursor: null,
|
|
|
|
|
|
prev_cursor: null,
|
|
|
|
|
|
has_more: false,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取群公告列表(游标分页)
|
|
|
|
|
|
* GET /api/v1/groups/:id/announcements/cursor
|
|
|
|
|
|
* @param groupId 群组ID
|
|
|
|
|
|
* @param params 游标分页请求参数
|
|
|
|
|
|
*/
|
|
|
|
|
|
async getGroupAnnouncementsCursor(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
groupId: string,
|
2026-03-20 23:00:27 +08:00
|
|
|
|
params: CursorPaginationRequest = {}
|
|
|
|
|
|
): Promise<CursorPaginationResponse<GroupAnnouncementResponse>> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await api.get<CursorPaginationResponse<GroupAnnouncementResponse>>(
|
2026-03-24 14:21:31 +08:00
|
|
|
|
`/groups/${encodeURIComponent(groupId)}/announcements/cursor`,
|
2026-03-23 23:38:53 +08:00
|
|
|
|
params
|
2026-03-20 23:00:27 +08:00
|
|
|
|
);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
return normalizeAnnouncementCursor(response.data);
|
2026-03-20 23:00:27 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取群公告列表失败:', error);
|
|
|
|
|
|
return {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
list: [],
|
2026-03-20 23:00:27 +08:00
|
|
|
|
next_cursor: null,
|
|
|
|
|
|
prev_cursor: null,
|
|
|
|
|
|
has_more: false,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-21 21:13:34 +08:00
|
|
|
|
}
|
2026-03-20 23:00:27 +08:00
|
|
|
|
|
2026-03-09 21:29:03 +08:00
|
|
|
|
// 导出群组服务实例
|
|
|
|
|
|
export const groupService = new GroupService();
|
|
|
|
|
|
|
|
|
|
|
|
// 导出类型以方便使用
|
|
|
|
|
|
export type {
|
|
|
|
|
|
GroupResponse,
|
|
|
|
|
|
GroupMemberResponse,
|
|
|
|
|
|
GroupAnnouncementResponse,
|
|
|
|
|
|
GroupListResponse,
|
|
|
|
|
|
GroupMemberListResponse,
|
|
|
|
|
|
GroupAnnouncementListResponse,
|
|
|
|
|
|
CreateGroupRequest,
|
|
|
|
|
|
InviteMembersRequest,
|
|
|
|
|
|
TransferOwnerRequest,
|
|
|
|
|
|
SetRoleRequest,
|
|
|
|
|
|
SetNicknameRequest,
|
|
|
|
|
|
SetMuteAllRequest,
|
|
|
|
|
|
SetJoinTypeRequest,
|
|
|
|
|
|
CreateAnnouncementRequest,
|
|
|
|
|
|
SetGroupAvatarRequest,
|
|
|
|
|
|
};
|