feat: 将搜索页面由Strapi迁移至Direcuts
- 路由页面相关源码修改 - 类型标注与组合式API - 相关工具函数
This commit is contained in:
@ -1,33 +1,25 @@
|
||||
import { MeiliSearch } from 'meilisearch';
|
||||
import type { SearchParams, SearchResponse } from 'meilisearch';
|
||||
import type { SearchParams } from 'meilisearch';
|
||||
|
||||
interface RawSearchSection {
|
||||
indexUid: string;
|
||||
response: SearchResponse<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export interface SearchHit extends Record<string, unknown> {
|
||||
indexUid: string;
|
||||
objectID?: string | number;
|
||||
}
|
||||
|
||||
export interface SearchSection {
|
||||
indexUid: string;
|
||||
hits: SearchHit[];
|
||||
estimatedTotalHits: number;
|
||||
processingTimeMs: number;
|
||||
}
|
||||
|
||||
const parseIndexes = (indexes: string | string[] | undefined): string[] => {
|
||||
const parseIndexes = (
|
||||
indexes: string | string[] | undefined,
|
||||
locale?: string
|
||||
): string[] => {
|
||||
if (!indexes) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let suffix = '';
|
||||
if (locale) {
|
||||
suffix = `_${locale}`;
|
||||
}
|
||||
|
||||
if (Array.isArray(indexes)) {
|
||||
return indexes.map((item) => item.trim()).filter(Boolean);
|
||||
return indexes.map((item) => `${item.trim()}${suffix}`).filter(Boolean);
|
||||
}
|
||||
return indexes
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
.map((item) => `${item.trim()}${suffix}`)
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
@ -56,10 +48,22 @@ export const useMeilisearch = () => {
|
||||
return meiliClient;
|
||||
};
|
||||
|
||||
const search = async (
|
||||
/**
|
||||
* 泛型搜索函数
|
||||
* @template T 文档类型, 如 MeiliProductIndex
|
||||
* ---
|
||||
* @param query 搜索关键词
|
||||
* @param params 其他搜索参数
|
||||
* @returns 搜索结果数组
|
||||
*/
|
||||
async function search<
|
||||
K extends MeiliSearchItemType = MeiliSearchItemType,
|
||||
T extends MeiliIndexMap[K] = MeiliIndexMap[K],
|
||||
>(
|
||||
query: string,
|
||||
params: SearchParams = {}
|
||||
): Promise<SearchSection[]> => {
|
||||
params: SearchParams = {},
|
||||
searchLocale?: string
|
||||
): Promise<SearchSection<T>[]> {
|
||||
const trimmedQuery = query.trim();
|
||||
if (!trimmedQuery) {
|
||||
return [];
|
||||
@ -70,34 +74,35 @@ export const useMeilisearch = () => {
|
||||
return [];
|
||||
}
|
||||
|
||||
const activeIndexes = indexes.value;
|
||||
const activeIndexes = indexes.value as K[];
|
||||
if (!activeIndexes.length) {
|
||||
console.warn('No Meilisearch indexes configured.');
|
||||
return [];
|
||||
}
|
||||
const rawIndexMap = Object.fromEntries(
|
||||
activeIndexes.map((index) => [`${index}_${searchLocale}`, index])
|
||||
);
|
||||
const indexesWithLocale = activeIndexes.map(
|
||||
(index) => index + (searchLocale ? `_${searchLocale}` : '')
|
||||
);
|
||||
|
||||
const requests = activeIndexes.map(async (indexUid) => {
|
||||
const response = await client.index(indexUid).search(trimmedQuery, {
|
||||
console.log(indexesWithLocale);
|
||||
|
||||
const requests = indexesWithLocale.map(async (indexUid) => {
|
||||
const response = await client.index(indexUid).search<T>(trimmedQuery, {
|
||||
limit: params.limit ?? 10,
|
||||
...params,
|
||||
});
|
||||
const safeResponse = JSON.parse(JSON.stringify(response));
|
||||
return {
|
||||
indexUid,
|
||||
response: {
|
||||
hits: safeResponse.hits,
|
||||
estimatedTotalHits:
|
||||
safeResponse.estimatedTotalHits ?? safeResponse.hits.length,
|
||||
processingTimeMs: safeResponse.processingTimeMs ?? 0,
|
||||
query: safeResponse.query,
|
||||
},
|
||||
} satisfies RawSearchSection;
|
||||
response,
|
||||
} satisfies RawSearchSection<T>;
|
||||
});
|
||||
|
||||
console.log((await requests[0])?.response.hits[0]?.locale);
|
||||
|
||||
const settled = await Promise.allSettled(requests);
|
||||
|
||||
console.log('Meilisearch settled results:', settled);
|
||||
|
||||
settled
|
||||
.filter(
|
||||
(result): result is PromiseRejectedResult =>
|
||||
@ -108,22 +113,22 @@ export const useMeilisearch = () => {
|
||||
});
|
||||
|
||||
return settled
|
||||
.filter((result) => result.status === 'fulfilled')
|
||||
.filter(
|
||||
(result): result is PromiseFulfilledResult<RawSearchSection<T>> =>
|
||||
result.status === 'fulfilled'
|
||||
)
|
||||
.map((result) => {
|
||||
const fulfilled = result as PromiseFulfilledResult<RawSearchSection>;
|
||||
const { indexUid, response } = result.value;
|
||||
return {
|
||||
indexUid: fulfilled.value.indexUid,
|
||||
hits: fulfilled.value.response.hits.map((hit) => ({
|
||||
...hit,
|
||||
indexUid: fulfilled.value.indexUid,
|
||||
})),
|
||||
indexUid: indexUid,
|
||||
rawIndex: rawIndexMap[indexUid],
|
||||
hits: response.hits,
|
||||
estimatedTotalHits:
|
||||
fulfilled.value.response.estimatedTotalHits ??
|
||||
fulfilled.value.response.hits.length,
|
||||
processingTimeMs: fulfilled.value.response.processingTimeMs ?? 0,
|
||||
response.estimatedTotalHits ?? response.hits.length,
|
||||
processingTimeMs: response.processingTimeMs ?? 0,
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
search,
|
||||
|
||||
Reference in New Issue
Block a user