📌 概述
筛选器管理模块允许用户保存和管理常用的筛选条件。该模块集成了 Cordova 框架与 OpenHarmony 原生能力,提供了完整的筛选器管理功能。用户可以创建多个筛选器,为每个筛选器设置特定的条件,然后快速应用这些筛选器来查看特定的数据。模块支持筛选器的编辑、删除和排序。
🔗 完整流程
第一步:筛选器数据加载
当用户进入筛选器管理页面时,应用会从数据库中加载所有已保存的筛选器。应用会显示每个筛选器的名称、条件和使用次数。
第二步:筛选器展示与管理
数据加载完成后,应用会将筛选器显示为列表形式。用户可以点击筛选器快速应用,也可以编辑或删除筛选器。用户可以创建新的筛选器。
第三步:筛选器应用与同步
当用户点击筛选器时,应用会立即应用该筛选器的条件,显示符合条件的数据。应用会更新筛选器的使用统计。
🔧 Web 代码实现
HTML 筛选器列表
<divid="filters-page"class="page"><divclass="page-header"><h1>筛选器</h1><buttonclass="btn btn-primary"onclick="openCreateFilterModal()">+ 新建筛选器</button></div><divid="filters-list"class="filters-list"><!-- 筛选器项动态生成 --></div><!-- 创建/编辑筛选器模态框 --><divid="filter-modal"class="modal"style="display:none;"><divclass="modal-content"><divclass="modal-header"><h2id="filter-modal-title">新建筛选器</h2><buttonclass="btn-close"onclick="closeFilterModal()">×</button></div><formid="filter-form"class="form"><divclass="form-group"><labelfor="filter-name">筛选器名称 *</label><inputtype="text"id="filter-name"name="name"required></div><divclass="form-group"><labelfor="filter-tea-type">茶叶类型</label><selectid="filter-tea-type"name="teaType"><optionvalue="">全部</option></select></div><divclass="form-group"><labelfor="filter-origin">产地</label><selectid="filter-origin"name="origin"><optionvalue="">全部</option></select></div><divclass="form-group"><labelfor="filter-rating-min">最低评分</label><selectid="filter-rating-min"name="ratingMin"><optionvalue="">全部</option><optionvalue="1">1 星及以上</option><optionvalue="2">2 星及以上</option><optionvalue="3">3 星及以上</option><optionvalue="4">4 星及以上</option><optionvalue="5">5 星</option></select></div><divclass="modal-actions"><buttontype="submit"class="btn btn-primary">保存</button><buttontype="button"class="btn btn-secondary"onclick="closeFilterModal()">取消</button></div></form></div></div></div>筛选器管理页面包含筛选器列表和创建筛选器的按钮。模态框用于创建或编辑筛选器。
筛选器管理逻辑
letallFilters=[];letcurrentEditingFilterId=null;asyncfunctionrenderFilters(){try{// 加载筛选器数据allFilters=awaitdb.getFilters();constlistContainer=document.getElementById('filters-list');listContainer.innerHTML='';if(allFilters.length===0){listContainer.innerHTML='<div class="no-data"><p>暂无筛选器</p></div>';return;}allFilters.forEach(filter=>{constfilterEl=document.createElement('div');filterEl.className='filter-item';filterEl.dataset.filterId=filter.id;constconditions=buildConditionString(filter);filterEl.innerHTML=`<div class="filter-info"> <div class="filter-name">${filter.name}</div> <div class="filter-conditions">${conditions}</div> <div class="filter-usage">使用次数:${filter.usageCount||0}</div> </div> <div class="filter-actions"> <button class="btn-icon" onclick="applyFilter(${filter.id})" title="应用">✓</button> <button class="btn-icon" onclick="editFilter(${filter.id})" title="编辑">✏️</button> <button class="btn-icon" onclick="deleteFilter(${filter.id})" title="删除">🗑️</button> </div>`;listContainer.appendChild(filterEl);});// 加载分类和产地constcategories=awaitdb.getTeaCategories();constorigins=awaitdb.getOrigins();populateSelectOptions('filter-tea-type',categories);populateSelectOptions('filter-origin',origins);document.getElementById('filter-form').addEventListener('submit',handleSaveFilter);}catch(error){console.error('Failed to render filters:',error);showToast('加载筛选器失败','error');}}functionbuildConditionString(filter){constconditions=[];if(filter.teaType)conditions.push(`茶叶:${filter.teaType}`);if(filter.origin)conditions.push(`产地:${filter.origin}`);if(filter.ratingMin)conditions.push(`评分:${filter.ratingMin}★+`);returnconditions.length>0?conditions.join(' | '):'无条件';}asyncfunctionapplyFilter(filterId){try{constfilter=awaitdb.getFilter(filterId);if(!filter){showToast('筛选器不存在','error');return;}// 更新使用次数awaitdb.updateFilterUsageCount(filterId);// 应用筛选器条件constrecords=awaitdb.getAllRecords();constfiltered=records.filter(record=>{if(filter.teaType&&record.teaType!==filter.teaType)returnfalse;if(filter.origin&&record.origin!==filter.origin)returnfalse;if(filter.ratingMin&&record.rating<filter.ratingMin)returnfalse;returntrue;});// 显示筛选结果showFilterResults(filtered);showToast(`应用筛选器:${filter.name}`,'success');if(window.cordova){cordova.exec(null,null,'TeaLogger','logEvent',['filter_applied',{filterId:filterId,resultCount:filtered.length}]);}}catch(error){console.error('Failed to apply filter:',error);showToast('应用筛选器失败','error');}}functionopenCreateFilterModal(){currentEditingFilterId=null;document.getElementById('filter-modal-title').textContent='新建筛选器';document.getElementById('filter-form').reset();document.getElementById('filter-modal').style.display='flex';}asyncfunctioneditFilter(filterId){try{constfilter=awaitdb.getFilter(filterId);if(!filter){showToast('筛选器不存在','error');return;}currentEditingFilterId=filterId;document.getElementById('filter-modal-title').textContent='编辑筛选器';// 填充表单document.getElementById('filter-name').value=filter.name;document.getElementById('filter-tea-type').value=filter.teaType||'';document.getElementById('filter-origin').value=filter.origin||'';document.getElementById('filter-rating-min').value=filter.ratingMin||'';document.getElementById('filter-modal').style.display='flex';}catch(error){console.error('Failed to edit filter:',error);showToast('加载筛选器失败','error');}}asyncfunctionhandleSaveFilter(event){event.preventDefault();constformData=newFormData(document.getElementById('filter-form'));constfilterData={name:formData.get('name'),teaType:formData.get('teaType')||null,origin:formData.get('origin')||null,ratingMin:parseInt(formData.get('ratingMin'))||null,createdAt:newDate().toISOString()};try{if(currentEditingFilterId){awaitdb.updateFilter(currentEditingFilterId,filterData);showToast('筛选器已更新','success');}else{awaitdb.addFilter(filterData);showToast('筛选器已创建','success');}closeFilterModal();renderFilters();}catch(error){console.error('Failed to save filter:',error);showToast('保存失败,请重试','error');}}asyncfunctiondeleteFilter(filterId){if(!confirm('确定要删除这个筛选器吗?')){return;}try{awaitdb.deleteFilter(filterId);showToast('筛选器已删除','success');renderFilters();}catch(error){console.error('Failed to delete filter:',error);showToast('删除失败,请重试','error');}}functioncloseFilterModal(){document.getElementById('filter-modal').style.display='none';currentEditingFilterId=null;}functionshowFilterResults(records){// 导航到记录列表页面,显示筛选结果navigateTo('record-list');// 在记录列表页面显示筛选后的结果}这段代码实现了完整的筛选器管理功能。renderFilters()加载并渲染筛选器列表。applyFilter()应用筛选器条件。handleSaveFilter()保存新增或修改的筛选器。deleteFilter()删除筛选器。
🔌 OpenHarmony 原生代码
筛选器数据库操作
// entry/src/main/ets/plugins/FilterManager.etsimport{relationalStore}from'@kit.ArkData';exportclassFilterManager{privatestore:relationalStore.RdbStore;asynccreateFilterTable():Promise<void>{constcreateTableSql=`CREATE TABLE IF NOT EXISTS filters ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, tea_type TEXT, origin TEXT, rating_min INTEGER, usage_count INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )`;awaitthis.store.executeSql(createTableSql);}asyncaddFilter(filter:Filter):Promise<number>{constvalues:relationalStore.ValuesBucket={name:filter.name,tea_type:filter.teaType,origin:filter.origin,rating_min:filter.ratingMin,usage_count:0,created_at:newDate().toISOString()};returnawaitthis.store.insert('filters',values);}asyncupdateFilterUsageCount(filterId:number):Promise<void>{constpredicates=newrelationalStore.RdbPredicates('filters');predicates.equalTo('id',filterId);constresultSet=awaitthis.store.query(predicates);if(resultSet.goToFirstRow()){constcurrentCount=resultSet.getColumnValue(resultSet.getColumnIndex('usage_count'))asnumber;constvalues:relationalStore.ValuesBucket={usage_count:currentCount+1};awaitthis.store.update(values,predicates);}resultSet.close();}}interfaceFilter{id?:number;name:string;teaType?:string;origin?:string;ratingMin?:number;usageCount?:number;}这个类管理筛选器的数据库操作。createFilterTable()创建筛选器表。addFilter()添加新筛选器。updateFilterUsageCount()更新筛选器的使用次数。
📝 总结
筛选器管理模块展示了如何在 Cordova 框架中实现筛选器管理功能。通过 Web 层的用户界面和交互,结合原生层的数据库操作,为用户提供了高效的数据筛选体验。