From 642521035b602ec460d08e9af1318b9acbd0bd83 Mon Sep 17 00:00:00 2001 From: baiyanyun Date: Mon, 15 Jun 2026 09:54:56 +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=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E8=A3=81=E5=86=B3=E5=9B=9E=E5=86=99=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DigitalEmployeeAdminWorkbenchRowDto.java | 10 ++++++ ...talEmployeeSyncApplicationServiceImpl.java | 11 +++++-- ...mployeeSyncApplicationServiceImplTest.java | 33 +++++++++++++++---- .../Content/DigitalEmployeeOps/index.tsx | 15 ++++++++- qiming/src/types/interfaces/systemManage.ts | 5 +++ .../scripts/check-digital-employee.js | 8 +++++ ...ital-employee-frontend-integration-plan.md | 4 +-- 7 files changed, 75 insertions(+), 11 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/dto/digital/DigitalEmployeeAdminWorkbenchRowDto.java b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/dto/digital/DigitalEmployeeAdminWorkbenchRowDto.java index 1b987014..3b9c57f2 100644 --- a/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/dto/digital/DigitalEmployeeAdminWorkbenchRowDto.java +++ b/qiming-backend/app-platform-modules/app-platform-agent/app-platform-agent-core-adapter/src/main/java/com/xspaceagi/agent/core/adapter/dto/digital/DigitalEmployeeAdminWorkbenchRowDto.java @@ -109,6 +109,16 @@ public class DigitalEmployeeAdminWorkbenchRowDto { private String sendRecordId; @JsonProperty("approval_decision_status") private String approvalDecisionStatus; + @JsonProperty("daily_report_approval_id") + private String dailyReportApprovalId; + @JsonProperty("daily_report_approval_action") + private String dailyReportApprovalAction; + @JsonProperty("daily_report_approval_actor") + private String dailyReportApprovalActor; + @JsonProperty("daily_report_approval_reason") + private String dailyReportApprovalReason; + @JsonProperty("daily_report_approval_recorded_at") + private String dailyReportApprovalRecordedAt; @JsonProperty("route_decision_id") private String routeDecisionId; @JsonProperty("service_id") 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 ee98f144..de21545a 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 @@ -71,7 +71,7 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye "notification:mark_read", "notification:dismiss", "notification_policy:pull_policy", "notification_policy:mark_reviewed", "notification_policy:dismiss", "artifact:mark_keep", "artifact:mark_expire", "artifact:mark_reviewed", "artifact:record_cleanup_request", - "daily_report:mark_delivered", "daily_report:mark_confirmed", "daily_report:request_approval", + "daily_report:mark_delivered", "daily_report:mark_confirmed", "daily_report:request_approval", "daily_report:record_approval_decision", "memory:archive_memory", "memory:restore_memory", "memory:mark_reviewed", "skill:mark_reviewed", "skill:dismiss", "policy_snapshot:pull_policy", "policy_snapshot:mark_reviewed", "policy_snapshot:dismiss", @@ -1123,6 +1123,11 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye .dailyReportFactId(firstString(businessView.get("daily_report_fact_id"), businessView.get("dailyReportFactId"), payload.get("daily_report_fact_id"), payload.get("dailyReportFactId"))) .sendRecordId(firstString(businessView.get("send_record_id"), businessView.get("sendRecordId"), payload.get("send_record_id"), payload.get("sendRecordId"))) .approvalDecisionStatus(firstString(businessView.get("approval_decision_status"), businessView.get("approvalDecisionStatus"), payload.get("approval_decision_status"), payload.get("approvalDecisionStatus"))) + .dailyReportApprovalId(firstString(businessView.get("daily_report_approval_id"), businessView.get("dailyReportApprovalId"), payload.get("daily_report_approval_id"), payload.get("dailyReportApprovalId"))) + .dailyReportApprovalAction(firstString(businessView.get("daily_report_approval_action"), businessView.get("dailyReportApprovalAction"), payload.get("daily_report_approval_action"), payload.get("dailyReportApprovalAction"))) + .dailyReportApprovalActor(firstString(businessView.get("daily_report_approval_actor"), businessView.get("dailyReportApprovalActor"), payload.get("daily_report_approval_actor"), payload.get("dailyReportApprovalActor"))) + .dailyReportApprovalReason(firstString(businessView.get("daily_report_approval_reason"), businessView.get("dailyReportApprovalReason"), payload.get("daily_report_approval_reason"), payload.get("dailyReportApprovalReason"))) + .dailyReportApprovalRecordedAt(firstString(businessView.get("daily_report_approval_recorded_at"), businessView.get("dailyReportApprovalRecordedAt"), payload.get("daily_report_approval_recorded_at"), payload.get("dailyReportApprovalRecordedAt"))) .routeDecisionId(firstString(businessView.get("route_decision_id"), payload.get("route_decision_id"))) .serviceId(firstString(businessView.get("service_id"), businessView.get("serviceId"), payload.get("service_id"), payload.get("serviceId"))) .serviceLeaseId(firstString(businessView.get("service_lease_id"), businessView.get("serviceLeaseId"), payload.get("service_lease_id"), payload.get("serviceLeaseId"))) @@ -1321,7 +1326,9 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye private boolean isDailyReportRow(DigitalEmployeeAdminWorkbenchRowDto row) { return StringUtils.equals(row.getCategory(), "daily_report") || startsWithAny(row.getKind(), "daily_report") - || StringUtils.isNotBlank(row.getReportId()); + || StringUtils.isNotBlank(row.getReportId()) + || StringUtils.isNotBlank(row.getDailyReportApprovalId()) + || StringUtils.isNotBlank(row.getDailyReportApprovalAction()); } private boolean isGovernanceCommandRow(DigitalEmployeeAdminWorkbenchRowDto row) { 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 482c9d5f..38f13a9c 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 @@ -1719,16 +1719,32 @@ class DigitalEmployeeSyncApplicationServiceImplTest { "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), + record("outbox-daily-report-approval", "event", "event-daily-report-3", 101L, new Date(13_000), + Map.ofEntries( + Map.entry("entity_type", "event"), + Map.entry("category", "daily_report"), + Map.entry("kind", "daily_report_approval_decision_recorded"), + Map.entry("status", "approved"), + Map.entry("title", "日报审批裁决已记录"), + Map.entry("report_id", "report-4"), + Map.entry("daily_report_approval_id", "daily-report-approval-1"), + Map.entry("daily_report_approval_action", "approved"), + Map.entry("daily_report_approval_actor", "operator-1"), + Map.entry("daily_report_approval_reason", "content_reviewed"), + Map.entry("daily_report_approval_recorded_at", "2026-06-13T10:30:00+08:00"), + Map.entry("approval_decision_status", "approved") + ), + Map.of("id", "event-daily-report-3", "kind", "daily_report_approval_decision_recorded")), + record("outbox-task", "task", "task-1", 101L, new Date(14_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), + record("outbox-approval", "approval", "approval-1", 101L, new Date(15_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), + record("outbox-notification", "notification", "notification-1", 101L, new Date(16_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), + record("outbox-audit", "event", "event-audit-1", 101L, new Date(17_000), Map.of("entity_type", "event", "category", "tool_call_audit", "title", "审计", "status", "warn"), Map.of("id", "event-audit-1", "status", "warn")) ))); @@ -1737,9 +1753,9 @@ class DigitalEmployeeSyncApplicationServiceImplTest { "daily_reports", null, null, null, null, null, null, null, null, null, null, null, 1L, 20L ); - assertThat(result.getTotal()).isEqualTo(3); + assertThat(result.getTotal()).isEqualTo(4); assertThat(result.getRecords()).extracting(DigitalEmployeeAdminWorkbenchRowDto::getEntityId) - .containsExactly("report-1", "event-daily-report-1", "event-daily-report-2"); + .containsExactly("report-1", "event-daily-report-1", "event-daily-report-2", "event-daily-report-3"); 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"); @@ -1751,6 +1767,11 @@ class DigitalEmployeeSyncApplicationServiceImplTest { 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"); + assertThat(result.getRecords().get(3).getDailyReportApprovalId()).isEqualTo("daily-report-approval-1"); + assertThat(result.getRecords().get(3).getDailyReportApprovalAction()).isEqualTo("approved"); + assertThat(result.getRecords().get(3).getDailyReportApprovalActor()).isEqualTo("operator-1"); + assertThat(result.getRecords().get(3).getDailyReportApprovalReason()).isEqualTo("content_reviewed"); + assertThat(result.getRecords().get(3).getDailyReportApprovalRecordedAt()).isEqualTo("2026-06-13T10:30:00+08:00"); } @Test diff --git a/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx b/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx index 9aac9dc9..9bb8711d 100644 --- a/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx +++ b/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx @@ -339,6 +339,7 @@ function allowedActions(record: DigitalEmployeeAdminWorkbenchRow, view: DigitalE { action: 'mark_delivered', label: '记录已送达' }, { action: 'mark_confirmed', label: '确认回执' }, { action: 'request_approval', label: '请求审批' }, + { action: 'record_approval_decision', label: '记录审批裁决' }, ]; } if (view === 'audits') { @@ -908,6 +909,8 @@ const DigitalEmployeeOps: React.FC = () => { `ReportFact ${detailRecord.daily_report_fact_id}`, detailRecord.send_record_id && `SendRecord ${detailRecord.send_record_id}`, + detailRecord.daily_report_approval_id && + `ReportApproval ${detailRecord.daily_report_approval_id}`, detailRecord.route_decision_id && `Route ${detailRecord.route_decision_id}`, detailRecord.policy_kind && `Policy ${detailRecord.policy_kind}`, @@ -1104,9 +1107,19 @@ const DigitalEmployeeOps: React.FC = () => { ` · 发送记录 ${detailRecord.send_record_id}`} {detailRecord.approval_decision_status && ` · 审批状态 ${detailRecord.approval_decision_status}`} + {detailRecord.daily_report_approval_id && + ` · 审批裁决 ${detailRecord.daily_report_approval_id}`} + {detailRecord.daily_report_approval_action && + ` · 裁决动作 ${detailRecord.daily_report_approval_action}`} + {detailRecord.daily_report_approval_actor && + ` · 裁决人 ${detailRecord.daily_report_approval_actor}`} + {detailRecord.daily_report_approval_reason && + ` · 裁决原因 ${detailRecord.daily_report_approval_reason}`} + {detailRecord.daily_report_approval_recorded_at && + ` · 裁决记录 ${detailRecord.daily_report_approval_recorded_at}`} {' '} - · 展示发送记录、审批状态和事实来源,只记录发送结果/审批/回执意图。 + · 展示发送记录、审批状态、审批裁决和事实来源,只记录发送结果/审批/回执/裁决意图,不触发真实发送或自动审批。 )} diff --git a/qiming/src/types/interfaces/systemManage.ts b/qiming/src/types/interfaces/systemManage.ts index f83eb6a4..470e6fc4 100644 --- a/qiming/src/types/interfaces/systemManage.ts +++ b/qiming/src/types/interfaces/systemManage.ts @@ -637,6 +637,11 @@ export interface DigitalEmployeeAdminWorkbenchRow { daily_report_fact_id?: string; send_record_id?: string; approval_decision_status?: string; + daily_report_approval_id?: string; + daily_report_approval_action?: string; + daily_report_approval_actor?: string; + daily_report_approval_reason?: string; + daily_report_approval_recorded_at?: string; route_decision_id?: string; service_id?: string; service_lease_id?: string; 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 869397fe..77dbc8ec 100644 --- a/qimingclaw/crates/agent-electron-client/scripts/check-digital-employee.js +++ b/qimingclaw/crates/agent-electron-client/scripts/check-digital-employee.js @@ -2791,15 +2791,23 @@ function checkDigitalAdminDailyReportWorkbench() { [service, "daily_reports", "backend daily report view"], [service, "isDailyReportRow", "backend daily report matcher"], [service, "daily_report", "backend daily report category"], + [service, "daily_report:record_approval_decision", "backend daily report approval decision action"], [dto, "report_id", "backend report id row field"], + [dto, "daily_report_approval_id", "backend daily report approval id row field"], + [dto, "daily_report_approval_action", "backend daily report approval action row field"], + [dto, "daily_report_approval_recorded_at", "backend daily report approval recorded at row field"], [test, "queryAdminWorkbenchDailyReportsReturnsDailyReportRowsOnly", "backend daily report workbench test"], + [test, "getDailyReportApprovalId", "backend daily report approval assertion"], [qimingTypes, "daily_reports", "qiming daily report view type"], + [qimingTypes, "daily_report_approval_id", "qiming daily report approval id type field"], [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 approval decision action"], [qimingOps, "记录发送结果", "qiming daily report send record action"], [docs, "正式管理端日报运营预览", "docs daily report absorption"], + [docs, "管理端日报审批裁决回写预览", "docs daily report approval decision absorption"], ]; const missing = requiredSnippets .filter(([content, snippet]) => !content.includes(snippet)) diff --git a/qimingclaw/docs/digital-employee-frontend-integration-plan.md b/qimingclaw/docs/digital-employee-frontend-integration-plan.md index 826de504..906833bb 100644 --- a/qimingclaw/docs/digital-employee-frontend-integration-plan.md +++ b/qimingclaw/docs/digital-employee-frontend-integration-plan.md @@ -614,8 +614,8 @@ 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 的 `daily_reports` 运营台视图会聚合日报生成、发送记录、确认回执和审批请求,qiming“数字员工运营台”的“日报运营”tab 可记录已送达、确认回执、请求审批和发送结果。发送账单审计外壳已开始吸收,qiming-backend 新增 `/api/digital-employee/admin/daily-reports/send-records`,qiming 运营台可在日报详情中“记录发送结果”,但不接真实第三方发送通道。正式管理端协作运营收口已开始吸收,日报运营详情会展示 `daily_report_fact_id`、`send_record_id` 和 `approval_decision_status`,用于解释事实来源、发送记录和审批状态。 - - 缺口:没有正式 DailyReport 物理表、真实管理端发送通道、正式外部管理端日报页面和审批裁决回写闭环。 + - 已吸收: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 运营台可在日报详情中“记录发送结果”,但不接真实第三方发送通道。正式管理端协作运营收口已开始吸收,日报运营详情会展示 `daily_report_fact_id`、`send_record_id` 和 `approval_decision_status`,用于解释事实来源、发送记录和审批状态。管理端日报审批裁决回写预览已开始吸收,日报运营详情可展示 `daily_report_approval_id`、裁决动作、裁决人、原因和记录时间,并只记录审批裁决意图,不触发真实发送或自动审批。 + - 缺口:没有正式 DailyReport 物理表、真实管理端发送通道和正式外部管理端日报页面。 - 建议:先稳定 Artifact/Event 派生日报交付模型,再根据管理端联调需要决定是否物化 DailyReport 表与发送记录表。 ## 管理端联动原则