Files
everything-is-suitable/everything-is-suitable-uniapp/src/services/searchService.ts
T
张翔 0c9a4ac96b feat: 添加 UniApp 核心源码文件
- App.vue 应用入口
- algorithms/ 算法模块(黄历、紫微斗数、运势、日历等)
- services/ 业务服务层
- utils/ 工具函数(storage、exportImport)
- 配置文件(manifest.json、pages.json、vite.config.ts)
- H5 入口 index.html
2026-04-29 21:15:55 +08:00

105 lines
3.2 KiB
TypeScript

import { AlmanacService } from './almanacService'
import type { Almanac } from '../algorithms/types'
import type { SearchCondition, SearchRequest, SearchResult } from '../types/search'
import { storage } from '../utils/storage'
export interface SearchParams {
keyword?: string
dateFrom?: string
dateTo?: string
suitableFilter?: string[]
unsuitableFilter?: string[]
}
export interface SearchHistoryItem {
keyword: string
timestamp: number
resultCount: number
}
function toSearchParams(request: SearchRequest): SearchParams {
const suitableFilter: string[] = []
const unsuitableFilter: string[] = []
for (const cond of request.conditions) {
if (cond.type === 'suitable') {
suitableFilter.push(...cond.items)
} else {
unsuitableFilter.push(...cond.items)
}
}
const today = new Date()
const dateFrom = today.toISOString().slice(0, 10)
const endDate = new Date(today)
endDate.setDate(endDate.getDate() + request.days)
const dateTo = endDate.toISOString().slice(0, 10)
return { suitableFilter, unsuitableFilter, dateFrom, dateTo }
}
function toSearchResult(almanac: Almanac, conditions: SearchCondition[]): SearchResult {
const matchedSuitable = conditions
.filter(c => c.type === 'suitable')
.flatMap(c => c.items)
.filter(item => almanac.suitable.includes(item))
const matchedUnsuitable = conditions
.filter(c => c.type === 'unsuitable')
.flatMap(c => c.items)
.filter(item => almanac.unsuitable.includes(item))
return {
date: almanac.solarDate,
lunarDate: `${almanac.lunarDate.lunarYear}${almanac.lunarDate.lunarMonth}${almanac.lunarDate.lunarDay}`,
weekday: almanac.lunarDate.weekday,
matchedItems: {
suitable: matchedSuitable,
unsuitable: matchedUnsuitable,
},
matchCount: matchedSuitable.length + matchedUnsuitable.length,
almanacData: almanac,
}
}
export class SearchService {
private almanacService = new AlmanacService()
private historyKey = 'search_history'
async search(request: SearchRequest): Promise<SearchResult[]> {
const params = toSearchParams(request)
const almanacs = await this.almanacService.searchAlmanacs(params)
this.addToHistory(
request.conditions.map(c => c.items.join(',')).join(';'),
almanacs.length,
)
return almanacs.map(a => toSearchResult(a, request.conditions))
}
async searchByKeyword(keyword: string): Promise<SearchResult[]> {
const params: SearchParams = { keyword }
const almanacs = await this.almanacService.searchAlmanacs(params)
this.addToHistory(keyword, almanacs.length)
return almanacs.map(a => toSearchResult(a, []))
}
async getSearchHistory(): Promise<SearchHistoryItem[]> {
return storage.get<SearchHistoryItem[]>(this.historyKey) ?? []
}
async clearSearchHistory(): Promise<void> {
storage.remove(this.historyKey)
}
private addToHistory(keyword: string, resultCount: number): void {
if (!keyword) return
const history = storage.get<SearchHistoryItem[]>(this.historyKey) ?? []
history.unshift({ keyword, timestamp: Date.now(), resultCount })
if (history.length > 50) history.length = 50
storage.set(this.historyKey, history)
}
}
const searchService = new SearchService()
export default searchService