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 44dc490c..eb36bfed 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
@@ -1003,6 +1003,7 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
case "notifications" -> isNotificationRow(row);
case "audits" -> isAuditRow(row);
case "daily_reports" -> isDailyReportRow(row);
+ case "governance_commands" -> isGovernanceCommandRow(row);
case "route_governance" -> isRouteGovernanceRow(row);
default -> true;
};
@@ -1072,6 +1073,12 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
|| StringUtils.isNotBlank(row.getReportId());
}
+ private boolean isGovernanceCommandRow(DigitalEmployeeAdminWorkbenchRowDto row) {
+ return StringUtils.equals(row.getCategory(), "governance")
+ || startsWithAny(row.getKind(), "governance_")
+ || StringUtils.isNotBlank(firstString(row.getBusinessView().get("command_id"), row.getPayload().get("command_id")));
+ }
+
private boolean isRouteGovernanceRow(DigitalEmployeeAdminWorkbenchRowDto row) {
return StringUtils.equals(row.getCategory(), "route_governance")
|| StringUtils.equals(row.getCategory(), "route_intervention")
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 9a976741..4bb9c1b7 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
@@ -468,6 +468,76 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
assertThat(result.getRecords().get(2).getRouteDecisionId()).isEqualTo("route-3");
}
+ @Test
+ void queryAdminWorkbenchGovernanceCommandsReturnsGovernanceRowsOnly() {
+ 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-governance-pause", "event", "event-governance-1", 101L, new Date(10_000),
+ Map.of(
+ "entity_type", "event",
+ "category", "governance",
+ "kind", "governance_pause_plan",
+ "status", "recorded",
+ "title", "暂停计划命令",
+ "summary", "低风险治理命令已记录",
+ "command_id", "command-1",
+ "plan_id", "plan-1",
+ "risk_level", "low"
+ ),
+ Map.of("id", "event-governance-1", "kind", "governance_pause_plan")),
+ record("outbox-governance-input", "event", "event-governance-2", 101L, new Date(11_000),
+ Map.of(
+ "entity_type", "event",
+ "kind", "governance_provide_task_input",
+ "status", "accepted",
+ "title", "补充任务输入",
+ "command_id", "command-2",
+ "task_id", "task-1",
+ "input_length", 18
+ ),
+ Map.of("id", "event-governance-2", "kind", "governance_provide_task_input")),
+ record("outbox-governance-rejected", "event", "event-governance-3", 101L, new Date(12_000),
+ Map.of(
+ "entity_type", "event",
+ "category", "governance",
+ "kind", "governance_cancel_task",
+ "status", "rejected",
+ "title", "取消任务被拒绝",
+ "command_id", "command-3",
+ "task_id", "task-2",
+ "error", "approval_required"
+ ),
+ Map.of("id", "event-governance-3", "kind", "governance_cancel_task")),
+ record("outbox-route", "event", "event-route-1", 101L, new Date(13_000),
+ Map.of("entity_type", "event", "category", "route_governance", "title", "路由", "status", "blocked"),
+ Map.of("id", "event-route-1", "status", "blocked")),
+ 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(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(16_000),
+ Map.of("entity_type", "notification", "title", "普通通知", "status", "unread"),
+ Map.of("id", "notification-1", "status", "unread"))
+ )));
+
+ DigitalEmployeeAdminWorkbenchPageDto result = service.queryAdminWorkbench(
+ "governance_commands", 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("event-governance-1", "event-governance-2", "event-governance-3");
+ assertThat(result.getRecords().get(0).getView()).isEqualTo("governance_commands");
+ assertThat(result.getRecords().get(0).getCategory()).isEqualTo("governance");
+ assertThat(result.getRecords().get(0).getStatus()).isEqualTo("recorded");
+ assertThat(result.getRecords().get(0).getSummary()).isEqualTo("低风险治理命令已记录");
+ assertThat(result.getRecords().get(0).getBusinessView()).containsEntry("command_id", "command-1");
+ assertThat(result.getRecords().get(1).getBusinessView()).containsEntry("input_length", 18);
+ assertThat(result.getRecords().get(2).getBusinessView()).containsEntry("error", "approval_required");
+ }
+
@Test
void queryAdminWorkbenchNotificationsReturnsNotificationRowsOnly() {
when(repository.queryBusinessRecords(eq(101L), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(1L), eq(20L)))
diff --git a/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx b/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx
index 78197654..9b733a47 100644
--- a/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx
+++ b/qiming/src/pages/SystemManagement/Content/DigitalEmployeeOps/index.tsx
@@ -44,6 +44,7 @@ const WORKBENCH_TABS: Array<{
{ key: 'notifications', label: '通知运营' },
{ key: 'audits', label: '审计诊断' },
{ key: 'daily_reports', label: '日报运营' },
+ { key: 'governance_commands', label: '治理命令' },
{ key: 'route_governance', label: '路由治理' },
{ key: 'policy_conflicts', label: '策略冲突' },
];
@@ -168,6 +169,9 @@ function actionTarget(record: DigitalEmployeeAdminWorkbenchRow, view: DigitalEmp
if (view === 'audits') {
return { entityType: 'audit', entityId: record.entity_id };
}
+ if (view === 'governance_commands') {
+ return { entityType: 'event', entityId: record.entity_id };
+ }
if (view === 'policy_conflicts') {
return {
entityType: 'policy_snapshot',
@@ -242,6 +246,12 @@ function allowedActions(record: DigitalEmployeeAdminWorkbenchRow, view: DigitalE
{ action: 'dismiss', label: '忽略' },
];
}
+ if (view === 'governance_commands') {
+ return [
+ { action: 'mark_reviewed', label: '标记已看' },
+ { action: 'dismiss', label: '忽略' },
+ ];
+ }
return [];
}
@@ -749,6 +759,17 @@ const DigitalEmployeeOps: React.FC = () => {
)}
+ {activeView === 'governance_commands' && (
+