From bf25bc5a472bd81dcfcb6f4d3eb73cc1b92cbdd3 Mon Sep 17 00:00:00 2001 From: baiyanyun Date: Sun, 7 Jun 2026 11:24:01 +0800 Subject: [PATCH] feat: filter digital sync links by device --- .../DigitalEmployeeSyncApplicationService.java | 1 + .../DigitalEmployeeSyncRecordRepository.java | 1 + .../DigitalEmployeeSyncApplicationServiceImpl.java | 2 ++ .../DigitalEmployeeSyncRecordRepositoryImpl.java | 2 ++ .../controller/DigitalEmployeeSyncController.java | 2 ++ .../Content/DigitalEmployeeSync/index.tsx | 13 ++++++++++++- qiming/src/services/systemManage.ts | 1 + qiming/src/types/interfaces/systemManage.ts | 1 + .../services/digitalEmployee/syncService.test.ts | 2 +- .../main/services/digitalEmployee/syncService.ts | 1 + .../digital-employee-frontend-integration-plan.md | 6 +++--- 11 files changed, 27 insertions(+), 5 deletions(-) diff --git a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/application/DigitalEmployeeSyncApplicationService.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/application/DigitalEmployeeSyncApplicationService.java index c0bdd2a2..f10c2a74 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/application/DigitalEmployeeSyncApplicationService.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/application/DigitalEmployeeSyncApplicationService.java @@ -9,6 +9,7 @@ public interface DigitalEmployeeSyncApplicationService { DigitalEmployeeSyncRecordPageDto queryRecords( String clientKey, + String deviceId, String entityType, String entityId, String outboxId, diff --git a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/repository/DigitalEmployeeSyncRecordRepository.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/repository/DigitalEmployeeSyncRecordRepository.java index a16e2641..b590f64f 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/repository/DigitalEmployeeSyncRecordRepository.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/repository/DigitalEmployeeSyncRecordRepository.java @@ -8,6 +8,7 @@ public interface DigitalEmployeeSyncRecordRepository extends IService queryRecords( Long tenantId, String clientKey, + String deviceId, String entityType, String entityId, String outboxId, diff --git a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/main/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImpl.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/main/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImpl.java index 4f463145..a8f44b73 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/main/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImpl.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/main/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImpl.java @@ -91,6 +91,7 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye @Override public DigitalEmployeeSyncRecordPageDto queryRecords( String clientKey, + String deviceId, String entityType, String entityId, String outboxId, @@ -114,6 +115,7 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye IPage page = digitalEmployeeSyncRecordRepository.queryRecords( tenantId, clientKey, + deviceId, entityType, entityId, outboxId, diff --git a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-infra/src/main/java/com/xspaceagi/agent/core/infra/repository/DigitalEmployeeSyncRecordRepositoryImpl.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-infra/src/main/java/com/xspaceagi/agent/core/infra/repository/DigitalEmployeeSyncRecordRepositoryImpl.java index 292db5dc..c1c4747f 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-infra/src/main/java/com/xspaceagi/agent/core/infra/repository/DigitalEmployeeSyncRecordRepositoryImpl.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-infra/src/main/java/com/xspaceagi/agent/core/infra/repository/DigitalEmployeeSyncRecordRepositoryImpl.java @@ -19,6 +19,7 @@ public class DigitalEmployeeSyncRecordRepositoryImpl public IPage queryRecords( Long tenantId, String clientKey, + String deviceId, String entityType, String entityId, String outboxId, @@ -28,6 +29,7 @@ public class DigitalEmployeeSyncRecordRepositoryImpl LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() .eq(tenantId != null, DigitalEmployeeSyncRecord::getTenantId, tenantId) .eq(StringUtils.isNotBlank(clientKey), DigitalEmployeeSyncRecord::getClientKey, clientKey) + .eq(StringUtils.isNotBlank(deviceId), DigitalEmployeeSyncRecord::getDeviceId, deviceId) .eq(StringUtils.isNotBlank(entityType), DigitalEmployeeSyncRecord::getEntityType, entityType) .eq(StringUtils.isNotBlank(entityId), DigitalEmployeeSyncRecord::getEntityId, entityId) .eq(StringUtils.isNotBlank(outboxId), DigitalEmployeeSyncRecord::getOutboxId, outboxId) diff --git a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-ui/src/main/java/com/xspaceagi/agent/web/ui/controller/DigitalEmployeeSyncController.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-ui/src/main/java/com/xspaceagi/agent/web/ui/controller/DigitalEmployeeSyncController.java index 3298f413..67bdd5e4 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-ui/src/main/java/com/xspaceagi/agent/web/ui/controller/DigitalEmployeeSyncController.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-ui/src/main/java/com/xspaceagi/agent/web/ui/controller/DigitalEmployeeSyncController.java @@ -31,6 +31,7 @@ public class DigitalEmployeeSyncController { @RequestMapping(path = "/records", method = RequestMethod.GET) public ReqResult queryRecords( @RequestParam(name = "client_key", required = false) String clientKey, + @RequestParam(name = "device_id", required = false) String deviceId, @RequestParam(name = "entity_type", required = false) String entityType, @RequestParam(name = "entity_id", required = false) String entityId, @RequestParam(name = "outbox_id", required = false) String outboxId, @@ -39,6 +40,7 @@ public class DigitalEmployeeSyncController { ) { return ReqResult.success(digitalEmployeeSyncApplicationService.queryRecords( clientKey, + deviceId, entityType, entityId, outboxId, diff --git a/qiming/src/pages/SystemManagement/Content/DigitalEmployeeSync/index.tsx b/qiming/src/pages/SystemManagement/Content/DigitalEmployeeSync/index.tsx index b48f0b42..68363a42 100644 --- a/qiming/src/pages/SystemManagement/Content/DigitalEmployeeSync/index.tsx +++ b/qiming/src/pages/SystemManagement/Content/DigitalEmployeeSync/index.tsx @@ -217,6 +217,7 @@ const DigitalEmployeeSync: React.FC = () => { const params = new URLSearchParams(location.search || ''); const values = { client_key: readSearchValue(params, 'client_key'), + device_id: readSearchValue(params, 'device_id'), entity_type: readSearchValue(params, 'entity_type'), entity_id: readSearchValue(params, 'entity_id'), outbox_id: readSearchValue(params, 'outbox_id'), @@ -228,6 +229,7 @@ const DigitalEmployeeSync: React.FC = () => { formRef.current?.resetFields(); formRef.current?.setFieldsValue({ client_key: undefined, + device_id: undefined, entity_type: undefined, entity_id: undefined, outbox_id: undefined, @@ -270,7 +272,10 @@ const DigitalEmployeeSync: React.FC = () => { dataIndex: 'device_id', width: 150, ellipsis: true, - hideInSearch: true, + fieldProps: { + placeholder: '输入设备 ID', + allowClear: true, + }, renderText: (value) => value || '--', }, { @@ -360,6 +365,7 @@ const DigitalEmployeeSync: React.FC = () => { pageSize?: number; current?: number; client_key?: string; + device_id?: string; entity_type?: string; entity_id?: string; outbox_id?: string; @@ -368,6 +374,7 @@ const DigitalEmployeeSync: React.FC = () => { pageNo: params.current || 1, pageSize: params.pageSize || 15, clientKey: params.client_key, + deviceId: params.device_id, entityType: params.entity_type, entityId: params.entity_id, outboxId: params.outbox_id, @@ -431,6 +438,10 @@ const DigitalEmployeeSync: React.FC = () => { 客户端 Key: {maskClientKey(payloadRecord.client_key)} + + 设备 ID: + {payloadRecord.device_id || '--'} + 实体: {payloadRecord.entity_type} / {payloadRecord.entity_id} diff --git a/qiming/src/services/systemManage.ts b/qiming/src/services/systemManage.ts index 80bc644f..7dc4709d 100644 --- a/qiming/src/services/systemManage.ts +++ b/qiming/src/services/systemManage.ts @@ -274,6 +274,7 @@ export async function apiDigitalEmployeeSyncRecordList( method: 'GET', params: { client_key: data.clientKey, + device_id: data.deviceId, entity_type: data.entityType, entity_id: data.entityId, outbox_id: data.outboxId, diff --git a/qiming/src/types/interfaces/systemManage.ts b/qiming/src/types/interfaces/systemManage.ts index e50cf3d1..6c02ff8b 100644 --- a/qiming/src/types/interfaces/systemManage.ts +++ b/qiming/src/types/interfaces/systemManage.ts @@ -542,6 +542,7 @@ export interface DigitalEmployeeSyncRecordInfo { export interface DigitalEmployeeSyncRecordListParams extends SystemPaginationParams { clientKey?: string; + deviceId?: string; entityType?: string; entityId?: string; outboxId?: string; diff --git a/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.test.ts b/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.test.ts index f3cae19d..b9e1b0d6 100644 --- a/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.test.ts +++ b/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.test.ts @@ -147,7 +147,7 @@ describe("digital employee sync service", () => { id: "plan:upsert:plan-2", dueForRetry: false, managementRecordUrl: - "https://manage.example.com/system/content/content-digital-employee-sync?entity_type=plan&entity_id=plan-2&outbox_id=plan%3Aupsert%3Aplan-2", + "https://manage.example.com/system/content/content-digital-employee-sync?device_id=device-001&entity_type=plan&entity_id=plan-2&outbox_id=plan%3Aupsert%3Aplan-2", attemptHistory: [ expect.objectContaining({ attemptNo: 1, diff --git a/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.ts b/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.ts index 75ca5f02..0c1402dc 100644 --- a/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.ts +++ b/qimingclaw/crates/agent-electron-client/src/main/services/digitalEmployee/syncService.ts @@ -636,6 +636,7 @@ function buildManagementRecordUrl( try { const endpoint = new URL(config.endpoint); const url = new URL(MANAGEMENT_SYNC_RECORD_PATH, endpoint.origin); + url.searchParams.set("device_id", getDeviceId()); url.searchParams.set("entity_type", row.entity_type); url.searchParams.set("entity_id", row.entity_id); url.searchParams.set("outbox_id", row.id); diff --git a/qimingclaw/docs/digital-employee-frontend-integration-plan.md b/qimingclaw/docs/digital-employee-frontend-integration-plan.md index 8098766c..dee3839e 100644 --- a/qimingclaw/docs/digital-employee-frontend-integration-plan.md +++ b/qimingclaw/docs/digital-employee-frontend-integration-plan.md @@ -448,7 +448,7 @@ crates/agent-electron-client/src/preload/webviewPerfBridge.ts - 同步状态通过 bridge 返回最近失败 outbox 明细,首页可直接看到实体类型、outbox ID、操作类型、重试次数、失败时间和下次自动重试时间。 - 本地 SQLite 额外记录 `digital_sync_attempts`,每次 outbox 推送成功、失败或部分 ack 缺失都会留下一次尝试历史,默认保留最近 30 天。 - 点击失败 outbox 可打开详情弹窗,查看完整错误、实体 ID、退避状态、最近重试历史,并可复制或导出诊断 JSON;也可触发手动 `flushSync` 立即重试。若已配置管理端同步地址,详情弹窗可直接打开对应的管理端同步记录深链。 -- qimingclaw 自动生成的管理端深链只携带 `entity_type`、`entity_id`、`outbox_id`,避免在 URL 中暴露客户端 Key;管理端列表仍保留客户端 Key 手动筛选能力。 +- qimingclaw 自动生成的管理端深链只携带 `device_id`、`entity_type`、`entity_id`、`outbox_id`,避免在 URL 中暴露客户端 Key,同时仍能区分同租户下的不同客户端;管理端列表仍保留客户端 Key 手动筛选能力。 新增 IPC / Bridge: @@ -482,10 +482,10 @@ qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-a GET /api/digital-employee/sync/records ``` -- 支持 `client_key`、`entity_type`、`entity_id`、`outbox_id`、`page_no`、`page_size` 查询参数。 +- 支持 `client_key`、`device_id`、`entity_type`、`entity_id`、`outbox_id`、`page_no`、`page_size` 查询参数。 - 按当前登录上下文租户隔离,默认每页 20 条,最大每页 100 条。 - 当前返回通用同步记录和原始 payload,用于管理端页面或联调工具先查看同步结果;后续再拆分为更丰富的 Plan / Task / Run / Event 查询模型。 -- 管理端已增加“数字员工同步记录”菜单、权限资源和列表页,可按客户端 Key、实体类型、实体 ID、Outbox ID 查询并查看 payload;URL 查询参数会预填筛选条件,并在命中 Outbox ID 时自动打开 payload 抽屉。 +- 管理端已增加“数字员工同步记录”菜单、权限资源和列表页,可按客户端 Key、设备 ID、实体类型、实体 ID、Outbox ID 查询并查看 payload;URL 查询参数会预填筛选条件,并在命中 Outbox ID 时自动打开 payload 抽屉。 - 管理端同步记录页会从通用 payload 中提炼标题、状态、Plan/Task/Run 关联、发生时间等业务摘要,列表和详情抽屉不再只能依赖原始 JSON 排障。 - 管理端列表和抽屉内的客户端 Key 仅脱敏展示,筛选框仍支持输入完整客户端 Key 精准查询。