吸收数字员工安全服务重启入口

This commit is contained in:
baiyanyun
2026-06-09 23:10:01 +08:00
parent 0d2008b35c
commit 91540dec0c
13 changed files with 717 additions and 155 deletions

View File

@@ -9,6 +9,7 @@ import {
getSchedulerJobs,
governanceCommand,
postDigitalEmployeeWorkdayAction,
restartManagedService,
} from '@/lib/api';
import { isTauri } from '@/lib/tauri';
import type {
@@ -720,6 +721,10 @@ function managedServiceSummary(service: DigitalEmployeeManagedService): string {
return `${service.name} ${service.status_label}${service.error ? `${service.error}` : deps}`;
}
function canRestartManagedService(service: DigitalEmployeeManagedService): boolean {
return service.service_id === 'fileServer' || service.service_id === 'guiServer';
}
function taskAgentSummary(agent: DigitalEmployeeTaskAgentState): string {
const next = agent.next_action === 'retry_or_skip' ? '重试或跳过' : agent.next_action === 'watch_progress' ? '观察进度' : agent.next_action;
return `${agent.title} ${agent.status_label},下一步 ${next}`;
@@ -1387,6 +1392,30 @@ export default function CommandDeck({ onNavigate }: { onNavigate: (target: Digit
}
}, [fetchProjection]);
const restartService = useCallback(async (service: DigitalEmployeeManagedService) => {
const actionKey = `managed-service:${service.service_id}:restart`;
setActionBusy(actionKey);
setActionError(null);
setActionNotice(null);
try {
const response = await restartManagedService(service.service_id, {
reason: 'digital_home_managed_service_issue',
actor: 'digital_employee_ui',
});
if (!response.ok) {
throw new Error(response.error || response.message || `${service.name} 重启失败`);
}
setActionNotice(`${service.name} 已提交安全重启。`);
await fetchProjection();
} catch (error) {
if (mountedRef.current) {
setActionError(error instanceof Error ? error.message : `${service.name} 重启失败`);
}
} finally {
if (mountedRef.current) setActionBusy(null);
}
}, [fetchProjection]);
const openDuty = useCallback((planItem: DigitalPlanItem) => {
onNavigate({ tab: 'missions', date: selectedDate, missionId: planItem.conversationId || planItem.id });
}, [onNavigate, selectedDate]);
@@ -1679,6 +1708,37 @@ export default function CommandDeck({ onNavigate }: { onNavigate: (target: Digit
{actionError || actionNotice || planDataError || workdayProjection?.demo_reason}
</div>
)}
{managedServiceIssues.length > 0 && (
<div className="de-management-sync-failures" aria-label="服务状态处理" style={{ marginBottom: 10 }}>
{managedServiceIssues.map((service) => {
const actionKey = `managed-service:${service.service_id}:restart`;
const restartable = canRestartManagedService(service);
return (
<div key={service.service_id} className="de-management-sync-failure" title={service.error || managedServiceSummary(service)}>
<span>{service.kind}</span>
<strong>{service.name}</strong>
<em>{service.status_label}</em>
<small>{managedServiceSummary(service)}</small>
{restartable && (
<button
type="button"
className="de-btn-secondary de-btn-sm"
disabled={actionBusy === actionKey}
onClick={(event) => {
event.stopPropagation();
void restartService(service);
}}
title={`安全重启 ${service.name}`}
>
<RefreshCw size={13} aria-hidden="true" />
<span>{actionBusy === actionKey ? '重启中...' : '重启'}</span>
</button>
)}
</div>
);
})}
</div>
)}
{selectionDirty && !actionNotice && !actionError && (
<div className="de-schedule-result de-schedule-result--success" style={{ marginBottom: 10 }}>