吸收数字员工管理端产物跨设备聚合预览
This commit is contained in:
@@ -54,6 +54,18 @@ public class DigitalEmployeeAdminWorkbenchRowDto {
|
||||
private String approvalId;
|
||||
@JsonProperty("artifact_id")
|
||||
private String artifactId;
|
||||
@JsonProperty("artifact_group_id")
|
||||
private String artifactGroupId;
|
||||
@JsonProperty("artifact_count")
|
||||
private Long artifactCount;
|
||||
@JsonProperty("device_count")
|
||||
private Long deviceCount;
|
||||
@JsonProperty("version_count")
|
||||
private Long versionCount;
|
||||
@JsonProperty("latest_artifact_id")
|
||||
private String latestArtifactId;
|
||||
@JsonProperty("version_key")
|
||||
private String versionKey;
|
||||
@JsonProperty("cleanup_request_id")
|
||||
private String cleanupRequestId;
|
||||
@JsonProperty("cleanup_eligible_count")
|
||||
|
||||
@@ -1069,6 +1069,12 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
|
||||
.triggerSource(firstString(businessView.get("trigger_source"), businessView.get("triggerSource"), payload.get("trigger_source"), payload.get("triggerSource")))
|
||||
.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))
|
||||
.artifactGroupId(firstString(businessView.get("artifact_group_id"), businessView.get("artifactGroupId"), payload.get("artifact_group_id"), payload.get("artifactGroupId")))
|
||||
.artifactCount(numberValue(firstPresent(businessView.get("artifact_count"), businessView.get("artifactCount"), payload.get("artifact_count"), payload.get("artifactCount"))))
|
||||
.deviceCount(numberValue(firstPresent(businessView.get("device_count"), businessView.get("deviceCount"), payload.get("device_count"), payload.get("deviceCount"))))
|
||||
.versionCount(numberValue(firstPresent(businessView.get("version_count"), businessView.get("versionCount"), payload.get("version_count"), payload.get("versionCount"))))
|
||||
.latestArtifactId(firstString(businessView.get("latest_artifact_id"), businessView.get("latestArtifactId"), payload.get("latest_artifact_id"), payload.get("latestArtifactId")))
|
||||
.versionKey(firstString(businessView.get("version_key"), businessView.get("versionKey"), payload.get("version_key"), payload.get("versionKey")))
|
||||
.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"))))
|
||||
@@ -1176,7 +1182,10 @@ public class DigitalEmployeeSyncApplicationServiceImpl implements DigitalEmploye
|
||||
private boolean isArtifactLifecycleRow(DigitalEmployeeAdminWorkbenchRowDto row) {
|
||||
return StringUtils.equals(row.getEntityType(), "artifact")
|
||||
|| startsWithAny(row.getKind(), "artifact_")
|
||||
|| StringUtils.equals(row.getCategory(), "artifact_lifecycle");
|
||||
|| StringUtils.equals(row.getCategory(), "artifact_lifecycle")
|
||||
|| StringUtils.isNotBlank(row.getArtifactGroupId())
|
||||
|| StringUtils.isNotBlank(row.getLatestArtifactId())
|
||||
|| row.getArtifactCount() != null;
|
||||
}
|
||||
|
||||
private boolean isServiceOperationsRow(DigitalEmployeeAdminWorkbenchRowDto row) {
|
||||
|
||||
@@ -1188,6 +1188,12 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
|
||||
"cleanup_request_id", "cleanup-request-1",
|
||||
"cleanup_eligible_count", 3,
|
||||
"batch_cleanup_disabled", true,
|
||||
"artifact_group_id", "daily-report-2026-06-13",
|
||||
"artifact_count", 4,
|
||||
"device_count", 2,
|
||||
"version_count", 3,
|
||||
"latest_artifact_id", "artifact-4",
|
||||
"version_key", "daily-report:2026-06-13",
|
||||
"summary", "等待清理"
|
||||
),
|
||||
Map.of("id", "artifact-1", "status", "available")),
|
||||
@@ -1245,6 +1251,12 @@ class DigitalEmployeeSyncApplicationServiceImplTest {
|
||||
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).getArtifactGroupId()).isEqualTo("daily-report-2026-06-13");
|
||||
assertThat(result.getRecords().get(0).getArtifactCount()).isEqualTo(4L);
|
||||
assertThat(result.getRecords().get(0).getDeviceCount()).isEqualTo(2L);
|
||||
assertThat(result.getRecords().get(0).getVersionCount()).isEqualTo(3L);
|
||||
assertThat(result.getRecords().get(0).getLatestArtifactId()).isEqualTo("artifact-4");
|
||||
assertThat(result.getRecords().get(0).getVersionKey()).isEqualTo("daily-report:2026-06-13");
|
||||
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");
|
||||
|
||||
@@ -120,6 +120,9 @@ function renderSummary(record: DigitalEmployeeAdminWorkbenchRow) {
|
||||
record.recovery_policy_id && `Recovery ${record.recovery_policy_id}`,
|
||||
record.auto_recovery_status && `AutoRecovery ${record.auto_recovery_status}`,
|
||||
record.artifact_id && `Artifact ${record.artifact_id}`,
|
||||
record.artifact_group_id && `ArtifactGroup ${record.artifact_group_id}`,
|
||||
record.artifact_count != null && `Artifacts ${record.artifact_count}`,
|
||||
record.version_count != null && `Versions ${record.version_count}`,
|
||||
record.cleanup_request_id && `Cleanup ${record.cleanup_request_id}`,
|
||||
record.route_decision_id && `Route ${record.route_decision_id}`,
|
||||
record.policy_kind && `Policy ${record.policy_kind}`,
|
||||
@@ -824,6 +827,10 @@ const DigitalEmployeeOps: React.FC = () => {
|
||||
detailRecord.recovery_policy_id &&
|
||||
`RecoveryPolicy ${detailRecord.recovery_policy_id}`,
|
||||
detailRecord.artifact_id && `Artifact ${detailRecord.artifact_id}`,
|
||||
detailRecord.artifact_group_id &&
|
||||
`ArtifactGroup ${detailRecord.artifact_group_id}`,
|
||||
detailRecord.latest_artifact_id &&
|
||||
`LatestArtifact ${detailRecord.latest_artifact_id}`,
|
||||
detailRecord.cleanup_request_id &&
|
||||
`CleanupRequest ${detailRecord.cleanup_request_id}`,
|
||||
detailRecord.notification_id &&
|
||||
@@ -922,10 +929,19 @@ const DigitalEmployeeOps: React.FC = () => {
|
||||
{detailRecord.artifact_id || detailRecord.entity_id || '--'}
|
||||
{detailRecord.cleanup_eligible_count != null &&
|
||||
` · 可清理 ${detailRecord.cleanup_eligible_count} 项`}
|
||||
{detailRecord.artifact_count != null &&
|
||||
` · 产物 ${detailRecord.artifact_count} 项`}
|
||||
{detailRecord.device_count != null &&
|
||||
` · 设备 ${detailRecord.device_count} 台`}
|
||||
{detailRecord.version_count != null &&
|
||||
` · 版本 ${detailRecord.version_count} 个`}
|
||||
{detailRecord.latest_artifact_id &&
|
||||
` · 最新产物 ${detailRecord.latest_artifact_id}`}
|
||||
{detailRecord.version_key && ` · 聚合键 ${detailRecord.version_key}`}
|
||||
{detailRecord.batch_cleanup_disabled && ' · 批量真实清理禁用'}
|
||||
<Typography.Text type="secondary">
|
||||
{' '}
|
||||
· 只允许记录批量清理申请和保留策略意图,不执行批量删除。
|
||||
· 展示跨设备/跨版本聚合,只允许记录批量清理申请和保留策略意图,不执行批量删除。
|
||||
</Typography.Text>
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
|
||||
@@ -603,6 +603,12 @@ export interface DigitalEmployeeAdminWorkbenchRow {
|
||||
trigger_source?: string;
|
||||
approval_id?: string;
|
||||
artifact_id?: string;
|
||||
artifact_group_id?: string;
|
||||
artifact_count?: number;
|
||||
device_count?: number;
|
||||
version_count?: number;
|
||||
latest_artifact_id?: string;
|
||||
version_key?: string;
|
||||
cleanup_request_id?: string;
|
||||
cleanup_eligible_count?: number;
|
||||
batch_cleanup_disabled?: boolean;
|
||||
|
||||
@@ -2323,13 +2323,22 @@ function checkDigitalAdminArtifactLifecycleWorkbench() {
|
||||
[service, "isArtifactLifecycleRow", "backend artifact lifecycle matcher"],
|
||||
[service, "artifact_", "backend artifact event classifier"],
|
||||
[dto, "artifact_id", "backend artifact id row field"],
|
||||
[dto, "artifact_group_id", "backend artifact group id row field"],
|
||||
[dto, "artifact_count", "backend artifact count row field"],
|
||||
[dto, "version_count", "backend artifact version count row field"],
|
||||
[dto, "latest_artifact_id", "backend latest artifact id row field"],
|
||||
[test, "queryAdminWorkbenchArtifactLifecycleReturnsArtifactRowsOnly", "backend artifact lifecycle test"],
|
||||
[test, "getArtifactGroupId", "backend artifact group assertion"],
|
||||
[qimingTypes, "artifact_lifecycle", "qiming artifact lifecycle view type"],
|
||||
[qimingTypes, "artifact_group_id", "qiming artifact group id field"],
|
||||
[qimingTypes, "version_count", "qiming artifact version count field"],
|
||||
[qimingOps, "产物治理", "qiming artifact lifecycle tab"],
|
||||
[qimingOps, "跨设备/跨版本聚合", "qiming artifact aggregate copy"],
|
||||
[qimingOps, "标记保留", "qiming artifact keep action"],
|
||||
[qimingOps, "标记到期", "qiming artifact expire action"],
|
||||
[qimingOps, "标记复核", "qiming artifact reviewed action"],
|
||||
[docs, "正式管理端产物生命周期预览", "docs artifact lifecycle absorption"],
|
||||
[docs, "正式管理端产物跨设备聚合预览", "docs artifact aggregate absorption"],
|
||||
];
|
||||
const missing = requiredSnippets
|
||||
.filter(([content, snippet]) => !content.includes(snippet))
|
||||
|
||||
@@ -584,7 +584,7 @@ GET /api/digital-employee/approvals
|
||||
|
||||
7. **产物交付闭环**
|
||||
- 已吸收:运行 payload 中的 artifacts / outputs / files / uri 可提取为正式 `digital_artifacts` 并同步;File Server workspace / upload / download / export / file update 生命周期状态已开始写入 Artifact payload 的 `delivery` 对象,embedded `/api/artifact` 和日报产物来源可读取交付阶段、状态、文件与 workspace 信息;Artifact 预览/下载权限已开始闭环,嵌入页通过受控 bridge 访问本地产物,并写入 `artifact_access_allowed` / `artifact_access_rejected` 审计事件;Artifact 版本/保留策略已开始闭环,业务产物视图可读取 version / retention 摘要,保留标记会写入 `artifact_retention_marked` / `artifact_retention_rejected` / `artifact_version_observed` 事件。真实文件清理执行已开始吸收,过期本地普通文件可通过独立 `cleanup` bridge 删除,清理结果会写入 `artifact_cleanup_executed` / `artifact_cleanup_rejected` / `artifact_cleanup_failed`,artifact payload 与业务视图会投影 `cleanup_status`、`deleted_at` 和原因字段。保留策略批量治理和跨设备聚合视图已开始吸收,embedded 业务视图新增 `artifact-groups` 产物聚合入口,可按版本/来源聚合产物、统计设备/版本/保留/清理状态,并通过受控批量接口写入保留、到期或复核标记;日报产物来源也提供批量标记到期入口。
|
||||
- 缺口:正式管理端产物生命周期预览已开始吸收,qiming“数字员工运营台”的“产物治理”tab 可只读聚合产物 lifecycle / access / retention / cleanup / version 业务视图,并通过低风险 admin action 记录 `mark_keep` / `mark_expire` / `mark_reviewed` 意图,等待客户端拉取执行;正式管理端协作运营收口已开始吸收,产物治理详情会展示 `cleanup_request_id`、`cleanup_eligible_count` 和 `batch_cleanup_disabled`,只允许记录批量清理申请,不执行批量真实清理。仍缺少批量真实文件清理、复杂跨设备图谱、正式外部生命周期工作台和更完整物化业务表。
|
||||
- 缺口:正式管理端产物生命周期预览已开始吸收,qiming“数字员工运营台”的“产物治理”tab 可只读聚合产物 lifecycle / access / retention / cleanup / version 业务视图,并通过低风险 admin action 记录 `mark_keep` / `mark_expire` / `mark_reviewed` 意图,等待客户端拉取执行;正式管理端协作运营收口已开始吸收,产物治理详情会展示 `cleanup_request_id`、`cleanup_eligible_count` 和 `batch_cleanup_disabled`,只允许记录批量清理申请,不执行批量真实清理。正式管理端产物跨设备聚合预览已开始吸收,产物治理详情可展示 artifact group、产物数、设备数、版本数、最新产物和 version key,用于解释跨设备/跨版本聚合但不触发批量真实删除。仍缺少批量真实文件清理、复杂跨设备图谱、正式外部生命周期工作台和更完整物化业务表。
|
||||
- 建议:下一轮围绕正式管理端生命周期工作台和跨设备图谱,把 embedded 预览聚合推进到跨端运营治理。
|
||||
|
||||
8. **审批 / 人工介入增强**
|
||||
|
||||
Reference in New Issue
Block a user