【摘要】小程序开发常陷入"假闭环"误区:看似功能完备(搜索、点赞、评论等),但用户未登录或操作失败时链路立即断裂。本文通过Sourcelin案例揭示真正闭环的关键:1)搜索需整合建议词、热搜和历史记录;2)互动功能需实现登录续做和失败回滚机制;3)分享路径需确保回流畅通。技术实现上,通过pending-actions.ts处理未登录操作,采用乐观更新与回滚策略保障体验连贯性。只有当用户在任何中断场景下都能恢复操作,才是真正的产品闭环。
小程序开发的"假闭环"陷阱与真实互动链路构建 ,做小程序最容易出现一种假闭环:内容能看了,搜索也能搜了,点赞收藏评论按钮也都摆上去了,但用户一旦没登录、搜不到词、评论失败或者从分享页回来,整条互动链路马上断掉。
Sourcelin 这轮把“搜索与互动”单独拿出来收口,核心不是继续铺页面,而是把搜索入口、互动动作、登录续做、分享回流和错误回滚都补到能连续使用。只有做到这一步,阅读才会真正进入“愿意继续操作”的阶段。
本次阶段推文基于产品文档、仓库现状和本地可提取开发记录生成,未完整依赖远端会话历史。
这个阶段为什么必须单独收口
产品文档5.1第 4 周把这一阶段定义得很直接:
- 搜索
- 点赞、收藏、评论
- 关注作者
- 分享
真正难的地方不是某个按钮能不能点,而是这些动作是不是还能回到原上下文继续执行。比如未登录时点了收藏,是直接报错,还是登录后自动续做?搜索是不是只有一个输入框,还是已经补齐建议、热搜和历史?这些差别,决定了它是“能演示”,还是“能用”。
仓库里这一阶段对应哪些页面和模块
- 搜索页:
sourcelin-ui/sourcelin-ui-uniapp/src/pages-article/search/search.vue - 文章详情:
sourcelin-ui/sourcelin-ui-uniapp/src/pages-article/detail/detail.vue - 社区互动:
sourcelin-ui/sourcelin-ui-uniapp/src/pages/community/community.vue - 文章 API:
sourcelin-ui/sourcelin-ui-uniapp/src/modules/article/api/article.api.ts - 互动 API:
sourcelin-ui/sourcelin-ui-uniapp/src/modules/interaction/api/interaction.api.ts - 评论 API:
sourcelin-ui/sourcelin-ui-uniapp/src/modules/comment/api/comment.api.ts - 登录续做与偏好:
sourcelin-ui/sourcelin-ui-uniapp/src/shared/utils/pending-actions.ts、sourcelin-ui/sourcelin-ui-uniapp/src/shared/utils/analytics.ts
这批目录一看就知道,这次不是只改一个页面,而是把搜索、详情、社区、登录续做和埋点一起补齐。
搜索不是“能搜”,而是先把搜索入口做顺
这次搜索页最关键的,不是searchArticles()这一个接口,而是把搜索建议、热搜词、搜索历史都接上了:
const[articleTerms,categories,tags]=awaitPromise.all([fetchSearchHotKeywords(),fetchCategoryList(),fetchTagList()]);constresult=awaitfetchSearchSuggestions(value);searchHistory.value=getStorage<string[]>(SEARCH_HISTORY_KEY,[]);这段代码背后的意义很明确:
- 用户还没正式搜索前,就能看到“热门搜索”。
- 输入过程中,会动态拿“搜索建议”。
- 搜过的词会进入“最近搜索”,下次可以直接点。
这样搜索页才不再只是一个空输入框,而是有了真正可用的搜索承接层。
下面是搜索功能的完整流程图,展示了从入口到结果的全链路设计:
这个流程图展示了搜索功能从入口到结果的全链路设计,重点突出了"搜索入口做顺"的理念。
互动闭环的关键,不是按钮,而是登录续做和失败回滚
文章详情页里,点赞、收藏、评论、关注都已经不是“点了再说”,而是按登录态和主链路做了收口:
functionrequireLogin(type:string,payload:unknown):boolean{if(userStore.isLoggedIn)returntrue;userStore.pushPendingAction({type,payload});uni.navigateTo({url:'/pages-user/login/login'});returnfalse;}这段实现非常关键。它意味着:
- 未登录时不会把用户粗暴打回去。
- 系统会记录这次动作是什么。
- 登录成功后可以继续补做之前那次点赞、收藏、评论或关注。
与此同时,点赞和收藏也补了乐观更新失败回滚:
constnext=!article.value.isCollected;article.value.isCollected=next;article.value.collectCount=Math.max(0,(article.value.collectCount||0)+(next?1:-1));try{if(next)awaitcollectTarget('article',article.value.id);elseawaituncollectTarget('article',article.value.id);}catch{article.value.isCollected=!next;article.value.collectCount=Math.max(0,(article.value.collectCount||0)+(next?-1:1));}这才是真正的闭环思路:先让交互顺,再把失败恢复补上,而不是一失败就把页面状态搞乱。
分享和社区互动也已经接进主路径
文章详情页已经补了小程序分享配置:
onShareAppMessage(()=>({title:article.value?.title||'Sourcelin Blog',path:article.value?.id?`/pages-article/detail/detail?id=${article.value.id}`:'/pages/home/home',imageUrl:coverUrl.value}));社区页这边也不是只做浏览,而是把说说和树洞的互动、评论抽屉、举报入口一起做进来了:
awaitcreateContentReport({targetType:currentTargetType,targetId:item.id,reason:reasons[selected],pagePath:'/pages/community/community'});到这里,“搜索与互动”这四个字才算站住:能找、能点、能评、能关注、能分享,而且失败时不直接崩。
我为什么现在确认这个阶段可以勾选完成
这次复核后,之前卡住这个阶段的几个点已经都补上了:
- 搜索联想、热搜词、搜索历史都已存在
- 文章详情和社区的点赞/收藏/评论/关注链路都已接入
- 未登录动作会触发登录续做,而不是丢失上下文
- 乐观更新失败有回滚
- 分享路径已经落到真实详情页
按产品文档和开发拆解的口径,这已经不是“基础可用”,而是该阶段的核心页面、核心交互和阶段验收项都闭合了,所以我会把它从未完成改为已完成,并生成这篇统一长文。
效果图
开发过程提示词(优化版)
请先读取 AGENTS.md、rules/frontend-uniapp.md、rules/api-contract.md, 以及 docs/product/UNIAPP_MINI_PROGRAM_PRODUCT_DESIGN.md 第 5.1 节和第 7 章校准。 本次只处理“搜索与互动”阶段,不扩展到用户资产、社区扩展或兼容优化。 请重点完成: 1. 搜索建议、热搜词、搜索历史 2. 文章详情的点赞、收藏、评论、关注、分享 3. 未登录触发后的登录续做 4. 乐观更新失败回滚 输出时必须说明: 1. 涉及的页面与模块 2. 依赖的接口 3. 哪些交互已经形成闭环 4. 剩余风险和验证证据这类任务里 AI 最容易跑偏的点
- 只补搜索接口,不补建议、热搜和历史,最后搜索页还是空的。
- 把互动理解成“按钮能调用接口”,却忘了登录续做和失败回滚。
- 在页面里直接写一堆请求,不把搜索、评论、互动沉到模块层。
- 搜索和互动都做了,但分享路径还是假路径,回流链路断着。
项目入口
- 在线演示:https://sourcelin.cn
- Gitee:https://gitee.com/my_lyq/sourcelin-cloud-blog
- GitHub:https://github.com/SourceLin/sourcelin-cloud-blog