
被微信拒审那天我正蹲在电脑前对着手机看后台状态页面突然弹出一条红底通知“当前提交的版本未通过审核原因类目与资质要求不符。”那一秒钟我脑子里不是“改Bug”而是“我到底做了什么”因为我这个项目从头到尾都是靠“一个人 AI”磨出来的前后大约3万行代码、1.8万张素材全是我一个人配合各种大模型工具一点一点拼出来的。那段时间“Vibecoding”这个词还没有现在这么火但回头看我做得就是标准的Vibecoding不懂的交给AI懂一点的框架自己搭让AI负责填肉我负责把控“感觉对不对”。这种模式前期确实爽功能迭代飞快但等到平台审核把合规问题砸到脸上时我才发现自己忽略了一整块工程能力——不是代码能力而是对一个产品“为什么能上线、凭什么能过审”的判断能力。这篇复盘就是想把我从被拒审那天开始做的事、踩的坑、改的路径完整写下来。适合那些一个人在做小程序、想做小游戏、或者准备靠AI辅助冲一个完整产品的人看。不用是科班程序员但一定要有耐心因为Vibecoding真正的门槛不在代码本身而在“你能不能把AI产出的东西当成半成品来管理”。1. 为什么我的小程序会变成“3万行代码 1.8万张素材”1.1 项目到底是个什么形态先说清楚项目定位。它是一个偏“图鉴收藏 分类浏览”类型的小程序用户可以按标签筛选内容、查看大图、收藏夹、离线缓存。没有复杂交易没有用户私密信息也没有需要实时通信的能力。这种项目天然适合一个人做因为核心是内容呈现和交互体验而不是后端架构。真正让它变得庞大的是两个原因第一我希望交互不要太“模板化”所以每个页面都有独立的动效和组件逻辑第二内容规模上去了图片素材为了适配不同尺寸和场景做了一堆衍生变体最后就变成了1.8万张素材文件。单看3万行代码和1.8万张素材好像是个大工程但拆开看代码大部分是重复性组件逻辑素材大部分是同一批原图的尺寸变体、切图、压缩图和特殊效果图。1.2 “Vibecoding”到底是什么意思经常有人问我Vibecoding是不是就是“让AI写代码自己不动手”我理解不是。Vibecoding更接近“用感觉驱动开发”你不需要一开始就把架构想得滴水不漏而是先有一个产品直觉然后让AI快速帮你把界面和逻辑跑起来你再像调音师一样一点一点调整到“手感对了”的状态。我的实际工作流程一般是我先画一个很潦草的手稿说清楚页面大概长什么样、有什么按钮、点了之后发生什么。把这段描述丢给大模型让它生成一个“能跑的版本”。我运行、体验、截图再把截图和问题回传给AI让它改。改到界面顺眼、交互顺手后再进入下一个模块。这种方式最大的优势是产能高。我一个人做这个东西从立项到第一次提审大概花了两个半月如果按照传统方式我不可能在这个时间内写完3万行代码更别提还有素材生产流程。1.3 数据和规模的意外膨胀一开始我真没计划要做这么大。原设想是四五个页面、几百张图就够结果随着需求越加越多——搜索结果、排序、收藏同步、空态页、引导页、加载动画、分享卡片——每个页面都要配套不同的图片状态素材数量指数级上升。尤其是加载动画和背景纹理这类的装饰素材同一套视觉要导出多种尺寸经常一种尺寸就几百张。到后面我索性用脚本批量生成不再手工处理。代码也一样AI生成的初始版本通常很臃肿同一个逻辑在不同页面各写了一份后来为了维护方便我又重构了一轮把共用部分抽象成组件代码量不减反增但结构清晰了很多。这里也想提醒看到这篇文章的人AI生成代码很便宜但“账面上很贵的”反而是你后续维护它的时间。如果你打算长期迭代尽早做模块拆分别等AI写出一堆重复代码后才想起来重构。2. 一个人管理3万行AI代码我靠的是这套方法2.1 代码到底分布在哪里先说代码总量。三万多行听起来吓人但分布其实很均匀。我按实际用途拆成了五块模块大致代码量行说明小程序页面代码约13000页面逻辑、事件绑定、状态管理组件代码约7000公共UI组件、卡片、列表、弹窗工具函数与数据层约5000埋点、缓存、请求、格式化素材生成脚本约4000Python Node 批量处理图片构建与配置约1500打包脚本、manifest、路由配置这个分布背后的逻辑很简单页面代码是最容易让AI生成的因为它不需要全局视野组件代码则是用来约束AI“别再写重复的东西”的关键。2.2 让AI生成代码时我会刻意控制上下文大小很多人用AI写代码时喜欢把整个项目丢给它希望它“理解所有代码”但在小程序这种规模下上下文塞得越满越容易让AI忽略最近的修改。我的做法是按文件对话。每次只针对一个文件或一组相关文件提问并且明确告诉AI“你只需要修改这个函数不要动其他代码”。比如我要给列表页加一个懒加载我会这样告诉AI当前文件是 pages/list/index.ts里面已经有 onReachBottom 方法。现在需要在这个方法里增加分页加载逻辑要求不超过50行保持现有接口不变错误处理用 catch。这种“约束式提示”比“帮我优化列表页”有效得多。AI生成的东西会变得很聚焦不需要我再花大量时间做diff审查。2.3 版本控制是Vibecoding的生命线Vibecoding项目里AI会频繁重写函数有时候它会把好的逻辑一并删掉这几乎无法避免。如果不用版本控制你根本不知道它动了什么。我使用的流程非常简单# 每次AI改完代码后先本地跑通 git add . git diff --cachedgit diff --cached这步很重要。提交前看一遍diff确认改动方向和预期一致。虽然AI画龙点睛的能力很强但它在“删除旧逻辑”这件事上特别激进经常为了让新功能跑通顺手把旧函数删了。我至少三次在diff里发现它删掉了埋点上报、错误边界之类看起来“不关键”但实际很重要的逻辑。另外遇到合并冲突时我不急着让AI“解决冲突”而是自己先看冲突上下文再决定保留哪边。因为AI并不了解你的整体意图它只知道当前文件里的这两段逻辑。2.4 公共抽象层是我坚持让AI照抄的一份代码为了不让AI每个页面都重新造一套轮子我写了一个非常基础的公共层包括请求封装、缓存管理器、图片懒加载、空态组件。然后我要求AI“以后所有新页面一律使用现有工具函数禁止自行实现”。这里有个反直觉的点让AI生成代码时“复制粘贴”反而比“创新”更重要。你在提示词里越是允许AI自由发挥它越容易写出不一样风格的代码后续维护成本越高。我对所有新增逻辑的默认要求是先看公共层有没有没有再说。公共层的代码也不复杂主要就是统一入口。比如图片加载export function loadImage(url: string): Promisestring { return new Promise((resolve, reject) { wx.getImageInfo({ src: url, success: (res) resolve(res.path), fail: reject, }); }); }这种函数谁都会写但它的意义在于所有页面都不敢自己搞一套图片加载逻辑。只要公共层存在AI再生成新页面时会倾向于引用它因为我在提示词里反复强调过。3. 1.8万张素材从AI初稿到管线化管理3.1 素材是怎么“膨胀”出来的项目素材包含四类主视觉插画、图标、卡片背景、动效序列帧。最初我想要的只是几百张主图但实际交付过程中发现每次设计变化都会带动一套衍生图变化。最典型的例子是主视觉从“亮色”改成“暗色调”后所有图标、加载动画、空态页都要重新出一版旧的又不想删最后新旧两版素材各占了几千张。后面我学聪明了决定把素材生成流程做成“管线”所有原始AI生成图都放在source/raw目录不直接用于真机展示凡是要发布到小程序里的图全部经过脚本自动处理从源图得到不同尺寸的压缩版本。3.2 自建批处理脚本替代手工调整我用的核心工具是 Python PillowPIL因为它的生态最成熟批量改尺寸、转格式、打水印都很方便。下面这段脚本是我整个素材管线的核心作用是把目录里所有超过某个宽度的图片重采样同时转成 WebP。from pathlib import Path from PIL import Image SOURCE_DIR Path(./source/raw) OUTPUT_DIR Path(./assets/processed) MAX_WIDTH 750 for img_path in SOURCE_DIR.rglob(*.png): img Image.open(img_path) if img.width MAX_WIDTH: ratio MAX_WIDTH / img.width img img.resize( (MAX_WIDTH, int(img.height * ratio)), Image.Resampling.LANCZOS, ) output_path OUTPUT_DIR / (img_path.stem .webp) img.save(output_path, WEBP, quality80) print(fprocessed: {img_path.name} - {output_path.name})这套脚本最大的好处是无论AI生成了多少张风格不一致的图最终处理完的产物在尺寸、格式、质量上都是统一的。这也是我后来能面对1.8万张素材而不崩溃的原因。3.3 用“索引文件”管理素材而不是硬编码路径素材多了以后最容易出现的问题就是代码里拼文件名拼错。我建立了一个manifest.json把所有素材的真实路径和配置集中管理。页面加载图片时不直接写字符串而是通过一个工具函数查表。{ card_001: { default: /assets/processed/card_001.webp, large: /assets/processed/card_001_large.webp, blur: /assets/processed/card_001_blur.webp } }这样做的原因是小程序包体有体积限制不可能把1.8万张全部塞进本地包。真正打包到本地的只有首屏需要的几百张其余素材放到内容分发链路上按需加载。通过 manifest 文件前端知道自己要用哪张图、应该去本地取还是远程取。3.4 包体大小和首屏速度的平衡方案下面这张表是我压缩前后的数据对比方案单张平均大小100张总大小首屏加载体验原始 PNG1200KB120MB不可能本地加载压缩 PNG280KB28MB仍然偏大WebP 质量8065KB6.5MB可接受WebP 质量60 尺寸裁剪28KB2.8MB流畅最终我选了“WebP 质量80 宽750裁剪”作为默认遇到纹理复杂的图片单独调低到65。其实这一步也很影响审核体验如果素材图加载太慢审核人员打开页面时转圈超过两秒可能直接影响审核结果。3.5 素材越界问题给后来者的一个警告素材管理不只是技术问题还是内容安全问题。1.8万张图里如果有某几张带外链水印、二维码、真人面部、品牌Logo都有可能成为审核拒绝的理由。我后面被拒审时很大一部分精力就是在排查这些素材。我现在给所有人的建议是无论AI图片生成工具给出来的图多好看都要在进入素材库前强制跑一遍内容扫描包括识别二维码、检测大段文字、查找可疑链接。这个成本远低于被拒审后全量排查的时间成本。4. 被微信拒审那天我启动的完整排查链路4.1 第一次被拒我收到的是什么反馈那次提审后台给出的拒绝理由有两条当前页面内容涉及信息展示未选择对应类目且未提供该分类所需资质。线上版本中部分素材存在明显外部品牌标识容易引起用户误解。第一条我还能理解第二条彻底让我懵了。我一直以为素材都是AI生成的怎么会带品牌标识后来我翻了一遍投放区域里的背景纹理图才发现AI在生成“运动风插画”时会在角落里画出类似知名品牌的Logo轮廓虽然不是完完全全的真Logo但审核人员看第一眼就会觉得是。这也是Vibecoding项目的独特风险AI生成的图片未必“干净”它的训练数据里边角料会混进视觉残留。文字同理AI画带有文字的海报时经常生成出类似真实品牌名称的字符串。人眼有时会忽略审核系统不会。4.2 审核意见背后到底在检查什么我后来把这次审核拆解成三个层面和代码项目里的“代码逻辑、用户体验、合规资质”一一对应审核层面常见检查点我的问题代码逻辑是否存在明显崩溃、白屏、反复加载没有大问题用户体验页面是否能顺畅走完核心流程基本满足合规资质类目是否匹配、内容是否违规、素材是否越界类目不匹配、素材有品牌残留值得注意的是审核人员并不关心你的AI开发流程也不关心代码写得高级不高级。他们只会把小程序当作一个真实产品来使用然后用现行规范来度量它。所以Vibecoding项目最容易输的不是功能而是“产品化外壳”——包括备案信息、用户协议、隐私保护指引、内容审核机制。4.3 从确定原因到精确定位素材我做了什么拿到拒审原因后我没有盲目删素材而是把全量素材跑了一遍自动扫描脚本。脚本主要做三件事检测图片里是否包含二维码、检测图片文件名和文件夹中是否有敏感关键词、检测图片的尺寸和色彩是否异常。import re from pathlib import Path from PIL import Image SCAN_DIR Path(./assets/processed) suspicious_files [] keywords [logo, brand, link, icon_, ad, promo] for img_path in SCAN_DIR.rglob(*.webp): name img_path.stem.lower() if any(kw in name for kw in keywords): suspicious_files.append(str(img_path)) continue img Image.open(img_path) gray img.convert(L) # 如果整张图中间区域大面积异常明亮可能隐藏水印 center_box (int(img.width*0.3), int(img.height*0.3), int(img.width*0.7), int(img.height*0.7)) region gray.crop(center_box) avg sum(region.getdata()) / (region.width * region.height) if avg 220: suspicious_files.append(str(img_path)) print(suspicious:, len(suspicious_files))这个脚本不算精确但能帮我把1.8万张图缩小到几十张重点名单然后我再挨个看这几十张最终在卡片背景里找到了四个问题素材。配合关键词过滤又排查出十几个命名上带有第三方品牌字母的图标文件。这整套链路走完大概花了我一个下午比我最初预计的人工翻图快太多了。4.4 修复方式与再次提审的经验定位到问题素材后我做三件事把所有可疑素材直接替换成自己重画的纯色几何背景而不是尝试把Logo“P掉”。审核看的是结果不是你的意图。在后台把小程序类目改成和“图文内容展示”更匹配的分类同时上传了对应的内容说明文档。重新提审时在审核备注里写了“已清理全部外部品牌标识并更新类目配置请复核”。这里有个小技巧审核备注一定要具体。不要写“已优化产品体验”而要说清楚“把哪一类内容移除了、类目改成什么、涉及哪些页面”。审核人员每天看很多版本你帮他省时间他也会更愿意给你通过。第二次提审后大约三个小时状态变成“审核通过”。那一刻我最大的感受不是开心而是一种后怕如果第一次没过的时候我选择“删点图赌一把再提”而不是把所有素材扫一遍第二次很可能还是被拒。Vibecoding不是“赌运气”你得把AI生成的东西当成不可信任的原材料来处理。5. 一个人 AI 做完整产品边界和可复用经验5.1 哪些事情AI干得好哪些事情AI根本干不了经历了这个项目后我给AI能力画了一条非常清楚的分界线AI擅长的把模糊需求变成可运行的原型代码批量生成重复性的页面逻辑处理素材的转换、格式化、批量整理按照你给的格式写配置文件和工具脚本AI不擅长的判断“这个功能是否需要存在”理解平台审核规则背后的业务逻辑做最终的产品走查、内容安全审查维护项目的长期演进而非一次性交付很多人觉得Vibecoding等于“其实可以不会写代码”我不同意。你至少得懂基础的程序逻辑、知道版本控制是什么、会看报错信息。AI可以帮你写代码但没办法帮你“思考产品为什么要这样设计”。被拒审那天我学到的第一课就是AI做的图再好看也不能替代你站在用户角度审核一遍自己产品的合规性。5.2 单人模式的时间和效率账这个项目从零到上线我一共花了大概两个半月。其中第一个月搭框架 让AI产出全部页面内核大约2万行代码。第三周批量生产素材把1.8万张素材管线搭完。最后三周联调、压缩、修Bug、过审。如果按传统方式找团队做同样的工作量需要至少三到四个人力。但Vibecoding不是没有代价我几乎每天晚上都要花一两个小时review AI生成的代码和素材周末的时间全部扑在走查上。说白了就是用时间换人力只不过这个时间消耗比亲自动手写代码小得多。5.3 给正在或准备走Vibecoding路线的人几条建议如果你也打算用一个人 AI的模式去做小程序或小游戏我比较想让你提前知道这几件事先定边界再动手。内容生产类工具适合AI涉及资金交易、用户隐私、实时反馈的产品AI生成的后端逻辑必须谨慎最好只做前端Demo后端找成熟方案。内容越多越要有“自动审查”的概念。AI生成的图片和文本一定要经过机器扫描后再入库不要相信AI的眼睛。版本控制习惯要前置。AI改代码经常顺手牵羊没有git历史遇到问题根本没法恢复。审核不是最后一环而是产品工程的一部分。从第一天做页面时就要考虑“这个页面会不会被审核盯上”而不是等快上线了才考虑。别迷信一次性生成。最好的Vibecoding节奏是“小步快跑”每次让AI改一个局部改完就自己跑一遍立刻发现和修正。5.4 最后我想说点可能不太“正确”的实话如果你期待一篇“AI取代程序员”或者“一个人也可以轻松做产品”的爽文我可能会让你失望。Vibecoding这条路有效但它对个人的基础设施能力要求并不低。你需要会成为AI的“产品经理”能拆需求、能描述清楚问题、能判断输出质量、能快速定位AI搞出来的问题。我那天被拒审时真正让我焦虑的不是改代码而是发现自己一直在“造功能”没有认真想过“上线”这件事包含了多少看不见的规则。做一个能跑的小程序和做一个能上线的小程序中间差的不是代码量是长时间跟真实世界规则打交道的经验。AI能帮你写3万行代码能帮你生成1.8万张素材但审不过去那一瞬间的落差还是得你自己面对。如果你现在也卡在类似的状态不妨先把产品逻辑放一放认真审视一遍我的类目对了没有用户协议写了没有素材里有没有自己都没看过的角落这些补齐之前代码写再多也只是半成品。