前阵子朋友问我:你天天说AI coding,到底行不行?我没给他看跑分,也没贴榜单,直接扔了个网址过去——一套真实在跑的企业报销SaaS系统。两周前,第二家内测公司刚把当月报销完整走完:员工提交单据、主管审批、财务复核、出纳导出打款文件,全流程在线。他说你们团队几个人做的?我说:就我一个,加几个AI编程Agent。
这不是标题党,也不是什么魔术。我把自己当小白鼠,用三个月从零搞定了这套多租户报销系统。选这个项目,是因为它足够“土”,又足够“硬”,刚好能看出当前AI coding的真实水位线。这篇文章我把整个过程中的高光、翻车、纠结和最终判断都摊开讲,想一个人做SaaS、或者正在评估AI编程能力的同行,应该能少走不少弯路。
1. 为什么拿“报销系统”这么不性感的产品来测AI水位线
1.1 报销系统不性感,但企业软件该有的坑它都有
很多人会觉得报销系统太无聊,没有AI产品酷。我恰恰是故意的。你想看清楚一个工具的真实水位线,不能拿一个自己写过八百遍的开源Demo去试,更不能拿算法题去试——那些都是AI训练集里的舒适区。企业报销系统这种“不算难、但处处是约束”的业务,才真正考验编程工具在真实工程场景里的表现。
我把典型报销场景拆开看,它包含:员工创建报销单,一张单子挂多条费用明细,发票可以是图片或PDF,上传后能自动识别出金额、日期、类型;单据提交后进审批流,部门主管审批,财务复核,出纳标记打款,最后沉淀到台账。再叠加上企业成员管理、部门层级、角色权限、预算项目、多公司租户隔离、账号安全、操作审计……全部盘下来大概20多个实体,80多个页面和接口。
这个规模对SaaS产品来说是很典型的“中小体量”。它有大量标准CRUD,有复杂的业务状态流转,有附件存储、第三方OCR、权限边界和数据防篡改,还牵扯到部署和长期运维。每一个坑都踩中企业级软件的经典难点,又不至于大到需要几十人团队。拿它当AI编程的磨刀石,再合适不过。
1.2 先把“成功标准”焊死,拒绝做成玩具Demo
立项时我给项目定了三条必须守住的红线,这也是我后来所有技术决策的底层依据:
- 必须是真实的多租户SaaS,不是单机玩具。两个不同公司注册进来,数据要物理逻辑上都隔离清楚。
- 要有商业化基础。订阅计费这些可以先不做,但用户模型、租户模型、权限模型不能挖坑,以后接支付、接套餐时不能推倒重来。
- 早期我一个人能运维。能接受用一套Docker Compose把所有服务拉起来,但这个编排必须稳定到我可以放心睡觉。
这三条不是产品需求,是工程约束。它们决定了我在后面所有环节都不会轻易接受AI给的“能用就行”的方案。
1.3 AI出初稿,领域边界必须人来定
开始之前我要先把调子定下来:我对AI coding的预期不是“让AI自由发挥直接交付”,而是把它当成一个记忆力极强、执行力很高、但对业务没有常识的实习生。同样的项目,如果直接甩给它一句“帮我做一个报销系统”,它大概率会给你一个又一个页面,每个页面看起来都很合理,连起来用却处处别扭。
所以我的工作方式很简单:AI负责快速产出第一稿,我负责知识注入和边界卡控。方向性的、跟钱和安全相关的判断,我必须亲自拍板;写页面、写CRUD、写接口对接这类执行性工作,尽量让AI多干。这个分工,几乎贯穿了项目全部周期。
2. 需求拆解阶段,AI替不了的那个“产品经理”
2.1 我花三天写的不是需求文档,是给AI的“约束清单”
很多人的误区是:AI coding开始了,就不需要写文档了,我直接用嘴说就行。我实测下来,对复杂的业务系统,这个想法会把你坑得很惨。AI在没有明确约束时确实能生成代码,但它不具备“项目经理”的追问能力,你不说清规则,它就会自动脑补一套规则。脑补出来的规则未必错,但常常和真实财务流程对不上。
我花了一周里最前面三天写需求文档。注意,这份文档不是给老板汇报用的PPT,是给AI执行的“约束清单”。里面包含:角色定义(员工、主管、财务、出纳、租户管理员);每种角色能做什么、不能做什么;报销单的状态机(草稿、审批中、已驳回、待财务复核、待打款、已完成、已关闭);每个状态之间哪些操作是合法的;金额字段统一用十进制、单位是分还是元;附件上传大小限制,发票文件如何归属;导出Excel的字段口径。
真正让我意外的是,文档写到一半时,我自己想清楚了不少以前模糊的问题。比如“驳回后单据到底回到草稿还是回到一个专门的已驳回状态”,这会影响员工二次提交流程。这种坑如果等AI写出来再发现,返工成本会高得多。
2.2 把“项目地图”喂给AI:为什么需要一份Context文档
文档写完我还没开工写代码,而是先建了一个叫 CONTEXT.md 的文件放在仓库根目录。里面是一份“项目地图”:目录结构、实体清单、每个实体的核心字段和关系、接口的命名规范、通用代码模式、已确定的技术栈、数据库迁移方式、异常处理与日志规范。
原因是:当前coding agent的能力上限,很大程度上取决于它能看到的上下文。它不像一个有十年经验的老同事,来了就能自己翻代码、理解业务。哪怕它有能力读完整个仓库,你也不能每次都让它重新读一遍所有文件,成本和走偏概率都太高。给一份精炼的Context文档,等于告诉它“你只要先读这份文件,就能避免绝大多数低级错误”。
这个文件我维护了全程。每做完一个模块,我就让AI把其中值得后续复用的模式追加进去。到项目后期,新需求的生成质量和速度明显比前期高,靠的就是这份“外部记忆”。
2.3 技术选型的第一原则:让工具的默认选项顺应AI擅长区
技术选型阶段,我也试过让AI直接给推荐方案。效果确实不错,它会把不同方案的优缺点列得很清楚,但最后真正左右我决策的其实是我自己的一个原则:尽可能让“默认选项”落在AI最擅长、训练数据最密集的领域里。
我最终的选择是:前端用 React + TypeScript + Next.js,后端用模块化的API服务,数据库用 PostgreSQL + Prisma ORM,对象存储放发票附件,Redis 做缓存和轻量任务队列,整体用Docker Compose编排。整套技术栈最大的特点就是“标准”。任何一个环节出问题,网上都有海量样本,AI给出的代码也会更可靠。
为了让AI发挥最大化,我还做了一个被很多人忽略的细节:所有接口都要有完整的类型定义。TypeScript的接口就是给AI最好的提示词。可以这么说,AI coding 在有强类型约束的代码库里,表现远好于在纯动态语言的项目里。类型系统帮它完成了一部分“思考”,剩下的事情就顺畅了。
3. 编码期真实实录:哪些地方快得离谱,哪些地方反复返工
3.1 标准CRUD和页面:第一周的效率让我重新怀疑人生
真正开工后,我是被AI的执行力惊到的。像“费用类型管理”“部门列表”“成员管理”这类功能,本质就是标准的增删改查加搜索分页,AI在做这些事情时极其顺手。上午给它描述清楚字段和接口格式,下午页面和API就都出来了,而且代码风格基本统一,错误处理也算完整。第一周结束,我算了笔账:如果按我过去手写全栈的速度,这些基础功能至少要三四周,现在一周就跑完,还不算期间反复调整需求花掉的时间。
这片区域我称之为AI编码的“浅水区”。它的水位线高得惊人,原因是这类代码在公开训练数据里到处都是,模型已经见过几十万遍。它要做出优秀成果的前提是:你要把字段、状态、接口模型写清楚。只要样例给的准,它生成的代码靠谱度高到可以只做抽查,不用逐行review。
3.2 审批状态机:AI第一次表现出“逻辑幻觉”
如果说标准CRUD让我低估了AI的难点,那审批状态机马上把我拉回现实。报销系统最核心的规则是状态流转,我的业务逻辑并不复杂,大致是:员工只能提交属于自己且状态为“草稿”的单据;主管只能审批自己部门或指定下属的单据;财务复核可驳回也可通过;出纳确认打款后单据进入已完成;除了草稿态,任何状态都不能被任意编辑或删除。
我把这段需求交给AI后,它给了一份比我想象中更完整的实现,用了状态字段加一堆if分支,看起来天衣无缝。可我一做测试就发现了问题:一条“草稿”状态的单据,居然可以被直接操作成“已完成”,说明它在流转逻辑里漏掉了中间状态的校验。更隐蔽的bug是:主管驳回后状态虽然回到“草稿”,但原审批记录被覆盖了,员工再次提交时历史审批意见全部丢失。
这种问题我不会说AI很蠢,它本质上是在做语言模型的概率续写,而不是在脑内画状态流转矩阵。业务规则如果没有被形式化地表达,它就会把“最像正确代码”的东西生成出来,而不是真正满足业务规则的代码。这个月我在笔记里写下一句话:不要用散文管理业务规则,要用表格、矩阵和断言管理业务规则。后来我把状态机画成二维表格,横轴是当前状态,纵轴是操作,中间是目标状态,喂给AI让它严格按表实现。回归测试一跑,逻辑瞬间稳了。
3.3 发票OCR与附件上传:成熟集成可以让AI写,但该接的服务不能省
报销系统绕不开发票处理。最开始我也天真了一下,心想OCR这种成熟能力,让AI写点代码去调第三方不就行了。可深入调研后发现,增值税发票的字段识别、真伪验查、税务合规这些坑,远比写几行调用代码复杂。个人开发者自己训练的模型既不合规也不准确,必须接专业的发票识别服务。
这个环节AI倒是帮了大忙。我把第三方服务的OpenAPI规范切给AI,让它生成客户端封装,它只用了十几分钟就把签名算法、异步回调、错误码处理全部对齐了。在我没有对着文档手写过一行的情况下,发票识别模块顺利跑通。这说明一个道理:凡是接口文档定义得清清楚楚、输入输出边界很明确的任务,都是AI编码的高水位区。而面对“整个模块该不该自研”这类问题,AI给不了好答案,因为它没有你的合规压力、成本预算和长期维护能力。
附件上传也让我有过一次教训。第一版实现走的是整文件multipart上传,单张几MB的发票还扛得住,一旦有人上传十几MB的PDF,请求直接超时。AI起初不会主动考虑到生产环境的大文件问题,我换成了对象存储直传加签名的方案,把这个需求说明白后,它写出了非常规范的分片直传代码。但从这次之后我确认了一件事:AI编码适合做“我已想清楚方案”的快速落地,而不是代替我判断生产环境会出什么问题。
4. 多租户隔离与防篡改:SaaS的生死线,不能全赌AI
4.1 差点上线才发现“跨租户越权”:一次典型多租户事故
整个项目里最让我后怕的,是上线前我自己做安全自查时发现的一个漏洞。场景是这样的:我用A租户的财务账号登录,把报销单详情页的URL参数换了一串数字,结果直接读到了B租户上传的发票图片和报销金额。当时我的冷汗一下就出来了——如果这个漏洞在真实客户那边被发现,产品信誉基本归零。
排查根因时,我发现大量列表查询和详情查询的where条件里,只过滤了业务资源ID,没有强制附加租户ID。问题是AI为什么这么写?因为在海量开源项目里,绝大多数后台都不涉及多租户,AI模仿了这些项目的常规写法。它没有内置“你是一个多租户系统”的安全上下文。每个接口单看都合理,连起来才暴露问题。
这次事故之后,我把多租户安全的规矩写死,并且嵌入了Context文档:所有业务表的查询必须带TenantId条件;Repository基类强制要求传入当前租户,不允许出现孤儿查询接口;模型关系设计上,核心子表外键要同时包含租户ID,从数据库层面杜绝跨租户关联;上线前用一个自动越权扫描脚本,遍历当前租户能访问的ID,再用另一个租户的登录态去尝试访问,只要200就算失败。这套扫描脚本其实是我让AI帮我写的,AI执行得很快,但“这里需要做越权扫描”这个判断只能由人来下。
4.2 不可篡改不是把表设成只读,而是“状态机+审计+哈希”组合
数据安全里还有一个反复被问的问题:你做的报销系统,怎么确保数据不可篡改?我梳理完实际方案后发现,真正工程意义上的“不可篡改”,不是把表权限设成只读就完事,而是把篡改成本提高到让内部人员都很难承受的程度。
我的做法可以拆成三块。第一块是业务层约束:报销单只有处于草稿状态才能被编辑或删除,进入审批流后任何变更都必须留痕,特殊修改要走“撤回”或“补充说明”流程,业务表只允许追加状态流转记录,不允许原地改历史。第二块是审计日志:所有敏感操作都会插入一条日志,包含操作人、时间戳、IP、User-Agent、操作前后JSON快照和结果;这条日志在数据库层是只追加的,应用账号对日志表只有INSERT权限,ORM里也禁止对它调用update或delete。第三块是哈希校验:关键业务字段快照生成一个content_hash字段,系统每天夜间跑一个任务把所有审计流水重新计算哈希并和历史值比对,一旦发现不一致立刻告警。
这套方案不是某个单一技术的魔法,它强调的就是“所有操作有人负责、历史记录无法静默改写”。AI能把触发审计的中间件和哈希校验脚本写得又快又好,但哪些字段属于资金敏感的、为什么审计日志的账号要和业务表分开、为什么不能用ORM默认的更新方法,这些判断来自对财务系统合规性的理解,模型不会替你想。
4.3 数据安全除了防篡改,还要想清楚备份怎么恢复
还有一个容易被AI coding光环掩盖的问题:数据备份和恢复演练。这一点很多人到了系统跑起来才想起来。我给生产库配了每日定时备份,自动推到对象存储,保留最近30天。可真正让我睡得着的不是备份脚本,而是我亲手做了一次“从空库恢复到昨天”的演练。如果没做过演练,备份就只是一堆没人验证过的文件。
AI在这块的帮助也是执行层面的。它能写出标准备份脚本,也懂得定时任务怎么写。但它不会替你考虑“恢复时间目标是多少”“恢复到什么时间点”“是否要保留历史归档”“合规要求日志保留多久”。这些都要结合业务风险来判断。我的建议是:再小的系统,也要把备份恢复演练当成上线前的必选项,这比多写100个功能都重要。
5. 一个人硬扛部署上线:AI coding的“环境盲区”
5.1 Docker Compose能起,不代表生产环境能跑
编码只占整个项目的一部分,上线部署才是让人真正体验“一个人做SaaS”这个词份量的环节。我早期信心很足,因为AI能很熟练地把Dockerfile、docker-compose.yml写好,本地docker compose up一跑,前后端、数据库、Redis全部起来,好像一切都在掌握中。
可到了生产环境,问题接踵而至:HTTPS证书自动续期怎么配;反向代理的超时时间为什么总在附件上传时拦截;容器里的时区默认是UTC,员工晚上提交的报销单在数据库里显示成了第二天;对象存储的跨域规则没配好,前端直传签名总是失败。这些问题的共同点是:它们依赖的是你真实的服务器、真实的域名、真实的云服务配置,而不是模型训练数据里那些通用样例。
AI能给出一个个零散的答案,但它无法替你完成“问题定位”这个过程。当你连错误日志都不知道去哪看的时候,你连问题都问不出来,自然也就得不到靠谱答案。所以在环境问题领域,AI coding的水位线比我预期低不少。它当不了一个全知全能的运维专家,更多时候像一个能查文档的助手,你必须有基本能力判断方向,它才能帮你快速补齐细节。
其实这也反过来说明了一个趋势:个人开发者全栈能力的门槛不是降低了,而是转移了。写业务代码的门槛被AI拉低很多,但部署、排障、网络、安全这些“环境经验”的价值不降反升。你就是被AI抢不走的那部分。
5.2 上线后的典型故障:日志、告警、半夜处理
我上线后的第一个“生产事故”既不是代码逻辑错误,也不是数据库问题,而是一个外部依赖的Webhook回调超时。发票识别服务在高峰期响应慢,导致回调处理线程被阻塞,积压任务越来越多,后台报销单一直处于“识别中”。这种外部依赖故障在开发阶段永远模拟不到,它考验的是整套系统有没有超时重试、熔断降级、失败队列。
这一课让我补上了可观测性。我一个人也不可能上很重的监控系统,但最少的东西必须要有:第一,所有应用的日志要汇总到统一位置,出了问题能按请求ID串联起来看完整链路;第二,配置一个活跃告警,Web服务错误率或接口耗时超过阈值时直接推到手机;第三,Sentry这类崩溃监控至少要接上,前端还是后端出错会推送带堆栈的告警。
深夜收到一次告警后,我索性准备了一个运维手册,把自己排查过的每个故障、执行过的每一条命令都备份在一个文档里。这种文档AI也能帮我维护,但写下一个“为什么要优先检查Redis连接数”的思考,AI目前很难代劳。
5.3 试运行期间的产品变化:AI能改代码,但改不了需求变化的原因
上线内测后我邀请了三家朋友公司,想着至少能撑几周。结果是第一周就有人反馈一个产品规则问题:他们公司不同部门的差旅标准不一样,有人能坐高铁一等座,有人只能坐二等座。这个规则在预算控制里属于常态,但我的系统当初只做了全公司统一的标准,根本没法按部门或者按职位配置。
这种需求变化没有技术难点,纯粹是业务模型设计时少考虑了一步。AI很快帮我加上了“费用标准规则表”,并调整了前端校验逻辑。不过,这背后的核心动作是“我发现了一个未预料的业务维度”,这需要你对客户场景有敏感度。AI coding再强,也无法替你参加客户的电话回访,听出那句“我们财务那边一般要先看预算有没有超”背后的真实诉求。
6. 三个月实测后,我看到的AI coding真实水位线
6.1 把AI coding表现分三档:浅水区、腰水区、深水区
做完整套项目,我给当前AI coding的能力画了一张粗糙的地图,叫“水位线三层分法”。
浅水区是标准增删改查、后台页面、字段校验、基于成熟API文档的第三方集成、单元测试补全、简单脚本工具。在这里,AI的完成度高得离谱,一个人加AI能达到一个小团队七八成的产出速度。前提是需求被描述清楚,不要让它猜。绝大多数想用它来提效的人,都应该把更多工作推进到这片区域。
腰水区是业务规则和状态流转、权限模型设计、复杂统计报表、跨模块一致性处理。在这里,AI的表现很不稳定。给它一张状态流转表,它能写出很稳的代码;给它一句“报销单要能审批”,它就会开始它的表演。在腰水区,AI不是一个独立的作业者,它需要一份已经被形式化表达了的规则。
深水区是安全边界设计、资金合规、防篡改审计方案、多租户隔离策略、核心数据一致性、复杂故障根因分析。在这里,AI能写执行代码,能帮你检查文档,但它现在还没有办法对你没说过的心智模型负责。它也不知道哪种“看起来能用”的方案会在合规场景里埋雷。
6.2 一张实测判定表,帮你决定什么任务可以交给AI
下面这份表格是我三个月的经验总结,分享给想复制这条路的人。它不是评测基准,只代表个体经验,但相当有参考价值。
| 任务类型 | AI实际表现 | 人的精力投入重点 |
|---|---|---|
| 标准CRUD与页面搭建 | 优秀,交付速度快 | 把字段和约束写清楚,检查边界 |
| 表单校验和交互细节 | 良好,但缺少极端情况考虑 | 补充生产环境和安全场景的用例 |
| 业务状态流转 | 不稳定,容易产生逻辑遗漏 | 用状态矩阵/表格形式化表达规则 |
| RBAC权限模型 | 能写,但需要人补齐多租户隔离 | 明确数据权限边界,设计自动越权测试 |
| 第三方服务对接 | 优秀,OpenAPI规范下神速 | 选择可靠服务商,把关数据合规 |
| 数据安全与防篡改方案 | 能实现细节,无法定义方向 | 架构判断、敏感字段识别、审计制度 |
| 部署与运维 | 能生成脚本,难以定位未知故障 | 熟悉基础设施,留好日志与监控 |
| 需求分析与产品判断 | 基本依赖人 | 自己上,别指望AI做客户访谈 |
如果你想判断某个任务该不该交给AI,最简单的问题就是:这个任务“如果目标是爬一座我爬过的山,AI会很强;如果是开路,别只丢给AI一个人去开路。”
6.3 给想“一个人做SaaS”的同行几条实操建议
第一,先写PRD,再开始coding。具体到金额字段用分还是元、状态机走哪些合法路径,这类规则不能靠AI脑补。一份维度和边界清楚的文档,至少能省下整个项目一半的返工时间。
第二,多租户安全一开始就写进规范和Context文档里。如果系统设计阶段没有隔离意识,后面补课痛苦程度成倍增加。建议把所有查询都收敛到带租户ID的Repository基类下,并做一个自动越权扫描脚本作为回归工具。
第三,凡是和钱、权限、数据安全相关的代码,无论AI写得多快,都要坚持人工review。我甚至要求AI对关键流程先写测试再写实现,这能逼着它把逻辑理清楚,也能让规则沉淀成可执行断言。
第四,不要指望AI记住你的全部背景。把项目的业务规则、技术决策、容易踩的坑都写进一个CONTEXT文档里,每次大任务前提醒它读取,这会让你感觉到它的表现上了一个大台阶。
第五,坚持自己完整做一遍部署和恢复演练。这不是传统的“体力活”,而是建立对系统的信心和掌控感。如果某天半夜出了故障,能起床救火的只有你自己,AI可以帮你查命令,但没法代替你做判断。
把这套流程跑完,我对AI coding的判断是一句大白话:它不会替你决定“什么是对的”,但只要你想清楚了,它能让你抵达目标的速度快上好几倍。这个结论,可能比任何一个新模型发布新闻都更接近真实水位线。