mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-06-16 13:34:04 +08:00
308314baac
- Pre-filter sessions by provider before indexing to prevent result truncation when FlexSearch limit cuts across providers - Switch tokenizer from "forward" to "full" for Chinese substring matching - Preserve FlexSearch relevance ranking when search query is present
73 lines
1.8 KiB
TypeScript
73 lines
1.8 KiB
TypeScript
import { useCallback, useMemo } from "react";
|
|
import FlexSearch from "flexsearch";
|
|
import type { SessionMeta } from "@/types";
|
|
|
|
interface UseSessionSearchOptions {
|
|
sessions: SessionMeta[];
|
|
providerFilter: string;
|
|
}
|
|
|
|
interface UseSessionSearchResult {
|
|
search: (query: string) => SessionMeta[];
|
|
}
|
|
|
|
/**
|
|
* 使用 FlexSearch 实现会话全文搜索
|
|
* 索引会话元数据(标题、摘要、项目目录等)
|
|
*/
|
|
export function useSessionSearch({
|
|
sessions,
|
|
providerFilter,
|
|
}: UseSessionSearchOptions): UseSessionSearchResult {
|
|
const filteredByProvider = useMemo(() => {
|
|
if (providerFilter === "all") return sessions;
|
|
return sessions.filter((s) => s.providerId === providerFilter);
|
|
}, [sessions, providerFilter]);
|
|
|
|
const index = useMemo(() => {
|
|
const nextIndex = new FlexSearch.Index({
|
|
tokenize: "full",
|
|
resolution: 9,
|
|
});
|
|
|
|
filteredByProvider.forEach((session, idx) => {
|
|
const metaContent = [
|
|
session.sessionId,
|
|
session.title,
|
|
session.summary,
|
|
session.projectDir,
|
|
session.sourcePath,
|
|
]
|
|
.filter(Boolean)
|
|
.join(" ");
|
|
|
|
nextIndex.add(idx, metaContent);
|
|
});
|
|
|
|
return nextIndex;
|
|
}, [filteredByProvider]);
|
|
|
|
const search = useCallback(
|
|
(query: string): SessionMeta[] => {
|
|
const needle = query.trim();
|
|
|
|
if (!needle) {
|
|
return [...filteredByProvider].sort((a, b) => {
|
|
const aTs = a.lastActiveAt ?? a.createdAt ?? 0;
|
|
const bTs = b.lastActiveAt ?? b.createdAt ?? 0;
|
|
return bTs - aTs;
|
|
});
|
|
}
|
|
|
|
const results = index.search(needle, {
|
|
limit: filteredByProvider.length,
|
|
}) as number[];
|
|
|
|
return results.map((idx) => filteredByProvider[idx]);
|
|
},
|
|
[index, filteredByProvider],
|
|
);
|
|
|
|
return { search };
|
|
}
|