ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

几个方案来回选不定?做一个随时切换的候选推荐页

几个方案来回选不定?做一个随时切换的候选推荐页 候选对比页面需要让大卡片和下方列表保持同一选择。页面只保存currentIndex当前标题、分数与颜色都从items[currentIndex]读取列表点击和“换一个结果”最终都只修改这个索引。interfacePickItem{id:numbertitle:stringscore:numbercolor:string}StatecurrentIndex:number0Statefavorites:number[][]StatepickCount:number0privatecurrent():PickItem{returnthis.items[this.currentIndex]}轮换逻辑对数组长度取模到最后一项后回到第一项。privatechoiceById(id:number):PickItem|undefined{returnthis.items.find((choice:PickItem)choice.idid)}privaterequireChoice(id:number):PickItem{consttarget:PickItem|undefinedthis.choiceById(id)if(!target){thrownewError(Choice not found: id)}returntarget}保留计数只在需要记录操作次数时才有意义。privatepick():void{this.pickCount1this.currentIndexthis.pickCount%this.items.length}目前手动点击列表只更新currentIndex不会同步pickCount。例如先手动选中第三项再点击“换一个结果”结果仍按旧计数计算可能跳回第二项。privatereplaceChoice(id:number,updater:(source:PickItem)PickItem):void{this.itemsthis.items.map((choice:PickItem)choice.idid?updater(choice):choice)}privateupdateChoiceMessage(id:number):void{consttarget:PickItem|undefinedthis.choiceById(id)this.messagetarget?状态已更新:目标记录不存在}收藏保存候选ID不保存索引。数组重新排序时ID仍能识别原项目。privatefavorite():void{constid:numberthis.current().idthis.favoritesthis.favorites.includes(id)?this.favorites.filter((value:number)value!id):[...this.favorites,id]}当前分数是预设值页面还没有比较维度与评分输入因此它展示的是候选浏览和收藏流程不是完整决策模型。加入维度后应保存每个方案在各维度的分值和权重再派生总分总分不应手动重复录入。privateremoveChoice(id:number):void{constbefore:numberthis.items.lengththis.itemsthis.items.filter((choice:PickItem)choice.id!id)this.messagethis.items.lengthbefore?记录已删除:没有找到要删除的记录}privatehasChoice(id:number):boolean{returnthis.items.some((choice:PickItem)choice.idid)}大卡片和候选列表都直接读取当前索引。手动点击列表修改currentIndex按钮则调用pick()。Text(this.current().title).fontSize(31).fontWeight(FontWeight.Bold)Text(推荐度${this.current().score})ForEach(this.items,(item:PickItem,index:number){Row({space:11}){Circle().fill(item.color)Text(item.title).layoutWeight(1)Text(item.score.toString())}.backgroundColor(this.currentIndexindex?#EEF0FF:Color.White).onClick((){this.currentIndexindex})})当前存在一处状态分叉手动点击只改currentIndexpickCount没有同步。先点第三项再点“换一个”结果仍根据旧计数计算。删除重复计数、直接基于当前索引前进会更稳定。privatechoiceKey(choice:PickItem):string{returnString(choice.id)}privateallChoiceKeys():string[]{returnthis.items.map((choice:PickItem)this.choiceKey(choice))}privatehasDuplicateChoiceKey():boolean{constkeys:string[]this.allChoiceKeys()returnnewSet(keys).size!keys.length}收藏状态只影响当前卡片文案和顶部数量不会改变候选排序。Text(this.favorites.includes(this.current().id)?♥ 已收藏:♡ 收藏这个结果).onClick((){this.favorite()})Text(收藏${this.favorites.length})收藏数组使用展开和过滤返回新数组ArkUI可以观察引用变化。候选ID与索引职责不同ID用于跨排序识别记录索引用于当前固定数组定位。编辑能力加入后应尽量把当前选择也迁移到ID。所有选择入口最终只改一个索引候选卡片点击和“换一个”按钮都更新currentIndex。当前结果、卡片高亮和收藏按钮读取同一索引privatecurrent():PickItem{returnthis.items[this.currentIndex]}privatepick():void{this.currentIndex(this.currentIndex1)%this.items.lengththis.message已选择${this.current().title}}privatefavorite():void{constid:numberthis.current().idthis.favoritesthis.favorites.includes(id)?this.favorites.filter((item:number)item!id):[...this.favorites,id]}如果按钮单独保存一份“推荐结果”列表点击另存一份“当前项”两个入口迟早会显示不同内容。现在索引是唯一选择状态按钮只是按固定规则计算下一个索引。privatefilterChoice(predicate:(source:PickItem)boolean):PickItem[]{returnthis.items.filter((choice:PickItem)predicate(choice))}privatecountChoice(predicate:(source:PickItem)boolean):number{returnthis.filterChoice(predicate).length}删除当前项时选择相邻候选数组为空时current()返回可空结果并进入空状态。顺序轮换与随机选择的差异当前pick()是可预测轮换每个候选都会依次出现适合“换一个”。如果界面文案改成随机就应使用真正的随机索引并决定是否允许连续两次相同。候选大于一条时可以从除当前项外的范围抽取只有一条时保持原项并提示。privatecopyChoiceList():PickItem[]{returnthis.items.map((choice:PickItem)({...choice}))}privaterestoreChoiceList(snapshot:PickItem[]):void{this.itemssnapshot.map((choice:PickItem)({...choice}))this.message数据已恢复}点击列表属于明确选择不应同时推动随机历史。收藏也不改变当前项只更新收藏集合。把三类事件分开以后消息文字才能准确说明发生的是主动选择、换项还是收藏切换。候选编辑与持久化新增候选先校验空名称生成稳定 ID。标题可以按需求允许重复例如两个同名餐厅位于不同地点唯一性仍依靠 ID。编辑名称不改变收藏关系删除时同步移除收藏 ID避免收藏计数包含不存在记录。privatefirstChoice():PickItem|undefined{returnthis.items.length0?this.items[0]:undefined}privatelastChoice():PickItem|undefined{constindex:numberthis.items.length-1returnindex0?this.items[index]:undefined}privateisChoiceListEmpty():boolean{returnthis.items.length0}空数组时pick()不访问索引一条记录时换项保持原值多条记录的轮换经过末项后准确回到首项。这些用例能同时覆盖两个选择入口的同步问题。候选编辑后仍按 ID 选择排序、删除和收藏都使用稳定对象身份privatecurrent():PickItem|undefined{returnthis.items.find((item:PickItem)item.idthis.currentId)}privateremove(id:number):void{constindex:numberthis.items.findIndex((item:PickItem)item.idid)this.itemsthis.items.filter((item:PickItem)item.id!id)this.favoritesthis.favorites.filter((value:number)value!id)if(idthis.currentId){this.currentIdthis.items[Math.min(index,this.items.length-1)]?.id??-1}}删除当前项时选择相邻候选收藏集合也不会留下失效 ID。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进