1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { LogUtil } from '../../baseUtil/LogUtil' 17import NoteData from '../../model/databaseModel/NoteData' 18import util from '@ohos.util' 19import relationalStore from '@ohos.data.relationalStore'; 20 21const TAG: string = 'SearchModel'; 22 23interface TextSpan { 24 type: 0 | 1; // 0 表示正常文本,1 表示高亮关键词 25 text: string; 26} 27 28/** 29 * Search service class 30 */ 31export class SearchModel { 32 private rdbStore: relationalStore.RdbStore | undefined = undefined; 33 34 /** 35 * Search 36 * 37 * @param query - query content 38 */ 39 public async search(noteDataArray: NoteData[], query: string): Promise<NoteData[]> { 40 LogUtil.info(TAG, "query is " + query) 41 if (!query) { 42 LogUtil.info(TAG, "query is null") 43 return [] 44 } 45 let searchData: NoteData[] = []; 46 noteDataArray.forEach((noteData) => { 47 let base64regex = new RegExp('/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/'); 48 let contentTextValue: string 49 if (base64regex.test(noteData.content_text) && noteData.content_text.length > 0) { 50 let Base64 = new util.Base64() 51 let textDecoder = new util.TextDecoder("utf-8", { ignoreBOM: true }) // utf-8:编码格式为utf-8,ignoreBOM:是否忽略BOM标记 52 let decodeStr = Base64.decodeSync(noteData.content_text) 53 contentTextValue = textDecoder.decode(decodeStr, { stream: false }) // stream:在随后的decode()调用中是否跟随附加数据块 54 } else { 55 contentTextValue = noteData.content_text 56 } 57 if (contentTextValue.replace(new RegExp('/<[^>]+>/g'), "").toLowerCase().indexOf(query.toLowerCase()) != -1 58 || noteData.title.toLowerCase().indexOf(query.toLowerCase()) != -1) { 59 LogUtil.info(TAG, "uuid " + noteData.uuid) 60 searchData.push(noteData); 61 } 62 }) 63 // 排序 64 return searchData; 65 } 66 67 splitToHighlightText(text: string, highlightKeyword: string): TextSpan[] { 68 let spans: TextSpan[] = []; 69 let lowerSpans: string[] = text.toLowerCase().split(highlightKeyword.toLowerCase()); 70 let keywordStartIndex = 0; 71 let keywordLength = highlightKeyword.length; 72 73 for (let i = 0; i < lowerSpans.length; i++) { 74 let normalText = text.substr(keywordStartIndex, lowerSpans[i].length); 75 spans.push({ 76 type: 0, 77 text: normalText 78 }) 79 // if not at last, append highlight keyword 80 if (i != lowerSpans.length - 1) { 81 keywordStartIndex += lowerSpans[i].length 82 let keywordText = text.substr(keywordStartIndex, keywordLength); 83 spans.push({ 84 type: 1, 85 text: keywordText 86 }) 87 keywordStartIndex += keywordLength 88 } 89 } 90 91 return spans 92 } 93} 94 95let searchModel = new SearchModel() 96 97export default searchModel as SearchModel