import { computed, ref } from 'vue' import { fetchAgentAssetVersionTimeline } from '../../services/agentAssets.js' import { buildDefaultRuntimeRule, formatDateTime, normalizeText, resolveRuleTemplateLabel, resolveTimelineEventMeta, stringifyRuntimeRule } from './auditViewModel.js' const VERSION_TIMELINE_CACHE_TTL = 60 * 1000 function normalizeAssetId(assetId) { return normalizeText(assetId) } function readVersionTimelineCache(timelineCache, assetId) { const key = normalizeAssetId(assetId) if (!key) { return null } const cached = timelineCache.get(key) if (!cached) { return null } const isExpired = Date.now() - cached.timestamp > VERSION_TIMELINE_CACHE_TTL return isExpired ? null : cached.items } function writeVersionTimelineCache(timelineCache, assetId, items) { const key = normalizeAssetId(assetId) if (!key) { return } timelineCache.set(key, { items, timestamp: Date.now() }) } function applyVersionPayloadToRulePreview(skill, version) { if (!skill || !version) { return } const selectedVersion = version.version skill.displayVersion = selectedVersion skill.displayVersionChangeNote = version.note || '无版本说明' if (skill.usesSpreadsheetRule) { return } if (typeof version.markdownContent === 'string') { skill.markdownContent = version.markdownContent } const runtimeRule = version.runtimeRule || buildDefaultRuntimeRule(skill) skill.runtimeRuleText = stringifyRuntimeRule(runtimeRule) skill.runtimeKind = normalizeText(runtimeRule.kind) || skill.runtimeKind || 'policy_rule_draft' skill.ruleTemplateKey = normalizeText(runtimeRule.template_key) || skill.ruleTemplateKey skill.ruleTemplateLabel = resolveRuleTemplateLabel(skill.ruleTemplateKey) } export function useAuditVersionTimeline({ selectedSkill, toast }) { const versionSwitchTarget = ref(null) const versionTimelineOpen = ref(false) const versionTimelineLoading = ref(false) const versionTimelineError = ref('') const versionTimelineItems = ref([]) const versionTimelineCache = new Map() const selectedVersionTimelineItems = computed(() => versionTimelineItems.value.map((item) => ({ ...item, meta: resolveTimelineEventMeta(item.event_type), timeLabel: formatDateTime(item.event_time) })) ) async function loadVersionTimeline(assetId = selectedSkill.value?.id, options = {}) { if (!assetId) { return } const cachedItems = options.force ? null : readVersionTimelineCache(versionTimelineCache, assetId) if (cachedItems) { versionTimelineItems.value = cachedItems return } versionTimelineLoading.value = true versionTimelineError.value = '' try { const payload = await fetchAgentAssetVersionTimeline(assetId) const nextItems = Array.isArray(payload) ? payload : [] versionTimelineItems.value = nextItems writeVersionTimelineCache(versionTimelineCache, assetId, nextItems) } catch (error) { versionTimelineError.value = error?.message || '操作记录加载失败,请稍后重试。' if (!options.silent) { toast(versionTimelineError.value) } versionTimelineItems.value = [] writeVersionTimelineCache(versionTimelineCache, assetId, []) } finally { versionTimelineLoading.value = false } } async function openVersionTimeline() { if (!selectedSkill.value?.id) { return } versionTimelineOpen.value = true await loadVersionTimeline(selectedSkill.value.id) } function closeVersionTimeline() { versionTimelineOpen.value = false } function clearVersionTimelineState() { versionTimelineOpen.value = false versionTimelineItems.value = [] versionTimelineError.value = '' versionSwitchTarget.value = null } function openVersionSwitch(version) { if (!selectedSkill.value || version.version === selectedSkill.value.displayVersion) { return } versionSwitchTarget.value = version } function cancelVersionSwitch() { versionSwitchTarget.value = null } function confirmVersionSwitch() { if (!selectedSkill.value || !versionSwitchTarget.value) { return } applyVersionPayloadToRulePreview(selectedSkill.value, versionSwitchTarget.value) versionSwitchTarget.value = null } return { versionSwitchTarget, versionTimelineOpen, versionTimelineLoading, versionTimelineError, selectedVersionTimelineItems, loadVersionTimeline, openVersionTimeline, closeVersionTimeline, clearVersionTimelineState, openVersionSwitch, cancelVersionSwitch, confirmVersionSwitch } }