吸收数字员工管理端协作运营收口

This commit is contained in:
baiyanyun
2026-06-13 15:08:14 +08:00
parent 95838dba04
commit c9d8aa3b93
7 changed files with 244 additions and 21 deletions

View File

@@ -37,10 +37,29 @@ public class DigitalEmployeeAdminWorkbenchRowDto {
private String approvalId;
@JsonProperty("artifact_id")
private String artifactId;
@JsonProperty("cleanup_request_id")
private String cleanupRequestId;
@JsonProperty("cleanup_eligible_count")
private Long cleanupEligibleCount;
@JsonProperty("batch_cleanup_disabled")
private Boolean batchCleanupDisabled;
@JsonProperty("notification_id")
private String notificationId;
@JsonProperty("subscription_policy_id")
private String subscriptionPolicyId;
private String channel;
@JsonProperty("delivery_status")
private String deliveryStatus;
@JsonProperty("conflict_status")
private String conflictStatus;
@JsonProperty("report_id")
private String reportId;
@JsonProperty("daily_report_fact_id")
private String dailyReportFactId;
@JsonProperty("send_record_id")
private String sendRecordId;
@JsonProperty("approval_decision_status")
private String approvalDecisionStatus;
@JsonProperty("route_decision_id")
private String routeDecisionId;
@JsonProperty("service_id")

View File

@@ -68,7 +68,7 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
"route_decision:mark_reviewed", "route_decision:dismiss", "route_decision:retry_policy_check",
"route:mark_reviewed", "route:dismiss", "route:retry_policy_check",
"notification:mark_read", "notification:dismiss",
"artifact:mark_keep", "artifact:mark_expire", "artifact:mark_reviewed",
"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",
"memory:archive_memory", "memory:restore_memory", "memory:mark_reviewed",
"skill:mark_reviewed", "skill:dismiss",
@@ -997,8 +997,18 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
.runId(businessRow.getRunId())
.approvalId(firstString(businessView.get("approval_id"), payload.get("approval_id"), "approval".equals(record.getEntityType()) ? record.getEntityId() : null))
.artifactId(firstString(businessView.get("artifact_id"), payload.get("artifact_id"), "artifact".equals(record.getEntityType()) ? record.getEntityId() : null))
.cleanupRequestId(firstString(businessView.get("cleanup_request_id"), businessView.get("cleanupRequestId"), payload.get("cleanup_request_id"), payload.get("cleanupRequestId")))
.cleanupEligibleCount(numberValue(firstPresent(businessView.get("cleanup_eligible_count"), businessView.get("cleanupEligibleCount"), payload.get("cleanup_eligible_count"), payload.get("cleanupEligibleCount"))))
.batchCleanupDisabled(nullableBooleanValue(firstPresent(businessView.get("batch_cleanup_disabled"), businessView.get("batchCleanupDisabled"), payload.get("batch_cleanup_disabled"), payload.get("batchCleanupDisabled"))))
.notificationId(firstString(businessView.get("notification_id"), payload.get("notification_id")))
.subscriptionPolicyId(firstString(businessView.get("subscription_policy_id"), businessView.get("subscriptionPolicyId"), payload.get("subscription_policy_id"), payload.get("subscriptionPolicyId")))
.channel(firstString(businessView.get("channel"), payload.get("channel")))
.deliveryStatus(firstString(businessView.get("delivery_status"), businessView.get("deliveryStatus"), payload.get("delivery_status"), payload.get("deliveryStatus")))
.conflictStatus(firstString(businessView.get("conflict_status"), businessView.get("conflictStatus"), payload.get("conflict_status"), payload.get("conflictStatus")))
.reportId(firstString(businessView.get("report_id"), payload.get("report_id")))
.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")))
.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")))
.memoryId(firstString(businessView.get("memory_id"), businessView.get("memoryId"), payload.get("memory_id"), payload.get("memoryId"), "memory".equals(record.getEntityType()) ? record.getEntityId() : null))
@@ -1377,6 +1387,13 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
return false;
}
private Boolean nullableBooleanValue(Object value) {
if (value == null) return null;
if (value instanceof Boolean bool) return bool;
if (value instanceof String text && StringUtils.isNotBlank(text)) return Boolean.parseBoolean(text.trim());
return null;
}
private boolean contains(String value, String fragment) {
return StringUtils.containsIgnoreCase(value, fragment);
}
@@ -1447,6 +1464,13 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
return null;
}
private Object firstPresent(Object... values) {
for (Object value : values) {
if (value != null) return value;
}
return null;
}
private String stringValue(Object value, String fallback) {
if (value == null) return fallback;
String text = Objects.toString(value, "").trim();

View File

@@ -870,14 +870,18 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
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-notification", "notification", "notification-1", 101L, new Date(10_000),
Map.of(
"entity_type", "notification",
"category", "notification",
"kind", "notification_received",
"status", "unread",
"title", "通知未读",
"notification_id", "notification-1",
"summary", "等待处理"
Map.ofEntries(
Map.entry("entity_type", "notification"),
Map.entry("category", "notification"),
Map.entry("kind", "notification_received"),
Map.entry("status", "unread"),
Map.entry("title", "通知未读"),
Map.entry("notification_id", "notification-1"),
Map.entry("subscription_policy_id", "subscription-policy-1"),
Map.entry("channel", "desktop"),
Map.entry("delivery_status", "delivered"),
Map.entry("conflict_status", "none"),
Map.entry("summary", "等待处理")
),
Map.of("id", "notification-1", "kind", "notification_received")),
record("outbox-action-notification", "event", "event-notification-1", 101L, new Date(11_000),
@@ -925,6 +929,10 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
assertThat(result.getRecords().get(0).getCategory()).isEqualTo("notification");
assertThat(result.getRecords().get(0).getStatus()).isEqualTo("unread");
assertThat(result.getRecords().get(0).getSummary()).isEqualTo("等待处理");
assertThat(result.getRecords().get(0).getSubscriptionPolicyId()).isEqualTo("subscription-policy-1");
assertThat(result.getRecords().get(0).getChannel()).isEqualTo("desktop");
assertThat(result.getRecords().get(0).getDeliveryStatus()).isEqualTo("delivered");
assertThat(result.getRecords().get(0).getConflictStatus()).isEqualTo("none");
assertThat(result.getRecords().get(1).getCategory()).isEqualTo("action_notification");
assertThat(result.getRecords().get(2).getNotificationId()).isEqualTo("notification-preference");
}
@@ -941,6 +949,9 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
"artifact_id", "artifact-1",
"retention_status", "expired",
"cleanup_status", "pending",
"cleanup_request_id", "cleanup-request-1",
"cleanup_eligible_count", 3,
"batch_cleanup_disabled", true,
"summary", "等待清理"
),
Map.of("id", "artifact-1", "status", "available")),
@@ -995,6 +1006,9 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
assertThat(result.getRecords().get(0).getCategory()).isEqualTo("artifact_lifecycle");
assertThat(result.getRecords().get(0).getStatus()).isEqualTo("available");
assertThat(result.getRecords().get(0).getSummary()).isEqualTo("等待清理");
assertThat(result.getRecords().get(0).getCleanupRequestId()).isEqualTo("cleanup-request-1");
assertThat(result.getRecords().get(0).getCleanupEligibleCount()).isEqualTo(3L);
assertThat(result.getRecords().get(0).getBatchCleanupDisabled()).isTrue();
assertThat(result.getRecords().get(0).getBusinessView()).containsEntry("retention_status", "expired");
assertThat(result.getRecords().get(1).getArtifactId()).isEqualTo("artifact-2");
assertThat(result.getRecords().get(2).getBusinessView()).containsEntry("cleanup_status", "deleted");
@@ -1137,15 +1151,18 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
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.ofEntries(
Map.entry("entity_type", "daily_report"),
Map.entry("category", "daily_report"),
Map.entry("kind", "daily_report_generated"),
Map.entry("status", "generated"),
Map.entry("title", "6 13 日日报"),
Map.entry("report_id", "report-1"),
Map.entry("daily_report_fact_id", "daily-report-fact-1"),
Map.entry("send_record_id", "send-record-1"),
Map.entry("approval_decision_status", "pending"),
Map.entry("summary", "日报已生成"),
Map.entry("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),
@@ -1195,6 +1212,9 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
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(0).getDailyReportFactId()).isEqualTo("daily-report-fact-1");
assertThat(result.getRecords().get(0).getSendRecordId()).isEqualTo("send-record-1");
assertThat(result.getRecords().get(0).getApprovalDecisionStatus()).isEqualTo("pending");
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");