From c26d867f79446c186244e7628ea96ff2c1904553 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 19 Jun 2026 16:58:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(providers):=20order=20preset=20selector=20?= =?UTF-8?q?=E2=80=94=20official=20first,=20prime=20partner=20next?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the default (Original) sort mode, float official-category presets to the very top, followed by prime partners (Kimi), then the rest in their original array order. Implemented as a three-way partition+concat so each group keeps its internal order and no preset is listed twice. --- .../providers/forms/ProviderPresetSelector.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/providers/forms/ProviderPresetSelector.tsx b/src/components/providers/forms/ProviderPresetSelector.tsx index da82dbbd4..8cc2d13ae 100644 --- a/src/components/providers/forms/ProviderPresetSelector.tsx +++ b/src/components/providers/forms/ProviderPresetSelector.tsx @@ -88,7 +88,21 @@ export function sortPresetEntries( t: PresetTranslator, ): PresetEntry[] { if (sortMode === PresetSortMode.Original) { - return [...entries]; + // 置顶优先级:官方分类 > 尊享合作伙伴(Kimi)> 其余原顺序。 + // 用分区拼接而非排序,确保每组内部各自的相对顺序都不变; + // 排他条件保证「既是官方又是 prime」的预设只归入官方组、不被重复。 + const official = entries.filter( + (entry) => entry.preset.category === "official", + ); + const prime = entries.filter( + (entry) => + entry.preset.category !== "official" && entry.preset.primePartner, + ); + const rest = entries.filter( + (entry) => + entry.preset.category !== "official" && !entry.preset.primePartner, + ); + return [...official, ...prime, ...rest]; } return [...entries].sort((a, b) =>