Compare commits
2 Commits
master
...
codex/clie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a574b2c661 | ||
|
|
5d87c9eee7 |
|
Before Width: | Height: | Size: 403 KiB |
|
Before Width: | Height: | Size: 403 KiB |
|
Before Width: | Height: | Size: 403 KiB |
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
license:
|
|
||||||
---
|
|
||||||
|
|
||||||
# Processing Guide
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "Skill template",
|
|
||||||
"config": {}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# Helper script for this skill
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("Process script placeholder")
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# API Documentation
|
|
||||||
|
|
||||||
Add interface descriptions related to skills here.
|
|
||||||
@@ -104,10 +104,6 @@
|
|||||||
<groupId>com.xspaceagi</groupId>
|
<groupId>com.xspaceagi</groupId>
|
||||||
<artifactId>app-platform-bill-web</artifactId>
|
<artifactId>app-platform-bill-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.application;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminWorkbenchPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminActionPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminActionRequestDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminActionResultDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminRecordRequestDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminRecordResultDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeBillingEstimateDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeBusinessViewPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeePlanBusinessViewDetailDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeePolicySnapshotPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncRecordPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncRequestDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncResponseDto;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface DigitalEmployeeSyncApplicationService {
|
|
||||||
DigitalEmployeeSyncResponseDto syncOutbox(DigitalEmployeeSyncRequestDto request);
|
|
||||||
|
|
||||||
DigitalEmployeeSyncRecordPageDto queryRecords(
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
String outboxId,
|
|
||||||
Long pageNo,
|
|
||||||
Long pageSize
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeeBusinessViewPageDto queryBusinessViews(
|
|
||||||
String entityType,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityId,
|
|
||||||
String status,
|
|
||||||
String syncStatus,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
Long pageNo,
|
|
||||||
Long pageSize
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeePlanBusinessViewDetailDto queryPlanBusinessViewDetail(
|
|
||||||
String planId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeeAdminWorkbenchPageDto queryAdminWorkbench(
|
|
||||||
String view,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
String status,
|
|
||||||
String kind,
|
|
||||||
String category,
|
|
||||||
String level,
|
|
||||||
String priority,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
Long pageNo,
|
|
||||||
Long pageSize
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeePolicySnapshotPageDto queryAdminPolicySnapshots(
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String status,
|
|
||||||
String policyKind,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
Long pageNo,
|
|
||||||
Long pageSize
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeeAdminActionResultDto createAdminAction(DigitalEmployeeAdminActionRequestDto request);
|
|
||||||
|
|
||||||
DigitalEmployeeAdminActionPageDto queryPendingAdminActions(
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
Long pageNo,
|
|
||||||
Long pageSize
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeeAdminActionResultDto markAdminActionResult(
|
|
||||||
Long actionId,
|
|
||||||
String status,
|
|
||||||
List<String> reasonCodes
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeeAdminRecordResultDto recordDailyReportSendResult(DigitalEmployeeAdminRecordRequestDto request);
|
|
||||||
|
|
||||||
DigitalEmployeeBillingEstimateDto queryBillingEstimates(
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo
|
|
||||||
);
|
|
||||||
|
|
||||||
DigitalEmployeeAdminRecordResultDto recordAuditArchive(DigitalEmployeeAdminRecordRequestDto request);
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeAdminActionDto {
|
|
||||||
private Long id;
|
|
||||||
@JsonProperty("client_key_masked")
|
|
||||||
private String clientKeyMasked;
|
|
||||||
@JsonProperty("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonProperty("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonProperty("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String action;
|
|
||||||
private String status;
|
|
||||||
@JsonProperty("reason_codes")
|
|
||||||
private List<String> reasonCodes;
|
|
||||||
@JsonProperty("request_payload")
|
|
||||||
private Map<String, Object> requestPayload;
|
|
||||||
@JsonProperty("created_at")
|
|
||||||
private Date createdAt;
|
|
||||||
@JsonProperty("processed_at")
|
|
||||||
private Date processedAt;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeAdminActionPageDto {
|
|
||||||
private Long total;
|
|
||||||
@JsonProperty("page_no")
|
|
||||||
private Long pageNo;
|
|
||||||
@JsonProperty("page_size")
|
|
||||||
private Long pageSize;
|
|
||||||
private List<DigitalEmployeeAdminActionDto> records;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DigitalEmployeeAdminActionRequestDto {
|
|
||||||
@JsonProperty("sync_record_id")
|
|
||||||
private Long syncRecordId;
|
|
||||||
@JsonProperty("client_key")
|
|
||||||
private String clientKey;
|
|
||||||
@JsonProperty("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonProperty("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonProperty("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String action;
|
|
||||||
@JsonProperty("request_payload")
|
|
||||||
private Map<String, Object> requestPayload;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeAdminActionResultDto {
|
|
||||||
private Boolean ok;
|
|
||||||
private String status;
|
|
||||||
@JsonProperty("reason_codes")
|
|
||||||
private List<String> reasonCodes;
|
|
||||||
private DigitalEmployeeAdminActionDto action;
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DigitalEmployeeAdminRecordRequestDto {
|
|
||||||
@JsonAlias("sync_record_id")
|
|
||||||
private Long syncRecordId;
|
|
||||||
@JsonAlias("client_key")
|
|
||||||
private String clientKey;
|
|
||||||
@JsonAlias("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonAlias("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonAlias("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String status;
|
|
||||||
private String endpoint;
|
|
||||||
@JsonAlias("remote_id")
|
|
||||||
private String remoteId;
|
|
||||||
@JsonAlias("archive_location")
|
|
||||||
private String archiveLocation;
|
|
||||||
@JsonAlias("archive_summary")
|
|
||||||
private Map<String, Object> archiveSummary;
|
|
||||||
private String reason;
|
|
||||||
@JsonProperty("request_payload")
|
|
||||||
@JsonAlias("requestPayload")
|
|
||||||
private Map<String, Object> requestPayload;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeAdminRecordResultDto {
|
|
||||||
private Boolean ok;
|
|
||||||
private String status;
|
|
||||||
@JsonProperty("reason_codes")
|
|
||||||
private List<String> reasonCodes;
|
|
||||||
private DigitalEmployeeAdminActionDto record;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeAdminWorkbenchPageDto {
|
|
||||||
private Long total;
|
|
||||||
@JsonProperty("page_no")
|
|
||||||
private Long pageNo;
|
|
||||||
@JsonProperty("page_size")
|
|
||||||
private Long pageSize;
|
|
||||||
private List<DigitalEmployeeAdminWorkbenchRowDto> records;
|
|
||||||
}
|
|
||||||
@@ -1,364 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeAdminWorkbenchRowDto {
|
|
||||||
private String view;
|
|
||||||
@JsonProperty("sync_record_id")
|
|
||||||
private Long syncRecordId;
|
|
||||||
@JsonProperty("sync_record_url")
|
|
||||||
private String syncRecordUrl;
|
|
||||||
@JsonProperty("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonProperty("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String operation;
|
|
||||||
private String title;
|
|
||||||
private String status;
|
|
||||||
private String kind;
|
|
||||||
private String category;
|
|
||||||
private String level;
|
|
||||||
private String priority;
|
|
||||||
private String summary;
|
|
||||||
@JsonProperty("plan_id")
|
|
||||||
private String planId;
|
|
||||||
@JsonProperty("task_id")
|
|
||||||
private String taskId;
|
|
||||||
@JsonProperty("run_id")
|
|
||||||
private String runId;
|
|
||||||
@JsonProperty("step_id")
|
|
||||||
private String stepId;
|
|
||||||
@JsonProperty("dependency_status")
|
|
||||||
private String dependencyStatus;
|
|
||||||
@JsonProperty("lease_state")
|
|
||||||
private String leaseState;
|
|
||||||
@JsonProperty("lease_source")
|
|
||||||
private String leaseSource;
|
|
||||||
@JsonProperty("dispatch_status")
|
|
||||||
private String dispatchStatus;
|
|
||||||
@JsonProperty("dispatch_policy_key")
|
|
||||||
private String dispatchPolicyKey;
|
|
||||||
@JsonProperty("orchestration_id")
|
|
||||||
private String orchestrationId;
|
|
||||||
@JsonProperty("trigger_source")
|
|
||||||
private String triggerSource;
|
|
||||||
@JsonProperty("approval_id")
|
|
||||||
private String approvalId;
|
|
||||||
@JsonProperty("approval_policy_id")
|
|
||||||
private String approvalPolicyId;
|
|
||||||
@JsonProperty("conflict_policy_id")
|
|
||||||
private String conflictPolicyId;
|
|
||||||
@JsonProperty("decision_guard_status")
|
|
||||||
private String decisionGuardStatus;
|
|
||||||
@JsonProperty("batch_accept_remote_disabled")
|
|
||||||
private Boolean batchAcceptRemoteDisabled;
|
|
||||||
@JsonProperty("auto_decision_disabled")
|
|
||||||
private Boolean autoDecisionDisabled;
|
|
||||||
@JsonProperty("policy_reason")
|
|
||||||
private String policyReason;
|
|
||||||
@JsonProperty("governance_policy_id")
|
|
||||||
private String governancePolicyId;
|
|
||||||
@JsonProperty("policy_guard_status")
|
|
||||||
private String policyGuardStatus;
|
|
||||||
@JsonProperty("hard_interrupt_disabled")
|
|
||||||
private Boolean hardInterruptDisabled;
|
|
||||||
@JsonProperty("artifact_id")
|
|
||||||
private String artifactId;
|
|
||||||
@JsonProperty("artifact_graph_id")
|
|
||||||
private String artifactGraphId;
|
|
||||||
@JsonProperty("artifact_group_id")
|
|
||||||
private String artifactGroupId;
|
|
||||||
@JsonProperty("group_key")
|
|
||||||
private String groupKey;
|
|
||||||
@JsonProperty("related_artifact_ids")
|
|
||||||
private List<String> relatedArtifactIds;
|
|
||||||
@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")
|
|
||||||
private Long cleanupEligibleCount;
|
|
||||||
@JsonProperty("batch_cleanup_disabled")
|
|
||||||
private Boolean batchCleanupDisabled;
|
|
||||||
@JsonProperty("retention_conflict_status")
|
|
||||||
private String retentionConflictStatus;
|
|
||||||
@JsonProperty("cleanup_conflict_status")
|
|
||||||
private String cleanupConflictStatus;
|
|
||||||
@JsonProperty("remote_delete_disabled")
|
|
||||||
private Boolean remoteDeleteDisabled;
|
|
||||||
@JsonProperty("notification_id")
|
|
||||||
private String notificationId;
|
|
||||||
@JsonProperty("collaboration_thread_id")
|
|
||||||
private String collaborationThreadId;
|
|
||||||
@JsonProperty("subscription_policy_id")
|
|
||||||
private String subscriptionPolicyId;
|
|
||||||
@JsonProperty("subscription_conflict_status")
|
|
||||||
private String subscriptionConflictStatus;
|
|
||||||
@JsonProperty("notification_policy_id")
|
|
||||||
private String notificationPolicyId;
|
|
||||||
@JsonProperty("subscription_status")
|
|
||||||
private String subscriptionStatus;
|
|
||||||
@JsonProperty("desktop_enabled")
|
|
||||||
private Boolean desktopEnabled;
|
|
||||||
@JsonProperty("minimum_level")
|
|
||||||
private String minimumLevel;
|
|
||||||
private String channel;
|
|
||||||
@JsonProperty("delivery_status")
|
|
||||||
private String deliveryStatus;
|
|
||||||
@JsonProperty("delivery_attempt_id")
|
|
||||||
private String deliveryAttemptId;
|
|
||||||
@JsonProperty("send_request_id")
|
|
||||||
private String sendRequestId;
|
|
||||||
@JsonProperty("real_push_disabled")
|
|
||||||
private Boolean realPushDisabled;
|
|
||||||
@JsonProperty("conflict_status")
|
|
||||||
private String conflictStatus;
|
|
||||||
@JsonProperty("report_id")
|
|
||||||
private String reportId;
|
|
||||||
@JsonProperty("daily_report_fact_id")
|
|
||||||
private String dailyReportFactId;
|
|
||||||
@JsonProperty("daily_report_table")
|
|
||||||
private String dailyReportTable;
|
|
||||||
@JsonProperty("daily_report_materialized")
|
|
||||||
private Boolean dailyReportMaterialized;
|
|
||||||
@JsonProperty("daily_report_physical_fact_status")
|
|
||||||
private String dailyReportPhysicalFactStatus;
|
|
||||||
@JsonProperty("send_record_id")
|
|
||||||
private String sendRecordId;
|
|
||||||
@JsonProperty("send_channel")
|
|
||||||
private String sendChannel;
|
|
||||||
@JsonProperty("send_request_status")
|
|
||||||
private String sendRequestStatus;
|
|
||||||
@JsonProperty("send_record_status")
|
|
||||||
private String sendRecordStatus;
|
|
||||||
@JsonProperty("formal_daily_report_page_disabled")
|
|
||||||
private Boolean formalDailyReportPageDisabled;
|
|
||||||
@JsonProperty("external_send_disabled")
|
|
||||||
private Boolean externalSendDisabled;
|
|
||||||
@JsonProperty("third_party_channel_disabled")
|
|
||||||
private Boolean thirdPartyChannelDisabled;
|
|
||||||
@JsonProperty("approval_decision_status")
|
|
||||||
private String approvalDecisionStatus;
|
|
||||||
@JsonProperty("advanced_query_supported")
|
|
||||||
private Boolean advancedQuerySupported;
|
|
||||||
@JsonProperty("aggregation_scope")
|
|
||||||
private String aggregationScope;
|
|
||||||
@JsonProperty("materialized_source")
|
|
||||||
private String materializedSource;
|
|
||||||
@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")
|
|
||||||
private String serviceId;
|
|
||||||
@JsonProperty("service_lease_id")
|
|
||||||
private String serviceLeaseId;
|
|
||||||
@JsonProperty("lease_holder")
|
|
||||||
private String leaseHolder;
|
|
||||||
@JsonProperty("lease_expires_at")
|
|
||||||
private String leaseExpiresAt;
|
|
||||||
@JsonProperty("restart_record_id")
|
|
||||||
private String restartRecordId;
|
|
||||||
@JsonProperty("restart_count")
|
|
||||||
private Long restartCount;
|
|
||||||
@JsonProperty("last_restart_at")
|
|
||||||
private String lastRestartAt;
|
|
||||||
@JsonProperty("recovery_policy_id")
|
|
||||||
private String recoveryPolicyId;
|
|
||||||
@JsonProperty("auto_recovery_status")
|
|
||||||
private String autoRecoveryStatus;
|
|
||||||
@JsonProperty("service_start_disabled")
|
|
||||||
private Boolean serviceStartDisabled;
|
|
||||||
@JsonProperty("service_stop_disabled")
|
|
||||||
private Boolean serviceStopDisabled;
|
|
||||||
@JsonProperty("lease_takeover_disabled")
|
|
||||||
private Boolean leaseTakeoverDisabled;
|
|
||||||
@JsonProperty("auto_recovery_disabled")
|
|
||||||
private Boolean autoRecoveryDisabled;
|
|
||||||
@JsonProperty("recovery_action_request_id")
|
|
||||||
private String recoveryActionRequestId;
|
|
||||||
@JsonProperty("start_request_id")
|
|
||||||
private String startRequestId;
|
|
||||||
@JsonProperty("stop_request_id")
|
|
||||||
private String stopRequestId;
|
|
||||||
@JsonProperty("lease_takeover_request_id")
|
|
||||||
private String leaseTakeoverRequestId;
|
|
||||||
@JsonProperty("auto_recovery_request_id")
|
|
||||||
private String autoRecoveryRequestId;
|
|
||||||
@JsonProperty("start_service_disabled")
|
|
||||||
private Boolean startServiceDisabled;
|
|
||||||
@JsonProperty("stop_service_disabled")
|
|
||||||
private Boolean stopServiceDisabled;
|
|
||||||
@JsonProperty("memory_id")
|
|
||||||
private String memoryId;
|
|
||||||
@JsonProperty("memory_key")
|
|
||||||
private String memoryKey;
|
|
||||||
@JsonProperty("governance_status")
|
|
||||||
private String governanceStatus;
|
|
||||||
@JsonProperty("merge_candidate_count")
|
|
||||||
private Long mergeCandidateCount;
|
|
||||||
@JsonProperty("duplicate_memory_ids")
|
|
||||||
private List<String> duplicateMemoryIds;
|
|
||||||
@JsonProperty("latest_memory_id")
|
|
||||||
private String latestMemoryId;
|
|
||||||
@JsonProperty("last_governance_action")
|
|
||||||
private String lastGovernanceAction;
|
|
||||||
@JsonProperty("last_reviewed_at")
|
|
||||||
private String lastReviewedAt;
|
|
||||||
@JsonProperty("memory_policy_id")
|
|
||||||
private String memoryPolicyId;
|
|
||||||
@JsonProperty("memory_policy_status")
|
|
||||||
private String memoryPolicyStatus;
|
|
||||||
@JsonProperty("merge_policy_id")
|
|
||||||
private String mergePolicyId;
|
|
||||||
@JsonProperty("merge_action_disabled")
|
|
||||||
private Boolean mergeActionDisabled;
|
|
||||||
@JsonProperty("remote_memory_policy_disabled")
|
|
||||||
private Boolean remoteMemoryPolicyDisabled;
|
|
||||||
@JsonProperty("skill_id")
|
|
||||||
private String skillId;
|
|
||||||
@JsonProperty("skill_version")
|
|
||||||
private String skillVersion;
|
|
||||||
@JsonProperty("install_status")
|
|
||||||
private String installStatus;
|
|
||||||
@JsonProperty("permission_scope")
|
|
||||||
private String permissionScope;
|
|
||||||
@JsonProperty("policy_source")
|
|
||||||
private String policySource;
|
|
||||||
@JsonProperty("policy_status")
|
|
||||||
private String policyStatus;
|
|
||||||
@JsonProperty("skill_install_request_id")
|
|
||||||
private String skillInstallRequestId;
|
|
||||||
@JsonProperty("skill_upgrade_request_id")
|
|
||||||
private String skillUpgradeRequestId;
|
|
||||||
@JsonProperty("permission_policy_id")
|
|
||||||
private String permissionPolicyId;
|
|
||||||
@JsonProperty("permission_edit_request_id")
|
|
||||||
private String permissionEditRequestId;
|
|
||||||
@JsonProperty("install_action_disabled")
|
|
||||||
private Boolean installActionDisabled;
|
|
||||||
@JsonProperty("upgrade_action_disabled")
|
|
||||||
private Boolean upgradeActionDisabled;
|
|
||||||
@JsonProperty("permission_edit_disabled")
|
|
||||||
private Boolean permissionEditDisabled;
|
|
||||||
@JsonProperty("tool_name")
|
|
||||||
private String toolName;
|
|
||||||
@JsonProperty("server_id")
|
|
||||||
private String serverId;
|
|
||||||
@JsonProperty("audit_archive_id")
|
|
||||||
private String auditArchiveId;
|
|
||||||
@JsonProperty("archive_status")
|
|
||||||
private String archiveStatus;
|
|
||||||
@JsonProperty("archive_location")
|
|
||||||
private String archiveLocation;
|
|
||||||
@JsonProperty("billing_estimate_id")
|
|
||||||
private String billingEstimateId;
|
|
||||||
@JsonProperty("billing_source")
|
|
||||||
private String billingSource;
|
|
||||||
private Boolean estimated;
|
|
||||||
@JsonProperty("diagnostic_id")
|
|
||||||
private String diagnosticId;
|
|
||||||
@JsonProperty("diagnostic_kind")
|
|
||||||
private String diagnosticKind;
|
|
||||||
@JsonProperty("issue_code")
|
|
||||||
private String issueCode;
|
|
||||||
@JsonProperty("repair_action")
|
|
||||||
private String repairAction;
|
|
||||||
@JsonProperty("repair_status")
|
|
||||||
private String repairStatus;
|
|
||||||
@JsonProperty("repair_reason")
|
|
||||||
private String repairReason;
|
|
||||||
@JsonProperty("safe_repair_disabled")
|
|
||||||
private Boolean safeRepairDisabled;
|
|
||||||
@JsonProperty("billing_actual_disabled")
|
|
||||||
private Boolean billingActualDisabled;
|
|
||||||
@JsonProperty("sandbox_archive_file_disabled")
|
|
||||||
private Boolean sandboxArchiveFileDisabled;
|
|
||||||
@JsonProperty("auto_repair_execution_disabled")
|
|
||||||
private Boolean autoRepairExecutionDisabled;
|
|
||||||
@JsonProperty("repair_approval_required")
|
|
||||||
private Boolean repairApprovalRequired;
|
|
||||||
@JsonProperty("recommended_action")
|
|
||||||
private String recommendedAction;
|
|
||||||
@JsonProperty("policy_kind")
|
|
||||||
private String policyKind;
|
|
||||||
@JsonProperty("policy_key")
|
|
||||||
private String policyKey;
|
|
||||||
@JsonProperty("policy_edit_request_id")
|
|
||||||
private String policyEditRequestId;
|
|
||||||
@JsonProperty("policy_edit_status")
|
|
||||||
private String policyEditStatus;
|
|
||||||
@JsonProperty("policy_edit_reason")
|
|
||||||
private String policyEditReason;
|
|
||||||
@JsonProperty("merge_request_id")
|
|
||||||
private String mergeRequestId;
|
|
||||||
@JsonProperty("memory_merge_request_id")
|
|
||||||
private String memoryMergeRequestId;
|
|
||||||
@JsonProperty("remote_memory_policy_request_id")
|
|
||||||
private String remoteMemoryPolicyRequestId;
|
|
||||||
@JsonProperty("merge_recommendation")
|
|
||||||
private String mergeRecommendation;
|
|
||||||
@JsonProperty("remote_policy_edit_disabled")
|
|
||||||
private Boolean remotePolicyEditDisabled;
|
|
||||||
@JsonProperty("auto_merge_disabled")
|
|
||||||
private Boolean autoMergeDisabled;
|
|
||||||
@JsonProperty("approval_policy_edit_disabled")
|
|
||||||
private Boolean approvalPolicyEditDisabled;
|
|
||||||
@JsonProperty("route_policy_edit_disabled")
|
|
||||||
private Boolean routePolicyEditDisabled;
|
|
||||||
@JsonProperty("route_recovery_disabled")
|
|
||||||
private Boolean routeRecoveryDisabled;
|
|
||||||
@JsonProperty("high_risk_execution_disabled")
|
|
||||||
private Boolean highRiskExecutionDisabled;
|
|
||||||
@JsonProperty("schedule_id")
|
|
||||||
private String scheduleId;
|
|
||||||
@JsonProperty("job_id")
|
|
||||||
private String jobId;
|
|
||||||
@JsonProperty("revision_id")
|
|
||||||
private String revisionId;
|
|
||||||
@JsonProperty("revision_fact_id")
|
|
||||||
private String revisionFactId;
|
|
||||||
@JsonProperty("revision_status")
|
|
||||||
private String revisionStatus;
|
|
||||||
@JsonProperty("revision_materialized")
|
|
||||||
private Boolean revisionMaterialized;
|
|
||||||
@JsonProperty("base_revision_id")
|
|
||||||
private String baseRevisionId;
|
|
||||||
@JsonProperty("changed_fields")
|
|
||||||
private List<String> changedFields;
|
|
||||||
@JsonProperty("occurred_at")
|
|
||||||
private String occurredAt;
|
|
||||||
@JsonProperty("synced_at")
|
|
||||||
private Date syncedAt;
|
|
||||||
@JsonProperty("client_key_masked")
|
|
||||||
private String clientKeyMasked;
|
|
||||||
@JsonProperty("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonProperty("business_view")
|
|
||||||
private Map<String, Object> businessView;
|
|
||||||
private Map<String, Object> payload;
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeBillingEstimateDto {
|
|
||||||
@JsonProperty("total_tokens")
|
|
||||||
private Long totalTokens;
|
|
||||||
@JsonProperty("input_tokens")
|
|
||||||
private Long inputTokens;
|
|
||||||
@JsonProperty("output_tokens")
|
|
||||||
private Long outputTokens;
|
|
||||||
@JsonProperty("estimated_cost_usd")
|
|
||||||
private BigDecimal estimatedCostUsd;
|
|
||||||
@JsonProperty("request_count")
|
|
||||||
private Long requestCount;
|
|
||||||
private Boolean estimated;
|
|
||||||
@JsonProperty("by_model")
|
|
||||||
private Map<String, ModelEstimate> byModel;
|
|
||||||
@JsonProperty("updated_at")
|
|
||||||
private Date updatedAt;
|
|
||||||
@JsonProperty("source_records")
|
|
||||||
private List<Long> sourceRecords;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public static class ModelEstimate {
|
|
||||||
@JsonProperty("total_tokens")
|
|
||||||
private Long totalTokens;
|
|
||||||
@JsonProperty("input_tokens")
|
|
||||||
private Long inputTokens;
|
|
||||||
@JsonProperty("output_tokens")
|
|
||||||
private Long outputTokens;
|
|
||||||
@JsonProperty("estimated_cost_usd")
|
|
||||||
private BigDecimal estimatedCostUsd;
|
|
||||||
@JsonProperty("request_count")
|
|
||||||
private Long requestCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeBusinessViewPageDto {
|
|
||||||
private Long total;
|
|
||||||
@JsonProperty("page_no")
|
|
||||||
private Long pageNo;
|
|
||||||
@JsonProperty("page_size")
|
|
||||||
private Long pageSize;
|
|
||||||
private List<DigitalEmployeeBusinessViewRowDto> records;
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeBusinessViewRowDto {
|
|
||||||
@JsonProperty("sync_record_id")
|
|
||||||
private Long syncRecordId;
|
|
||||||
@JsonProperty("sync_record_url")
|
|
||||||
private String syncRecordUrl;
|
|
||||||
@JsonProperty("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonProperty("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String operation;
|
|
||||||
private String title;
|
|
||||||
private String status;
|
|
||||||
private String summary;
|
|
||||||
@JsonProperty("plan_id")
|
|
||||||
private String planId;
|
|
||||||
@JsonProperty("task_id")
|
|
||||||
private String taskId;
|
|
||||||
@JsonProperty("run_id")
|
|
||||||
private String runId;
|
|
||||||
private String kind;
|
|
||||||
@JsonProperty("occurred_at")
|
|
||||||
private String occurredAt;
|
|
||||||
@JsonProperty("started_at")
|
|
||||||
private String startedAt;
|
|
||||||
@JsonProperty("finished_at")
|
|
||||||
private String finishedAt;
|
|
||||||
@JsonProperty("duration_ms")
|
|
||||||
private Long durationMs;
|
|
||||||
@JsonProperty("sync_status")
|
|
||||||
private String syncStatus;
|
|
||||||
@JsonProperty("client_key_masked")
|
|
||||||
private String clientKeyMasked;
|
|
||||||
@JsonProperty("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonProperty("synced_at")
|
|
||||||
private Date syncedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
@JsonProperty("business_view")
|
|
||||||
private Map<String, Object> businessView;
|
|
||||||
private Map<String, Object> payload;
|
|
||||||
@JsonProperty("task_count")
|
|
||||||
private Integer taskCount;
|
|
||||||
@JsonProperty("run_count")
|
|
||||||
private Integer runCount;
|
|
||||||
@JsonProperty("latest_event_at")
|
|
||||||
private String latestEventAt;
|
|
||||||
@JsonProperty("last_event_message")
|
|
||||||
private String lastEventMessage;
|
|
||||||
@JsonProperty("advanced_query_supported")
|
|
||||||
private Boolean advancedQuerySupported;
|
|
||||||
@JsonProperty("aggregation_scope")
|
|
||||||
private String aggregationScope;
|
|
||||||
@JsonProperty("materialized_source")
|
|
||||||
private String materializedSource;
|
|
||||||
private Boolean materialized;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeePlanBusinessViewDetailDto {
|
|
||||||
private DigitalEmployeeBusinessViewRowDto plan;
|
|
||||||
private List<DigitalEmployeeBusinessViewRowDto> tasks;
|
|
||||||
private List<DigitalEmployeeBusinessViewRowDto> runs;
|
|
||||||
private List<DigitalEmployeeBusinessViewRowDto> events;
|
|
||||||
private List<DigitalEmployeeBusinessViewRowDto> artifacts;
|
|
||||||
private List<DigitalEmployeeBusinessViewRowDto> approvals;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeePolicySnapshotPageDto {
|
|
||||||
private Long total;
|
|
||||||
@JsonProperty("page_no")
|
|
||||||
private Long pageNo;
|
|
||||||
@JsonProperty("page_size")
|
|
||||||
private Long pageSize;
|
|
||||||
private List<DigitalEmployeePolicySnapshotRowDto> records;
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeePolicySnapshotRowDto {
|
|
||||||
@JsonProperty("policy_kind")
|
|
||||||
private String policyKind;
|
|
||||||
@JsonProperty("policy_key")
|
|
||||||
private String policyKey;
|
|
||||||
private String status;
|
|
||||||
private String summary;
|
|
||||||
@JsonProperty("client_count")
|
|
||||||
private Integer clientCount;
|
|
||||||
@JsonProperty("device_count")
|
|
||||||
private Integer deviceCount;
|
|
||||||
@JsonProperty("conflict_keys")
|
|
||||||
private List<String> conflictKeys;
|
|
||||||
@JsonProperty("latest_synced_at")
|
|
||||||
private Date latestSyncedAt;
|
|
||||||
@JsonProperty("recommended_resolution")
|
|
||||||
private String recommendedResolution;
|
|
||||||
@JsonProperty("route_decision_count")
|
|
||||||
private Integer routeDecisionCount;
|
|
||||||
@JsonProperty("blocked_count")
|
|
||||||
private Integer blockedCount;
|
|
||||||
@JsonProperty("approval_required_count")
|
|
||||||
private Integer approvalRequiredCount;
|
|
||||||
@JsonProperty("missing_context_count")
|
|
||||||
private Integer missingContextCount;
|
|
||||||
@JsonProperty("not_mapped_count")
|
|
||||||
private Integer notMappedCount;
|
|
||||||
@JsonProperty("intervention_conflict_status")
|
|
||||||
private String interventionConflictStatus;
|
|
||||||
@JsonProperty("approval_policy_id")
|
|
||||||
private String approvalPolicyId;
|
|
||||||
@JsonProperty("conflict_policy_id")
|
|
||||||
private String conflictPolicyId;
|
|
||||||
@JsonProperty("decision_guard_status")
|
|
||||||
private String decisionGuardStatus;
|
|
||||||
@JsonProperty("batch_accept_remote_disabled")
|
|
||||||
private Boolean batchAcceptRemoteDisabled;
|
|
||||||
@JsonProperty("auto_decision_disabled")
|
|
||||||
private Boolean autoDecisionDisabled;
|
|
||||||
@JsonProperty("policy_reason")
|
|
||||||
private String policyReason;
|
|
||||||
@JsonProperty("dispatch_policy_key")
|
|
||||||
private String dispatchPolicyKey;
|
|
||||||
@JsonProperty("max_per_sweep")
|
|
||||||
private Long maxPerSweep;
|
|
||||||
@JsonProperty("auto_dispatch_ready_steps")
|
|
||||||
private Boolean autoDispatchReadySteps;
|
|
||||||
@JsonProperty("catch_up_on_startup")
|
|
||||||
private Boolean catchUpOnStartup;
|
|
||||||
@JsonProperty("max_run_history")
|
|
||||||
private Long maxRunHistory;
|
|
||||||
@JsonProperty("sync_record_url")
|
|
||||||
private String syncRecordUrl;
|
|
||||||
@JsonProperty("client_key_masked")
|
|
||||||
private String clientKeyMasked;
|
|
||||||
@JsonProperty("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonProperty("business_view")
|
|
||||||
private Map<String, Object> businessView;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeSyncAckDto {
|
|
||||||
@JsonProperty("outbox_id")
|
|
||||||
private String outboxId;
|
|
||||||
@JsonProperty("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonProperty("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
@JsonProperty("remote_id")
|
|
||||||
private String remoteId;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DigitalEmployeeSyncItemDto {
|
|
||||||
@JsonAlias("outbox_id")
|
|
||||||
private String outboxId;
|
|
||||||
@JsonAlias("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonAlias("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String operation;
|
|
||||||
@JsonAlias("contract_version")
|
|
||||||
private String contractVersion;
|
|
||||||
@JsonAlias("entity_summary")
|
|
||||||
private Map<String, Object> entitySummary;
|
|
||||||
@JsonAlias("business_view")
|
|
||||||
private Map<String, Object> businessView;
|
|
||||||
private Map<String, Object> payload;
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeSyncRecordDto {
|
|
||||||
private Long id;
|
|
||||||
@JsonProperty("client_key")
|
|
||||||
private String clientKey;
|
|
||||||
@JsonProperty("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
@JsonProperty("outbox_id")
|
|
||||||
private String outboxId;
|
|
||||||
@JsonProperty("entity_type")
|
|
||||||
private String entityType;
|
|
||||||
@JsonProperty("entity_id")
|
|
||||||
private String entityId;
|
|
||||||
private String operation;
|
|
||||||
@JsonProperty("contract_version")
|
|
||||||
private String contractVersion;
|
|
||||||
@JsonProperty("entity_summary")
|
|
||||||
private String entitySummary;
|
|
||||||
@JsonProperty("business_view")
|
|
||||||
private String businessView;
|
|
||||||
private String payload;
|
|
||||||
@JsonProperty("synced_at")
|
|
||||||
private Date syncedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeSyncRecordPageDto {
|
|
||||||
private Long total;
|
|
||||||
@JsonProperty("page_no")
|
|
||||||
private Long pageNo;
|
|
||||||
@JsonProperty("page_size")
|
|
||||||
private Long pageSize;
|
|
||||||
private List<DigitalEmployeeSyncRecordDto> records;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DigitalEmployeeSyncRequestDto {
|
|
||||||
@JsonAlias("client_key")
|
|
||||||
private String clientKey;
|
|
||||||
@JsonAlias("device_id")
|
|
||||||
private String deviceId;
|
|
||||||
private List<DigitalEmployeeSyncItemDto> items;
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.dto.digital;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DigitalEmployeeSyncResponseDto {
|
|
||||||
private List<DigitalEmployeeSyncAckDto> acked;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeAdminAction;
|
|
||||||
|
|
||||||
public interface DigitalEmployeeAdminActionRepository extends IService<DigitalEmployeeAdminAction> {
|
|
||||||
IPage<DigitalEmployeeAdminAction> queryActions(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String status,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeArtifactLifecycle;
|
|
||||||
|
|
||||||
public interface DigitalEmployeeArtifactLifecycleRepository extends IService<DigitalEmployeeArtifactLifecycle> {
|
|
||||||
void upsertBySyncRecord(DigitalEmployeeArtifactLifecycle lifecycle);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeBusinessFact;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public interface DigitalEmployeeBusinessFactRepository extends IService<DigitalEmployeeBusinessFact> {
|
|
||||||
void upsertBySyncRecord(DigitalEmployeeBusinessFact fact);
|
|
||||||
|
|
||||||
IPage<DigitalEmployeeBusinessFact> queryFacts(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
String syncStatus,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeDailyReportFact;
|
|
||||||
|
|
||||||
public interface DigitalEmployeeDailyReportFactRepository extends IService<DigitalEmployeeDailyReportFact> {
|
|
||||||
void upsertBySyncRecord(DigitalEmployeeDailyReportFact fact);
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeSyncRecord;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public interface DigitalEmployeeSyncRecordRepository extends IService<DigitalEmployeeSyncRecord> {
|
|
||||||
IPage<DigitalEmployeeSyncRecord> queryRecords(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
String outboxId,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
);
|
|
||||||
|
|
||||||
IPage<DigitalEmployeeSyncRecord> queryBusinessRecords(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
String syncStatus,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@TableName("digital_employee_admin_action")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class DigitalEmployeeAdminAction {
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
@TableField(value = "_tenant_id")
|
|
||||||
private Long tenantId;
|
|
||||||
private Long userId;
|
|
||||||
private String clientKey;
|
|
||||||
private String deviceId;
|
|
||||||
private String entityType;
|
|
||||||
private String entityId;
|
|
||||||
private String action;
|
|
||||||
private String status;
|
|
||||||
private String reasonCodes;
|
|
||||||
private String requestPayload;
|
|
||||||
private Date processedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@TableName("digital_employee_artifact_lifecycle")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class DigitalEmployeeArtifactLifecycle {
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
@TableField(value = "_tenant_id")
|
|
||||||
private Long tenantId;
|
|
||||||
private Long syncRecordId;
|
|
||||||
private String clientKey;
|
|
||||||
private String deviceId;
|
|
||||||
private String artifactId;
|
|
||||||
private String planId;
|
|
||||||
private String taskId;
|
|
||||||
private String runId;
|
|
||||||
private String status;
|
|
||||||
private String retentionStatus;
|
|
||||||
private String cleanupStatus;
|
|
||||||
private String deletedAt;
|
|
||||||
private String versionKey;
|
|
||||||
private String source;
|
|
||||||
private String businessView;
|
|
||||||
private Date syncedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@TableName("digital_employee_business_fact")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class DigitalEmployeeBusinessFact {
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
@TableField(value = "_tenant_id")
|
|
||||||
private Long tenantId;
|
|
||||||
private Long userId;
|
|
||||||
private Long syncRecordId;
|
|
||||||
private String clientKey;
|
|
||||||
private String deviceId;
|
|
||||||
private String outboxId;
|
|
||||||
private String entityType;
|
|
||||||
private String entityId;
|
|
||||||
private String operation;
|
|
||||||
private String title;
|
|
||||||
private String status;
|
|
||||||
private String summary;
|
|
||||||
private String planId;
|
|
||||||
private String taskId;
|
|
||||||
private String runId;
|
|
||||||
private String kind;
|
|
||||||
private String category;
|
|
||||||
private String occurredAt;
|
|
||||||
private String startedAt;
|
|
||||||
private String finishedAt;
|
|
||||||
private Long durationMs;
|
|
||||||
private String syncStatus;
|
|
||||||
private String businessView;
|
|
||||||
private String payload;
|
|
||||||
private Date syncedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@TableName("digital_employee_daily_report_fact")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class DigitalEmployeeDailyReportFact {
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
@TableField(value = "_tenant_id")
|
|
||||||
private Long tenantId;
|
|
||||||
private Long syncRecordId;
|
|
||||||
private String clientKey;
|
|
||||||
private String deviceId;
|
|
||||||
private String reportId;
|
|
||||||
private String dailyReportFactId;
|
|
||||||
private String planId;
|
|
||||||
private String status;
|
|
||||||
private String physicalFactStatus;
|
|
||||||
private String deliveryStatus;
|
|
||||||
private String approvalStatus;
|
|
||||||
private String approvalDecisionStatus;
|
|
||||||
private String confirmedAt;
|
|
||||||
private String reportDate;
|
|
||||||
private String sendRecordId;
|
|
||||||
private String sendChannel;
|
|
||||||
private String sendRequestStatus;
|
|
||||||
private String sendRecordStatus;
|
|
||||||
private String materializedSource;
|
|
||||||
private String businessView;
|
|
||||||
private Date syncedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.adapter.repository.entity;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@TableName("digital_employee_sync_record")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class DigitalEmployeeSyncRecord {
|
|
||||||
@TableId(value = "id", type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
@TableField(value = "_tenant_id")
|
|
||||||
private Long tenantId;
|
|
||||||
private Long userId;
|
|
||||||
private String clientKey;
|
|
||||||
private String deviceId;
|
|
||||||
private String outboxId;
|
|
||||||
private String entityType;
|
|
||||||
private String entityId;
|
|
||||||
private String operation;
|
|
||||||
private String contractVersion;
|
|
||||||
private String entitySummary;
|
|
||||||
private String businessView;
|
|
||||||
private String payload;
|
|
||||||
private Date syncedAt;
|
|
||||||
private Date modified;
|
|
||||||
private Date created;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.dao.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeAdminAction;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DigitalEmployeeAdminActionMapper extends BaseMapper<DigitalEmployeeAdminAction> {
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.dao.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeArtifactLifecycle;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DigitalEmployeeArtifactLifecycleMapper extends BaseMapper<DigitalEmployeeArtifactLifecycle> {
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.dao.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeBusinessFact;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DigitalEmployeeBusinessFactMapper extends BaseMapper<DigitalEmployeeBusinessFact> {
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.dao.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeDailyReportFact;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DigitalEmployeeDailyReportFactMapper extends BaseMapper<DigitalEmployeeDailyReportFact> {
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.dao.mapper;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeSyncRecord;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface DigitalEmployeeSyncRecordMapper extends BaseMapper<DigitalEmployeeSyncRecord> {
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeAdminActionRepository;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeAdminAction;
|
|
||||||
import com.xspaceagi.agent.core.infra.dao.mapper.DigitalEmployeeAdminActionMapper;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class DigitalEmployeeAdminActionRepositoryImpl
|
|
||||||
extends ServiceImpl<DigitalEmployeeAdminActionMapper, DigitalEmployeeAdminAction>
|
|
||||||
implements DigitalEmployeeAdminActionRepository {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IPage<DigitalEmployeeAdminAction> queryActions(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String status,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
) {
|
|
||||||
LambdaQueryWrapper<DigitalEmployeeAdminAction> queryWrapper = new LambdaQueryWrapper<DigitalEmployeeAdminAction>()
|
|
||||||
.eq(tenantId != null, DigitalEmployeeAdminAction::getTenantId, tenantId)
|
|
||||||
.eq(StringUtils.isNotBlank(clientKey), DigitalEmployeeAdminAction::getClientKey, clientKey)
|
|
||||||
.eq(StringUtils.isNotBlank(deviceId), DigitalEmployeeAdminAction::getDeviceId, deviceId)
|
|
||||||
.eq(StringUtils.isNotBlank(status), DigitalEmployeeAdminAction::getStatus, status)
|
|
||||||
.orderByAsc(DigitalEmployeeAdminAction::getCreated)
|
|
||||||
.orderByAsc(DigitalEmployeeAdminAction::getId);
|
|
||||||
return page(new Page<>(pageNo, pageSize), queryWrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeArtifactLifecycleRepository;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeArtifactLifecycle;
|
|
||||||
import com.xspaceagi.agent.core.infra.dao.mapper.DigitalEmployeeArtifactLifecycleMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class DigitalEmployeeArtifactLifecycleRepositoryImpl
|
|
||||||
extends ServiceImpl<DigitalEmployeeArtifactLifecycleMapper, DigitalEmployeeArtifactLifecycle>
|
|
||||||
implements DigitalEmployeeArtifactLifecycleRepository {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upsertBySyncRecord(DigitalEmployeeArtifactLifecycle lifecycle) {
|
|
||||||
if (lifecycle == null || lifecycle.getTenantId() == null || lifecycle.getSyncRecordId() == null) return;
|
|
||||||
DigitalEmployeeArtifactLifecycle existing = getOne(new LambdaQueryWrapper<DigitalEmployeeArtifactLifecycle>()
|
|
||||||
.eq(DigitalEmployeeArtifactLifecycle::getTenantId, lifecycle.getTenantId())
|
|
||||||
.eq(DigitalEmployeeArtifactLifecycle::getSyncRecordId, lifecycle.getSyncRecordId()), false);
|
|
||||||
if (existing == null) {
|
|
||||||
save(lifecycle);
|
|
||||||
} else {
|
|
||||||
lifecycle.setId(existing.getId());
|
|
||||||
lifecycle.setCreated(existing.getCreated());
|
|
||||||
updateById(lifecycle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeBusinessFactRepository;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeBusinessFact;
|
|
||||||
import com.xspaceagi.agent.core.infra.dao.mapper.DigitalEmployeeBusinessFactMapper;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class DigitalEmployeeBusinessFactRepositoryImpl
|
|
||||||
extends ServiceImpl<DigitalEmployeeBusinessFactMapper, DigitalEmployeeBusinessFact>
|
|
||||||
implements DigitalEmployeeBusinessFactRepository {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upsertBySyncRecord(DigitalEmployeeBusinessFact fact) {
|
|
||||||
if (fact == null || fact.getTenantId() == null || fact.getSyncRecordId() == null) return;
|
|
||||||
DigitalEmployeeBusinessFact existing = getOne(new LambdaQueryWrapper<DigitalEmployeeBusinessFact>()
|
|
||||||
.eq(DigitalEmployeeBusinessFact::getTenantId, fact.getTenantId())
|
|
||||||
.eq(DigitalEmployeeBusinessFact::getSyncRecordId, fact.getSyncRecordId()), false);
|
|
||||||
if (existing == null) {
|
|
||||||
save(fact);
|
|
||||||
} else {
|
|
||||||
fact.setId(existing.getId());
|
|
||||||
fact.setCreated(existing.getCreated());
|
|
||||||
updateById(fact);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IPage<DigitalEmployeeBusinessFact> queryFacts(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
String syncStatus,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
) {
|
|
||||||
LambdaQueryWrapper<DigitalEmployeeBusinessFact> queryWrapper = new LambdaQueryWrapper<DigitalEmployeeBusinessFact>()
|
|
||||||
.eq(tenantId != null, DigitalEmployeeBusinessFact::getTenantId, tenantId)
|
|
||||||
.eq(StringUtils.isNotBlank(clientKey), DigitalEmployeeBusinessFact::getClientKey, clientKey)
|
|
||||||
.eq(StringUtils.isNotBlank(deviceId), DigitalEmployeeBusinessFact::getDeviceId, deviceId)
|
|
||||||
.eq(StringUtils.isNotBlank(entityType), DigitalEmployeeBusinessFact::getEntityType, entityType)
|
|
||||||
.eq(StringUtils.isNotBlank(entityId), DigitalEmployeeBusinessFact::getEntityId, entityId)
|
|
||||||
.eq(StringUtils.isNotBlank(syncStatus), DigitalEmployeeBusinessFact::getSyncStatus, syncStatus)
|
|
||||||
.ge(updatedFrom != null, DigitalEmployeeBusinessFact::getSyncedAt, updatedFrom)
|
|
||||||
.le(updatedTo != null, DigitalEmployeeBusinessFact::getSyncedAt, updatedTo)
|
|
||||||
.orderByDesc(DigitalEmployeeBusinessFact::getSyncedAt)
|
|
||||||
.orderByDesc(DigitalEmployeeBusinessFact::getId);
|
|
||||||
return page(new Page<>(pageNo, pageSize), queryWrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeDailyReportFactRepository;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeDailyReportFact;
|
|
||||||
import com.xspaceagi.agent.core.infra.dao.mapper.DigitalEmployeeDailyReportFactMapper;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class DigitalEmployeeDailyReportFactRepositoryImpl
|
|
||||||
extends ServiceImpl<DigitalEmployeeDailyReportFactMapper, DigitalEmployeeDailyReportFact>
|
|
||||||
implements DigitalEmployeeDailyReportFactRepository {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upsertBySyncRecord(DigitalEmployeeDailyReportFact fact) {
|
|
||||||
if (fact == null || fact.getTenantId() == null || fact.getSyncRecordId() == null) return;
|
|
||||||
DigitalEmployeeDailyReportFact existing = getOne(new LambdaQueryWrapper<DigitalEmployeeDailyReportFact>()
|
|
||||||
.eq(DigitalEmployeeDailyReportFact::getTenantId, fact.getTenantId())
|
|
||||||
.eq(DigitalEmployeeDailyReportFact::getSyncRecordId, fact.getSyncRecordId()), false);
|
|
||||||
if (existing == null) {
|
|
||||||
save(fact);
|
|
||||||
} else {
|
|
||||||
fact.setId(existing.getId());
|
|
||||||
fact.setCreated(existing.getCreated());
|
|
||||||
updateById(fact);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.xspaceagi.agent.core.infra.repository;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.DigitalEmployeeSyncRecordRepository;
|
|
||||||
import com.xspaceagi.agent.core.adapter.repository.entity.DigitalEmployeeSyncRecord;
|
|
||||||
import com.xspaceagi.agent.core.infra.dao.mapper.DigitalEmployeeSyncRecordMapper;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class DigitalEmployeeSyncRecordRepositoryImpl
|
|
||||||
extends ServiceImpl<DigitalEmployeeSyncRecordMapper, DigitalEmployeeSyncRecord>
|
|
||||||
implements DigitalEmployeeSyncRecordRepository {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IPage<DigitalEmployeeSyncRecord> queryRecords(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
String outboxId,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
) {
|
|
||||||
LambdaQueryWrapper<DigitalEmployeeSyncRecord> queryWrapper = new LambdaQueryWrapper<DigitalEmployeeSyncRecord>()
|
|
||||||
.eq(tenantId != null, DigitalEmployeeSyncRecord::getTenantId, tenantId)
|
|
||||||
.eq(StringUtils.isNotBlank(clientKey), DigitalEmployeeSyncRecord::getClientKey, clientKey)
|
|
||||||
.eq(StringUtils.isNotBlank(deviceId), DigitalEmployeeSyncRecord::getDeviceId, deviceId)
|
|
||||||
.eq(StringUtils.isNotBlank(entityType), DigitalEmployeeSyncRecord::getEntityType, entityType)
|
|
||||||
.eq(StringUtils.isNotBlank(entityId), DigitalEmployeeSyncRecord::getEntityId, entityId)
|
|
||||||
.eq(StringUtils.isNotBlank(outboxId), DigitalEmployeeSyncRecord::getOutboxId, outboxId)
|
|
||||||
.orderByDesc(DigitalEmployeeSyncRecord::getSyncedAt)
|
|
||||||
.orderByDesc(DigitalEmployeeSyncRecord::getId);
|
|
||||||
return page(new Page<>(pageNo, pageSize), queryWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IPage<DigitalEmployeeSyncRecord> queryBusinessRecords(
|
|
||||||
Long tenantId,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityType,
|
|
||||||
String entityId,
|
|
||||||
Date updatedFrom,
|
|
||||||
Date updatedTo,
|
|
||||||
String syncStatus,
|
|
||||||
long pageNo,
|
|
||||||
long pageSize
|
|
||||||
) {
|
|
||||||
LambdaQueryWrapper<DigitalEmployeeSyncRecord> queryWrapper = new LambdaQueryWrapper<DigitalEmployeeSyncRecord>()
|
|
||||||
.eq(tenantId != null, DigitalEmployeeSyncRecord::getTenantId, tenantId)
|
|
||||||
.eq(StringUtils.isNotBlank(clientKey), DigitalEmployeeSyncRecord::getClientKey, clientKey)
|
|
||||||
.eq(StringUtils.isNotBlank(deviceId), DigitalEmployeeSyncRecord::getDeviceId, deviceId)
|
|
||||||
.eq(StringUtils.isNotBlank(entityType), DigitalEmployeeSyncRecord::getEntityType, entityType)
|
|
||||||
.eq(StringUtils.isNotBlank(entityId), DigitalEmployeeSyncRecord::getEntityId, entityId)
|
|
||||||
.ge(updatedFrom != null, DigitalEmployeeSyncRecord::getSyncedAt, updatedFrom)
|
|
||||||
.le(updatedTo != null, DigitalEmployeeSyncRecord::getSyncedAt, updatedTo)
|
|
||||||
.orderByDesc(DigitalEmployeeSyncRecord::getSyncedAt)
|
|
||||||
.orderByDesc(DigitalEmployeeSyncRecord::getId);
|
|
||||||
return page(new Page<>(pageNo, pageSize), queryWrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
package com.xspaceagi.agent.web.ui.controller;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.application.DigitalEmployeeSyncApplicationService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminActionPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminActionRequestDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminActionResultDto;
|
|
||||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
|
||||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/digital-employee/admin/actions")
|
|
||||||
public class DigitalEmployeeAdminActionController {
|
|
||||||
|
|
||||||
private static final String CLIENT_KEY_HEADER = "X-Qiming-Client-Key";
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST)
|
|
||||||
@RequestMapping(method = RequestMethod.POST)
|
|
||||||
public ReqResult<DigitalEmployeeAdminActionResultDto> createAction(
|
|
||||||
@RequestBody(required = false) DigitalEmployeeAdminActionRequestDto request
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.createAdminAction(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(path = "/pending", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeAdminActionPageDto> pendingActions(
|
|
||||||
@RequestHeader(name = CLIENT_KEY_HEADER, required = false) String headerClientKey,
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
String normalizedClientKey = StringUtils.defaultIfBlank(clientKey, headerClientKey);
|
|
||||||
if (StringUtils.isBlank(normalizedClientKey)) {
|
|
||||||
return ReqResult.create("0001", "客户端 Key 缺失", null);
|
|
||||||
}
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.queryPendingAdminActions(
|
|
||||||
normalizedClientKey.trim(),
|
|
||||||
deviceId,
|
|
||||||
pageNo,
|
|
||||||
pageSize
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(path = "/{actionId}/result", method = RequestMethod.POST)
|
|
||||||
public ReqResult<DigitalEmployeeAdminActionResultDto> markResult(
|
|
||||||
@PathVariable("actionId") Long actionId,
|
|
||||||
@RequestBody(required = false) Map<String, Object> body
|
|
||||||
) {
|
|
||||||
String status = body == null ? null : String.valueOf(body.get("status"));
|
|
||||||
List<String> reasonCodes = reasonCodes(body == null ? null : body.get("reason_codes"));
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.markAdminActionResult(actionId, status, reasonCodes));
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> reasonCodes(Object value) {
|
|
||||||
if (value instanceof List<?> list) {
|
|
||||||
return list.stream().map(String::valueOf).toList();
|
|
||||||
}
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package com.xspaceagi.agent.web.ui.controller;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.application.DigitalEmployeeSyncApplicationService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeePolicySnapshotPageDto;
|
|
||||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
|
||||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/digital-employee/admin/policies")
|
|
||||||
public class DigitalEmployeeAdminPolicyController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/snapshots", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeePolicySnapshotPageDto> querySnapshots(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "policy_kind", required = false) String policyKind,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.queryAdminPolicySnapshots(
|
|
||||||
clientKey,
|
|
||||||
deviceId,
|
|
||||||
status,
|
|
||||||
policyKind,
|
|
||||||
parseDate(updatedFrom),
|
|
||||||
parseDate(updatedTo),
|
|
||||||
pageNo,
|
|
||||||
pageSize
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date parseDate(String value) {
|
|
||||||
if (StringUtils.isBlank(value)) return null;
|
|
||||||
String trimmed = value.trim();
|
|
||||||
try {
|
|
||||||
return Date.from(Instant.parse(trimmed));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
try {
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
|
||||||
} catch (Exception ignoredAgain) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
package com.xspaceagi.agent.web.ui.controller;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.application.DigitalEmployeeSyncApplicationService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminRecordRequestDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminRecordResultDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeBillingEstimateDto;
|
|
||||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
|
||||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/digital-employee/admin")
|
|
||||||
public class DigitalEmployeeAdminRecordController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/daily-reports/send-records", method = RequestMethod.POST)
|
|
||||||
public ReqResult<DigitalEmployeeAdminRecordResultDto> recordDailyReportSendResult(
|
|
||||||
@RequestBody(required = false) DigitalEmployeeAdminRecordRequestDto request
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.recordDailyReportSendResult(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/billing/estimates", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBillingEstimateDto> queryBillingEstimates(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.queryBillingEstimates(
|
|
||||||
clientKey,
|
|
||||||
deviceId,
|
|
||||||
parseDate(updatedFrom),
|
|
||||||
parseDate(updatedTo)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/audit-archives", method = RequestMethod.POST)
|
|
||||||
public ReqResult<DigitalEmployeeAdminRecordResultDto> recordAuditArchive(
|
|
||||||
@RequestBody(required = false) DigitalEmployeeAdminRecordRequestDto request
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.recordAuditArchive(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date parseDate(String value) {
|
|
||||||
if (StringUtils.isBlank(value)) return null;
|
|
||||||
String trimmed = value.trim();
|
|
||||||
try {
|
|
||||||
return Date.from(Instant.parse(trimmed));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
try {
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
|
||||||
} catch (Exception ignoredAgain) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
package com.xspaceagi.agent.web.ui.controller;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.application.DigitalEmployeeSyncApplicationService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeAdminWorkbenchPageDto;
|
|
||||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
|
||||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/digital-employee/admin/workbench")
|
|
||||||
public class DigitalEmployeeAdminWorkbenchController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/{view}", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeAdminWorkbenchPageDto> queryWorkbench(
|
|
||||||
@PathVariable("view") String view,
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_type", required = false) String entityType,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "kind", required = false) String kind,
|
|
||||||
@RequestParam(name = "category", required = false) String category,
|
|
||||||
@RequestParam(name = "level", required = false) String level,
|
|
||||||
@RequestParam(name = "priority", required = false) String priority,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.queryAdminWorkbench(
|
|
||||||
view,
|
|
||||||
clientKey,
|
|
||||||
deviceId,
|
|
||||||
entityType,
|
|
||||||
entityId,
|
|
||||||
status,
|
|
||||||
kind,
|
|
||||||
category,
|
|
||||||
level,
|
|
||||||
priority,
|
|
||||||
parseDate(updatedFrom),
|
|
||||||
parseDate(updatedTo),
|
|
||||||
pageNo,
|
|
||||||
pageSize
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date parseDate(String value) {
|
|
||||||
if (StringUtils.isBlank(value)) return null;
|
|
||||||
String trimmed = value.trim();
|
|
||||||
try {
|
|
||||||
return Date.from(Instant.parse(trimmed));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
try {
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
|
||||||
} catch (Exception ignoredAgain) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
package com.xspaceagi.agent.web.ui.controller;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.application.DigitalEmployeeSyncApplicationService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeBusinessViewPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeePlanBusinessViewDetailDto;
|
|
||||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
|
||||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/digital-employee")
|
|
||||||
public class DigitalEmployeeBusinessViewController {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/plans", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBusinessViewPageDto> queryPlans(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "sync_status", required = false) String syncStatus,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(query("plan", clientKey, deviceId, entityId, status, syncStatus, updatedFrom, updatedTo, pageNo, pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/plans/{plan_id}", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeePlanBusinessViewDetailDto> queryPlanDetail(
|
|
||||||
@PathVariable("plan_id") String planId,
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.queryPlanBusinessViewDetail(planId, clientKey, deviceId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/tasks", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBusinessViewPageDto> queryTasks(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "sync_status", required = false) String syncStatus,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(query("task", clientKey, deviceId, entityId, status, syncStatus, updatedFrom, updatedTo, pageNo, pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/runs", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBusinessViewPageDto> queryRuns(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "sync_status", required = false) String syncStatus,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(query("run", clientKey, deviceId, entityId, status, syncStatus, updatedFrom, updatedTo, pageNo, pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/events", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBusinessViewPageDto> queryEvents(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "sync_status", required = false) String syncStatus,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(query("event", clientKey, deviceId, entityId, status, syncStatus, updatedFrom, updatedTo, pageNo, pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/artifacts", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBusinessViewPageDto> queryArtifacts(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "sync_status", required = false) String syncStatus,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(query("artifact", clientKey, deviceId, entityId, status, syncStatus, updatedFrom, updatedTo, pageNo, pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/approvals", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeBusinessViewPageDto> queryApprovals(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "status", required = false) String status,
|
|
||||||
@RequestParam(name = "sync_status", required = false) String syncStatus,
|
|
||||||
@RequestParam(name = "updated_from", required = false) String updatedFrom,
|
|
||||||
@RequestParam(name = "updated_to", required = false) String updatedTo,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(query("approval", clientKey, deviceId, entityId, status, syncStatus, updatedFrom, updatedTo, pageNo, pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
private DigitalEmployeeBusinessViewPageDto query(
|
|
||||||
String entityType,
|
|
||||||
String clientKey,
|
|
||||||
String deviceId,
|
|
||||||
String entityId,
|
|
||||||
String status,
|
|
||||||
String syncStatus,
|
|
||||||
String updatedFrom,
|
|
||||||
String updatedTo,
|
|
||||||
Long pageNo,
|
|
||||||
Long pageSize
|
|
||||||
) {
|
|
||||||
return digitalEmployeeSyncApplicationService.queryBusinessViews(
|
|
||||||
entityType,
|
|
||||||
clientKey,
|
|
||||||
deviceId,
|
|
||||||
entityId,
|
|
||||||
status,
|
|
||||||
syncStatus,
|
|
||||||
parseDate(updatedFrom),
|
|
||||||
parseDate(updatedTo),
|
|
||||||
pageNo,
|
|
||||||
pageSize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Date parseDate(String value) {
|
|
||||||
if (StringUtils.isBlank(value)) return null;
|
|
||||||
String trimmed = value.trim();
|
|
||||||
try {
|
|
||||||
return Date.from(Instant.parse(trimmed));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
try {
|
|
||||||
LocalDateTime localDateTime = LocalDateTime.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
|
||||||
} catch (Exception ignoredAgain) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package com.xspaceagi.agent.web.ui.controller;
|
|
||||||
|
|
||||||
import com.xspaceagi.agent.core.adapter.application.DigitalEmployeeSyncApplicationService;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncRecordPageDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncRequestDto;
|
|
||||||
import com.xspaceagi.agent.core.adapter.dto.digital.DigitalEmployeeSyncResponseDto;
|
|
||||||
import com.xspaceagi.system.spec.annotation.RequireResource;
|
|
||||||
import com.xspaceagi.system.spec.dto.ReqResult;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import static com.xspaceagi.system.spec.enums.ResourceEnum.CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/digital-employee/sync")
|
|
||||||
public class DigitalEmployeeSyncController {
|
|
||||||
|
|
||||||
private static final String CLIENT_KEY_HEADER = "X-Qiming-Client-Key";
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private DigitalEmployeeSyncApplicationService digitalEmployeeSyncApplicationService;
|
|
||||||
|
|
||||||
@RequestMapping(path = "/outbox", method = RequestMethod.POST)
|
|
||||||
public ReqResult<DigitalEmployeeSyncResponseDto> syncOutbox(
|
|
||||||
@RequestHeader(name = CLIENT_KEY_HEADER, required = false) String headerClientKey,
|
|
||||||
@RequestBody(required = false) DigitalEmployeeSyncRequestDto request
|
|
||||||
) {
|
|
||||||
if (StringUtils.isBlank(headerClientKey)) {
|
|
||||||
return ReqResult.create("0001", "客户端 Key header 缺失", null);
|
|
||||||
}
|
|
||||||
if (request == null) {
|
|
||||||
request = new DigitalEmployeeSyncRequestDto();
|
|
||||||
}
|
|
||||||
String normalizedHeaderClientKey = headerClientKey.trim();
|
|
||||||
if (StringUtils.isBlank(request.getClientKey())) {
|
|
||||||
request.setClientKey(normalizedHeaderClientKey);
|
|
||||||
} else if (!StringUtils.equals(request.getClientKey().trim(), normalizedHeaderClientKey)) {
|
|
||||||
return ReqResult.create("0001", "客户端 Key header 与请求体不一致", null);
|
|
||||||
} else {
|
|
||||||
request.setClientKey(request.getClientKey().trim());
|
|
||||||
}
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.syncOutbox(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequireResource(CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST)
|
|
||||||
@RequestMapping(path = "/records", method = RequestMethod.GET)
|
|
||||||
public ReqResult<DigitalEmployeeSyncRecordPageDto> queryRecords(
|
|
||||||
@RequestParam(name = "client_key", required = false) String clientKey,
|
|
||||||
@RequestParam(name = "device_id", required = false) String deviceId,
|
|
||||||
@RequestParam(name = "entity_type", required = false) String entityType,
|
|
||||||
@RequestParam(name = "entity_id", required = false) String entityId,
|
|
||||||
@RequestParam(name = "outbox_id", required = false) String outboxId,
|
|
||||||
@RequestParam(name = "page_no", required = false) Long pageNo,
|
|
||||||
@RequestParam(name = "page_size", required = false) Long pageSize
|
|
||||||
) {
|
|
||||||
return ReqResult.success(digitalEmployeeSyncApplicationService.queryRecords(
|
|
||||||
clientKey,
|
|
||||||
deviceId,
|
|
||||||
entityType,
|
|
||||||
entityId,
|
|
||||||
outboxId,
|
|
||||||
pageNo,
|
|
||||||
pageSize
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -417,16 +417,6 @@ public enum ResourceEnum {
|
|||||||
CONTENT_SKILL_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_skill_query_detail", "查询详情", "content_skill"),
|
CONTENT_SKILL_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_skill_query_detail", "查询详情", "content_skill"),
|
||||||
CONTENT_SKILL_DELETE(ResourceTypeEnum.OPERATION, "content_skill_delete", "删除", "content_skill"),
|
CONTENT_SKILL_DELETE(ResourceTypeEnum.OPERATION, "content_skill_delete", "删除", "content_skill"),
|
||||||
|
|
||||||
// 2级模块 - 数字员工同步记录
|
|
||||||
CONTENT_DIGITAL_EMPLOYEE_SYNC(ResourceTypeEnum.MODULE, "content_digital_employee_sync", "数字员工同步记录", "content_manage"),
|
|
||||||
|
|
||||||
CONTENT_DIGITAL_EMPLOYEE_SYNC_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_digital_employee_sync_query_list", "查询列表", "content_digital_employee_sync"),
|
|
||||||
|
|
||||||
// 2级模块 - 数字员工运营台
|
|
||||||
CONTENT_DIGITAL_EMPLOYEE_OPS(ResourceTypeEnum.MODULE, "content_digital_employee_ops", "数字员工运营台", "content_manage"),
|
|
||||||
|
|
||||||
CONTENT_DIGITAL_EMPLOYEE_OPS_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_digital_employee_ops_query_list", "查询列表", "content_digital_employee_ops"),
|
|
||||||
|
|
||||||
// ================== 多语言管理模块 ==================
|
// ================== 多语言管理模块 ==================
|
||||||
I18N_LANG_MANAGE(ResourceTypeEnum.MODULE, "i18n_lang_manage", "多语言管理模块", "root"),
|
I18N_LANG_MANAGE(ResourceTypeEnum.MODULE, "i18n_lang_manage", "多语言管理模块", "root"),
|
||||||
I18N_LANG_QUERY(ResourceTypeEnum.OPERATION, "i18n_lang_query", "查询", "i18n_lang_manage"),
|
I18N_LANG_QUERY(ResourceTypeEnum.OPERATION, "i18n_lang_query", "查询", "i18n_lang_manage"),
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
CREATE TABLE `digital_employee_sync_record`
|
|
||||||
(
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|
||||||
`_tenant_id` BIGINT DEFAULT NULL COMMENT '租户ID',
|
|
||||||
`user_id` BIGINT DEFAULT NULL COMMENT '用户ID',
|
|
||||||
`client_key` VARCHAR(128) NOT NULL COMMENT '客户端配置Key',
|
|
||||||
`device_id` VARCHAR(128) DEFAULT NULL COMMENT '设备ID',
|
|
||||||
`outbox_id` VARCHAR(255) NOT NULL COMMENT '客户端outbox ID',
|
|
||||||
`entity_type` VARCHAR(32) NOT NULL COMMENT '实体类型:plan/task/run/event/artifact/approval',
|
|
||||||
`entity_id` VARCHAR(255) NOT NULL COMMENT '客户端实体ID',
|
|
||||||
`operation` VARCHAR(32) NOT NULL COMMENT '操作类型',
|
|
||||||
`payload` JSON DEFAULT NULL COMMENT '实体快照',
|
|
||||||
`synced_at` DATETIME NOT NULL COMMENT '最近同步时间',
|
|
||||||
`modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
||||||
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_client_outbox` (`client_key`, `outbox_id`),
|
|
||||||
KEY `idx_client_entity` (`client_key`, `entity_type`, `entity_id`),
|
|
||||||
KEY `idx_tenant_client_entity_time` (`_tenant_id`, `client_key`, `entity_type`, `entity_id`, `synced_at`),
|
|
||||||
KEY `idx_tenant_user_time` (`_tenant_id`, `user_id`, `synced_at`)
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_unicode_ci
|
|
||||||
COMMENT = '数字员工客户端同步记录';
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
-- Add digital employee sync records menu and resource.
|
|
||||||
-- Idempotent for existing tenants: creates menu/resource rows, binds menu to resource,
|
|
||||||
-- and grants super_admin default access. Other roles can be granted this menu
|
|
||||||
-- from the menu permission management UI.
|
|
||||||
|
|
||||||
INSERT INTO sys_resource (`parent_id`, `code`, `name`, `description`, `source`, `type`, `sort_index`, `status`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT parent.id, 'content_digital_employee_sync', '数字员工同步记录', '数字员工同步记录', 1, 1, 90, 1, parent.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_resource parent
|
|
||||||
WHERE parent.`code` = 'content_manage' AND parent.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_resource r
|
|
||||||
WHERE r.`_tenant_id` = parent.`_tenant_id` AND r.`code` = 'content_digital_employee_sync' AND r.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sys_resource (`parent_id`, `code`, `name`, `description`, `source`, `type`, `sort_index`, `status`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT parent.id, 'content_digital_employee_sync_query_list', '查询列表', '查询数字员工同步记录', 1, 2, 1, 1, parent.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_resource parent
|
|
||||||
WHERE parent.`code` = 'content_digital_employee_sync' AND parent.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_resource r
|
|
||||||
WHERE r.`_tenant_id` = parent.`_tenant_id` AND r.`code` = 'content_digital_employee_sync_query_list' AND r.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sys_menu (`parent_id`, `code`, `name`, `description`, `source`, `path`, `open_type`, `icon`, `sort_index`, `status`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT parent.id, 'content_digital_employee_sync', '数字员工同步记录', '数字员工同步记录', 1, '/system/content/content-digital-employee-sync', 1, '', 90, 1, parent.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_menu parent
|
|
||||||
WHERE parent.`code` = 'content_manage' AND parent.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_menu m
|
|
||||||
WHERE m.`_tenant_id` = parent.`_tenant_id` AND m.`code` = 'content_digital_employee_sync' AND m.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sys_menu_resource (`menu_id`, `resource_id`, `resource_bind_type`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT m.id, r.id, 1, m.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_menu m
|
|
||||||
JOIN sys_resource r ON r.`_tenant_id` = m.`_tenant_id` AND r.`code` = 'content_digital_employee_sync' AND r.`yn` = 1
|
|
||||||
WHERE m.`code` = 'content_digital_employee_sync' AND m.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_menu_resource mr
|
|
||||||
WHERE mr.`_tenant_id` = m.`_tenant_id` AND mr.`menu_id` = m.id AND mr.`resource_id` = r.id AND mr.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
UPDATE sys_menu_resource mr
|
|
||||||
JOIN sys_menu m ON m.id = mr.menu_id AND m.`_tenant_id` = mr.`_tenant_id` AND m.`code` = 'content_digital_employee_sync' AND m.`yn` = 1
|
|
||||||
JOIN sys_resource r ON r.id = mr.resource_id AND r.`_tenant_id` = mr.`_tenant_id` AND r.`code` = 'content_digital_employee_sync' AND r.`yn` = 1
|
|
||||||
SET mr.`resource_bind_type` = 1,
|
|
||||||
mr.`modified` = CURRENT_TIMESTAMP
|
|
||||||
WHERE mr.`yn` = 1;
|
|
||||||
|
|
||||||
INSERT INTO sys_role_menu (`role_id`, `menu_id`, `menu_bind_type`, `resource_tree_json`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT role.id,
|
|
||||||
menu.id,
|
|
||||||
1,
|
|
||||||
JSON_ARRAY(JSON_OBJECT('id', resource.id, 'code', resource.`code`, 'resourceBindType', 1)),
|
|
||||||
menu.`_tenant_id`,
|
|
||||||
0,
|
|
||||||
'system',
|
|
||||||
1
|
|
||||||
FROM sys_role role
|
|
||||||
JOIN sys_menu menu ON menu.`_tenant_id` = role.`_tenant_id` AND menu.`code` = 'content_digital_employee_sync' AND menu.`yn` = 1
|
|
||||||
JOIN sys_resource resource ON resource.`_tenant_id` = role.`_tenant_id` AND resource.`code` = 'content_digital_employee_sync' AND resource.`yn` = 1
|
|
||||||
WHERE role.`code` = 'super_admin' AND role.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_role_menu rm
|
|
||||||
WHERE rm.`_tenant_id` = role.`_tenant_id` AND rm.`role_id` = role.id AND rm.`menu_id` = menu.id AND rm.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
UPDATE sys_role_menu rm
|
|
||||||
JOIN sys_role role ON role.id = rm.role_id AND role.`_tenant_id` = rm.`_tenant_id` AND role.`code` = 'super_admin' AND role.`yn` = 1
|
|
||||||
JOIN sys_menu menu ON menu.id = rm.menu_id AND menu.`_tenant_id` = rm.`_tenant_id` AND menu.`code` = 'content_digital_employee_sync' AND menu.`yn` = 1
|
|
||||||
JOIN sys_resource resource ON resource.`_tenant_id` = rm.`_tenant_id` AND resource.`code` = 'content_digital_employee_sync' AND resource.`yn` = 1
|
|
||||||
SET rm.`menu_bind_type` = 1,
|
|
||||||
rm.`resource_tree_json` = JSON_ARRAY(JSON_OBJECT('id', resource.id, 'code', resource.`code`, 'resourceBindType', 1)),
|
|
||||||
rm.`modified` = CURRENT_TIMESTAMP
|
|
||||||
WHERE rm.`yn` = 1;
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
ALTER TABLE `digital_employee_sync_record`
|
|
||||||
ADD COLUMN `contract_version` VARCHAR(128) DEFAULT NULL COMMENT '客户端同步契约版本' AFTER `operation`,
|
|
||||||
ADD COLUMN `entity_summary` JSON DEFAULT NULL COMMENT '客户端实体摘要' AFTER `contract_version`,
|
|
||||||
ADD COLUMN `business_view` JSON DEFAULT NULL COMMENT '客户端业务视图投影' AFTER `entity_summary`;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `digital_employee_admin_action` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
|
||||||
`_tenant_id` BIGINT DEFAULT NULL COMMENT '租户 ID',
|
|
||||||
`user_id` BIGINT DEFAULT NULL COMMENT '创建用户 ID',
|
|
||||||
`client_key` VARCHAR(128) DEFAULT NULL COMMENT '客户端 Key',
|
|
||||||
`device_id` VARCHAR(128) DEFAULT NULL COMMENT '设备 ID',
|
|
||||||
`entity_type` VARCHAR(64) DEFAULT NULL COMMENT '实体类型',
|
|
||||||
`entity_id` VARCHAR(128) DEFAULT NULL COMMENT '实体 ID',
|
|
||||||
`action` VARCHAR(64) DEFAULT NULL COMMENT '管理端动作',
|
|
||||||
`status` VARCHAR(32) DEFAULT NULL COMMENT '状态 pending/applied/rejected/failed',
|
|
||||||
`reason_codes` JSON DEFAULT NULL COMMENT '原因码',
|
|
||||||
`request_payload` JSON DEFAULT NULL COMMENT '请求附加参数',
|
|
||||||
`processed_at` DATETIME DEFAULT NULL COMMENT '客户端处理时间',
|
|
||||||
`modified` DATETIME DEFAULT NULL COMMENT '更新时间',
|
|
||||||
`created` DATETIME DEFAULT NULL COMMENT '创建时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `idx_de_admin_action_pending` (`_tenant_id`, `client_key`, `device_id`, `status`, `created`),
|
|
||||||
KEY `idx_de_admin_action_entity` (`_tenant_id`, `entity_type`, `entity_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数字员工管理端远程动作意图';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `digital_employee_business_fact` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`_tenant_id` BIGINT NOT NULL COMMENT '租户ID',
|
|
||||||
`user_id` BIGINT DEFAULT NULL COMMENT '用户ID',
|
|
||||||
`sync_record_id` BIGINT NOT NULL COMMENT '同步记录ID',
|
|
||||||
`client_key` VARCHAR(255) DEFAULT NULL COMMENT '客户端Key',
|
|
||||||
`device_id` VARCHAR(255) DEFAULT NULL COMMENT '设备ID',
|
|
||||||
`outbox_id` VARCHAR(255) DEFAULT NULL COMMENT '客户端outbox ID',
|
|
||||||
`entity_type` VARCHAR(64) NOT NULL COMMENT '实体类型',
|
|
||||||
`entity_id` VARCHAR(255) NOT NULL COMMENT '实体ID',
|
|
||||||
`operation` VARCHAR(64) DEFAULT NULL COMMENT '操作',
|
|
||||||
`title` VARCHAR(512) DEFAULT NULL COMMENT '标题',
|
|
||||||
`status` VARCHAR(128) DEFAULT NULL COMMENT '业务状态',
|
|
||||||
`summary` VARCHAR(1024) DEFAULT NULL COMMENT '摘要',
|
|
||||||
`plan_id` VARCHAR(255) DEFAULT NULL COMMENT '计划ID',
|
|
||||||
`task_id` VARCHAR(255) DEFAULT NULL COMMENT '任务ID',
|
|
||||||
`run_id` VARCHAR(255) DEFAULT NULL COMMENT '运行ID',
|
|
||||||
`kind` VARCHAR(255) DEFAULT NULL COMMENT '类型',
|
|
||||||
`category` VARCHAR(128) DEFAULT NULL COMMENT '分类',
|
|
||||||
`occurred_at` VARCHAR(64) DEFAULT NULL COMMENT '发生时间',
|
|
||||||
`started_at` VARCHAR(64) DEFAULT NULL COMMENT '开始时间',
|
|
||||||
`finished_at` VARCHAR(64) DEFAULT NULL COMMENT '结束时间',
|
|
||||||
`duration_ms` BIGINT DEFAULT NULL COMMENT '耗时毫秒',
|
|
||||||
`sync_status` VARCHAR(128) DEFAULT NULL COMMENT '同步状态',
|
|
||||||
`business_view` JSON DEFAULT NULL COMMENT '业务视图快照',
|
|
||||||
`payload` JSON DEFAULT NULL COMMENT '安全payload快照',
|
|
||||||
`synced_at` DATETIME DEFAULT NULL COMMENT '同步时间',
|
|
||||||
`modified` DATETIME NOT NULL COMMENT '修改时间',
|
|
||||||
`created` DATETIME NOT NULL COMMENT '创建时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_de_business_fact_record` (`_tenant_id`, `sync_record_id`),
|
|
||||||
KEY `idx_de_business_fact_entity` (`_tenant_id`, `entity_type`, `entity_id`),
|
|
||||||
KEY `idx_de_business_fact_plan` (`_tenant_id`, `plan_id`, `entity_type`),
|
|
||||||
KEY `idx_de_business_fact_client` (`_tenant_id`, `client_key`, `device_id`, `synced_at`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数字员工业务事实物化表';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `digital_employee_artifact_lifecycle` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`_tenant_id` BIGINT NOT NULL COMMENT '租户ID',
|
|
||||||
`sync_record_id` BIGINT NOT NULL COMMENT '同步记录ID',
|
|
||||||
`client_key` VARCHAR(255) DEFAULT NULL COMMENT '客户端Key',
|
|
||||||
`device_id` VARCHAR(255) DEFAULT NULL COMMENT '设备ID',
|
|
||||||
`artifact_id` VARCHAR(255) NOT NULL COMMENT '产物ID',
|
|
||||||
`plan_id` VARCHAR(255) DEFAULT NULL COMMENT '计划ID',
|
|
||||||
`task_id` VARCHAR(255) DEFAULT NULL COMMENT '任务ID',
|
|
||||||
`run_id` VARCHAR(255) DEFAULT NULL COMMENT '运行ID',
|
|
||||||
`status` VARCHAR(128) DEFAULT NULL COMMENT '状态',
|
|
||||||
`retention_status` VARCHAR(128) DEFAULT NULL COMMENT '保留状态',
|
|
||||||
`cleanup_status` VARCHAR(128) DEFAULT NULL COMMENT '清理状态',
|
|
||||||
`deleted_at` VARCHAR(64) DEFAULT NULL COMMENT '删除时间',
|
|
||||||
`version_key` VARCHAR(255) DEFAULT NULL COMMENT '版本Key',
|
|
||||||
`source` VARCHAR(255) DEFAULT NULL COMMENT '来源',
|
|
||||||
`business_view` JSON DEFAULT NULL COMMENT '业务视图快照',
|
|
||||||
`synced_at` DATETIME DEFAULT NULL COMMENT '同步时间',
|
|
||||||
`modified` DATETIME NOT NULL COMMENT '修改时间',
|
|
||||||
`created` DATETIME NOT NULL COMMENT '创建时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_de_artifact_lifecycle_record` (`_tenant_id`, `sync_record_id`),
|
|
||||||
KEY `idx_de_artifact_lifecycle_artifact` (`_tenant_id`, `artifact_id`),
|
|
||||||
KEY `idx_de_artifact_lifecycle_plan` (`_tenant_id`, `plan_id`, `task_id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数字员工产物生命周期物化表';
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `digital_employee_daily_report_fact` (
|
|
||||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`_tenant_id` BIGINT NOT NULL COMMENT '租户ID',
|
|
||||||
`sync_record_id` BIGINT NOT NULL COMMENT '同步记录ID',
|
|
||||||
`client_key` VARCHAR(255) DEFAULT NULL COMMENT '客户端Key',
|
|
||||||
`device_id` VARCHAR(255) DEFAULT NULL COMMENT '设备ID',
|
|
||||||
`report_id` VARCHAR(255) NOT NULL COMMENT '日报ID',
|
|
||||||
`daily_report_fact_id` VARCHAR(255) DEFAULT NULL COMMENT '日报事实ID',
|
|
||||||
`plan_id` VARCHAR(255) DEFAULT NULL COMMENT '计划ID',
|
|
||||||
`status` VARCHAR(128) DEFAULT NULL COMMENT '状态',
|
|
||||||
`physical_fact_status` VARCHAR(128) DEFAULT NULL COMMENT '物理事实状态',
|
|
||||||
`delivery_status` VARCHAR(128) DEFAULT NULL COMMENT '交付状态',
|
|
||||||
`approval_status` VARCHAR(128) DEFAULT NULL COMMENT '审批状态',
|
|
||||||
`approval_decision_status` VARCHAR(128) DEFAULT NULL COMMENT '审批裁决状态',
|
|
||||||
`confirmed_at` VARCHAR(64) DEFAULT NULL COMMENT '确认时间',
|
|
||||||
`report_date` VARCHAR(64) DEFAULT NULL COMMENT '日报日期',
|
|
||||||
`send_record_id` VARCHAR(255) DEFAULT NULL COMMENT '发送记录ID',
|
|
||||||
`send_channel` VARCHAR(128) DEFAULT NULL COMMENT '发送渠道',
|
|
||||||
`send_request_status` VARCHAR(128) DEFAULT NULL COMMENT '发送请求状态',
|
|
||||||
`send_record_status` VARCHAR(128) DEFAULT NULL COMMENT '发送记录状态',
|
|
||||||
`materialized_source` VARCHAR(128) DEFAULT NULL COMMENT '物化来源',
|
|
||||||
`business_view` JSON DEFAULT NULL COMMENT '业务视图快照',
|
|
||||||
`synced_at` DATETIME DEFAULT NULL COMMENT '同步时间',
|
|
||||||
`modified` DATETIME NOT NULL COMMENT '修改时间',
|
|
||||||
`created` DATETIME NOT NULL COMMENT '创建时间',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `uk_de_daily_report_fact_record` (`_tenant_id`, `sync_record_id`),
|
|
||||||
KEY `idx_de_daily_report_fact_report` (`_tenant_id`, `report_id`),
|
|
||||||
KEY `idx_de_daily_report_fact_client` (`_tenant_id`, `client_key`, `device_id`, `synced_at`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数字员工日报事实物化表';
|
|
||||||
|
|
||||||
-- Add digital employee admin operations workbench menu and resource.
|
|
||||||
-- Idempotent for existing tenants: creates menu/resource rows, binds menu to resource,
|
|
||||||
-- and grants super_admin default access. Other roles can be granted this menu
|
|
||||||
-- from the menu permission management UI.
|
|
||||||
|
|
||||||
INSERT INTO sys_resource (`parent_id`, `code`, `name`, `description`, `source`, `type`, `sort_index`, `status`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT parent.id, 'content_digital_employee_ops', '数字员工运营台', '数字员工运营台', 1, 1, 91, 1, parent.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_resource parent
|
|
||||||
WHERE parent.`code` = 'content_manage' AND parent.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_resource r
|
|
||||||
WHERE r.`_tenant_id` = parent.`_tenant_id` AND r.`code` = 'content_digital_employee_ops' AND r.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sys_resource (`parent_id`, `code`, `name`, `description`, `source`, `type`, `sort_index`, `status`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT parent.id, 'content_digital_employee_ops_query_list', '查询列表', '查询数字员工运营台', 1, 2, 1, 1, parent.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_resource parent
|
|
||||||
WHERE parent.`code` = 'content_digital_employee_ops' AND parent.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_resource r
|
|
||||||
WHERE r.`_tenant_id` = parent.`_tenant_id` AND r.`code` = 'content_digital_employee_ops_query_list' AND r.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sys_menu (`parent_id`, `code`, `name`, `description`, `source`, `path`, `open_type`, `icon`, `sort_index`, `status`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT parent.id, 'content_digital_employee_ops', '数字员工运营台', '数字员工运营台', 1, '/system/content/content-digital-employee-ops', 1, '', 91, 1, parent.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_menu parent
|
|
||||||
WHERE parent.`code` = 'content_manage' AND parent.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_menu m
|
|
||||||
WHERE m.`_tenant_id` = parent.`_tenant_id` AND m.`code` = 'content_digital_employee_ops' AND m.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO sys_menu_resource (`menu_id`, `resource_id`, `resource_bind_type`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT m.id, r.id, 1, m.`_tenant_id`, 0, 'system', 1
|
|
||||||
FROM sys_menu m
|
|
||||||
JOIN sys_resource r ON r.`_tenant_id` = m.`_tenant_id` AND r.`code` = 'content_digital_employee_ops' AND r.`yn` = 1
|
|
||||||
WHERE m.`code` = 'content_digital_employee_ops' AND m.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_menu_resource mr
|
|
||||||
WHERE mr.`_tenant_id` = m.`_tenant_id` AND mr.`menu_id` = m.id AND mr.`resource_id` = r.id AND mr.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
UPDATE sys_menu_resource mr
|
|
||||||
JOIN sys_menu m ON m.id = mr.menu_id AND m.`_tenant_id` = mr.`_tenant_id` AND m.`code` = 'content_digital_employee_ops' AND m.`yn` = 1
|
|
||||||
JOIN sys_resource r ON r.id = mr.resource_id AND r.`_tenant_id` = mr.`_tenant_id` AND r.`code` = 'content_digital_employee_ops' AND r.`yn` = 1
|
|
||||||
SET mr.`resource_bind_type` = 1,
|
|
||||||
mr.`modified` = CURRENT_TIMESTAMP
|
|
||||||
WHERE mr.`yn` = 1;
|
|
||||||
|
|
||||||
INSERT INTO sys_role_menu (`role_id`, `menu_id`, `menu_bind_type`, `resource_tree_json`, `_tenant_id`, `creator_id`, `creator`, `yn`)
|
|
||||||
SELECT role.id,
|
|
||||||
menu.id,
|
|
||||||
1,
|
|
||||||
JSON_ARRAY(JSON_OBJECT('id', resource.id, 'code', resource.`code`, 'resourceBindType', 1)),
|
|
||||||
menu.`_tenant_id`,
|
|
||||||
0,
|
|
||||||
'system',
|
|
||||||
1
|
|
||||||
FROM sys_role role
|
|
||||||
JOIN sys_menu menu ON menu.`_tenant_id` = role.`_tenant_id` AND menu.`code` = 'content_digital_employee_ops' AND menu.`yn` = 1
|
|
||||||
JOIN sys_resource resource ON resource.`_tenant_id` = role.`_tenant_id` AND resource.`code` = 'content_digital_employee_ops' AND resource.`yn` = 1
|
|
||||||
WHERE role.`code` = 'super_admin' AND role.`yn` = 1
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1 FROM sys_role_menu rm
|
|
||||||
WHERE rm.`_tenant_id` = role.`_tenant_id` AND rm.`role_id` = role.id AND rm.`menu_id` = menu.id AND rm.`yn` = 1
|
|
||||||
);
|
|
||||||
|
|
||||||
UPDATE sys_role_menu rm
|
|
||||||
JOIN sys_role role ON role.id = rm.role_id AND role.`_tenant_id` = rm.`_tenant_id` AND role.`code` = 'super_admin' AND role.`yn` = 1
|
|
||||||
JOIN sys_menu menu ON menu.id = rm.menu_id AND menu.`_tenant_id` = rm.`_tenant_id` AND menu.`code` = 'content_digital_employee_ops' AND menu.`yn` = 1
|
|
||||||
JOIN sys_resource resource ON resource.`_tenant_id` = rm.`_tenant_id` AND resource.`code` = 'content_digital_employee_ops' AND resource.`yn` = 1
|
|
||||||
SET rm.`menu_bind_type` = 1,
|
|
||||||
rm.`resource_tree_json` = JSON_ARRAY(JSON_OBJECT('id', resource.id, 'code', resource.`code`, 'resourceBindType', 1)),
|
|
||||||
rm.`modified` = CURRENT_TIMESTAMP
|
|
||||||
WHERE rm.`yn` = 1;
|
|
||||||
@@ -33,8 +33,7 @@
|
|||||||
"serve": "http-server ./dist",
|
"serve": "http-server ./dist",
|
||||||
"setup": "max setup",
|
"setup": "max setup",
|
||||||
"start": "npm run dev",
|
"start": "npm run dev",
|
||||||
"test": "vitest run",
|
"test": "vitest",
|
||||||
"test:watch": "vitest",
|
|
||||||
"verify-commit": "max verify-commit"
|
"verify-commit": "max verify-commit"
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
@@ -141,15 +140,14 @@
|
|||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"esbuild": "^0.27.0",
|
"esbuild": "^0.27.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"jest-axe": "^10.0.0",
|
"jsdom": "^27.3.0",
|
||||||
"jsdom": "^22.1.0",
|
|
||||||
"lint-staged": "^13.2.0",
|
"lint-staged": "^13.2.0",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"prettier-plugin-organize-imports": "^3.2.2",
|
"prettier-plugin-organize-imports": "^3.2.2",
|
||||||
"prettier-plugin-packagejson": "^2.4.3",
|
"prettier-plugin-packagejson": "^2.4.3",
|
||||||
"standard-version": "^9.5.0",
|
"standard-version": "^9.5.0",
|
||||||
"typescript": "^5.0.3",
|
"typescript": "^5.0.3",
|
||||||
"vitest": "^0.34.6"
|
"vitest": "^4.0.15"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.27.0",
|
"packageManager": "pnpm@10.27.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -1,477 +0,0 @@
|
|||||||
import { XProTable } from '@/components/ProComponents';
|
|
||||||
import WorkspaceLayout from '@/components/WorkspaceLayout';
|
|
||||||
import { SUCCESS_CODE } from '@/constants/codes.constants';
|
|
||||||
import { apiDigitalEmployeeSyncRecordList } from '@/services/systemManage';
|
|
||||||
import type { DigitalEmployeeSyncRecordInfo } from '@/types/interfaces/systemManage';
|
|
||||||
import type {
|
|
||||||
ActionType,
|
|
||||||
FormInstance,
|
|
||||||
ProColumns,
|
|
||||||
} from '@ant-design/pro-components';
|
|
||||||
import { Button, Drawer, message, Space, Tag, Typography } from 'antd';
|
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import { useLocation, useModel, useSearchParams } from 'umi';
|
|
||||||
|
|
||||||
const ENTITY_TYPE_OPTIONS = {
|
|
||||||
plan: { text: 'Plan' },
|
|
||||||
task: { text: 'Task' },
|
|
||||||
run: { text: 'Run' },
|
|
||||||
event: { text: 'Event' },
|
|
||||||
artifact: { text: 'Artifact' },
|
|
||||||
approval: { text: 'Approval' },
|
|
||||||
};
|
|
||||||
|
|
||||||
const ENTITY_TYPE_TONE: Record<string, string> = {
|
|
||||||
plan: 'blue',
|
|
||||||
task: 'geekblue',
|
|
||||||
run: 'purple',
|
|
||||||
event: 'cyan',
|
|
||||||
artifact: 'green',
|
|
||||||
approval: 'orange',
|
|
||||||
};
|
|
||||||
|
|
||||||
const STATUS_TONE: Record<string, string> = {
|
|
||||||
running: 'processing',
|
|
||||||
pending: 'warning',
|
|
||||||
completed: 'success',
|
|
||||||
success: 'success',
|
|
||||||
synced: 'success',
|
|
||||||
failed: 'error',
|
|
||||||
error: 'error',
|
|
||||||
cancelled: 'default',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface PayloadObject {
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SyncBusinessSummary {
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
status?: string;
|
|
||||||
statusTone: string;
|
|
||||||
meta: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatPayload(payload?: string): string {
|
|
||||||
if (!payload) return '{}';
|
|
||||||
try {
|
|
||||||
return JSON.stringify(JSON.parse(payload), null, 2);
|
|
||||||
} catch {
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parsePayload(payload?: string): unknown {
|
|
||||||
if (!payload) return null;
|
|
||||||
try {
|
|
||||||
return JSON.parse(payload);
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isPayloadObject(value: unknown): value is PayloadObject {
|
|
||||||
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function valueAsString(value: unknown): string {
|
|
||||||
if (typeof value === 'string') return value.trim();
|
|
||||||
if (typeof value === 'number' || typeof value === 'boolean')
|
|
||||||
return String(value);
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function pickString(payload: PayloadObject, keys: string[]): string {
|
|
||||||
for (const key of keys) {
|
|
||||||
const value = valueAsString(payload[key]);
|
|
||||||
if (value) return value;
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function compactSummaryText(value: string, maxLength = 96): string {
|
|
||||||
const text = value.replace(/\s+/g, ' ').trim();
|
|
||||||
return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text;
|
|
||||||
}
|
|
||||||
|
|
||||||
function maskClientKey(value?: string): string {
|
|
||||||
const key = value?.trim();
|
|
||||||
if (!key) return '--';
|
|
||||||
if (key.length <= 4) return '****';
|
|
||||||
if (key.length <= 10) return `${key.slice(0, 2)}****${key.slice(-2)}`;
|
|
||||||
return `${key.slice(0, 4)}...${key.slice(-4)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function entityLabel(entityType: string): string {
|
|
||||||
return (
|
|
||||||
ENTITY_TYPE_OPTIONS[entityType as keyof typeof ENTITY_TYPE_OPTIONS]?.text ||
|
|
||||||
entityType ||
|
|
||||||
'Entity'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function statusTone(status?: string): string {
|
|
||||||
return status ? STATUS_TONE[status.toLowerCase()] || 'default' : 'default';
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildBusinessSummary(
|
|
||||||
record: DigitalEmployeeSyncRecordInfo,
|
|
||||||
): SyncBusinessSummary {
|
|
||||||
const payload = parsePayload(record.payload);
|
|
||||||
const entity = entityLabel(record.entity_type);
|
|
||||||
if (!isPayloadObject(payload)) {
|
|
||||||
return {
|
|
||||||
title: `${entity} ${record.entity_id}`,
|
|
||||||
description: 'Payload 暂无法解析,查看详情可读取原始内容。',
|
|
||||||
status: record.operation,
|
|
||||||
statusTone: 'default',
|
|
||||||
meta: [record.outbox_id],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const status = pickString(payload, ['status', 'currentStatus', 'kind']);
|
|
||||||
const title =
|
|
||||||
pickString(payload, ['title', 'name', 'message', 'objective']) ||
|
|
||||||
`${entity} ${record.entity_id}`;
|
|
||||||
const description = compactSummaryText(
|
|
||||||
pickString(payload, ['objective', 'summary', 'message', 'uri']) ||
|
|
||||||
record.outbox_id,
|
|
||||||
);
|
|
||||||
const meta = [
|
|
||||||
pickString(payload, ['planId', 'plan_id']) &&
|
|
||||||
`Plan ${pickString(payload, ['planId', 'plan_id'])}`,
|
|
||||||
pickString(payload, ['taskId', 'task_id']) &&
|
|
||||||
`Task ${pickString(payload, ['taskId', 'task_id'])}`,
|
|
||||||
pickString(payload, ['runId', 'run_id']) &&
|
|
||||||
`Run ${pickString(payload, ['runId', 'run_id'])}`,
|
|
||||||
pickString(payload, ['assignedSkillId']) &&
|
|
||||||
`Skill ${pickString(payload, ['assignedSkillId'])}`,
|
|
||||||
pickString(payload, ['occurred_at', 'started_at', 'finished_at']),
|
|
||||||
].filter((item): item is string => Boolean(item));
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: compactSummaryText(title, 72),
|
|
||||||
description,
|
|
||||||
status: status || record.operation,
|
|
||||||
statusTone: statusTone(status),
|
|
||||||
meta: meta.slice(0, 3),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderBusinessSummary(record: DigitalEmployeeSyncRecordInfo) {
|
|
||||||
const summary = buildBusinessSummary(record);
|
|
||||||
return (
|
|
||||||
<div style={{ minWidth: 0 }}>
|
|
||||||
<Space size={6} wrap>
|
|
||||||
<Typography.Text strong ellipsis style={{ maxWidth: 260 }}>
|
|
||||||
{summary.title}
|
|
||||||
</Typography.Text>
|
|
||||||
{summary.status && (
|
|
||||||
<Tag color={summary.statusTone}>{summary.status}</Tag>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
<Typography.Text
|
|
||||||
type="secondary"
|
|
||||||
ellipsis
|
|
||||||
style={{ display: 'block', maxWidth: 330, fontSize: 12 }}
|
|
||||||
>
|
|
||||||
{summary.description}
|
|
||||||
</Typography.Text>
|
|
||||||
{summary.meta.length > 0 && (
|
|
||||||
<Space size={[4, 4]} wrap style={{ marginTop: 4 }}>
|
|
||||||
{summary.meta.map((item) => (
|
|
||||||
<Tag key={item} color="default" style={{ marginInlineEnd: 0 }}>
|
|
||||||
{item}
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
</Space>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function readSearchValue(
|
|
||||||
params: URLSearchParams,
|
|
||||||
key: string,
|
|
||||||
): string | undefined {
|
|
||||||
const value = params.get(key)?.trim();
|
|
||||||
return value || undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DigitalEmployeeSync: React.FC = () => {
|
|
||||||
const { hasPermission } = useModel('menuModel');
|
|
||||||
const actionRef = useRef<ActionType>();
|
|
||||||
const formRef = useRef<FormInstance>();
|
|
||||||
const autoOpenedOutboxRef = useRef<string | null>(null);
|
|
||||||
const location = useLocation();
|
|
||||||
const [, setSearchParams] = useSearchParams();
|
|
||||||
const [payloadRecord, setPayloadRecord] =
|
|
||||||
useState<DigitalEmployeeSyncRecordInfo | null>(null);
|
|
||||||
const formattedPayload = useMemo(
|
|
||||||
() => (payloadRecord ? formatPayload(payloadRecord.payload) : ''),
|
|
||||||
[payloadRecord],
|
|
||||||
);
|
|
||||||
|
|
||||||
const formInitialValues = useMemo(() => {
|
|
||||||
const params = new URLSearchParams(location.search || '');
|
|
||||||
const values = {
|
|
||||||
client_key: readSearchValue(params, 'client_key'),
|
|
||||||
device_id: readSearchValue(params, 'device_id'),
|
|
||||||
entity_type: readSearchValue(params, 'entity_type'),
|
|
||||||
entity_id: readSearchValue(params, 'entity_id'),
|
|
||||||
outbox_id: readSearchValue(params, 'outbox_id'),
|
|
||||||
};
|
|
||||||
return Object.values(values).some(Boolean) ? values : undefined;
|
|
||||||
}, [location.search]);
|
|
||||||
|
|
||||||
const handleReset = useCallback(() => {
|
|
||||||
formRef.current?.resetFields();
|
|
||||||
formRef.current?.setFieldsValue({
|
|
||||||
client_key: undefined,
|
|
||||||
device_id: undefined,
|
|
||||||
entity_type: undefined,
|
|
||||||
entity_id: undefined,
|
|
||||||
outbox_id: undefined,
|
|
||||||
});
|
|
||||||
actionRef.current?.setPageInfo?.({ current: 1, pageSize: 15 });
|
|
||||||
autoOpenedOutboxRef.current = null;
|
|
||||||
if (location.search) {
|
|
||||||
setSearchParams(new URLSearchParams());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
actionRef.current?.reload();
|
|
||||||
}, [location.search, setSearchParams]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
autoOpenedOutboxRef.current = null;
|
|
||||||
}, [location.search]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const state = location.state as any;
|
|
||||||
if (state?._t) {
|
|
||||||
handleReset();
|
|
||||||
}
|
|
||||||
}, [location.state, handleReset]);
|
|
||||||
|
|
||||||
const columns: ProColumns<DigitalEmployeeSyncRecordInfo>[] = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
title: '客户端 Key',
|
|
||||||
dataIndex: 'client_key',
|
|
||||||
width: 190,
|
|
||||||
ellipsis: true,
|
|
||||||
renderText: (value) => maskClientKey(value),
|
|
||||||
fieldProps: {
|
|
||||||
placeholder: '输入客户端 Key',
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '设备 ID',
|
|
||||||
dataIndex: 'device_id',
|
|
||||||
width: 150,
|
|
||||||
ellipsis: true,
|
|
||||||
fieldProps: {
|
|
||||||
placeholder: '输入设备 ID',
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
renderText: (value) => value || '--',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '实体类型',
|
|
||||||
dataIndex: 'entity_type',
|
|
||||||
width: 120,
|
|
||||||
valueType: 'select',
|
|
||||||
valueEnum: ENTITY_TYPE_OPTIONS,
|
|
||||||
fieldProps: {
|
|
||||||
placeholder: '选择实体类型',
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
render: (_, record) => (
|
|
||||||
<Tag color={ENTITY_TYPE_TONE[record.entity_type] || 'default'}>
|
|
||||||
{record.entity_type || '--'}
|
|
||||||
</Tag>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '实体 ID',
|
|
||||||
dataIndex: 'entity_id',
|
|
||||||
width: 180,
|
|
||||||
ellipsis: true,
|
|
||||||
fieldProps: {
|
|
||||||
placeholder: '输入实体 ID',
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '业务摘要',
|
|
||||||
dataIndex: 'payload',
|
|
||||||
width: 360,
|
|
||||||
hideInSearch: true,
|
|
||||||
render: (_, record) => renderBusinessSummary(record),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Outbox ID',
|
|
||||||
dataIndex: 'outbox_id',
|
|
||||||
width: 220,
|
|
||||||
ellipsis: true,
|
|
||||||
fieldProps: {
|
|
||||||
placeholder: '输入 Outbox ID',
|
|
||||||
allowClear: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
dataIndex: 'operation',
|
|
||||||
align: 'center',
|
|
||||||
width: 90,
|
|
||||||
hideInSearch: true,
|
|
||||||
renderText: (value) => value || '--',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '同步时间',
|
|
||||||
dataIndex: 'synced_at',
|
|
||||||
align: 'center',
|
|
||||||
width: 170,
|
|
||||||
hideInSearch: true,
|
|
||||||
valueType: 'dateTime',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '创建时间',
|
|
||||||
dataIndex: 'created',
|
|
||||||
align: 'center',
|
|
||||||
width: 170,
|
|
||||||
hideInSearch: true,
|
|
||||||
valueType: 'dateTime',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '详情',
|
|
||||||
valueType: 'option',
|
|
||||||
fixed: 'right',
|
|
||||||
align: 'center',
|
|
||||||
width: 90,
|
|
||||||
render: (_, record) => (
|
|
||||||
<Button type="link" onClick={() => setPayloadRecord(record)}>
|
|
||||||
查看
|
|
||||||
</Button>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const request = async (params: {
|
|
||||||
pageSize?: number;
|
|
||||||
current?: number;
|
|
||||||
client_key?: string;
|
|
||||||
device_id?: string;
|
|
||||||
entity_type?: string;
|
|
||||||
entity_id?: string;
|
|
||||||
outbox_id?: string;
|
|
||||||
}) => {
|
|
||||||
const response = await apiDigitalEmployeeSyncRecordList({
|
|
||||||
pageNo: params.current || 1,
|
|
||||||
pageSize: params.pageSize || 15,
|
|
||||||
clientKey: params.client_key,
|
|
||||||
deviceId: params.device_id,
|
|
||||||
entityType: params.entity_type,
|
|
||||||
entityId: params.entity_id,
|
|
||||||
outboxId: params.outbox_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.code !== SUCCESS_CODE) {
|
|
||||||
message.error(response.message || '查询数字员工同步记录失败');
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = response.data?.records || [];
|
|
||||||
const outboxId = params.outbox_id?.trim();
|
|
||||||
const matchedRecord = outboxId
|
|
||||||
? records.find((record) => record.outbox_id === outboxId)
|
|
||||||
: null;
|
|
||||||
if (
|
|
||||||
response.code === SUCCESS_CODE &&
|
|
||||||
outboxId &&
|
|
||||||
matchedRecord &&
|
|
||||||
autoOpenedOutboxRef.current !== outboxId
|
|
||||||
) {
|
|
||||||
autoOpenedOutboxRef.current = outboxId;
|
|
||||||
setPayloadRecord(matchedRecord);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: records,
|
|
||||||
total: response.data?.total || 0,
|
|
||||||
success: response.code === SUCCESS_CODE,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<WorkspaceLayout title="数字员工同步记录" hideScroll>
|
|
||||||
<XProTable<DigitalEmployeeSyncRecordInfo>
|
|
||||||
key={location.pathname + (location.search || '')}
|
|
||||||
actionRef={actionRef}
|
|
||||||
formRef={formRef}
|
|
||||||
rowKey="id"
|
|
||||||
columns={columns}
|
|
||||||
request={request}
|
|
||||||
onReset={handleReset}
|
|
||||||
form={
|
|
||||||
formInitialValues ? { initialValues: formInitialValues } : undefined
|
|
||||||
}
|
|
||||||
showQueryButtons={hasPermission(
|
|
||||||
'content_digital_employee_sync_query_list',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Drawer
|
|
||||||
width={720}
|
|
||||||
title="同步详情"
|
|
||||||
open={Boolean(payloadRecord)}
|
|
||||||
onClose={() => setPayloadRecord(null)}
|
|
||||||
>
|
|
||||||
{payloadRecord && (
|
|
||||||
<>
|
|
||||||
<div style={{ marginBottom: 16 }}>
|
|
||||||
{renderBusinessSummary(payloadRecord)}
|
|
||||||
</div>
|
|
||||||
<Typography.Paragraph>
|
|
||||||
<Typography.Text strong>客户端 Key:</Typography.Text>
|
|
||||||
{maskClientKey(payloadRecord.client_key)}
|
|
||||||
</Typography.Paragraph>
|
|
||||||
<Typography.Paragraph>
|
|
||||||
<Typography.Text strong>设备 ID:</Typography.Text>
|
|
||||||
{payloadRecord.device_id || '--'}
|
|
||||||
</Typography.Paragraph>
|
|
||||||
<Typography.Paragraph>
|
|
||||||
<Typography.Text strong>实体:</Typography.Text>
|
|
||||||
{payloadRecord.entity_type} / {payloadRecord.entity_id}
|
|
||||||
</Typography.Paragraph>
|
|
||||||
<Typography.Paragraph>
|
|
||||||
<Typography.Text strong>Outbox:</Typography.Text>
|
|
||||||
{payloadRecord.outbox_id}
|
|
||||||
</Typography.Paragraph>
|
|
||||||
<Typography.Paragraph copyable={{ text: formattedPayload }}>
|
|
||||||
<pre
|
|
||||||
style={{
|
|
||||||
maxHeight: 'calc(100vh - 260px)',
|
|
||||||
overflow: 'auto',
|
|
||||||
margin: 0,
|
|
||||||
padding: 16,
|
|
||||||
background: '#f6f8fa',
|
|
||||||
border: '1px solid #e5e7eb',
|
|
||||||
borderRadius: 6,
|
|
||||||
whiteSpace: 'pre-wrap',
|
|
||||||
wordBreak: 'break-word',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{formattedPayload}
|
|
||||||
</pre>
|
|
||||||
</Typography.Paragraph>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Drawer>
|
|
||||||
</WorkspaceLayout>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DigitalEmployeeSync;
|
|
||||||
@@ -351,18 +351,6 @@ const routes = [
|
|||||||
name: getRouteLabel('PC.Routes.contentSkill'),
|
name: getRouteLabel('PC.Routes.contentSkill'),
|
||||||
component: '@/pages/SystemManagement/Content/Skill',
|
component: '@/pages/SystemManagement/Content/Skill',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'content-digital-employee-sync',
|
|
||||||
name: '数字员工同步记录',
|
|
||||||
component:
|
|
||||||
'@/pages/SystemManagement/Content/DigitalEmployeeSync',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'content-digital-employee-ops',
|
|
||||||
name: '数字员工运营台',
|
|
||||||
component:
|
|
||||||
'@/pages/SystemManagement/Content/DigitalEmployeeOps',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,10 +53,6 @@ const MENU_ICON_MAP: Record<string, string> = {
|
|||||||
system_log_query: 'icons-nav-log',
|
system_log_query: 'icons-nav-log',
|
||||||
// 内容管理
|
// 内容管理
|
||||||
content_manage: 'icons-nav-cube',
|
content_manage: 'icons-nav-cube',
|
||||||
// 数字员工同步记录
|
|
||||||
content_digital_employee_sync: 'icons-nav-robot',
|
|
||||||
// 数字员工运营台
|
|
||||||
content_digital_employee_ops: 'icons-nav-robot',
|
|
||||||
// 支付与收益(开发者)
|
// 支付与收益(开发者)
|
||||||
dev_payment_earnings: 'icons-nav-my-earnings',
|
dev_payment_earnings: 'icons-nav-my-earnings',
|
||||||
// 订阅与积分(管理员)
|
// 订阅与积分(管理员)
|
||||||
|
|||||||
@@ -7,19 +7,7 @@ import type { Page, RequestResponse } from '@/types/interfaces/request';
|
|||||||
import type {
|
import type {
|
||||||
AccessStatsResult,
|
AccessStatsResult,
|
||||||
AddSystemUserParams,
|
AddSystemUserParams,
|
||||||
DigitalEmployeeAdminActionResult,
|
|
||||||
DigitalEmployeeAdminActionSubmitParams,
|
|
||||||
DigitalEmployeeAdminRecordResult,
|
|
||||||
DigitalEmployeeAdminRecordSubmitParams,
|
|
||||||
ConversationStatsResult,
|
ConversationStatsResult,
|
||||||
DigitalEmployeeBillingEstimate,
|
|
||||||
DigitalEmployeeBillingEstimateParams,
|
|
||||||
DigitalEmployeeAdminWorkbenchListParams,
|
|
||||||
DigitalEmployeeAdminWorkbenchPage,
|
|
||||||
DigitalEmployeePolicySnapshotListParams,
|
|
||||||
DigitalEmployeePolicySnapshotPage,
|
|
||||||
DigitalEmployeeSyncRecordListParams,
|
|
||||||
DigitalEmployeeSyncRecordPage,
|
|
||||||
ModelConfigDto,
|
ModelConfigDto,
|
||||||
NotifyMessageSendParams,
|
NotifyMessageSendParams,
|
||||||
OnlineMonitorInfo,
|
OnlineMonitorInfo,
|
||||||
@@ -276,142 +264,6 @@ export async function apiSystemResourceAgentDelete(data: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询数字员工同步记录
|
|
||||||
export async function apiDigitalEmployeeSyncRecordList(
|
|
||||||
data: DigitalEmployeeSyncRecordListParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeeSyncRecordPage>> {
|
|
||||||
return request('/api/digital-employee/sync/records', {
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
entity_type: data.entityType,
|
|
||||||
entity_id: data.entityId,
|
|
||||||
outbox_id: data.outboxId,
|
|
||||||
page_no: data.pageNo,
|
|
||||||
page_size: data.pageSize,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数字员工正式运营台
|
|
||||||
export async function apiDigitalEmployeeAdminWorkbenchList(
|
|
||||||
data: DigitalEmployeeAdminWorkbenchListParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeeAdminWorkbenchPage>> {
|
|
||||||
return request(`/api/digital-employee/admin/workbench/${data.view}`, {
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
entity_type: data.entityType,
|
|
||||||
entity_id: data.entityId,
|
|
||||||
status: data.status,
|
|
||||||
kind: data.kind,
|
|
||||||
category: data.category,
|
|
||||||
level: data.level,
|
|
||||||
priority: data.priority,
|
|
||||||
updated_from: data.updatedFrom,
|
|
||||||
updated_to: data.updatedTo,
|
|
||||||
page_no: data.pageNo,
|
|
||||||
page_size: data.pageSize,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数字员工跨设备策略快照冲突
|
|
||||||
export async function apiDigitalEmployeeAdminPolicySnapshots(
|
|
||||||
data: DigitalEmployeePolicySnapshotListParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeePolicySnapshotPage>> {
|
|
||||||
return request('/api/digital-employee/admin/policies/snapshots', {
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
status: data.status,
|
|
||||||
policy_kind: data.policyKind,
|
|
||||||
updated_from: data.updatedFrom,
|
|
||||||
updated_to: data.updatedTo,
|
|
||||||
page_no: data.pageNo,
|
|
||||||
page_size: data.pageSize,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录数字员工管理端低风险动作意图
|
|
||||||
export async function apiDigitalEmployeeAdminActionSubmit(
|
|
||||||
data: DigitalEmployeeAdminActionSubmitParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeeAdminActionResult>> {
|
|
||||||
return request('/api/digital-employee/admin/actions', {
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
sync_record_id: data.syncRecordId,
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
entity_type: data.entityType,
|
|
||||||
entity_id: data.entityId,
|
|
||||||
action: data.action,
|
|
||||||
request_payload: data.requestPayload,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录数字员工日报发送结果
|
|
||||||
export async function apiDigitalEmployeeAdminDailyReportSendRecord(
|
|
||||||
data: DigitalEmployeeAdminRecordSubmitParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeeAdminRecordResult>> {
|
|
||||||
return request('/api/digital-employee/admin/daily-reports/send-records', {
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
sync_record_id: data.syncRecordId,
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
entity_type: data.entityType,
|
|
||||||
entity_id: data.entityId,
|
|
||||||
status: data.status,
|
|
||||||
endpoint: data.endpoint,
|
|
||||||
remote_id: data.remoteId,
|
|
||||||
reason: data.reason,
|
|
||||||
request_payload: data.requestPayload,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询数字员工账单估算
|
|
||||||
export async function apiDigitalEmployeeAdminBillingEstimates(
|
|
||||||
data: DigitalEmployeeBillingEstimateParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeeBillingEstimate>> {
|
|
||||||
return request('/api/digital-employee/admin/billing/estimates', {
|
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
updated_from: data.updatedFrom,
|
|
||||||
updated_to: data.updatedTo,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 记录数字员工审计归档摘要
|
|
||||||
export async function apiDigitalEmployeeAdminAuditArchive(
|
|
||||||
data: DigitalEmployeeAdminRecordSubmitParams,
|
|
||||||
): Promise<RequestResponse<DigitalEmployeeAdminRecordResult>> {
|
|
||||||
return request('/api/digital-employee/admin/audit-archives', {
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
sync_record_id: data.syncRecordId,
|
|
||||||
client_key: data.clientKey,
|
|
||||||
device_id: data.deviceId,
|
|
||||||
entity_type: data.entityType,
|
|
||||||
entity_id: data.entityId,
|
|
||||||
status: data.status,
|
|
||||||
archive_location: data.archiveLocation,
|
|
||||||
archive_summary: data.archiveSummary,
|
|
||||||
reason: data.reason,
|
|
||||||
request_payload: data.requestPayload,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询网页应用列表
|
// 查询网页应用列表
|
||||||
export async function apiSystemResourceWebappList(
|
export async function apiSystemResourceWebappList(
|
||||||
data: SystemWebappListParams,
|
data: SystemWebappListParams,
|
||||||
|
|||||||
@@ -516,430 +516,6 @@ export interface SystemAgentListParams extends SystemPaginationParams {
|
|||||||
// 智能体列表分页响应
|
// 智能体列表分页响应
|
||||||
export type SystemAgentPage = SystemPageResult<SystemAgentInfo>;
|
export type SystemAgentPage = SystemPageResult<SystemAgentInfo>;
|
||||||
|
|
||||||
// 数字员工同步记录
|
|
||||||
export interface DigitalEmployeeSyncRecordInfo {
|
|
||||||
id: number;
|
|
||||||
client_key: string;
|
|
||||||
device_id?: string;
|
|
||||||
outbox_id: string;
|
|
||||||
entity_type:
|
|
||||||
| 'plan'
|
|
||||||
| 'task'
|
|
||||||
| 'run'
|
|
||||||
| 'event'
|
|
||||||
| 'artifact'
|
|
||||||
| 'approval'
|
|
||||||
| string;
|
|
||||||
entity_id: string;
|
|
||||||
operation: string;
|
|
||||||
payload: string;
|
|
||||||
synced_at: string;
|
|
||||||
modified: string;
|
|
||||||
created: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数字员工同步记录查询参数
|
|
||||||
export interface DigitalEmployeeSyncRecordListParams
|
|
||||||
extends SystemPaginationParams {
|
|
||||||
clientKey?: string;
|
|
||||||
deviceId?: string;
|
|
||||||
entityType?: string;
|
|
||||||
entityId?: string;
|
|
||||||
outboxId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数字员工同步记录分页响应
|
|
||||||
export interface DigitalEmployeeSyncRecordPage {
|
|
||||||
total: number;
|
|
||||||
page_no: number;
|
|
||||||
page_size: number;
|
|
||||||
records: DigitalEmployeeSyncRecordInfo[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DigitalEmployeeAdminWorkbenchView =
|
|
||||||
| 'business'
|
|
||||||
| 'interventions'
|
|
||||||
| 'approval_governance'
|
|
||||||
| 'approval_policies'
|
|
||||||
| 'service_operations'
|
|
||||||
| 'artifact_lifecycle'
|
|
||||||
| 'notifications'
|
|
||||||
| 'notification_policies'
|
|
||||||
| 'audits'
|
|
||||||
| 'daily_reports'
|
|
||||||
| 'governance_commands'
|
|
||||||
| 'route_governance'
|
|
||||||
| 'policy_conflicts'
|
|
||||||
| 'memory_governance'
|
|
||||||
| 'memory_policies'
|
|
||||||
| 'skill_audits'
|
|
||||||
| 'policy_center'
|
|
||||||
| 'scheduler_operations'
|
|
||||||
| 'plan_step_dispatch'
|
|
||||||
| 'plan_governance'
|
|
||||||
| 'plan_revisions'
|
|
||||||
| 'governance_policies'
|
|
||||||
| 'plan_revision_materialization';
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminWorkbenchRow {
|
|
||||||
view: DigitalEmployeeAdminWorkbenchView | string;
|
|
||||||
sync_record_id: number;
|
|
||||||
sync_record_url?: string;
|
|
||||||
entity_type?: string;
|
|
||||||
entity_id?: string;
|
|
||||||
operation?: string;
|
|
||||||
title?: string;
|
|
||||||
status?: string;
|
|
||||||
kind?: string;
|
|
||||||
category?: string;
|
|
||||||
level?: string;
|
|
||||||
priority?: string;
|
|
||||||
summary?: string;
|
|
||||||
plan_id?: string;
|
|
||||||
task_id?: string;
|
|
||||||
run_id?: string;
|
|
||||||
step_id?: string;
|
|
||||||
dependency_status?: string;
|
|
||||||
lease_state?: string;
|
|
||||||
lease_source?: string;
|
|
||||||
dispatch_status?: string;
|
|
||||||
dispatch_policy_key?: string;
|
|
||||||
max_per_sweep?: number;
|
|
||||||
auto_dispatch_ready_steps?: boolean;
|
|
||||||
catch_up_on_startup?: boolean;
|
|
||||||
max_run_history?: number;
|
|
||||||
orchestration_id?: string;
|
|
||||||
trigger_source?: string;
|
|
||||||
approval_id?: string;
|
|
||||||
approval_policy_id?: string;
|
|
||||||
conflict_policy_id?: string;
|
|
||||||
decision_guard_status?: string;
|
|
||||||
batch_accept_remote_disabled?: boolean;
|
|
||||||
auto_decision_disabled?: boolean;
|
|
||||||
policy_reason?: string;
|
|
||||||
governance_policy_id?: string;
|
|
||||||
policy_guard_status?: string;
|
|
||||||
hard_interrupt_disabled?: boolean;
|
|
||||||
artifact_id?: string;
|
|
||||||
artifact_graph_id?: string;
|
|
||||||
artifact_group_id?: string;
|
|
||||||
group_key?: string;
|
|
||||||
related_artifact_ids?: 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;
|
|
||||||
retention_conflict_status?: string;
|
|
||||||
cleanup_conflict_status?: string;
|
|
||||||
remote_delete_disabled?: boolean;
|
|
||||||
notification_id?: string;
|
|
||||||
collaboration_thread_id?: string;
|
|
||||||
subscription_policy_id?: string;
|
|
||||||
subscription_conflict_status?: string;
|
|
||||||
notification_policy_id?: string;
|
|
||||||
subscription_status?: string;
|
|
||||||
desktop_enabled?: boolean;
|
|
||||||
minimum_level?: string;
|
|
||||||
channel?: string;
|
|
||||||
delivery_status?: string;
|
|
||||||
delivery_attempt_id?: string;
|
|
||||||
send_request_id?: string;
|
|
||||||
real_push_disabled?: boolean;
|
|
||||||
conflict_status?: string;
|
|
||||||
report_id?: string;
|
|
||||||
daily_report_fact_id?: string;
|
|
||||||
daily_report_table?: string;
|
|
||||||
daily_report_materialized?: boolean;
|
|
||||||
daily_report_physical_fact_status?: string;
|
|
||||||
send_record_id?: string;
|
|
||||||
send_channel?: string;
|
|
||||||
send_request_status?: string;
|
|
||||||
send_record_status?: string;
|
|
||||||
formal_daily_report_page_disabled?: boolean;
|
|
||||||
external_send_disabled?: boolean;
|
|
||||||
third_party_channel_disabled?: boolean;
|
|
||||||
approval_decision_status?: string;
|
|
||||||
advanced_query_supported?: boolean;
|
|
||||||
aggregation_scope?: string;
|
|
||||||
materialized_source?: 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;
|
|
||||||
lease_holder?: string;
|
|
||||||
lease_expires_at?: string;
|
|
||||||
restart_record_id?: string;
|
|
||||||
restart_count?: number;
|
|
||||||
last_restart_at?: string;
|
|
||||||
recovery_policy_id?: string;
|
|
||||||
auto_recovery_status?: string;
|
|
||||||
service_start_disabled?: boolean;
|
|
||||||
service_stop_disabled?: boolean;
|
|
||||||
lease_takeover_disabled?: boolean;
|
|
||||||
auto_recovery_disabled?: boolean;
|
|
||||||
recovery_action_request_id?: string;
|
|
||||||
start_request_id?: string;
|
|
||||||
stop_request_id?: string;
|
|
||||||
lease_takeover_request_id?: string;
|
|
||||||
auto_recovery_request_id?: string;
|
|
||||||
start_service_disabled?: boolean;
|
|
||||||
stop_service_disabled?: boolean;
|
|
||||||
memory_id?: string;
|
|
||||||
memory_key?: string;
|
|
||||||
governance_status?: string;
|
|
||||||
merge_candidate_count?: number;
|
|
||||||
duplicate_memory_ids?: string[];
|
|
||||||
latest_memory_id?: string;
|
|
||||||
last_governance_action?: string;
|
|
||||||
last_reviewed_at?: string;
|
|
||||||
memory_policy_id?: string;
|
|
||||||
memory_policy_status?: string;
|
|
||||||
merge_policy_id?: string;
|
|
||||||
merge_action_disabled?: boolean;
|
|
||||||
remote_memory_policy_disabled?: boolean;
|
|
||||||
skill_id?: string;
|
|
||||||
skill_version?: string;
|
|
||||||
install_status?: string;
|
|
||||||
permission_scope?: string;
|
|
||||||
policy_source?: string;
|
|
||||||
policy_status?: string;
|
|
||||||
skill_install_request_id?: string;
|
|
||||||
skill_upgrade_request_id?: string;
|
|
||||||
permission_policy_id?: string;
|
|
||||||
permission_edit_request_id?: string;
|
|
||||||
install_action_disabled?: boolean;
|
|
||||||
upgrade_action_disabled?: boolean;
|
|
||||||
permission_edit_disabled?: boolean;
|
|
||||||
tool_name?: string;
|
|
||||||
server_id?: string;
|
|
||||||
audit_archive_id?: string;
|
|
||||||
archive_status?: string;
|
|
||||||
archive_location?: string;
|
|
||||||
billing_estimate_id?: string;
|
|
||||||
billing_source?: string;
|
|
||||||
estimated?: boolean;
|
|
||||||
diagnostic_id?: string;
|
|
||||||
diagnostic_kind?: string;
|
|
||||||
issue_code?: string;
|
|
||||||
repair_action?: string;
|
|
||||||
repair_status?: string;
|
|
||||||
repair_reason?: string;
|
|
||||||
safe_repair_disabled?: boolean;
|
|
||||||
billing_actual_disabled?: boolean;
|
|
||||||
sandbox_archive_file_disabled?: boolean;
|
|
||||||
auto_repair_execution_disabled?: boolean;
|
|
||||||
repair_approval_required?: boolean;
|
|
||||||
recommended_action?: string;
|
|
||||||
policy_kind?: string;
|
|
||||||
policy_key?: string;
|
|
||||||
policy_edit_request_id?: string;
|
|
||||||
policy_edit_status?: string;
|
|
||||||
policy_edit_reason?: string;
|
|
||||||
merge_request_id?: string;
|
|
||||||
memory_merge_request_id?: string;
|
|
||||||
remote_memory_policy_request_id?: string;
|
|
||||||
merge_recommendation?: string;
|
|
||||||
remote_policy_edit_disabled?: boolean;
|
|
||||||
auto_merge_disabled?: boolean;
|
|
||||||
approval_policy_edit_disabled?: boolean;
|
|
||||||
route_policy_edit_disabled?: boolean;
|
|
||||||
route_recovery_disabled?: boolean;
|
|
||||||
high_risk_execution_disabled?: boolean;
|
|
||||||
schedule_id?: string;
|
|
||||||
job_id?: string;
|
|
||||||
revision_id?: string;
|
|
||||||
revision_fact_id?: string;
|
|
||||||
revision_status?: string;
|
|
||||||
revision_materialized?: boolean;
|
|
||||||
base_revision_id?: string;
|
|
||||||
changed_fields?: string[];
|
|
||||||
conflict_keys?: string[];
|
|
||||||
recommended_resolution?: string;
|
|
||||||
route_decision_count?: number;
|
|
||||||
blocked_count?: number;
|
|
||||||
approval_required_count?: number;
|
|
||||||
missing_context_count?: number;
|
|
||||||
not_mapped_count?: number;
|
|
||||||
intervention_conflict_status?: string;
|
|
||||||
occurred_at?: string;
|
|
||||||
synced_at?: string;
|
|
||||||
latest_synced_at?: string;
|
|
||||||
materialized?: boolean;
|
|
||||||
client_key_masked?: string;
|
|
||||||
device_id?: string;
|
|
||||||
business_view?: Record<string, unknown>;
|
|
||||||
payload?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminWorkbenchListParams
|
|
||||||
extends SystemPaginationParams {
|
|
||||||
view: DigitalEmployeeAdminWorkbenchView;
|
|
||||||
clientKey?: string;
|
|
||||||
deviceId?: string;
|
|
||||||
entityType?: string;
|
|
||||||
entityId?: string;
|
|
||||||
status?: string;
|
|
||||||
kind?: string;
|
|
||||||
category?: string;
|
|
||||||
level?: string;
|
|
||||||
priority?: string;
|
|
||||||
updatedFrom?: string;
|
|
||||||
updatedTo?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminWorkbenchPage {
|
|
||||||
total: number;
|
|
||||||
page_no: number;
|
|
||||||
page_size: number;
|
|
||||||
records: DigitalEmployeeAdminWorkbenchRow[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeePolicySnapshotRow {
|
|
||||||
policy_kind?: string;
|
|
||||||
policy_key?: string;
|
|
||||||
status?: string;
|
|
||||||
summary?: string;
|
|
||||||
client_count?: number;
|
|
||||||
device_count?: number;
|
|
||||||
conflict_keys?: string[];
|
|
||||||
latest_synced_at?: string;
|
|
||||||
recommended_resolution?: string;
|
|
||||||
route_decision_count?: number;
|
|
||||||
blocked_count?: number;
|
|
||||||
approval_required_count?: number;
|
|
||||||
missing_context_count?: number;
|
|
||||||
not_mapped_count?: number;
|
|
||||||
intervention_conflict_status?: string;
|
|
||||||
memory_policy_id?: string;
|
|
||||||
memory_policy_status?: string;
|
|
||||||
merge_policy_id?: string;
|
|
||||||
merge_action_disabled?: boolean;
|
|
||||||
remote_memory_policy_disabled?: boolean;
|
|
||||||
approval_policy_id?: string;
|
|
||||||
conflict_policy_id?: string;
|
|
||||||
decision_guard_status?: string;
|
|
||||||
batch_accept_remote_disabled?: boolean;
|
|
||||||
auto_decision_disabled?: boolean;
|
|
||||||
policy_reason?: string;
|
|
||||||
policy_edit_request_id?: string;
|
|
||||||
policy_edit_status?: string;
|
|
||||||
policy_edit_reason?: string;
|
|
||||||
merge_request_id?: string;
|
|
||||||
merge_recommendation?: string;
|
|
||||||
remote_policy_edit_disabled?: boolean;
|
|
||||||
auto_merge_disabled?: boolean;
|
|
||||||
approval_policy_edit_disabled?: boolean;
|
|
||||||
route_policy_edit_disabled?: boolean;
|
|
||||||
route_recovery_disabled?: boolean;
|
|
||||||
high_risk_execution_disabled?: boolean;
|
|
||||||
dispatch_policy_key?: string;
|
|
||||||
max_per_sweep?: number;
|
|
||||||
auto_dispatch_ready_steps?: boolean;
|
|
||||||
catch_up_on_startup?: boolean;
|
|
||||||
max_run_history?: number;
|
|
||||||
sync_record_url?: string;
|
|
||||||
client_key_masked?: string;
|
|
||||||
device_id?: string;
|
|
||||||
business_view?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeePolicySnapshotListParams
|
|
||||||
extends SystemPaginationParams {
|
|
||||||
clientKey?: string;
|
|
||||||
deviceId?: string;
|
|
||||||
status?: string;
|
|
||||||
policyKind?: string;
|
|
||||||
updatedFrom?: string;
|
|
||||||
updatedTo?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeePolicySnapshotPage {
|
|
||||||
total: number;
|
|
||||||
page_no: number;
|
|
||||||
page_size: number;
|
|
||||||
records: DigitalEmployeePolicySnapshotRow[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminActionSubmitParams {
|
|
||||||
syncRecordId?: number;
|
|
||||||
clientKey?: string;
|
|
||||||
deviceId?: string;
|
|
||||||
entityType?: string;
|
|
||||||
entityId?: string;
|
|
||||||
action: string;
|
|
||||||
requestPayload?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminActionResult {
|
|
||||||
ok: boolean;
|
|
||||||
status?: string;
|
|
||||||
reason_codes?: string[];
|
|
||||||
action?: {
|
|
||||||
id: number;
|
|
||||||
status: string;
|
|
||||||
action: string;
|
|
||||||
entity_type?: string;
|
|
||||||
entity_id?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminRecordSubmitParams {
|
|
||||||
syncRecordId?: number;
|
|
||||||
clientKey?: string;
|
|
||||||
deviceId?: string;
|
|
||||||
entityType?: string;
|
|
||||||
entityId?: string;
|
|
||||||
status?: string;
|
|
||||||
endpoint?: string;
|
|
||||||
remoteId?: string;
|
|
||||||
archiveLocation?: string;
|
|
||||||
archiveSummary?: Record<string, unknown>;
|
|
||||||
reason?: string;
|
|
||||||
requestPayload?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeAdminRecordResult {
|
|
||||||
ok: boolean;
|
|
||||||
status?: string;
|
|
||||||
reason_codes?: string[];
|
|
||||||
record?: DigitalEmployeeAdminActionResult['action'];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeBillingEstimateParams {
|
|
||||||
clientKey?: string;
|
|
||||||
deviceId?: string;
|
|
||||||
updatedFrom?: string;
|
|
||||||
updatedTo?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeBillingModelEstimate {
|
|
||||||
total_tokens?: number;
|
|
||||||
input_tokens?: number;
|
|
||||||
output_tokens?: number;
|
|
||||||
estimated_cost_usd?: number | string;
|
|
||||||
request_count?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DigitalEmployeeBillingEstimate {
|
|
||||||
total_tokens?: number;
|
|
||||||
input_tokens?: number;
|
|
||||||
output_tokens?: number;
|
|
||||||
estimated_cost_usd?: number | string;
|
|
||||||
request_count?: number;
|
|
||||||
estimated?: boolean;
|
|
||||||
by_model?: Record<string, DigitalEmployeeBillingModelEstimate>;
|
|
||||||
updated_at?: string;
|
|
||||||
source_records?: number[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 网页应用信息
|
// 网页应用信息
|
||||||
export type SystemWebappInfo = SystemResourceInfo;
|
export type SystemWebappInfo = SystemResourceInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
* Axe smoke coverage for low-level shared UI components.
|
* Axe smoke coverage for low-level shared UI components.
|
||||||
*/
|
*/
|
||||||
import ActionMenu from '@/components/base/ActionMenu';
|
import {
|
||||||
import CopyButton from '@/components/base/CopyButton';
|
ActionMenu,
|
||||||
import CopyIconButton from '@/components/base/CopyIconButton';
|
CopyButton,
|
||||||
import MenuListItem from '@/components/base/MenuListItem';
|
CopyIconButton,
|
||||||
import SecondMenuItem from '@/components/base/SecondMenuItem';
|
MenuListItem,
|
||||||
|
SecondMenuItem,
|
||||||
|
} from '@/components/base';
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { axe } from 'jest-axe';
|
import { axe } from 'jest-axe';
|
||||||
import { describe, expect, it, vi } from 'vitest';
|
import { describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
vi.mock('@/components/base/SvgIcon', () => ({
|
|
||||||
default: ({ name }: { name: string }) => (
|
|
||||||
<span aria-hidden="true" data-icon={name} />
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
|
|
||||||
vi.mock('@/services/i18nRuntime', () => ({
|
|
||||||
dict: (key: string) => key,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const assertNoViolations = async (element: HTMLElement) => {
|
const assertNoViolations = async (element: HTMLElement) => {
|
||||||
const results = await axe(element);
|
const results = await axe(element);
|
||||||
expect(results.violations).toEqual([]);
|
expect(results.violations).toEqual([]);
|
||||||
|
|||||||
@@ -1,52 +1,4 @@
|
|||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { TextDecoder, TextEncoder } from 'node:util';
|
|
||||||
|
|
||||||
Object.assign(globalThis, { TextDecoder, TextEncoder });
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
Object.assign(window, { TextDecoder, TextEncoder });
|
|
||||||
}
|
|
||||||
|
|
||||||
class MemoryStorage implements Storage {
|
|
||||||
private readonly store = new Map<string, string>();
|
|
||||||
|
|
||||||
get length() {
|
|
||||||
return this.store.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this.store.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
getItem(key: string) {
|
|
||||||
return this.store.get(key) ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
key(index: number) {
|
|
||||||
return Array.from(this.store.keys())[index] ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeItem(key: string) {
|
|
||||||
this.store.delete(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
setItem(key: string, value: string) {
|
|
||||||
this.store.set(key, String(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ensureStorage = (name: 'localStorage' | 'sessionStorage') => {
|
|
||||||
const current = globalThis[name];
|
|
||||||
if (current) return;
|
|
||||||
|
|
||||||
Object.defineProperty(globalThis, name, {
|
|
||||||
configurable: true,
|
|
||||||
value: new MemoryStorage(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ensureStorage('localStorage');
|
|
||||||
ensureStorage('sessionStorage');
|
|
||||||
|
|
||||||
// antd 响应式依赖 matchMedia,测试环境补齐
|
// antd 响应式依赖 matchMedia,测试环境补齐
|
||||||
if (typeof window !== 'undefined' && !window.matchMedia) {
|
if (typeof window !== 'undefined' && !window.matchMedia) {
|
||||||
|
|||||||
@@ -11,11 +11,6 @@ export default defineConfig({
|
|||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
environmentOptions: {
|
|
||||||
jsdom: {
|
|
||||||
url: 'http://localhost/',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
setupFiles: './tests/setupTests.ts',
|
setupFiles: './tests/setupTests.ts',
|
||||||
exclude: [...configDefaults.exclude, 'tests/**/*[Vv]2*.test.{ts,tsx}'],
|
exclude: [...configDefaults.exclude, 'tests/**/*[Vv]2*.test.{ts,tsx}'],
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
*.tsbuildinfo
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<link rel="icon" type="image/png" href="./logo.png" />
|
|
||||||
<title>数字员工</title>
|
|
||||||
<script>
|
|
||||||
window.__QIMINGCLAW_EMBEDDED_DIGITAL__ = true;
|
|
||||||
try {
|
|
||||||
window.localStorage.setItem("qimingclaw_digital_token", "qimingclaw_embedded_digital_employee");
|
|
||||||
window.localStorage.removeItem("zeroclaw_token");
|
|
||||||
window.sessionStorage.setItem("qimingclaw_digital_logged_in", "1");
|
|
||||||
window.sessionStorage.removeItem("sgrobot_logged_in");
|
|
||||||
} catch (error) {
|
|
||||||
console.warn("[qimingclaw] digital employee auth bootstrap skipped", error);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
Before Width: | Height: | Size: 372 KiB |
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@qiming-ai/sgrobot-digital-embedded",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.1.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc -b && vite build",
|
|
||||||
"dev": "vite"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"animejs": "^4.4.1",
|
|
||||||
"lucide-react": "^0.468.0",
|
|
||||||
"react": "^19.0.0",
|
|
||||||
"react-dom": "^19.0.0",
|
|
||||||
"react-markdown": "^10.1.0",
|
|
||||||
"react-router-dom": "^7.1.1",
|
|
||||||
"remark-gfm": "^4.0.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tailwindcss/vite": "^4.3.0",
|
|
||||||
"@types/node": "^25.3.0",
|
|
||||||
"@types/react": "^19.0.7",
|
|
||||||
"@types/react-dom": "^19.0.3",
|
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
|
||||||
"tailwindcss": "^4.0.0",
|
|
||||||
"typescript": "~5.7.2",
|
|
||||||
"vite": "^6.0.7"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# qimingclaw embedded patches
|
|
||||||
|
|
||||||
This directory records qimingclaw-only adaptations around the sgRobot digital employee UI.
|
|
||||||
|
|
||||||
- `src/main.tsx` mounts the digital employee page directly at `#/digital`.
|
|
||||||
- `src/lib/basePath.ts` fixes static assets under `/sgrobot-digital`.
|
|
||||||
- `src/lib/tauri.ts` disables sgRobot/Tauri gateway detection inside the Electron webview.
|
|
||||||
- `src/lib/qimingclawAdapter.ts` provides the first qimingclaw-native digital employee API projection.
|
|
||||||
- `src/lib/api.ts` calls the qimingclaw adapter before falling back to normal HTTP fetch.
|
|
||||||
- `index.html` injects a local token so copied sgRobot pages do not show the pairing screen.
|
|
||||||
- `window.QimingClawBridge.digital.getSnapshot()` is read when the page runs inside qimingclaw's Electron webview.
|
|
||||||
|
|
||||||
Run `npm run sync:sgrobot-digital` from `crates/agent-electron-client` after changing the upstream sgRobot digital UI.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Digital Employee Static Assets
|
|
||||||
|
|
||||||
This directory is owned by the React digital employee frontend.
|
|
||||||
|
|
||||||
- `avatars/` keeps the original digital employee character images used by the home page `Avatar3D` stage.
|
|
||||||
- Do not place the legacy Vue standalone application bundle here.
|
|
||||||
- If an avatar file is renamed, update `src/pages/digital/CommandDeck.tsx` in the same change.
|
|
||||||
|
Before Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 483 KiB |
|
Before Width: | Height: | Size: 507 KiB |
|
Before Width: | Height: | Size: 154 KiB |
|
Before Width: | Height: | Size: 147 KiB |
|
Before Width: | Height: | Size: 552 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 543 KiB |
|
Before Width: | Height: | Size: 2.1 MiB |
@@ -1,29 +0,0 @@
|
|||||||
import Gem from './Gem';
|
|
||||||
import Stage from './Stage';
|
|
||||||
|
|
||||||
interface Avatar3DProps {
|
|
||||||
avatarSrc: string;
|
|
||||||
altText?: string;
|
|
||||||
statusLabel?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Avatar3D({ avatarSrc, altText = '数字员工', statusLabel }: Avatar3DProps) {
|
|
||||||
return (
|
|
||||||
<div className="de-avatar-container" aria-hidden="true">
|
|
||||||
<div className="de-avatar-glass-space">
|
|
||||||
<div className="de-avatar-roof">
|
|
||||||
<div className="de-avatar-roof-face" />
|
|
||||||
<div className="de-avatar-roof-glow" />
|
|
||||||
</div>
|
|
||||||
<div className="de-avatar-glass-left" />
|
|
||||||
<div className="de-avatar-glass-right" />
|
|
||||||
<Gem className="de-gem-1" />
|
|
||||||
<Gem className="de-gem-2" />
|
|
||||||
<Gem className="de-gem-3" />
|
|
||||||
</div>
|
|
||||||
{statusLabel && <div className="de-avatar-state-label">{statusLabel}</div>}
|
|
||||||
<img src={avatarSrc} alt={altText} className="de-avatar-img" />
|
|
||||||
<Stage />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import type { ReactNode } from 'react';
|
|
||||||
|
|
||||||
interface CardTitleBarProps {
|
|
||||||
title: string;
|
|
||||||
children?: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function CardTitleBar({ title, children }: CardTitleBarProps) {
|
|
||||||
return (
|
|
||||||
<div className="de-card-title-bar">
|
|
||||||
<span className="de-card-title-bar-text">{title}</span>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,686 +0,0 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
|
||||||
import {
|
|
||||||
buildDemoFlowEvents,
|
|
||||||
buildDemoPlanMessages,
|
|
||||||
buildDemoRuns,
|
|
||||||
buildDemoTasks,
|
|
||||||
getDemoMissions,
|
|
||||||
} from '@/pages/digital/demoScenario';
|
|
||||||
import {
|
|
||||||
displayBackendMessage,
|
|
||||||
displayBusinessText,
|
|
||||||
displayEventKind,
|
|
||||||
displayStatus,
|
|
||||||
type Mission,
|
|
||||||
} from '@/lib/consoleDataAdapter';
|
|
||||||
import { getDebugPlanFlow, getDebugTasksForPlan, getPlanMessages, type PlanMessage } from '@/lib/api';
|
|
||||||
import type { DebugRun, DebugTask, FlowResponse } from '@/types/api';
|
|
||||||
import StatusBadge from './StatusBadge';
|
|
||||||
|
|
||||||
interface FlowDetailPanelProps {
|
|
||||||
mission: Mission;
|
|
||||||
onClose: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stepVariant(status: string): 'info' | 'success' | 'warning' | 'danger' {
|
|
||||||
switch (status) {
|
|
||||||
case 'succeeded': case 'completed': case 'Succeeded': return 'success';
|
|
||||||
case 'failed': return 'danger';
|
|
||||||
case 'Failed': return 'danger';
|
|
||||||
case 'running': case 'active': case 'Running': return 'info';
|
|
||||||
default: return 'warning';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fmtTime(ts?: string | null): string {
|
|
||||||
if (!ts) return '未记录';
|
|
||||||
return new Date(ts).toLocaleString('zh-CN', { hour12: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
function missionPeriodLabel(mission: Mission): string {
|
|
||||||
const text = `${mission.id} ${mission.title} ${mission.objective}`.toLowerCase();
|
|
||||||
if (text.includes('month') || text.includes('monthly') || text.includes('月')) return '月度任务';
|
|
||||||
if (text.includes('week') || text.includes('weekly') || text.includes('周')) return '周任务';
|
|
||||||
if (text.includes('临时') || text.includes('adhoc') || text.includes('hotlist') || text.includes('monitor')) return '临时任务';
|
|
||||||
return '日常任务';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDone(status: string): boolean {
|
|
||||||
return ['succeeded', 'success', 'finished', 'complete', 'completed'].includes(status.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFailed(status: string): boolean {
|
|
||||||
return ['failed', 'error', 'cancelled', 'canceled', 'aborted', 'rejected', 'deadletter'].includes(status.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
function progressText(mission: Mission): string {
|
|
||||||
const total = mission.steps.length;
|
|
||||||
if (total === 0) return displayStatus(mission.status);
|
|
||||||
const done = mission.steps.filter((step) => isDone(step.status)).length;
|
|
||||||
const failed = mission.steps.filter((step) => isFailed(step.status)).length;
|
|
||||||
const running = mission.steps.filter((step) => ['running', 'active', 'queued', 'leased'].includes(step.status.toLowerCase())).length;
|
|
||||||
const parts = [`已完成 ${done}/${total}`];
|
|
||||||
if (failed > 0) parts.push(`失败 ${failed}`);
|
|
||||||
if (running > 0 && failed === 0) parts.push(`处理中 ${running}`);
|
|
||||||
return parts.join(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
function businessTimelineMessage(message: string): string {
|
|
||||||
return message
|
|
||||||
.replace(/^启动计划:/, '接收委托:')
|
|
||||||
.replace(/^准备步骤:/, '准备工作:')
|
|
||||||
.replace(/^创建任务:/, '安排工作:')
|
|
||||||
.replace(/^任务失败:/, '工作失败:')
|
|
||||||
.replace(/^开始处理:/, '开始处理:')
|
|
||||||
.replace(/^完成任务:/, '完成工作:')
|
|
||||||
.replace(/^调用技能:/, '数字员工处理:')
|
|
||||||
.replace(/^执行开始:/, '开始执行:')
|
|
||||||
.replace(/^执行完成:/, '执行完成:')
|
|
||||||
.replace(/^执行失败:/, '执行失败:')
|
|
||||||
.replace(/,将使用[^,。]+/, '')
|
|
||||||
.replace(/,分配给[^,。]+/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFailureMessage(message: string): boolean {
|
|
||||||
return /失败|failed|error|timeout|unavailable/i.test(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
function businessKindLabel(kind: string, message = ''): string {
|
|
||||||
if (isFailureMessage(message)) return '失败';
|
|
||||||
if (kind === 'artifact') return '产物';
|
|
||||||
if (kind === 'task_summary') return '结果';
|
|
||||||
if (kind === 'task_running' || kind === 'run') return '处理中';
|
|
||||||
if (kind === 'task_done' || kind === 'run_done') return '完成';
|
|
||||||
return '过程';
|
|
||||||
}
|
|
||||||
|
|
||||||
function messageRoleLabel(role: string): string {
|
|
||||||
if (role === 'user') return '用户';
|
|
||||||
if (role === 'assistant') return '数字员工';
|
|
||||||
if (role === 'system') return '系统';
|
|
||||||
return '消息';
|
|
||||||
}
|
|
||||||
|
|
||||||
type DetailEvent = {
|
|
||||||
event_id: string;
|
|
||||||
kind: string;
|
|
||||||
occurred_at: string | null;
|
|
||||||
message: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ApprovalSummary = {
|
|
||||||
id: string;
|
|
||||||
status: string;
|
|
||||||
note: string;
|
|
||||||
requestedAt: string | null;
|
|
||||||
decidedAt: string | null;
|
|
||||||
decidedBy: string | null;
|
|
||||||
runId: string;
|
|
||||||
taskId: string | null;
|
|
||||||
planId: string | null;
|
|
||||||
targetKind: string;
|
|
||||||
targetId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function skillLabel(skillId: string | null | undefined): string {
|
|
||||||
return displayBusinessText(skillId || '', skillId || '自动化技能');
|
|
||||||
}
|
|
||||||
|
|
||||||
function toolBusinessMessage(toolName: string, success: string, elapsedMs: string): string {
|
|
||||||
const result = success === 'true' ? '成功' : '失败';
|
|
||||||
if (toolName.includes('zhihu-hotlist') && toolName.includes('extract_hotlist')) {
|
|
||||||
return `调用技能:知乎热榜采集,结果:${result},耗时 ${elapsedMs}ms`;
|
|
||||||
}
|
|
||||||
if (toolName.includes('office-export-xlsx') && toolName.includes('export_xlsx')) {
|
|
||||||
return `调用技能:Excel 导出,结果:${result},耗时 ${elapsedMs}ms`;
|
|
||||||
}
|
|
||||||
return `调用技能:${toolName},结果:${result},耗时 ${elapsedMs}ms`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function valueText(value: unknown): string {
|
|
||||||
return typeof value === 'string' ? value : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function eventTime(event: DetailEvent): string {
|
|
||||||
return event.occurred_at || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function earliestTime(values: Array<string | null | undefined>): string | null {
|
|
||||||
return values
|
|
||||||
.filter((value): value is string => Boolean(value))
|
|
||||||
.sort((a, b) => a.localeCompare(b))[0] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function latestByResultSubject(events: DetailEvent[]): DetailEvent[] {
|
|
||||||
const bySubject = new Map<string, DetailEvent>();
|
|
||||||
for (const event of events) {
|
|
||||||
const subject = event.message.split(',结果:')[0]?.split(',状态:')[0] || event.message;
|
|
||||||
const current = bySubject.get(subject);
|
|
||||||
if (!current || eventTime(event).localeCompare(eventTime(current)) > 0) {
|
|
||||||
bySubject.set(subject, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Array.from(bySubject.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
function approvalSummariesFromRuns(runs: DebugRun[]): ApprovalSummary[] {
|
|
||||||
const byId = new Map<string, ApprovalSummary>();
|
|
||||||
for (const run of runs) {
|
|
||||||
for (const approval of run.approvals || []) {
|
|
||||||
const id = valueText(approval.approval_id) || `approval-${run.run_id}`;
|
|
||||||
byId.set(id, {
|
|
||||||
id,
|
|
||||||
status: valueText(approval.status) || 'requested',
|
|
||||||
note: valueText(approval.note) || '等待人工审批',
|
|
||||||
requestedAt: valueText(approval.requested_at) || null,
|
|
||||||
decidedAt: valueText(approval.decided_at) || null,
|
|
||||||
decidedBy: valueText(approval.decided_by) || null,
|
|
||||||
runId: valueText(approval.run_id) || run.run_id,
|
|
||||||
taskId: valueText(approval.task_id) || run.task_id || null,
|
|
||||||
planId: valueText(approval.plan_id) || run.plan_id || null,
|
|
||||||
targetKind: valueText(approval.target_kind) || 'task',
|
|
||||||
targetId: valueText(approval.target_id) || run.task_id || run.run_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Array.from(byId.values()).sort((a, b) => (b.requestedAt || '').localeCompare(a.requestedAt || ''));
|
|
||||||
}
|
|
||||||
|
|
||||||
function objectValue(value: unknown): Record<string, unknown> | null {
|
|
||||||
return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeOutputPath(value: string): string {
|
|
||||||
return value.replace(/\\\\/g, '\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildOperationalTimeline(
|
|
||||||
mission: Mission,
|
|
||||||
tasks: DebugTask[],
|
|
||||||
runs: DebugRun[],
|
|
||||||
messages: PlanMessage[],
|
|
||||||
flowEvents?: FlowResponse['events'],
|
|
||||||
): DetailEvent[] {
|
|
||||||
const events: DetailEvent[] = [];
|
|
||||||
const add = (kind: string, occurredAt: string | null | undefined, message: string, id: string) => {
|
|
||||||
if (!message.trim()) return;
|
|
||||||
events.push({ event_id: id, kind, occurred_at: occurredAt ?? null, message });
|
|
||||||
};
|
|
||||||
const addOutputFacts = (rawOutput: string, occurredAt: string | null | undefined, idPrefix: string, sourceName: string) => {
|
|
||||||
let parsedOutputPath = false;
|
|
||||||
try {
|
|
||||||
const parsed = objectValue(JSON.parse(rawOutput));
|
|
||||||
if (parsed) {
|
|
||||||
const label = typeof parsed.label === 'string' ? parsed.label.trim() : '';
|
|
||||||
const value = parsed.value;
|
|
||||||
if (label && value !== undefined && value !== null) {
|
|
||||||
add('task_summary', occurredAt, `${label}:${String(value)}`, `metric-${idPrefix}-${sourceName}`);
|
|
||||||
}
|
|
||||||
const outputPath = typeof parsed.output_path === 'string' ? parsed.output_path.trim() : '';
|
|
||||||
if (outputPath) {
|
|
||||||
parsedOutputPath = true;
|
|
||||||
add('artifact', occurredAt, `产物生成:${normalizeOutputPath(outputPath)}`, `artifact-${idPrefix}-${sourceName}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Some execution messages are human-readable text. Regex extraction below handles those.
|
|
||||||
}
|
|
||||||
|
|
||||||
const rowCountMatch = rawOutput.match(/"row_count"\s*:\s*(\d+)/);
|
|
||||||
if (rowCountMatch?.[1]) {
|
|
||||||
add('task_summary', occurredAt, `数据处理完成:共 ${rowCountMatch[1]} 条记录`, `rows-${idPrefix}-${sourceName}`);
|
|
||||||
}
|
|
||||||
const pathMatch = rawOutput.match(/"output_path"\s*:\s*"([^"]+\.(?:xlsx|xls|csv|json|html|pdf|png|jpg|jpeg|txt))"/i);
|
|
||||||
const outputPath = pathMatch?.[1];
|
|
||||||
if (outputPath && !parsedOutputPath) {
|
|
||||||
add('artifact', occurredAt, `产物生成:${normalizeOutputPath(outputPath)}`, `artifact-regex-${idPrefix}-${sourceName}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
add('plan', mission.createdAt || mission.updatedAt, `启动计划:${mission.title},目标:${mission.objective}`, `plan-${mission.id}`);
|
|
||||||
|
|
||||||
if (tasks.length === 0) {
|
|
||||||
for (const step of mission.steps) {
|
|
||||||
const skills = step.preferredSkills.map(skillLabel).join('、') || '自动化技能';
|
|
||||||
add('task', mission.updatedAt || mission.createdAt, `准备步骤:${step.title},将使用 ${skills}`, `step-${step.id}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const task of tasks) {
|
|
||||||
const skill = skillLabel(task.assigned_skill_id);
|
|
||||||
const taskRuns = runs.filter((run) => run.task_id === task.task_id);
|
|
||||||
const firstRunAt = earliestTime(taskRuns.map((run) => run.created_at));
|
|
||||||
const taskCreatedAt = earliestTime([task.created_at, task.started_at, firstRunAt]);
|
|
||||||
add('task', taskCreatedAt, `创建任务:${task.title || '子任务'},分配给 ${skill}`, `task-create-${task.task_id}`);
|
|
||||||
if (task.started_at) add('task_running', task.started_at, `开始处理:${task.title || '子任务'}`, `task-start-${task.task_id}`);
|
|
||||||
if (task.finished_at) {
|
|
||||||
const taskDoneVerb = isFailed(task.status) ? '任务失败' : '完成任务';
|
|
||||||
const errorDetail = isFailed(task.status) && task.error_message ? `,原因:${task.error_message}` : '';
|
|
||||||
add('task_done', task.finished_at, `${taskDoneVerb}:${task.title || '子任务'},状态:${displayStatus(task.status)}${errorDetail}`, `task-finish-${task.task_id}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const run of runs) {
|
|
||||||
const task = tasks.find((item) => item.task_id === run.task_id);
|
|
||||||
const taskTitle = task?.title || '任务执行';
|
|
||||||
const runSkill = skillLabel(run.skill_id || task?.assigned_skill_id);
|
|
||||||
const hasSessionToolForTask = messages.some((message) => (message.content || '').includes(`[Task ${run.task_id}] tool_call`));
|
|
||||||
if (!hasSessionToolForTask) {
|
|
||||||
add('skill_tool', run.created_at, `调用技能:${runSkill},处理:${taskTitle}`, `run-skill-${run.run_id}`);
|
|
||||||
}
|
|
||||||
add('run', run.created_at, `执行开始:${taskTitle},第 ${run.attempt_no || 1} 次`, `run-start-${run.run_id}`);
|
|
||||||
if (run.completed_at) {
|
|
||||||
const runDoneVerb = isFailed(run.lifecycle) ? '执行失败' : '执行完成';
|
|
||||||
add('run_done', run.completed_at, `${runDoneVerb}:${taskTitle},结果:${displayStatus(run.lifecycle)}`, `run-done-${run.run_id}`);
|
|
||||||
}
|
|
||||||
for (const [index, runEvent] of (run.events || []).entries()) {
|
|
||||||
addOutputFacts(
|
|
||||||
valueText(runEvent.message),
|
|
||||||
runEvent.occurred_at || run.completed_at || run.created_at,
|
|
||||||
`run-${run.run_id}-${runEvent.event_id || index}`,
|
|
||||||
run.skill_id || task?.assigned_skill_id || 'run',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const [index, artifact] of (run.artifacts || []).entries()) {
|
|
||||||
const uri = valueText(artifact.uri);
|
|
||||||
const name = valueText(artifact.name) || uri;
|
|
||||||
if (uri || name) {
|
|
||||||
add('artifact', run.completed_at || run.created_at, `产物生成:${name}${uri && uri !== name ? `(${uri})` : ''}`, `run-artifact-${run.run_id}-${index}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const message of messages) {
|
|
||||||
const content = message.content || '';
|
|
||||||
const toolMatch = content.match(/\[Task ([^\]]+)\] tool_call name=([^\s]+) success=(true|false) elapsed_ms=(\d+) args=(.*?) output=(.*)$/s);
|
|
||||||
if (toolMatch) {
|
|
||||||
const taskId = toolMatch[1] || '';
|
|
||||||
const toolName = toolMatch[2] || '';
|
|
||||||
const success = toolMatch[3] || 'false';
|
|
||||||
const elapsedMs = toolMatch[4] || '0';
|
|
||||||
const output = toolMatch[6] || '';
|
|
||||||
add('skill_tool', message.created_at, toolBusinessMessage(toolName, success, elapsedMs), `tool-${taskId}-${message.created_at}-${toolName}`);
|
|
||||||
addOutputFacts(output, message.created_at, `message-${message.created_at}`, toolName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const hotlistCount = content.match(/共采集到\s*\**\s*(\d+)\s*条/);
|
|
||||||
if (hotlistCount?.[1]) {
|
|
||||||
add('task_summary', message.created_at, `采集完成:获得 ${hotlistCount[1]} 条知乎热榜数据`, `summary-hotlist-${message.created_at}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (content.includes('[Task ') && content.includes('Excel')) {
|
|
||||||
add('task_summary', message.created_at, '导出完成:Excel 文件已生成', `summary-excel-${message.created_at}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.length <= 1) {
|
|
||||||
for (const event of flowEvents || []) {
|
|
||||||
add(event.kind, event.occurred_at, displayBackendMessage(event.message, event.message), event.event_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return events
|
|
||||||
.sort((a, b) => (a.occurred_at || '').localeCompare(b.occurred_at || ''))
|
|
||||||
.slice(-40);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function FlowDetailPanel({ mission, onClose }: FlowDetailPanelProps) {
|
|
||||||
const [tasks, setTasks] = useState<DebugTask[]>([]);
|
|
||||||
const [runs, setRuns] = useState<DebugRun[]>([]);
|
|
||||||
const [flow, setFlow] = useState<FlowResponse | null>(null);
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [sessionMessages, setSessionMessages] = useState<PlanMessage[]>([]);
|
|
||||||
const [sessionOpen, setSessionOpen] = useState(false);
|
|
||||||
const [advancedOpen, setAdvancedOpen] = useState(false);
|
|
||||||
const [sessionLoading, setSessionLoading] = useState(false);
|
|
||||||
const [sessionError, setSessionError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
const planId = mission.sourceIds.planId || mission.id;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let cancelled = false;
|
|
||||||
const refresh = () => {
|
|
||||||
setLoading(true);
|
|
||||||
Promise.allSettled([
|
|
||||||
getDebugTasksForPlan(planId),
|
|
||||||
getDebugPlanFlow(planId),
|
|
||||||
getPlanMessages(planId),
|
|
||||||
]).then(([tasksResult, flowResult, messagesResult]) => {
|
|
||||||
if (cancelled) return;
|
|
||||||
const demoMission = getDemoMissions().find((item) => item.id === planId);
|
|
||||||
const fallbackTasks = demoMission ? buildDemoTasks([demoMission]) : [];
|
|
||||||
const fallbackRuns = fallbackTasks.length > 0 ? buildDemoRuns(fallbackTasks) : [];
|
|
||||||
if (tasksResult.status === 'fulfilled') {
|
|
||||||
setTasks(tasksResult.value.tasks && tasksResult.value.tasks.length > 0 ? tasksResult.value.tasks : fallbackTasks);
|
|
||||||
setRuns(tasksResult.value.runs && tasksResult.value.runs.length > 0 ? tasksResult.value.runs : fallbackRuns);
|
|
||||||
} else {
|
|
||||||
setTasks(fallbackTasks);
|
|
||||||
setRuns(fallbackRuns);
|
|
||||||
}
|
|
||||||
if (flowResult.status === 'fulfilled' && flowResult.value?.events && flowResult.value.events.length > 0) {
|
|
||||||
setFlow(flowResult.value);
|
|
||||||
} else {
|
|
||||||
setFlow(demoMission ? { events: buildDemoFlowEvents(demoMission) } as FlowResponse : null);
|
|
||||||
}
|
|
||||||
if (messagesResult.status === 'fulfilled' && messagesResult.value.messages.length > 0) {
|
|
||||||
setSessionMessages(messagesResult.value.messages);
|
|
||||||
} else if (demoMission) {
|
|
||||||
setSessionMessages(buildDemoPlanMessages(demoMission));
|
|
||||||
} else {
|
|
||||||
setSessionMessages([]);
|
|
||||||
}
|
|
||||||
}).finally(() => {
|
|
||||||
if (!cancelled) setLoading(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
refresh();
|
|
||||||
const timer = window.setInterval(refresh, 3000);
|
|
||||||
return () => {
|
|
||||||
cancelled = true;
|
|
||||||
window.clearInterval(timer);
|
|
||||||
};
|
|
||||||
}, [planId]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setSessionMessages([]);
|
|
||||||
setSessionOpen(false);
|
|
||||||
setAdvancedOpen(false);
|
|
||||||
setSessionError(null);
|
|
||||||
}, [planId]);
|
|
||||||
|
|
||||||
const loadSessionMessages = async () => {
|
|
||||||
if (sessionLoading) return;
|
|
||||||
setSessionOpen(true);
|
|
||||||
setSessionLoading(true);
|
|
||||||
setSessionError(null);
|
|
||||||
try {
|
|
||||||
const data = await getPlanMessages(planId);
|
|
||||||
if (data.messages && data.messages.length > 0) {
|
|
||||||
setSessionMessages(data.messages);
|
|
||||||
} else {
|
|
||||||
const demoMission = getDemoMissions().find((item) => item.id === planId);
|
|
||||||
setSessionMessages(demoMission ? buildDemoPlanMessages(demoMission) : []);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
const demoMission = getDemoMissions().find((item) => item.id === planId);
|
|
||||||
if (demoMission) {
|
|
||||||
setSessionMessages(buildDemoPlanMessages(demoMission));
|
|
||||||
setSessionError(null);
|
|
||||||
} else {
|
|
||||||
setSessionMessages([]);
|
|
||||||
setSessionError(err instanceof Error ? err.message : '读取会话失败');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
setSessionLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const runsByTask = useMemo(() => {
|
|
||||||
const grouped = new Map<string, DebugRun[]>();
|
|
||||||
for (const run of runs) {
|
|
||||||
const list = grouped.get(run.task_id) || [];
|
|
||||||
list.push(run);
|
|
||||||
grouped.set(run.task_id, list);
|
|
||||||
}
|
|
||||||
for (const list of grouped.values()) {
|
|
||||||
list.sort((a, b) => (b.created_at || '').localeCompare(a.created_at || ''));
|
|
||||||
}
|
|
||||||
return grouped;
|
|
||||||
}, [runs]);
|
|
||||||
|
|
||||||
const eventTimeline = useMemo(
|
|
||||||
() => buildOperationalTimeline(mission, tasks, runs, sessionMessages, flow?.events),
|
|
||||||
[flow?.events, mission, runs, sessionMessages, tasks],
|
|
||||||
);
|
|
||||||
|
|
||||||
const businessTimeline = useMemo(
|
|
||||||
() => eventTimeline
|
|
||||||
.filter((event) => event.kind !== 'skill_tool')
|
|
||||||
.slice(-12),
|
|
||||||
[eventTimeline],
|
|
||||||
);
|
|
||||||
|
|
||||||
const approvalSummaries = useMemo(
|
|
||||||
() => approvalSummariesFromRuns(runs),
|
|
||||||
[runs],
|
|
||||||
);
|
|
||||||
|
|
||||||
const resultEvents = useMemo(
|
|
||||||
() => {
|
|
||||||
const facts = eventTimeline.filter((event) => ['artifact', 'task_summary'].includes(event.kind));
|
|
||||||
const taskResults = eventTimeline.filter((event) => event.kind === 'task_done');
|
|
||||||
const runResults = latestByResultSubject(eventTimeline.filter((event) => event.kind === 'run_done'));
|
|
||||||
const terminal = taskResults.length > 0 ? taskResults : runResults;
|
|
||||||
return [...facts, ...terminal]
|
|
||||||
.sort((a, b) => eventTime(a).localeCompare(eventTime(b)))
|
|
||||||
.slice(-6);
|
|
||||||
},
|
|
||||||
[eventTimeline],
|
|
||||||
);
|
|
||||||
|
|
||||||
const latestEventAt = useMemo(
|
|
||||||
() => eventTimeline.reduce<string | null>((latest, event) => {
|
|
||||||
if (!event.occurred_at) return latest;
|
|
||||||
if (!latest || event.occurred_at.localeCompare(latest) > 0) return event.occurred_at;
|
|
||||||
return latest;
|
|
||||||
}, null),
|
|
||||||
[eventTimeline],
|
|
||||||
);
|
|
||||||
const displayUpdatedAt = mission.updatedAt || latestEventAt;
|
|
||||||
|
|
||||||
const openAdvanced = () => {
|
|
||||||
const nextOpen = !advancedOpen;
|
|
||||||
setAdvancedOpen(nextOpen);
|
|
||||||
if (nextOpen && !sessionOpen) {
|
|
||||||
void loadSessionMessages();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="de-drawer" role="dialog" aria-label={mission.title}>
|
|
||||||
<div className="de-drawer-head">
|
|
||||||
<div className="de-drawer-title-group">
|
|
||||||
<span className="de-drawer-eyebrow">委托详情</span>
|
|
||||||
<h3>{mission.title}</h3>
|
|
||||||
</div>
|
|
||||||
<button className="de-btn-secondary" onClick={onClose} aria-label="关闭">✕</button>
|
|
||||||
</div>
|
|
||||||
<div className="de-drawer-status-line">
|
|
||||||
<StatusBadge variant={stepVariant(mission.status)} label={displayStatus(mission.status)} />
|
|
||||||
<span className="de-drawer-meta">{missionPeriodLabel(mission)}</span>
|
|
||||||
<span className="de-drawer-meta">{progressText(mission)}</span>
|
|
||||||
</div>
|
|
||||||
<div className="de-drawer-timeline">
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<div className="de-detail-section-head">
|
|
||||||
<h4>委托概览</h4>
|
|
||||||
</div>
|
|
||||||
<div className="de-detail-kv">
|
|
||||||
<span>业务目标</span><strong>{mission.objective || '未填写'}</strong>
|
|
||||||
<span>周期</span><strong>{missionPeriodLabel(mission)}</strong>
|
|
||||||
<span>当前进度</span><strong>{progressText(mission)}</strong>
|
|
||||||
<span>启动时间</span><strong>{fmtTime(mission.createdAt)}</strong>
|
|
||||||
<span>状态</span><strong>{displayStatus(mission.status)}</strong>
|
|
||||||
<span>更新时间</span><strong>{fmtTime(displayUpdatedAt)}</strong>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{approvalSummaries.length > 0 ? (
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<div className="de-detail-section-head">
|
|
||||||
<h4>审批状态</h4>
|
|
||||||
<span className="de-chain-plan-id">{approvalSummaries.length} 项执行期审批</span>
|
|
||||||
</div>
|
|
||||||
<div className="de-event-list">
|
|
||||||
{approvalSummaries.map((approval) => (
|
|
||||||
<div key={`approval-${approval.id}`} className="de-event-row">
|
|
||||||
<strong>{displayStatus(approval.status)}</strong>
|
|
||||||
<span>
|
|
||||||
{approval.note}
|
|
||||||
{' '}
|
|
||||||
{approval.taskId ? `Task ${approval.taskId}` : `Target ${approval.targetKind}:${approval.targetId}`}
|
|
||||||
{approval.runId ? ` / Run ${approval.runId}` : ''}
|
|
||||||
{approval.decidedBy ? ` / ${approval.decidedBy}` : ''}
|
|
||||||
</span>
|
|
||||||
<time>{fmtTime(approval.decidedAt || approval.requestedAt)}</time>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<section className="de-detail-section de-execution-chain">
|
|
||||||
<div className="de-detail-section-head">
|
|
||||||
<h4>业务过程</h4>
|
|
||||||
<span className="de-chain-plan-id">最近更新:{fmtTime(displayUpdatedAt || mission.createdAt)}</span>
|
|
||||||
</div>
|
|
||||||
{loading && businessTimeline.length === 0 ? (
|
|
||||||
<p className="de-empty-text">正在读取业务过程...</p>
|
|
||||||
) : businessTimeline.length === 0 ? (
|
|
||||||
<p className="de-empty-text">暂无业务过程。重新执行本任务后会显示处理进展。</p>
|
|
||||||
) : (
|
|
||||||
<div className="de-chain-list">
|
|
||||||
{businessTimeline.map((event) => (
|
|
||||||
<div key={`chain-${event.event_id}`} className={`de-chain-row de-chain-row--${event.kind} ${isFailureMessage(event.message) ? 'de-chain-row--danger' : ''}`}>
|
|
||||||
<strong>{businessKindLabel(event.kind, event.message)}</strong>
|
|
||||||
<span>{businessTimelineMessage(event.message)}</span>
|
|
||||||
<time>{fmtTime(event.occurred_at)}</time>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<h4>结果与产物</h4>
|
|
||||||
{resultEvents.length > 0 ? (
|
|
||||||
<div className="de-event-list">
|
|
||||||
{[...resultEvents].reverse().map((event) => (
|
|
||||||
<div key={`result-${event.event_id}`} className={`de-event-row ${isFailureMessage(event.message) ? 'de-event-row--danger' : ''}`}>
|
|
||||||
<strong>{businessKindLabel(event.kind, event.message)}</strong>
|
|
||||||
<span>{businessTimelineMessage(event.message)}</span>
|
|
||||||
<time>{fmtTime(event.occurred_at)}</time>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p className="de-empty-text">任务完成后,这里会显示结果摘要和产物入口。</p>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<h4>步骤进展</h4>
|
|
||||||
{loading ? <p className="de-empty-text">正在读取执行情况...</p> : null}
|
|
||||||
{mission.steps.length === 0 ? (
|
|
||||||
<p className="de-empty-text">暂无步骤进展</p>
|
|
||||||
) : (
|
|
||||||
mission.steps.map((step, i) => (
|
|
||||||
<div key={step.id} className="de-step-node">
|
|
||||||
<div className={`de-step-dot de-step-dot--${step.status}`} />
|
|
||||||
{i < mission.steps.length - 1 && <div className="de-step-line" />}
|
|
||||||
<div className="de-step-content">
|
|
||||||
<strong>{step.title}</strong>
|
|
||||||
<span>{displayStatus(step.status)}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<div className="de-detail-section-head">
|
|
||||||
<h4>高级详情</h4>
|
|
||||||
<button className="de-btn-secondary de-btn-sm" onClick={openAdvanced} disabled={sessionLoading}>
|
|
||||||
{advancedOpen ? '收起' : '展开'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{advancedOpen ? (
|
|
||||||
<>
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<div className="de-detail-section-head">
|
|
||||||
<h4>技术链路</h4>
|
|
||||||
<span className="de-chain-plan-id">仅用于排障</span>
|
|
||||||
</div>
|
|
||||||
{eventTimeline.length > 0 ? (
|
|
||||||
<div className="de-event-list">
|
|
||||||
{eventTimeline.slice(-20).reverse().map((event) => (
|
|
||||||
<div key={event.event_id} className={`de-event-row ${isFailureMessage(event.message) ? 'de-event-row--danger' : ''}`}>
|
|
||||||
<strong>{displayEventKind(event.kind)}</strong>
|
|
||||||
<span>{event.message}</span>
|
|
||||||
<time>{fmtTime(event.occurred_at)}</time>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p className="de-empty-text">暂无事件日志</p>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<div className="de-detail-section-head">
|
|
||||||
<h4>会话记录</h4>
|
|
||||||
<button className="de-btn-secondary de-btn-sm" onClick={loadSessionMessages} disabled={sessionLoading}>
|
|
||||||
刷新
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{sessionError ? (
|
|
||||||
<p className="de-empty-text">会话读取失败:{sessionError}</p>
|
|
||||||
) : sessionLoading ? (
|
|
||||||
<p className="de-empty-text">正在读取会话...</p>
|
|
||||||
) : sessionMessages.length === 0 ? (
|
|
||||||
<p className="de-empty-text">暂无会话消息。</p>
|
|
||||||
) : (
|
|
||||||
<div className="de-session-message-list">
|
|
||||||
{sessionMessages.map((message, index) => (
|
|
||||||
<div key={`${message.role}-${index}`} className={`de-session-message de-session-message--${message.role === 'user' ? 'user' : 'agent'}`}>
|
|
||||||
<div className="de-session-message-role">{messageRoleLabel(message.role)}</div>
|
|
||||||
<p>{displayBackendMessage(message.content, message.content)}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="de-detail-section">
|
|
||||||
<h4>任务与执行记录</h4>
|
|
||||||
{tasks.length === 0 ? (
|
|
||||||
<p className="de-empty-text">暂无原始任务记录</p>
|
|
||||||
) : (
|
|
||||||
tasks.map((task) => {
|
|
||||||
const taskRuns = runsByTask.get(task.task_id) || [];
|
|
||||||
const latestRun = taskRuns[0];
|
|
||||||
return (
|
|
||||||
<div key={task.task_id} className="de-task-run-card">
|
|
||||||
<div className="de-task-run-head">
|
|
||||||
<span>{task.title || '子任务'}</span>
|
|
||||||
<StatusBadge variant={stepVariant(task.status)} label={displayStatus(task.status)} />
|
|
||||||
</div>
|
|
||||||
<div className="de-task-run-meta">
|
|
||||||
<span>skill_id:{task.assigned_skill_id || '未分配'}</span>
|
|
||||||
<span>开始:{fmtTime(task.started_at)}</span>
|
|
||||||
<span>结束:{fmtTime(task.finished_at)}</span>
|
|
||||||
</div>
|
|
||||||
<div className="de-task-run-meta">
|
|
||||||
<span>task_id:{task.task_id}</span>
|
|
||||||
<span>执行记录:{taskRuns.length} 次</span>
|
|
||||||
{latestRun ? <span>最近结果:{displayStatus(latestRun.lifecycle)}</span> : null}
|
|
||||||
</div>
|
|
||||||
{isFailed(task.status) && task.error_message ? (
|
|
||||||
<div className="de-task-run-error">
|
|
||||||
<strong>失败原因:</strong>{task.error_message}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<p className="de-empty-text">默认隐藏排障信息;需要排障时可展开。</p>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
interface GemProps {
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Gem({ className = '' }: GemProps) {
|
|
||||||
return <div className={`de-gem ${className}`} aria-hidden="true" />;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import type { ReactNode, CSSProperties } from 'react';
|
|
||||||
|
|
||||||
interface GlassCardProps {
|
|
||||||
children: ReactNode;
|
|
||||||
className?: string;
|
|
||||||
style?: CSSProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function GlassCard({ children, className = '', style }: GlassCardProps) {
|
|
||||||
return (
|
|
||||||
<div className={`de-card ${className}`} style={style}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||