Files
OpenFlare/frontend/lib/utils/search-data.ts
T
ryan 454542c1d0 docs(i18n): 恢复并补齐英文版 vitepress,README 默认改为英文
- README 默认英文:README.en.md → README.md(英文为默认),中文移至 README.zh-CN.md,语言切换链接同步
- 恢复被删除的 docs/en/ 英文文档(git 历史 cc5e53c5^),删除 4 篇已废弃文件
- 英文导航 config.ts 对齐中文结构(新增 Deployment/Changelog 侧栏,同步 Guide/Design 条目)
- 翻译 15 篇中文新增文档:guide 5 篇(certificates/pages-usage/proxy-config/uptime-kuma/zone-domain-migration)+ design 10 篇(zone-design/cloudflare-pointing/waf-orchestration/origin-error-page/edge-cache-design/pages-design/logstore/kuma-design/login-captcha/observability 三篇)
- en 首页更新(新增 Pages 特性、tagline 同步);changelog 英文入口指向中文版
- vitepress 构建验证:43 个英文页面全部渲染

注意:29 篇旧英文文档为恢复版,部分内容(如 deployment/server、reference/configuration)可能落后于中文,需后续逐篇同步
2026-08-16 23:18:29 +08:00

425 lines
10 KiB
TypeScript

import PinyinMatch from 'pinyin-match';
type MatchResult = [number, number] | false;
type MatchFunction = (input: string, keys: string) => MatchResult;
// Handle CJS/ESM interop for pinyin-match
const match = ((): MatchFunction | null => {
const p = PinyinMatch as unknown;
if (!p) return null;
// Check for .default.match (common in some ESM bundles)
const withDefault = p as { default?: { match?: MatchFunction } };
if (typeof withDefault.default?.match === 'function') {
return withDefault.default.match;
}
// Check for .match (defined in its typings)
const withMatch = p as { match?: MatchFunction };
if (typeof withMatch.match === 'function') {
return withMatch.match;
}
// Check if it's the function itself
if (typeof p === 'function') {
return p as MatchFunction;
}
// Fallback
return null;
})();
export interface SearchItemSource {
id: string;
titleKey: string;
descriptionKey: string;
url: string;
category: 'page' | 'feature' | 'setting' | 'admin';
keywords: string[];
icon?: string;
}
export interface SearchItem extends SearchItemSource {
title: string;
description: string;
matchRange?: [number, number];
}
/**
* 全局搜索数据源
* 包含所有可搜索的页面和功能
*/
export const searchData: SearchItemSource[] = [
// ==================== 总览 ====================
{
id: 'home',
titleKey: 'nav.dashboard',
descriptionKey: 'search.items.homeDesc',
url: '/',
category: 'page',
keywords: ['home', '主页', '首页', 'dashboard', '总览'],
},
// ==================== 文档库 ====================
{
id: 'docs-how-to-use',
titleKey: 'nav.usageDocs',
descriptionKey: 'search.items.usageDocsDesc',
url: 'https://openflare.fyrn.link/',
category: 'page',
keywords: ['docs', '文档', '使用', 'how to', 'tutorial', '教程', 'help'],
},
// ==================== 业务控制台 ====================
{
id: 'console-nodes',
titleKey: 'nav.nodes',
descriptionKey: 'search.items.nodesDesc',
url: '/nodes',
category: 'page',
keywords: [
'node',
'节点',
'边缘节点',
'中继',
'内网穿透',
'tunnel',
'服务器',
],
},
{
id: 'console-proxy-routes',
titleKey: 'nav.proxyRoutes',
descriptionKey: 'search.items.proxyRoutesDesc',
url: '/proxy-routes',
category: 'page',
keywords: ['route', '规则', '路由', '代理', '反向代理', 'proxy'],
},
{
id: 'console-websites',
titleKey: 'nav.websites',
descriptionKey: 'search.items.websitesDesc',
url: '/websites',
category: 'page',
keywords: ['website', 'domain', '网站', '域名', '站点'],
},
{
id: 'console-certificates',
titleKey: 'nav.certificates',
descriptionKey: 'search.items.certificatesDesc',
url: '/certificates',
category: 'page',
keywords: ['certificate', 'ssl', 'tls', '证书', 'https', '加密'],
},
{
id: 'console-dns-accounts',
titleKey: 'nav.dnsAccounts',
descriptionKey: 'search.items.dnsAccountsDesc',
url: '/dns-accounts',
category: 'page',
keywords: [
'dns',
'dns account',
'账号',
'域名解析',
'cloudflare',
'aliyun',
'tencent',
],
},
{
id: 'console-origins',
titleKey: 'nav.origins',
descriptionKey: 'search.items.originsDesc',
url: '/origins',
category: 'page',
keywords: ['origin', '源站', '后端', 'backend', '服务器', '负载均衡'],
},
{
id: 'console-responses',
titleKey: 'nav.responses',
descriptionKey: 'search.items.responsesDesc',
url: '/responses',
category: 'page',
keywords: [
'响应页面',
'错误页',
'联系页',
'源站',
'502',
'503',
'5xx',
'Service Worker',
'离线兜底',
'error page',
],
},
{
id: 'console-waf',
titleKey: 'nav.waf',
descriptionKey: 'search.items.wafDesc',
url: '/waf',
category: 'page',
keywords: ['waf', '防火墙', '安全', 'security', '拦截', '规则'],
},
{
id: 'console-ip-groups',
titleKey: 'nav.ipGroups',
descriptionKey: 'search.items.ipGroupsDesc',
url: '/ip-groups',
category: 'page',
keywords: ['ip', 'ip group', 'ip组', '黑名单', '白名单', '访问控制'],
},
{
id: 'console-rate-limits',
titleKey: 'nav.rateLimits',
descriptionKey: 'search.items.rateLimitsDesc',
url: '/rate-limits',
category: 'page',
keywords: [
'限流',
'rate limit',
'limit_conn',
'limit_rate',
'并发',
'带宽',
],
},
{
id: 'console-pages',
titleKey: 'nav.pages',
descriptionKey: 'search.items.pagesDesc',
url: '/pages',
category: 'page',
keywords: ['pages', '静态托管', 'cdn', '网站', '部署', 'static'],
},
{
id: 'console-config-versions',
titleKey: 'nav.configVersions',
descriptionKey: 'search.items.configVersionsDesc',
url: '/config-versions',
category: 'page',
keywords: ['version', 'config', '版本', '发布', '回滚', '对比', '部署'],
},
{
id: 'console-access-logs',
titleKey: 'nav.accessLogs',
descriptionKey: 'search.items.accessLogsDesc',
url: '/access-logs',
category: 'page',
keywords: ['log', 'logs', '访问日志', '分析', '流量', '请求'],
},
{
id: 'console-apply-logs',
titleKey: 'nav.applyLogs',
descriptionKey: 'search.items.applyLogsDesc',
url: '/apply-logs',
category: 'page',
keywords: [
'apply',
'log',
'logs',
'应用记录',
'配置下发',
'同步',
'部署历史',
],
},
{
id: 'console-performance',
titleKey: 'nav.performance',
descriptionKey: 'search.items.performanceDesc',
url: '/performance',
category: 'page',
keywords: ['performance', '性能', '调优', '优化', '参数', '连接', '超时'],
},
// ==================== 个人设置 ====================
{
id: 'settings',
titleKey: 'search.items.globalSettings',
descriptionKey: 'search.items.settingsDesc',
url: '/settings',
category: 'setting',
keywords: ['settings', '设置', '偏好', 'preferences'],
},
{
id: 'settings-profile',
titleKey: 'user.profile',
descriptionKey: 'search.items.profileDesc',
url: '/settings/profile',
category: 'setting',
keywords: ['profile', '资料', '个人', '我的', '信息', 'avatar'],
},
{
id: 'settings-appearance',
titleKey: 'search.items.appearance',
descriptionKey: 'search.items.appearanceDesc',
url: '/settings/appearance',
category: 'setting',
keywords: ['appearance', '外观', '主题', 'theme', 'dark', 'light'],
},
{
id: 'admin-settings',
titleKey: 'nav.adminSettings',
descriptionKey: 'search.items.adminSettingsDesc',
url: '/admin/settings',
category: 'admin',
keywords: [
'admin',
'管理员',
'系统设置',
'安全',
'security',
'oidc',
'login',
],
},
{
id: 'admin-system',
titleKey: 'nav.system',
descriptionKey: 'search.items.systemDesc',
url: '/admin/system',
category: 'admin',
keywords: ['admin', '管理员', '系统', '配置', 'system', 'configurations'],
},
{
id: 'admin-users',
titleKey: 'nav.users',
descriptionKey: 'search.items.usersDesc',
url: '/admin/users',
category: 'admin',
keywords: ['admin', '管理员', '用户', '管理', 'users', 'status'],
},
{
id: 'admin-tasks',
titleKey: 'nav.tasks',
descriptionKey: 'search.items.tasksDesc',
url: '/admin/tasks',
category: 'admin',
keywords: [
'admin',
'管理员',
'任务',
'异步',
'tasks',
'scheduler',
'worker',
],
},
{
id: 'admin-files',
titleKey: 'nav.storage',
descriptionKey: 'search.items.storageDesc',
url: '/admin/files',
category: 'admin',
keywords: ['admin', '管理员', '存储', '文件', 'files', 'upload', 's3'],
},
{
id: 'admin-database',
titleKey: 'nav.database',
descriptionKey: 'search.items.databaseDesc',
url: '/admin/database',
category: 'admin',
keywords: ['admin', '管理员', '数据库', 'database', 'sql', 'query', 'gorm'],
},
{
id: 'admin-push',
titleKey: 'nav.push',
descriptionKey: 'search.items.pushDesc',
url: '/admin/push',
category: 'admin',
keywords: [
'admin',
'管理员',
'推送',
'通知',
'push',
'mail',
'telegram',
'lark',
],
},
{
id: 'admin-logs',
titleKey: 'nav.logs',
descriptionKey: 'search.items.logsDesc',
url: '/admin/logs',
category: 'admin',
keywords: ['admin', '管理员', '日志', 'logs', 'system log', 'terminal'],
},
];
/**
* 搜索功能
* @param query 搜索关键词
* @param isAdmin 是否为管理员
* @param t 文案解析函数(layout 命名空间)
* @returns 匹配的搜索结果
*/
export function searchItems(
query: string,
isAdmin: boolean = false,
t: (key: string) => string,
): SearchItem[] {
const trimmedQuery = query.trim();
// 非管理员不能搜索 admin 类别项
const filteredData = isAdmin
? searchData
: searchData.filter((item) => item.category !== 'admin');
const resolved = filteredData.map((item) => ({
...item,
title: t(item.titleKey),
description: t(item.descriptionKey),
}));
if (!trimmedQuery) {
return resolved;
}
return resolved
.map((item) => {
// 优先匹配标题
const titleMatch =
typeof match === 'function' ? match(item.title, trimmedQuery) : null;
if (titleMatch) {
return { ...item, matchRange: titleMatch as [number, number] };
}
// 匹配描述
if (
typeof match === 'function' &&
match(item.description, trimmedQuery)
) {
return item;
}
// 匹配关键词
if (
item.keywords.some(
(keyword) =>
typeof match === 'function' && match(keyword, trimmedQuery),
)
) {
return item;
}
return null;
})
.filter((item): item is SearchItem => item !== null)
.sort((a, b) => {
// 标题匹配优先
if (a.matchRange && !b.matchRange) return -1;
if (!a.matchRange && b.matchRange) return 1;
// 如果都是标题匹配,按匹配位置排序
if (a.matchRange && b.matchRange) {
return a.matchRange[0] - b.matchRange[0];
}
return 0;
});
}