1
0
forked from boos/BoosAPI

Repair release-branch CI after folding dev onto main

The release branch inherited a few merge-shaped regressions after the
large dev snapshot was layered onto the latest main snapshot. This
commit restores the main-compatible stats and TokenRoutes behavior the
CI suite expects and adds the missing multi-brand helper export so the
release branch reflects a coherent post-merge tree instead of a
partially regressed hybrid.

Constraint: Must keep the release branch mergeable to main while preserving the current publish snapshot shape
Rejected: Re-open the whole release merge and hand-resolve every file again | too broad for targeted CI repair
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: When dev and main have drifted heavily, re-run the main-facing CI tests after any conflict normalization pass
Tested: targeted vitest suite for failing CI jobs plus update-center coverage; typecheck
Not-tested: Full npm test still not representative locally because of unrelated untracked tmp/sub2api suites outside the PR branch content
This commit is contained in:
cita-777
2026-04-17 23:26:22 +08:00
parent f335a330e3
commit 4aa888e581
3 changed files with 1551 additions and 1231 deletions
File diff suppressed because it is too large Load Diff
+28 -12
View File
@@ -777,30 +777,46 @@ export function getAllBrandNames(): string[] {
return BRAND_DEFINITIONS.map((brand) => brand.name);
}
export function getBrand(modelName: string): BrandInfo | null {
function toBrandInfo(brand: BrandDefinition): BrandInfo {
return {
name: brand.name,
icon: brand.icon,
color: brand.color,
};
}
export function getMatchingBrands(modelName: string): BrandInfo[] {
const context = buildMatchContext(modelName);
const matches: BrandInfo[] = [];
const seen = new Set<string>();
const add = (brand: BrandDefinition) => {
if (seen.has(brand.name)) return;
seen.add(brand.name);
matches.push(toBrandInfo(brand));
};
for (const definition of BRAND_DEFINITIONS) {
if (definition.rules.some((rule) => matchesRule(context, rule))) {
return {
name: definition.name,
icon: definition.icon,
color: definition.color,
};
add(definition);
}
}
for (const candidate of context.candidates) {
for (const rule of BRAND_FALLBACK_BOUNDARY_RULES) {
if (rule.boundaryRegex.test(candidate)) {
return {
name: rule.brand.name,
icon: rule.brand.icon,
color: rule.brand.color,
};
add(rule.brand);
}
}
}
return null;
return matches;
}
export function getMatchingBrandNames(modelName: string): string[] {
return getMatchingBrands(modelName).map((brand) => brand.name);
}
export function getBrand(modelName: string): BrandInfo | null {
return getMatchingBrands(modelName)[0] || null;
}
+40 -15
View File
@@ -93,8 +93,14 @@ const EMPTY_ROUTE_FORM: RouteEditorForm = {
sourceRouteIds: [],
advancedOpen: false,
};
const DESKTOP_DETAIL_ENTER_MS = 260;
const DESKTOP_DETAIL_COLLAPSE_MS = 200;
function prefersReducedMotion(): boolean {
return typeof globalThis.matchMedia === 'function'
&& globalThis.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
function getRouteRoutingStrategySuccessMessage(value: RouteRoutingStrategy): string {
if (value === 'round_robin') return '已切换为轮询策略';
if (value === 'stable_first') return '已切换为稳定优先策略';
@@ -114,30 +120,44 @@ export function DesktopDetailPanelPresence({
}) {
const [shouldRender, setShouldRender] = useState(open);
const [isOpen, setIsOpen] = useState(open);
const [isEntering, setIsEntering] = useState(false);
const [isClosing, setIsClosing] = useState(false);
const hasEverOpenedRef = useRef(open);
useEffect(() => {
const reduceMotion = prefersReducedMotion();
if (open) {
hasEverOpenedRef.current = true;
setShouldRender(true);
setIsClosing(false);
if (typeof window !== 'undefined' && typeof window.requestAnimationFrame === 'function') {
const rafId = window.requestAnimationFrame(() => setIsOpen(true));
return () => window.cancelAnimationFrame(rafId);
}
setIsOpen(true);
return undefined;
setIsClosing(false);
if (reduceMotion) {
setIsEntering(false);
return undefined;
}
setIsEntering(true);
const enterTimerId = globalThis.setTimeout(() => {
setIsEntering(false);
}, DESKTOP_DETAIL_ENTER_MS);
return () => globalThis.clearTimeout(enterTimerId);
}
if (!hasEverOpenedRef.current) {
setShouldRender(false);
setIsOpen(false);
setIsEntering(false);
setIsClosing(false);
return undefined;
}
setIsOpen(false);
setIsEntering(false);
if (reduceMotion) {
setShouldRender(false);
setIsClosing(false);
return undefined;
}
setIsClosing(true);
const timerId = globalThis.setTimeout(() => {
setShouldRender(false);
@@ -150,7 +170,7 @@ export function DesktopDetailPanelPresence({
if (!shouldRender) return null;
return (
<div
className={`route-detail-panel-presence ${isOpen ? 'is-open' : ''} ${isClosing ? 'is-closing' : ''}`.trim()}
className={`route-detail-panel-presence ${isOpen ? 'is-open' : ''} ${isEntering ? 'is-entering' : ''} ${isClosing ? 'is-closing' : ''}`.trim()}
style={{ gridColumn: '1 / -1' }}
>
{children(isClosing)}
@@ -1280,15 +1300,20 @@ export default function TokenRoutes() {
const isCurrentlyExpanded = expandedRouteIds.includes(routeId);
if (isCurrentlyExpanded) {
if (!isMobile) {
setClosingDesktopDetailRouteIds((prev) => (prev.includes(routeId) ? prev : [...prev, routeId]));
const existingTimer = desktopDetailCloseTimersRef.current[routeId];
if (existingTimer) {
globalThis.clearTimeout(existingTimer);
}
desktopDetailCloseTimersRef.current[routeId] = globalThis.setTimeout(() => {
const reduceMotion = prefersReducedMotion();
if (reduceMotion) {
setClosingDesktopDetailRouteIds((prev) => prev.filter((id) => id !== routeId));
delete desktopDetailCloseTimersRef.current[routeId];
}, DESKTOP_DETAIL_COLLAPSE_MS);
} else {
setClosingDesktopDetailRouteIds((prev) => (prev.includes(routeId) ? prev : [...prev, routeId]));
const existingTimer = desktopDetailCloseTimersRef.current[routeId];
if (existingTimer) {
globalThis.clearTimeout(existingTimer);
}
desktopDetailCloseTimersRef.current[routeId] = globalThis.setTimeout(() => {
setClosingDesktopDetailRouteIds((prev) => prev.filter((id) => id !== routeId));
delete desktopDetailCloseTimersRef.current[routeId];
}, DESKTOP_DETAIL_COLLAPSE_MS);
}
}
setExpandedRouteIds((prev) => prev.filter((id) => id !== routeId));
} else {