除夕那天晚上我还在改需求文档,窗外的鞭炮声和隔壁群里的“新年好”轮番轰炸,我盯着文档里“打工了马”四个字,突然笑出声。这个谐音梗太适合马年了——谁问“打工了吗”,我就甩一个小程序给他,让他自己打卡。于是,我用AI写了一个“打工了马”小程序,从创意到上线,前后花了不到两天。这篇文章就把整个过程的实操思路、代码取舍和踩坑记录摊开给你看,适合那些想用AI做点小玩意儿、但不想被技术细节劝退的开发者,也适合产品、运营同学围观一下“AI辅助开发”到底能到什么程度。
1. “打工了马”的创意从哪来:一句话谐音背后的产品定位
1.1 谐音梗为何能成为小程序入口
先解释一下这个名字。“打工了马”读起来就是“打工了吗”,马年一到,它自带两层信息:一层是“马”这个生肖符号,另一层是“打工人”这个持续流行的自嘲身份。小程序这种轻量产品,最适合承载这种“一句话就能讲清楚”的梗。用户不用看说明文档,光看到名字就想点进来。
同类谐音梗小程序之所以能传播,核心不是技术,而是“情绪共鸣”。打工人年底最怕被问什么?年终奖、KPI、跳槽打算。而“打工了吗”这句问候,既带着一丝苦哈哈的幽默,又不像“你升职了吗”那样有冒犯感。它把压力转化成了一种可以主动玩起来的互动。所以我在最开始就给自己定了一个原则:这个小程序不是工具,是一个“可以甩给朋友的表情包生成器”。
1.2 功能裁剪:只留下一个主行为
一个周末小项目最怕的就是功能堆砌。我一开始脑子里飘过很多想法:马年运势、每日宜忌、工位风水、职场避雷指南……全塞进去,别说两天,两个月都做不完。
后来我做了减法,把整个小程序收敛成一个核心行为:打卡。用户进入页面看到一匹马,点击打卡按钮,选择自己今天的“打工姿势”,马开始奔跑,屏幕浮出一句带“马”字的打工人语录,然后可以分享给朋友。整个链路不超过三次点击。
这个“三个页面”的产品结构,是我在需求文档里反复琢磨后定下来的:
- 首页/打卡页:马的状态展示 + 打卡按钮
- 选择弹层:三种打工状态,对应不同语录
- 结果展示:语录生成 + 分享卡片
砍掉的功能包括:排行榜、连续打卡日历、自定义头像、语音播报。原因很简单,这些功能每一个都要引入一套新的状态管理,AI写代码能写,但测试和修边界的时间全得我来扛。
1.3 技术选型:为什么原生结构更适合AI协作
我选择用小程序原生语法而非跨平台框架,并不是因为原生更好,而是因为AI生成原生小程序的代码时,模板化程度特别高。WXML、WXSS、JS文件结构固定,AI见过的样本多,生成质量稳定。
跨平台框架虽然组件化更优雅,但多了一层编译和配置,AI容易在配置文件和依赖版本上翻车。对这个项目来说,原生小程序足够轻,包体小,审核也省心。这里想给第一次用AI做小程序的朋友一个建议:你不需要在技术选型上纠结,选AI训练语料最多的那套结构,就是最高效的路线。
2. 让AI干活前,我先把需求“翻译”成了一堆人话
2.1 我写的需求描述:从一句话到一张“对话清单”
很多人让AI写代码,喜欢发一句“帮我写个小程序,首页有一匹马在跑,点击打卡出文案”,然后抱怨生成的东西不能用。问题不在AI能力,而在需求描述太模糊。AI不知道马在页面什么位置、跑多久、打卡后文案怎么展示、一天能不能打多次卡——它只能靠猜。
我的做法是:把需求写成一张“对话清单”。所谓的对话清单,就是明确地告诉AI这三个维度——页面结构、交互逻辑、边界条件。
页面结构这块,我第一版prompt是这样写的:
- 顶部区域:显示当前日期和一个“今日打工进度”文案
- 中间区域:留出马的形象位,先用一个圆形占位,后续替换动效
- 底部区域:固定的打卡按钮
交互逻辑我写得更细:
- 首次打开页面时,马处于静止状态,按钮文案是“今天打工了吗”
- 点击按钮,弹出半屏弹窗,里面有三个选项:“工位搬砖”“居家摸鱼”“在逃马马”
- 用户任选一个,弹窗关闭,马开始横向奔跑,顶部进度文案变成“今天已打工”
- 奔跑2秒后,屏幕中间淡入一句打工人语录,底部出现“分享战报”按钮
边界条件我也直接写进去了:
- 同一天最多打卡一次,如果已经打卡,再次进入页面不弹窗,只显示结果
- 不登录、不授权、不采集任何用户信息
- 所有数据存在本地缓存即可,不需要后端
当我把这份清单给AI的时候,生成结果明显靠谱多了。它自动拆出了三个文件,页面结构基本符合预期,交互逻辑也按顺序实现了。这个“人和AI协作”的关键步骤,是把藏在脑子里的产品假设全部变成文字。
2.2 把AI当结对编程搭档:三轮对话式生成
我把整个开发过程分成三轮,每一轮只让AI做一件事。
第一轮:静态骨架。我只让它生成页面布局和样式,不写任何逻辑。这轮的核心是确认视觉结构,看看占位元素和底栏是否合理。
第二轮:交互逻辑。让AI在上一步骨架基础上,加上点击事件、弹窗状态、文案替换。这轮常见的问题是AI会把逻辑分散写在不同函数里,命名混乱,但不用急,先跑通。
第三轮:边界评审。我让AI自己列出“这个打卡流程可能出现的异常情况”,它会说出跨天问题、重复点击、缓存数据格式错误等。这个环节很有价值,相当于让AI做了一次免费的代码审查。
我的建议是,把AI当成一个手速很快、但经验一般的实习生。你不能把整个项目甩给它然后等成品,而是要把任务拆成“能一次性完成”的粒度——每个任务不要让AI同时兼顾页面、交互、数据、分享,否则它一定会加戏。
2.3 哪些AI建议我拒绝了:加功能是最容易的错
第一轮生成骨架时,AI自作主张加了三个我明确没要求的东西:
- 一个“关于我们”页面,用来展示开发者信息
- 一个加载动画,页面进入时旋转一圈
- 一个分享朋友圈的引导悬浮球
这三个东西AI当然没有恶意,它只是基于“小程序应该长这样”的训练经验做了补全。但对我的场景来说,每个都是负担。关于我们页面没有内容可放,加载动画拖慢首屏,朋友圈引导更是触碰了平台审核的红线。
我在这里学到的经验是:AI生成的代码,你至少要保留“拒绝权”。看到AI主动加料的地方,先问自己三个问题——这个东西用户真的需要吗?它会不会引入额外的权限申请?它会不会增加审核风险?如果回答都是否定的,直接删。删代码比写代码容易,但前提是你得敢删。
3. 马匹奔跑动效:AI生成的代码,我只留了三成
3.1 动效方案对比:CSS逐帧动画够用了
小程序里做动画,主流方案有三种:CSS动画、Canvas绘制、逐帧序列图。我一开始犹豫要不要上Canvas,因为AI用Canvas画一匹奔跑的马听起来很酷。但冷静想了一下,我的场景根本不复杂:一匹马从页面左侧跑到右侧,两秒结束,循环往复。这种固定路径的位移,CSS动效完全能扛住,而且性能更好、代码更少。
Canvas适合的场景是:马的路径不固定、需要跟随手势、画面里超过三个运动元素。我这个需求里马跑的是直线,不需要碰触,CSS的transform + translateX就是最合适的方案。这里顺手给AI写了个补充需求,让它把马达的主体放在一个container里,用CSS类切换来控制跑动状态:静止时不动,打卡后添加一个running类名,触发keyframes动画。这个决策的好处是,状态切换和动画解耦,后面加“冲刺”效果时,只需要改样式类,不用动JS逻辑。
3.2 AI生成的动画代码里的三个坑
AI生成的动画代码,逻辑一般没错,但体验问题不少。我实际跑通后发现了三个典型问题。
第一个坑:动画默认页面加载即执行。AI喜欢在样式中直接写animation: run 2s infinite,结果一进页面马就跑起来了,根本不管用户有没有打卡。这完全偏离了“打卡触发奔跑”的核心交互。修复方式就是前面说的,把动画挂在.running这个类名下,默认不添加。
第二个坑:马跑到右边界后直接消失。AI用translateX(100vw)作为终点,马确实跑到了屏幕右边缘,但因为是无限循环,它会在左边界“瞬移”回来,视觉上非常生硬。我改成在80%关键帧处让马停一下,再往回走,模拟“跑进马厩”的节奏。这个细节让整个动效从“机械循环”变成了“有情节”。
第三个坑:关键帧过于密集。AI给了我一个包含8个关键帧的复杂动画,还加了左右晃动、上下弹跳。真机一跑,中低端安卓机上明显掉帧。我砍到了3个关键帧,只保留横向位移和轻微的垂直起伏。记住,动效是加分项,不是主角,流畅比炫酷重要。
3.3 手工改造:让马的状态跟打卡动作绑定
AI生成之后,我上手改了最重要的一处逻辑:把动效和打卡状态以“状态机”的方式绑定。整个页面只有三种状态:
- 未打卡:马在围栏里低头站着,偶尔抬头(用1秒的透明度闪烁模拟)
- 打卡中:马开始奔跑,背景出现速度线
- 已打卡:马停在屏幕中央,头顶冒出一句语录
实现上我写了一个简单的状态管理对象,把state绑定到页面的data上,WXML里用wx:if区分渲染区域,WXSS里用不同的类名控制动效。这样AI可以专注于单个状态的样式生成,我来组织状态的转移逻辑。后来我想增加一个隐藏彩蛋:连续打卡三天后,马会变成金色。这个需求只改样式类和判断条件,完全不需要动架构,这就是状态机设计带来的红利。
4. 打卡与语录生成:状态管理里最容易翻车的三个细节
4.1 跨天判断:别用时间戳,用日期字符串
打卡功能最核心的数据,只有三样:上次打卡日期、打卡状态、当前命中的语录索引。存本地缓存就够了。
AI第一版代码里,判断“今天是否已打卡”用的是时间戳毫秒数比较,比如记录一个lastCheckTime,然后拿当前时间戳去对比。这个方案有个隐蔽的坑:如果用户凌晨打卡,系统记录的毫秒时间戳落在昨天,第二天早上打开时,时间戳差值超过24小时,判断逻辑会认为“今天还没打卡”,导致用户连续两天显示成同一天的数据。跨天边界一碰就翻车。
我的修复方式很简单:不使用时间戳,而是用本地格式化后的日期字符串yyyy-mm-dd做key。判断逻辑改成了:
function hasCheckedToday(record) { const today = formatDate(new Date()); return record.lastCheckDate === today; }这样无论用户几点打卡,判断依据都是“自然日”,而不是24小时滚动窗口。类似的坑可以在很多日程管理、签到类小程序里看到,建议写这类功能时默认就用日期字符串作为跨天判断的依据。
4.2 语录随机不重复:一个“日期偏移”的土办法
语录是这个产品的灵魂。我准备了三组共30句带“马”字的打工人语录,比如“马不停蹄地打工,原地踏步的工资”“还有多少KPI要赶,马都快累瘦了”这类。需求要求:同一个人一周内不重复,同时最好大家同一天看到的句子一致,这样群里甩卡片时能产生共同话题。
AI给我第一版方案是:随机洗牌后取第一个,再把取过的索引存缓存。这个方案能保证不重复,但是有两个问题——用户第一次、第二次打开时,每个人看到的都是不同的句子,缺少“同一天共鸣”;而且一旦洗牌逻辑写错,会出现连续两天同句的bug。
我最后用的是“日期偏移”的土办法:把30句按条数排列,用“今天是今年的第几天”作为索引偏移量,算出当天应该取哪一句。方法很原始,但满足了全部要求:
- 同一天所有人都能拿到同一个“当日语录”
- 第二天自动换一句,不会与前一天重复
- 当30句循环完毕才重复,频率低,用户感知不到
这个算法实现不到十行,但它证明了AI写代码时更倾向于“计算正确”,而人需要负责“体验正确”。体验正确往往意味着牺牲一点技术优雅度,选用更笨但更贴合场景的方案。
4.3 补卡功能为什么砍掉:轻量应用的取舍课
开发到一半,我一个朋友提了需求:“昨天忘打卡了,今天能补吗?”我犹豫了一下,还是决定不做。
补卡听起来是刚需,但会给数据模型引入“历史记录”。一旦有补卡,就要考虑用户能不能补前天的、补卡后连续天数怎么算、补卡操作如何追溯。这些逻辑加进去,AI代码量会翻一倍,但真正使用补卡功能的用户可能不到1%。对一个主打轻量和分享的产品来说,这个功能带来的复杂度完全对不起它的价值。
我最后的方案是:不做补卡,但做一个“漏卡提示”——如果用户昨天没打卡,当天首次进入时顶部会出现一句“昨天马儿休息了,今天继续搬砖吗”。这句话既安抚了情绪,又引导了新的打卡动作,比补卡功能轻得多。想清楚这一点之后,我更加坚定这个项目的主线:打卡是唯一的关键行为,其他都让路。
5. 上线打磨:从“AI写出来了”到“真的能给人用”
5.1 提审前的自检清单:把“默认不授权”写进代码
小程序上线前要过开放平台的审核,我的经验是:审核最大的阻力往往不是你功能不行,而是你申请了不该申请的权限。我这个产品完全不需要手机号、位置、相册,所以代码里直接不写任何scope授权。
我做了一份自检清单,逐项打钩后才提交:
| 检查项 | 我的处理 | 原因 |
|---|---|---|
| 用户隐私 | 不请求任何授权 | 避免审核流程拉长和隐私风险 |
| 缓存策略 | 只用本地缓存 | 数据不上传,不需要服务器 |
| 内容合规 | 语录无敏感词 | 打工人自嘲,不涉及具体行业 |
| 分享行为 | 分享卡片正常展示 | 分享出去要能打开对应页面 |
| 页面栈 | 返回逻辑无死循环 | 连续跳转不能卡死 |
特别提醒一点:AI生成代码时,经常会自动加上获取用户头像昵称的调用,比如“等你授权后展示头像”。这个小程序完全不需要,所以我全局搜索了authorize和getUserProfile,逐条删掉。审核就是一次减法,去掉所有多余的东西,通过率自然高。
5.2 分享路径与场景值:AI写不出来的关键一跳
分享功能我踩了一个有价值的坑。最初让AI写分享,它直接写了个按钮,调用官方分享接口,没有指定跳转路径。结果分享出去的卡片,朋友点击后只能进入首页,还得手动点一次打卡,整个传播链路断了一截。
这里的核心知识是“场景值”和小程序分享路径的对应关系。正确的做法是:在onShareAppMessage里带上自定义路径和参数,比如把当前页面路径和打卡状态拼进分享卡片;好友点击后,打卡页读取这些参数,直接展示分享者的战报,并引导新用户进入打卡流程。节奏理应是:A分享→B点开→B看到A的马跑了多少天→B打卡→B再分享。AI无法凭空知道这个“分享即传播”的循环逻辑,它只会按通用范本生成,这部分是人的产品设计经验,是AI替代不了的。
5.3 上线后看三件事:打开率、完成率、分享率
小程序发出去之后,我每天看数据,重点观察三个指标:打卡页打开率、打卡完成率、分享转化率。
打开率低,说明入口的吸引力和名字的传播力不够。这里“打工了马”这个名字本身就承担了一半的拉新作用——朋友收到卡片,看到这名字就愿意点一下。完成率低,问题大概率出在动效上:马跑得太久,或者语录文案不够共鸣。分享率低,则是语录和战报卡片本身缺少“晒点”。上线第一天,我发现打卡完成率只有60%,后来把奔跑动画从2.5秒缩短到1.5秒,完成率立刻提到了83%。一个动效时长的调整就能带来这么大的变化,实际效果让我很意外。
数据观察期我也做了两个小迭代:一是加了一个“隐藏成就”彩蛋,连续打卡三天后,马的头顶会多出一个小小的“年度全勤”徽章;二是支持用户自定义工牌昵称,让语录卡片看起来更像自己的专属战报。两个功能加起来不到50行代码,但对传播有实打实的助推——大家晒战报,不就是为了让朋友看到自己的“马”吗。
这趟做下来,我最大的感受是:AI确实让开发从“从零敲代码”变成了“需求和想法的翻译”,但真正让小程序走完上全流程的还是人对边界和体验的判断。什么时候该砍功能,动效怎么改更舒服,分享链路怎么设计才能跑通,这些AI都教不了。它像一个手速极快的助手,你的方向对了,它能让收尾快十倍;你的方向错了,它也能让你在错误的代码上反复横跳。想用AI做点什么的朋友,我的建议是:先花一小时把你的需求写到能让另一个人直接开干的程度,再找AI帮忙,你会发现整个过程顺畅得不像话。马年到了,打工总是逃不掉的,但用什么样的姿态打,这张“战报”可以自己说了算。