import type { VersionWithContext } from './derive'; import type { XiaobaoRiskInsight } from './xiaobao-risk-cache'; import { WORK_HOURS } from './work-hours'; const UNFINISHED_VERSION_STATUSES = new Set(['planned', 'developing', 'paused']); const PAGE_REFRESH_ADVICE_PATTERNS = [ /(刷新|重新加载|重载).*(页面|浏览器|小宝|预警)/i, /(页面|浏览器|小宝|预警).*(刷新|重新加载|重载)/i, /(手动|主动).*(触发|刷新).*(更新|预警|分析)/i, /(manual|manually).*(refresh|reload|trigger)/i, /(refresh|reload).*(page|browser|xiaobao|warning)/i, ]; export interface XiaobaoWarningVersionFilter { canManage: boolean; userName?: string; } export function filterXiaobaoWarningVersions( versions: VersionWithContext[], filter: XiaobaoWarningVersionFilter, ): VersionWithContext[] { return versions.filter((version) => { if (!UNFINISHED_VERSION_STATUSES.has(version.status)) return false; if (filter.canManage) return true; if (!filter.userName) return false; return (version.members ?? []).some((member) => member.name === filter.userName); }); } export function formatRemainingWork(hours: number): string { const safeHours = Number.isFinite(hours) && hours > 0 ? hours : 0; const days = safeHours / WORK_HOURS.hoursPerDay; return `${formatNumber(safeHours)}h / ${formatNumber(days)}天`; } export function sanitizeRiskInsight(insight: XiaobaoRiskInsight): XiaobaoRiskInsight { return { ...insight, suggestedActions: insight.suggestedActions.filter((action) => !isPageRefreshAdvice(action)), ownerHints: insight.ownerHints.filter((hint) => !isPageRefreshAdvice(hint)), }; } function formatNumber(value: number): string { if (Number.isInteger(value)) return String(value); return value.toFixed(1).replace(/\.0$/, ''); } function isPageRefreshAdvice(text: string): boolean { return PAGE_REFRESH_ADVICE_PATTERNS.some((pattern) => pattern.test(text)); }