From d5025c0ebcaf913b08a7ff0f6f4222ed29d5cb5b Mon Sep 17 00:00:00 2001 From: baiyanyun Date: Sat, 13 Jun 2026 14:00:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=B8=E6=94=B6=E6=95=B0=E5=AD=97=E5=91=98?= =?UTF-8?q?=E5=B7=A5=E7=AE=A1=E7=90=86=E7=AB=AF=E6=97=A5=E6=8A=A5=E8=BF=90?= =?UTF-8?q?=E8=90=A5=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...mployeeSyncApplicationServiceImplTest.java | 68 +++++++++++++++ .../scripts/check-digital-employee.js | 86 +++++++++++++++++++ ...ital-employee-frontend-integration-plan.md | 2 +- 3 files changed, 155 insertions(+), 1 deletion(-) diff --git a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/test/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImplTest.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/test/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImplTest.java index 34644fc1..9a976741 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/test/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImplTest.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-application/src/test/java/com/xspaceagi/agent/core/application/service/DigitalEmployeeSyncApplicationServiceImplTest.java @@ -735,6 +735,74 @@ class DigitalEmployeeSyncApplicationServiceImplTest { assertThat(row.getPayload()).containsEntry("tool_name", "shell"); } + @Test + void queryAdminWorkbenchDailyReportsReturnsDailyReportRowsOnly() { + when(repository.queryBusinessRecords(eq(101L), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(1L), eq(20L))) + .thenReturn(page(List.of( + record("outbox-daily-report", "daily_report", "report-1", 101L, new Date(10_000), + Map.of( + "entity_type", "daily_report", + "category", "daily_report", + "kind", "daily_report_generated", + "status", "generated", + "title", "6 月 13 日日报", + "report_id", "report-1", + "summary", "日报已生成", + "artifact_id", "artifact-report-1" + ), + Map.of("id", "report-1", "kind", "daily_report_generated")), + record("outbox-daily-report-delivered", "event", "event-daily-report-1", 101L, new Date(11_000), + Map.of( + "entity_type", "event", + "category", "daily_report", + "kind", "daily_report_send_recorded", + "status", "delivered", + "title", "日报发送已记录", + "report_id", "report-2", + "delivery_status", "delivered" + ), + Map.of("id", "event-daily-report-1", "kind", "daily_report_send_recorded")), + record("outbox-daily-report-confirmed", "event", "event-daily-report-2", 101L, new Date(12_000), + Map.of( + "entity_type", "event", + "kind", "daily_report_confirmed", + "status", "confirmed", + "title", "日报确认回执", + "report_id", "report-3", + "confirmed_at", "2026-06-13T10:00:00+08:00" + ), + Map.of("id", "event-daily-report-2", "kind", "daily_report_confirmed")), + record("outbox-task", "task", "task-1", 101L, new Date(13_000), + Map.of("entity_type", "task", "title", "普通任务", "status", "running"), + Map.of("id", "task-1", "status", "running")), + record("outbox-approval", "approval", "approval-1", 101L, new Date(14_000), + Map.of("entity_type", "approval", "title", "普通审批", "status", "pending"), + Map.of("id", "approval-1", "status", "pending")), + record("outbox-notification", "notification", "notification-1", 101L, new Date(15_000), + Map.of("entity_type", "notification", "title", "普通通知", "status", "unread"), + Map.of("id", "notification-1", "status", "unread")), + record("outbox-audit", "event", "event-audit-1", 101L, new Date(16_000), + Map.of("entity_type", "event", "category", "tool_call_audit", "title", "审计", "status", "warn"), + Map.of("id", "event-audit-1", "status", "warn")) + ))); + + DigitalEmployeeAdminWorkbenchPageDto result = service.queryAdminWorkbench( + "daily_reports", null, null, null, null, null, null, null, null, null, null, null, 1L, 20L + ); + + assertThat(result.getTotal()).isEqualTo(3); + assertThat(result.getRecords()).extracting(DigitalEmployeeAdminWorkbenchRowDto::getEntityId) + .containsExactly("report-1", "event-daily-report-1", "event-daily-report-2"); + assertThat(result.getRecords().get(0).getView()).isEqualTo("daily_reports"); + assertThat(result.getRecords().get(0).getReportId()).isEqualTo("report-1"); + assertThat(result.getRecords().get(0).getCategory()).isEqualTo("daily_report"); + assertThat(result.getRecords().get(0).getStatus()).isEqualTo("generated"); + assertThat(result.getRecords().get(0).getSummary()).isEqualTo("日报已生成"); + assertThat(result.getRecords().get(1).getReportId()).isEqualTo("report-2"); + assertThat(result.getRecords().get(1).getBusinessView()).containsEntry("delivery_status", "delivered"); + assertThat(result.getRecords().get(2).getBusinessView()).containsEntry("confirmed_at", "2026-06-13T10:00:00+08:00"); + } + @Test void createAdminActionRecordsLowRiskActionAsPending() { DigitalEmployeeAdminActionRequestDto request = adminActionRequest("approval", "approval-1", "keep_local"); diff --git a/qimingclaw/crates/agent-electron-client/scripts/check-digital-employee.js b/qimingclaw/crates/agent-electron-client/scripts/check-digital-employee.js index d17de0cc..a22c67fb 100644 --- a/qimingclaw/crates/agent-electron-client/scripts/check-digital-employee.js +++ b/qimingclaw/crates/agent-electron-client/scripts/check-digital-employee.js @@ -1839,6 +1839,91 @@ function checkDigitalAdminAuditDiagnosticsWorkbench() { console.log("[DigitalEmployeeCheck] admin audit diagnostics workbench hooks OK"); } +function checkDigitalAdminDailyReportWorkbench() { + console.log("\n[DigitalEmployeeCheck] Verify admin daily report workbench hooks"); + const backendRoot = path.resolve(packageRoot, "..", "..", "..", "qiming-backend"); + const qimingRoot = path.resolve(packageRoot, "..", "..", "..", "qiming"); + const servicePath = path.join( + backendRoot, + "app-platform-modules", + "app-platform-agent", + "app-platform-agent-core-application", + "src", + "main", + "java", + "com", + "xspaceagi", + "agent", + "core", + "application", + "service", + "DigitalEmployeeSyncApplicationServiceImpl.java", + ); + const dtoPath = path.join( + backendRoot, + "app-platform-modules", + "app-platform-agent", + "app-platform-agent-core-adapter", + "src", + "main", + "java", + "com", + "xspaceagi", + "agent", + "core", + "adapter", + "dto", + "digital", + "DigitalEmployeeAdminWorkbenchRowDto.java", + ); + const testPath = path.join( + backendRoot, + "app-platform-modules", + "app-platform-agent", + "app-platform-agent-core-application", + "src", + "test", + "java", + "com", + "xspaceagi", + "agent", + "core", + "application", + "service", + "DigitalEmployeeSyncApplicationServiceImplTest.java", + ); + const qimingOpsPath = path.join(qimingRoot, "src", "pages", "SystemManagement", "Content", "DigitalEmployeeOps", "index.tsx"); + const qimingTypesPath = path.join(qimingRoot, "src", "types", "interfaces", "systemManage.ts"); + const docsPath = path.resolve(packageRoot, "..", "..", "docs", "digital-employee-frontend-integration-plan.md"); + const service = fs.readFileSync(servicePath, "utf8"); + const dto = fs.readFileSync(dtoPath, "utf8"); + const test = fs.readFileSync(testPath, "utf8"); + const qimingOps = fs.readFileSync(qimingOpsPath, "utf8"); + const qimingTypes = fs.readFileSync(qimingTypesPath, "utf8"); + const docs = fs.readFileSync(docsPath, "utf8"); + const requiredSnippets = [ + [service, "daily_reports", "backend daily report view"], + [service, "isDailyReportRow", "backend daily report matcher"], + [service, "daily_report", "backend daily report category"], + [dto, "report_id", "backend report id row field"], + [test, "queryAdminWorkbenchDailyReportsReturnsDailyReportRowsOnly", "backend daily report workbench test"], + [qimingTypes, "daily_reports", "qiming daily report view type"], + [qimingOps, "日报运营", "qiming daily report tab"], + [qimingOps, "记录已送达", "qiming daily report delivered action"], + [qimingOps, "确认回执", "qiming daily report confirmed action"], + [qimingOps, "请求审批", "qiming daily report approval action"], + [qimingOps, "记录发送结果", "qiming daily report send record action"], + [docs, "正式管理端日报运营预览", "docs daily report absorption"], + ]; + const missing = requiredSnippets + .filter(([content, snippet]) => !content.includes(snippet)) + .map(([, , label]) => label); + if (missing.length > 0) { + throw new Error(`Missing admin daily report workbench hooks: ${missing.join(", ")}`); + } + console.log("[DigitalEmployeeCheck] admin daily report workbench hooks OK"); +} + function checkLocalDatabaseSchema() { console.log("\n[DigitalEmployeeCheck] Verify local SQLite digital schema"); const dbPath = path.join(os.homedir(), ".qimingclaw", "qimingclaw.db"); @@ -1907,6 +1992,7 @@ function main() { checkDigitalAdminNotificationWorkbench(); checkDigitalAdminArtifactLifecycleWorkbench(); checkDigitalAdminAuditDiagnosticsWorkbench(); + checkDigitalAdminDailyReportWorkbench(); checkLocalDatabaseSchema(); console.log("\n[DigitalEmployeeCheck] All checks passed"); } catch (error) { diff --git a/qimingclaw/docs/digital-employee-frontend-integration-plan.md b/qimingclaw/docs/digital-employee-frontend-integration-plan.md index 053d139d..bd938dda 100644 --- a/qimingclaw/docs/digital-employee-frontend-integration-plan.md +++ b/qimingclaw/docs/digital-employee-frontend-integration-plan.md @@ -614,7 +614,7 @@ GET /api/digital-employee/approvals - 建议:先使用 sync record 派生业务查询模型和 embedded 业务视图预览承接联调,再按容量和查询压力决定是否拆 Plan / Task / Run / Event 物理业务表。 13. **日报实体与导出交付** - - 已吸收:embedded 页面可基于当前 workday projection 导出本地文本日报;生成日报时会通过 qimingclaw bridge 写入 `daily_report` text / HTML / PDF Artifact 与 `daily_report_generated` Event,并可通过 `/api/digital-employee/daily-reports` 和详情接口读取只读日报投影。日报 HTML/PDF 导出、发送记录、管理端确认回执和日报发送审批已开始吸收,交付动作会写入 `daily_report_send_recorded` / `daily_report_confirmed` / `daily_report_approval_requested` 事件,sync `business_view.category = daily_report` 可被管理端筛选消费。管理端正式日报页面预览已开始吸收,embedded 新增“日报运营”入口,展示日报生成、交付、确认、审批和关联产物状态,并复用现有生成、记录发送、确认回执和请求审批动作。发送账单审计外壳已开始吸收,qiming-backend 新增 `/api/digital-employee/admin/daily-reports/send-records`,qiming 运营台可在日报详情中“记录发送结果”,但不接真实第三方发送通道。 + - 已吸收:embedded 页面可基于当前 workday projection 导出本地文本日报;生成日报时会通过 qimingclaw bridge 写入 `daily_report` text / HTML / PDF Artifact 与 `daily_report_generated` Event,并可通过 `/api/digital-employee/daily-reports` 和详情接口读取只读日报投影。日报 HTML/PDF 导出、发送记录、管理端确认回执和日报发送审批已开始吸收,交付动作会写入 `daily_report_send_recorded` / `daily_report_confirmed` / `daily_report_approval_requested` 事件,sync `business_view.category = daily_report` 可被管理端筛选消费。管理端正式日报页面预览和正式管理端日报运营预览已开始吸收,embedded 新增“日报运营”入口,展示日报生成、交付、确认、审批和关联产物状态,并复用现有生成、记录发送、确认回执和请求审批动作;qiming-backend 的 `daily_reports` 运营台视图会聚合日报生成、发送记录、确认回执和审批请求,qiming“数字员工运营台”的“日报运营”tab 可记录已送达、确认回执、请求审批和发送结果。发送账单审计外壳已开始吸收,qiming-backend 新增 `/api/digital-employee/admin/daily-reports/send-records`,qiming 运营台可在日报详情中“记录发送结果”,但不接真实第三方发送通道。 - 缺口:没有正式 DailyReport 物理表、真实管理端发送通道、正式外部管理端日报页面和审批裁决回写闭环。 - 建议:先稳定 Artifact/Event 派生日报交付模型,再根据管理端联调需要决定是否物化 DailyReport 表与发送记录表。