feat(service-party-app): 添加获取已注册参与方列表API

新增 grpc.getRegisteredParties() API,用于查询 Message Router 中已注册的参与方:
- grpc-client.ts: 添加 getRegisteredParties() 方法
- main.ts: 添加 IPC 处理器
- preload.ts: 暴露 API 到渲染进程
- electron.d.ts: 添加类型定义

此功能用于测试和调试,确认 Service-Party-App 是否成功注册到 Message Router。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-28 22:50:46 -08:00
parent de29fa4800
commit 73034c072c
4 changed files with 79 additions and 0 deletions

View File

@ -217,6 +217,16 @@ function setupIpcHandlers() {
}
});
// gRPC - 获取已注册的参与方列表
ipcMain.handle('grpc:getRegisteredParties', async (_event, { roleFilter, onlyOnline }) => {
try {
const parties = await grpcClient?.getRegisteredParties(roleFilter, onlyOnline);
return { success: true, parties: parties || [] };
} catch (error) {
return { success: false, error: (error as Error).message, parties: [] };
}
});
// gRPC - 验证签名会话 (通过 Account 服务 HTTP API)
ipcMain.handle('grpc:validateSigningSession', async (_event, { code }) => {
try {

View File

@ -78,6 +78,18 @@ interface SessionEvent {
messageHash?: Buffer;
}
interface RegisteredParty {
partyId: string;
role: string;
online: boolean;
registeredAt: string;
lastSeenAt: string;
}
interface GetRegisteredPartiesResponse {
parties: RegisteredParty[];
}
/**
* gRPC - Message Router
*
@ -390,4 +402,40 @@ export class GrpcClient extends EventEmitter {
);
});
}
/**
*
* @param roleFilter (persistent/delegate/temporary)
* @param onlyOnline 线
*/
async getRegisteredParties(roleFilter?: string, onlyOnline?: boolean): Promise<RegisteredParty[]> {
if (!this.client) {
throw new Error('Not connected');
}
return new Promise((resolve, reject) => {
(this.client as grpc.Client & { getRegisteredParties: (req: unknown, callback: (err: Error | null, res: GetRegisteredPartiesResponse) => void) => void })
.getRegisteredParties(
{
role_filter: roleFilter || '',
only_online: onlyOnline || false,
},
(err: Error | null, response: GetRegisteredPartiesResponse) => {
if (err) {
reject(err);
} else {
// 转换字段名从 snake_case 到 camelCase
const parties = (response.parties || []).map((p: { party_id?: string; partyId?: string; role?: string; party_role?: string; online?: boolean; registered_at?: string; registeredAt?: string; last_seen_at?: string; lastSeenAt?: string }) => ({
partyId: p.party_id || p.partyId || '',
role: p.role || p.party_role || '',
online: p.online || false,
registeredAt: p.registered_at || p.registeredAt || '',
lastSeenAt: p.last_seen_at || p.lastSeenAt || '',
}));
resolve(parties);
}
}
);
});
}
}

View File

@ -42,6 +42,10 @@ contextBridge.exposeInMainWorld('electronAPI', {
testConnection: (url: string) =>
ipcRenderer.invoke('grpc:testConnection', { url }),
// 获取已注册的参与方列表
getRegisteredParties: (roleFilter?: string, onlyOnline?: boolean) =>
ipcRenderer.invoke('grpc:getRegisteredParties', { roleFilter, onlyOnline }),
// 签名相关
validateSigningSession: (code: string) =>
ipcRenderer.invoke('grpc:validateSigningSession', { code }),

View File

@ -146,6 +146,21 @@ interface TestConnectionResult {
error?: string;
}
// 已注册的参与方
interface RegisteredParty {
partyId: string;
role: string;
online: boolean;
registeredAt: string;
lastSeenAt: string;
}
interface GetRegisteredPartiesResult {
success: boolean;
parties: RegisteredParty[];
error?: string;
}
interface SessionEvent {
type: 'participant_joined' | 'status_changed' | 'completed' | 'failed';
participant?: Participant;
@ -413,6 +428,8 @@ interface ElectronAPI {
getSessionStatus: (sessionId: string) => Promise<GetSessionStatusResult>;
subscribeSessionEvents: (sessionId: string, callback: (event: SessionEvent) => void) => () => void;
testConnection: (url: string) => Promise<TestConnectionResult>;
// 获取已注册的参与方列表
getRegisteredParties: (roleFilter?: string, onlyOnline?: boolean) => Promise<GetRegisteredPartiesResult>;
// 签名相关
validateSigningSession: (code: string) => Promise<ValidateSigningSessionResult>;
joinSigningSession: (params: JoinSigningSessionParams) => Promise<JoinSigningSessionResult>;