一、概述
本篇基于上一節 Python 實現的雙通道搜索服務(聚合 SearxNG + 本地知識庫),構建一個完整的 HarmonyOS ArkTS 前端頁面。用戶可在輸入框中輸入關鍵詞,實時查詢本地服務 http://localhost:5001/search?q=...
,返回結果自動渲染在頁面中,支持中文和英文關鍵詞的綜合查詢體驗。
二、目標說明
- 使用 ArkTS 開發搜索界面組件
- 輸入關鍵詞并發起 HTTP 請求
- 支持異步加載并實時顯示搜索結果
- 解析標準結構體
{ results: [{ title, content, url }] }
并渲染結果列表
三、目錄結構
SearchApp/
├── src/main/ets/
│ ├── pages/
│ │ └── Index.ets # 主頁面:包含輸入框、按鈕和結果列表
│ ├── components/
│ │ └── SearchDisplay.ets # 每條搜索結果的顯示組件
│ ├── services/
│ │ └── SearchService.ets # 封裝 HTTP 調用和 JSON 解析
│ ├── utils/
│ │ └── HttpClient.ets # 通用的 httpRequestText 實現
│ ├── types/
│ │ └── SearchTypes.ets # SearchResponse 和 SearchResultList 類型定義
│ └── configs/
│ └── Config.ets # 搜索 API URL 配置項
四、關鍵代碼實現
1. 配置文件(Config.ets)
export const config = {searchApiUrl: "http://192.168.1.103:5001/search"
}
2. 類型定義(SearchTypes.ets)
// src/main/ets/types/SearchTypes.ets/*** 單條搜索結果*/
export interface SearchResponse {title: stringcontent: stringurl: string
}/*** 后端返回的結果結構*/
export interface SearchResultList {results: SearchResponse[]
}
3. 搜索服務(SearchService.ets)
// src/main/ets/services/SearchService.etsimport { httpRequestText } from '../utils/HttpClient'
import { http } from '@kit.NetworkKit'
import { SearchResponse, SearchResultList } from '../types/SearchTypes'export class SearchService {private apiUrl: stringconstructor(apiUrl: string) {this.apiUrl = apiUrl}public async search(query: string,onItem?: (item: SearchResponse) => void): Promise<SearchResponse[]> {const url: string = `${this.apiUrl}?q=${encodeURIComponent(query)}`let buffer: string = ''try {await httpRequestText(url,http.RequestMethod.GET,'',60000,(chunk: string) => {buffer += chunk})} catch {console.error('SearchService 網絡請求失敗')throw new Error('Search 請求失敗')}let list: SearchResponse[]try {// 使用已定義的接口類型,而非內聯對象字面量const parsed = JSON.parse(buffer) as SearchResultListlist = parsed.results} catch {console.error('SearchService JSON 解析失敗,buffer=', buffer)throw new Error('返回數據格式錯誤')}list.forEach((item: SearchResponse) => {if (onItem) {onItem(item)}})return list}
}
4. 單條結果展示組件(SearchDisplay.ets)
// src/main/ets/components/SearchDisplay.etsimport { SearchResponse } from '../types/SearchTypes';@Component
export struct SearchDisplay {private item!: SearchResponse;build() {Column() {Text(this.item.title).fontSize(18).fontWeight('bold').margin({ bottom: 4 });Text(this.item.content).fontSize(14).margin({ bottom: 4 });Text(this.item.url).fontSize(12).fontColor('#888'); // 使用 fontColor 設置文本顏色}.padding(10).backgroundColor('#F5F5F5').margin({ bottom: 10 });}
}
5. 主頁面實現(Index.ets)
// src/main/ets/pages/Index.etsimport { SearchDisplay } from '../components/SearchDisplay'
import { config } from '../configs/Config'
import { SearchService } from '../services/SearchService'
import { SearchResponse } from '../types/SearchTypes'@Entry
@Component
export struct Index {@State query: string = 'HarmonyOS'@State results: SearchResponse[] = []public async fetchData(): Promise<void> {this.results = []try {const res: SearchResponse[] = await new SearchService(config.searchApiUrl).search(this.query)this.results = res} catch {console.error('搜索失敗')}}public build(): void {Column() {TextInput({ text: this.query, placeholder: '輸入搜索關鍵詞,如 ChatGPT' }).onChange((value: string): void => {this.query = value}).width('match_parent').height(50).width(300).margin({ bottom: 12 })Button('搜索').width('match_parent').height(50).onClick((): void => {this.fetchData()}).margin({ bottom: 20 })ForEach(this.results, (item: SearchResponse): void => {SearchDisplay({ item })})}.padding({ left: 20, right: 20, top: 20 })}
}
五、運行效果示例
如圖所示,輸入 “HarmonyOS” 或 “ChatGPT” 后,前端立即展示聚合搜索結果:
六、總結
本篇在第40篇的 Python 搜索服務基礎上,構建了 HarmonyOS 的前端頁面。整個流程完整覆蓋:
- 構建
TextInput
、按鈕、結果展示組件 - 使用
HttpClient.ets
封裝請求 - 實現 JSON 結構的嚴格類型解析與響應式渲染
通過該示例,開發人員可以快速將本地服務能力集成進 HarmonyOS App,用于搭建多模態查詢工具、Dify Agent 插件原型或獨立智能體前端。下一步可考慮引入分頁、加載動畫或語音輸入等多模態交互能力。