吸收数字员工技能远端策略下发

This commit is contained in:
baiyanyun
2026-06-11 09:04:08 +08:00
parent 751ce45619
commit 8ab3d73fb1
18 changed files with 876 additions and 207 deletions

View File

@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback, useRef } from 'react';
import GlassCard from '@/components/digital/GlassCard';
import CardTitleBar from '@/components/digital/CardTitleBar';
import { adaptSkillSummaries, type SkillSummary } from '@/lib/consoleDataAdapter';
import { getSkills, setSkillEnabled } from '@/lib/api';
import { getSkills, pullSkillPolicies, setSkillEnabled } from '@/lib/api';
import { domSafeId } from './navigation';
type TaskCadence = 'daily' | 'weekly' | 'monthly' | 'adhoc';
@@ -81,6 +81,8 @@ function skillMetaBadges(skill: SkillSummary): string[] {
const badges: string[] = [];
if (skill.serverId) badges.push(skill.serverId);
if (skill.running !== null && skill.running !== undefined) badges.push(skill.running ? '运行中' : '未运行');
if (skill.policySource === 'remote') badges.push('远端策略');
if (skill.remotePolicy && skill.remotePolicy.enabled === false) badges.push('管理端禁用');
if (skill.governancePolicy) badges.push(policyLabels[skill.governancePolicy]);
if (typeof skill.toolCount === 'number') badges.push(`${skill.toolCount} 工具`);
if (skill.allowTools?.length) badges.push(`allow ${skill.allowTools.length}`);
@@ -174,7 +176,9 @@ export default function SkillLibrary({ focusSkillId }: { focusSkillId?: string |
const [cadenceFilter, setCadenceFilter] = useState<'all' | TaskCadence>('all');
const [selectedSkillId, setSelectedSkillId] = useState<string | null>(focusSkillId ?? null);
const [updatingSkillId, setUpdatingSkillId] = useState<string | null>(null);
const [pullingPolicies, setPullingPolicies] = useState(false);
const [actionError, setActionError] = useState<string | null>(null);
const [actionNotice, setActionNotice] = useState<string | null>(null);
const mountedRef = useRef(false);
useEffect(() => {
@@ -217,6 +221,7 @@ export default function SkillLibrary({ focusSkillId }: { focusSkillId?: string |
const nextEnabled = !skill.enabled;
setUpdatingSkillId(skill.id);
setActionError(null);
setActionNotice(null);
try {
const result = await setSkillEnabled(skill.id, nextEnabled);
if (!result.ok) {
@@ -233,6 +238,22 @@ export default function SkillLibrary({ focusSkillId }: { focusSkillId?: string |
}
}, []);
const pullPolicies = useCallback(async () => {
setPullingPolicies(true);
setActionError(null);
setActionNotice(null);
try {
const result = await pullSkillPolicies();
if (!result.ok) throw new Error(result.error || '技能策略拉取失败');
await fetchSkills();
setActionNotice(result.skipped ? '技能策略无需重复拉取。' : '技能策略已更新。');
} catch (err) {
setActionError(err instanceof Error ? err.message : '技能策略拉取失败');
} finally {
setPullingPolicies(false);
}
}, [fetchSkills]);
const filtered = skills
.filter(s => cadenceFilter === 'all' || getCadence(s) === cadenceFilter)
.filter(s => {
@@ -322,6 +343,9 @@ export default function SkillLibrary({ focusSkillId }: { focusSkillId?: string |
<div style={{ padding: '14px 18px' }}>
<GlassCard>
<CardTitleBar title="学习技能">
<button onClick={pullPolicies} disabled={pullingPolicies} className="de-btn-secondary de-btn-sm">
{pullingPolicies ? '拉取中...' : '拉取策略'}
</button>
<button onClick={fetchSkills} className="de-btn-secondary de-btn-sm"></button>
</CardTitleBar>
<div className="de-card-body">
@@ -330,6 +354,11 @@ export default function SkillLibrary({ focusSkillId }: { focusSkillId?: string |
{actionError}
</div>
)}
{actionNotice && (
<div className="de-schedule-result" style={{ marginBottom: 12 }}>
{actionNotice}
</div>
)}
<div className="de-skill-toolbar">
<input type="text" className="de-input" placeholder="搜索业务能力..." value={search} onChange={e => setSearch(e.target.value)} />
<div className="de-filter-row">