AI辅助编程实战:从零构建全栈二手书交换平台
1. 这次辅导的背景与目标月初的时候有位A同学找到我说他想体验一下用AI辅助编程做完整项目但一直卡在“不知道从哪里开始”。他看过很多AI写代码的演示视频自己也用AI生成过一些零散的函数和页面但真要独立完成一个“能跑起来、有前后端、能连数据库”的项目时就不知道该怎么组织整个流程了。这其实是很多编程学习者面对AI工具时的真实状态单独让AI写一段代码并不难难的是把整个项目的骨架搭起来让AI产出的代码能拼成一个完整可运行的系统。于是我们约定做一次完整的辅导目标很简单——用一周时间让A同学在AI辅助下完成一个“二手书籍交换平台”的完整全栈实践覆盖从原型设计到前后端开发再到调试上线的全流程。选择“二手书籍交换平台”这个选题是有讲究的。它的业务逻辑不复杂用户能注册登录、发布书籍、浏览列表、发起交换请求足够覆盖前后端联调、数据库设计、权限控制这些核心环节但又不会像电商系统那样堆满订单、支付、库存等重逻辑。对第一次完整走一遍AI辅助开发流程的人来说这是刚好能驾驭的复杂度。这篇辅导实录我会把我们实践过程中的每一个关键环节都拆开来讲——包括我们是怎么用AI做原型拆解的怎么让AI生成前端组件和后端接口怎么设计数据库以及在联调阶段踩过哪些坑。不管你是想入门全栈开发还是想更高效地使用AI编程工具这里面记录的思路和踩坑经验应该都能用得上。2. 需求拆解阶段先让AI帮你理清“做什么”2.1 一句话需求远远不够但要会“翻译”成提示词辅导开始的第一件事我让A同学把项目需求写出来。他写的是“做一个二手书籍交换平台”。然后我问他这句话里有几个角色每个角色能做什么他想了想大致说出了“用户、管理员、发布书籍、换书”这些词但说不全。这时候就要用AI来帮忙“翻译”需求了。我给A同学演示了一种提示词写法把一句话需求交给AI让它按“角色-功能-行为”三个维度拆解并要求它排除掉不合理的功能。我用的提示词大致是这样的我准备开发一个二手书籍交换平台面向高校学生。 请按以下格式帮我梳理需求 1. 系统有哪些角色每个角色的核心诉求是什么 2. 每个角色可以执行哪些操作操作之间有什么依赖关系 3. 哪些功能是MVP最小可行产品必须包含的哪些可以放到后续迭代 4. 指出需求描述中可能存在歧义或遗漏的地方AI给出的结果里MVP范围基本符合预期用户注册登录、书籍发布与管理、书籍列表与搜索、交换请求、站内通知。它甚至还提示我们“交换请求”这个流程存在状态流转——是“待接受、已接受、已拒绝、已完成”这个提醒非常关键因为一开始A同学根本没考虑到请求要设计成有状态的数据。这个阶段最重要的经验是不要拿一句话需求去让AI直接写代码而是先让它帮你把需求“摊开”。AI在需求拆解上的价值不是替你做产品决策而是帮你把想不清楚的角落露出来让你尽早发现遗漏。2.2 用AI生成页面清单和用户故事原型就有了雏形需求拆解完成后我让A同学继续用AI生成用户故事和页面清单。A同学一开始觉得“用户故事”这种偏产品的东西没什么用但等AI把结果列出来之后他就明白了——用户故事本质上就是每个功能点的验收标准。我们让AI按这样的格式输出角色普通用户 需求我希望能浏览所有可交换的书籍 验收标准 - 书籍列表按发布时间倒序排列 - 每本书显示封面、书名、作者、发布者昵称 - 点击任一书籍可进入详情页 - 支持按书名关键字搜索当前端页面清单生成出来时整个项目的轮廓已经非常清楚了注册登录页、书籍列表页、书籍详情页、发布书籍页、个人中心页、交换请求管理页一共6个主要页面。这时候我给A同学演示了一个后续一直用到的工作方法——把AI生成的页面清单核对一遍剔除掉与MVP无关的内容然后保存为项目根目录下的一个requirements.md文件。这份文件在整个开发过程中一直发挥着作用。后续每次让AI生成代码时我们都会把对应的用户故事段落贴进提示词里AI生成的代码就会更贴近预期。页面清单是后续开发流程的“锚点”能有效防止AI跑偏。2.3 原型要不要画这一步不能省很多用AI编程的人会跳过原型设计认为“UI让AI生成就行了”。在这次辅导中我坚持让A同学先做一版低保真原型——不是用专业原型工具而是手绘框图的方式把6个页面的布局画出来。这个过程用了不到一个下午但价值远大于“画图”本身。画原型的过程实际上是在脑子里把每个页面需要展示的数据字段敲定下来。比如书籍列表页我们需要展示封面、书名、作者、发布者昵称、交换意向那后端接口返回的数据结构就基本确定了至少需要一个book对象包含title、author、coverUrl、ownerName等字段。反过来如果你的接口设计先行再回头画原型经常会出现前端要的数据后端给不了、后端给的数据前端用不上的尴尬情况。对于初学者我推荐两种原型方式一是纸笔手绘简单直接二是用在线白板工具方便调整。选哪种不重要重要的是让页面结构先于代码成型。这一步做得好后面用AI生成前端代码时提示词里可以直接描述“左侧是筛选面板右侧是卡片列表”AI生成的布局准确率会高很多。提示如果你实在不想画原型也至少要让AI先输出一份“页面结构描述文档”再让它生成代码。跳过结构直接写代码大概率会陷入反复修改布局的泥潭。3. 前端实现阶段让AI写组件做人肉代码审查3.1 脚手架选型与技术栈的确定需求确认后我们开始搭项目。技术栈上A同学学过一点前端但不太熟后端则是零基础。我帮他做了个决定前端用React生态工具链用Vite后端用Node.js的Express框架数据库选SQLite。选这个组合不是因为它最“先进”而是因为它足够轻、足够容易理解。我在辅导中特别跟A同学解释了选型逻辑不要被社区里的技术争论带偏。Vite开发服务器启动快配置简单适合小型项目Express是最经典的Node后端框架中间件机制清晰AI训练语料里覆盖面广生成的代码质量相对稳定SQLite则是文件型数据库不需要单独安装服务在这类学习项目中能省掉大量环境配置的时间。以下是初始化前端项目的命令npm create vitelatest book-exchange-fe -- --template react-ts cd book-exchange-fe npm install npm run dev后端则是手动初始化的mkdir book-exchange-be cd book-exchange-be npm init -y npm install express cors better-sqlite3注意better-sqlite3是同步API写起来直观适合初学者理解数据库操作。如果以后项目规模变大再换PostgreSQL数据模型层面的设计仍然可以复用。3.2 提示词里带上下文AI生成的代码质量才稳定脚手架跑起来后就要开始写真正的业务代码了。A同学第一次让AI生成代码时提示词写得非常简略“写一个登录页”。AI返回的代码看起来像模像样但仔细看用的UI库和状态管理方案都跟我们项目里引入的不一致等于用不了。我指出问题所在——提示词缺乏上下文约束。AI不是人它不知道你的项目里装了哪些依赖、有没有统一的请求封装、组件目录结构是什么样。如果你不给它这些信息它就会按照自己“看过”的常见项目惯例来生成代码结果自然对不上。我们修正后的提示词格式是在这个React Vite TypeScript项目中请实现登录页面。 项目环境说明 - 已安装antd组件库axiosreact-router-dom - 接口请求统一封装在 src/api/http.ts 导出的 http 实例中 - 登录接口为 POST /api/auth/login参数为 { username, password }返回 { token, nickname } - 登录成功后将token存入localStorage并跳转到 /books 页面 - 项目所有页面组件存放在 src/pages/ 目录下 请输出LoginPage.tsx 完整代码并说明需要同步修改哪些路由配置。这版提示词生成出来的代码A同学几乎没做修改就直接接入了项目。执行路径一下子就顺畅了。我让A同学记住一个核心原则提示词里写的项目约束越多AI的输出越贴合现状。哪怕你是用AI写一个很小的组件也尽量把“这个组件在其他模块里怎么被引用”交代清楚。3.3 组件拆分与状态管理不要盲从AI的代码结构AI连续生成多个页面后A同学遇到一个新问题AI生成的代码全部堆在一个文件里有的页面组件700多行后面根本维护不动。他问我“是不是我提示词写错了”。这里其实是AI辅助编程的一个典型陷阱AI默认按照“最小工作量”原则输出代码它不会主动帮你做组件抽象。你要在提示词里明确要求它拆分组件。我们后来在提示词里加了这样的约束请将该页面拆分为 - 页面容器组件负责数据获取和状态管理 - 列表展示组件只接收props不直接请求接口 - 单独的卡片组件 每个组件单独一个文件输出文件路径和完整代码这个约束加进去之后AI生成的代码结构明显好了很多。在状态管理上我们坚持一个原则大部分状态放在页面级组件里全局共享的登录态才用Context。A同学之前在网上看到过各种状态管理方案的讨论我给他的建议是在这个项目阶段不要引入Redux之类的库——不是它不好而是你的项目规模不需要。一个AuthContext就够用了保持简单比追求架构完备更重要。3.4 前端调试的经验积累前端页面逐步完成后A同学自己做了几轮人工测试期间遇到两个让我印象比较深的问题。第一个是封面图片加载失败的问题——因为他用的测试图片URL来自外网图片挂了导致页面布局破碎。排查后我们给img标签加了onError处理替换成默认占位图。这个细节后来被证明很重要因为书籍封面本来就是用户上传的外部资源加载失败是常态。第二个是“列表页搜索后URL不变”的问题。A同学实现了搜索功能但搜索条件只存在组件的useState里页面刷新后就丢了。我指出这个场景应该把搜索关键字同步到URL的query参数中比如/books?keywordxxx。这样不仅刷新后状态保留还能支持分享链接。AI可以帮你写业务代码但“把哪些状态同步到URL”这种产品决策需要你基于对用户体验的理解来判断AI不会替你想到这一层。4. 后端开发实践AI能写接口代码业务规则要自己把关4.1 数据模型设计AI建议的字段不一定合理后端开发开始前我们先用AI草拟了一份数据模型。AI生成的初始版本里有users、books、exchange_requests三个表字段设计大体合理但A同学在检查时发现了几个问题。最大的问题是AI把“书籍封面”字段设计成了cover_url字符串但没考虑书籍可能会传多张图。第二个问题是exchange_requests表里没有request_message字段这意味着用户发交换请求时只能选书不能附一句话说明体验会很差。我们把这些问题汇总后直接让AI重新生成了完整的建表SQL并把新字段加入。这里要强调一个贯穿本次辅导的核心观点AI生成的数据模型本质上是根据“行业常见做法”预测出来的不是根据“你的具体业务”设计出来的。你必须要基于自己的业务去校验尤其是唯一约束、外键关系、状态流转这三个方面。没有外键约束的表关系会在联调阶段让你付出成倍的排查代价。最终我们采用的表结构大概是这样CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, nickname TEXT NOT NULL, created_at TEXT DEFAULT (datetime(now, localtime)) ); CREATE TABLE books ( id INTEGER PRIMARY KEY AUTOINCREMENT, owner_id INTEGER NOT NULL, title TEXT NOT NULL, author TEXT NOT NULL, description TEXT, cover_url TEXT, status TEXT NOT NULL DEFAULT available, created_at TEXT DEFAULT (datetime(now, localtime)), FOREIGN KEY (owner_id) REFERENCES users(id) ); CREATE TABLE exchange_requests ( id INTEGER PRIMARY KEY AUTOINCREMENT, book_id INTEGER NOT NULL, requester_id INTEGER NOT NULL, request_message TEXT, status TEXT NOT NULL DEFAULT pending, created_at TEXT DEFAULT (datetime(now, localtime)), FOREIGN KEY (book_id) REFERENCES books(id), FOREIGN KEY (requester_id) REFERENCES users(id) );4.2 接口设计怎么让AI生成风格统一的路由后端的接口设计我们先是在文档里列出全部需要实现的接口清单包括路径、方法、参数、返回结构。这一份接口清单是联调顺利进行的基础。我们让AI根据接口清单批量生成路由代码。A同学一开始觉得这样“太机械了”但我告诉他这正是AI擅长的部分——重复度高的CRUD接口交给AI批量生成效率最高。真正需要人工仔细把关的是两类接口涉及权限校验的以及涉及业务状态流转的。以发布书籍为例这个接口必须校验“当前登录用户是否就是书的发布者”而不是仅仅接收一个ownerId参数。很多AI生成的接口代码会把user_id直接放在请求体里这是初学者容易忽略的安全漏洞。我们在提示词里明确写了“从JWT中解析当前用户ID禁止从请求体中读取用户ID”生成代码才符合要求。接口路由的实现我们让AI输出了一段示例作为模板router.get(/books, (req, res) { const books db.prepare(SELECT ... FROM books WHERE status ?).all(available); res.json({ data: books }); });然后基于这个模板让AI批量生成其他接口。保持接口风格统一的方法是给AI提供一块“样板代码”它能明显降低生成结果之间的风格差异。后面联调阶段几乎没有因为字段命名不一致而对前端返工收益都来自这一步。4.3 数据库操作与联调第一次跑通全流程所有接口写完后到了联调这一步。A同学把前后端两个服务同时启动第一次在浏览器里完整走了一遍“注册-登录-发布书籍-浏览列表-发起交换请求”的操作流程。跑通的那一刻他挺兴奋的但紧接着就发现了几个问题。第一个问题后端返回的时间字段是UTC格式前端直接显示出来比本地时间少了8个小时。解决方案是在SQL查询时直接用strftime把时间转换为本地时区字符串返回或者前端统一做时间格式化。我们选了后端转换因为项目里涉及时间的字段都要统一处理放在后端一处解决更干净。第二个问题比较隐蔽——当列表页同时发起多个请求时浏览器的并发请求数量有限出现了一部分图片和接口请求被挂起的情况。排查后确认是后端接口响应速度不稳定个别查询没走索引。我们在books表的owner_id和status字段上各加了一条索引响应速度立刻恢复正常。这算是给A同学上的一堂真实的数据库性能课。提示使用AI生成SQL查询时最好在提示词里注明需要按查询条件创建索引。AI生成的建表语句默认不会包含索引因为索引依赖具体的查询模式这部分通常要靠开发者自己补充。5. 联调排错实录那些AI帮不了你的关键时刻5.1 登录态丢失问题联调过程中遇到的第一个疑难问题是“登录后刷新页面就退出登录”。A同学排查了很久发现前端登录成功后把token存到了localStorage但axios请求拦截器读取token的key写错了一个叫token一个叫auth_token两边对不上。这种问题跟踪起来很费时间因为报错信息往往是泛泛的401。我教了A同学一个排查习惯遇到认证相关的问题先打开浏览器的Network面板看请求头里有没有带上Authorization字段再看后端返回的是401还是403。通过这个顺序能快速定位是前端没带token还是后端没验过token。如果AI帮你写的代理解不够这种排查思路才是真正解决问题的关键。5.2 跨域问题的处理前后端分离开发时跨域几乎是必遇到的问题。前端服务跑在5173端口后端跑在3000端口前端直接请求后端接口会被浏览器拦截。我们用的是后端cors中间件但最开始配置时把origin设成了*导致携带cookie的请求仍然被拦截——因为浏览器的credentials模式不允许通配符来源。A同学一开始没想通为什么“已经配了CORS还报跨域错误”。我给他打了个比方浏览器好比一个严格的宿管前端要访问后端就像访客进宿舍楼origin: *相当于告诉宿管“谁都可以进”但你还想让访客带行李携带cookie/凭证进去宿管就会说不行指定了允许名单才行。最终我们把origin改成了前端的准确地址const cors require(cors); app.use(cors({ origin: http://localhost:5173, credentials: true }));5.3 数据状态不更新的问题交换请求的状态流转是业务里相对复杂的一段逻辑。用户A对某本书发起请求后用户B需要能在自己的个人中心看到“收到的请求”并执行接受或拒绝操作。我们让AI生成了这块前后端代码但测试时发现一个概率性bug用户B刷新页面后才看得到新请求如果不刷新页面列表不会自动更新。原因是前端在“获取请求列表”之后缓存了数据没有在页面重新聚焦时刷新接口。解决方案是在“收到的请求”页面挂载时每次请求最新数据同时加一个定时轮询。这个案例很典型——它提示我们AI能帮你写“从接口取数”的代码但它不会主动考虑“数据什么时候该更新”。凡是依赖外部状态变化的功能前端都需要显式地处理刷新时机。5.4 常见问题速查表这次辅导实践过程中我们遇到并解决的问题不少整理成表格对后续参考会更直观问题现象可能原因排查要点解决方案登录后刷新就失效前端存储key不一致Network面板看请求头统一token的存取key接口能通但页面白屏返回字段名对不上对比接口返回与前端取值前端按后端实际字段取值时间显示差8小时UTC/本地时区未转换检查数据库时间值后端统一转换时区图片加载导致布局错乱外链图片不可用检查图片URL可访问性增加onError占位图请求被挂起、响应慢缺索引查看慢查询日志为常用查询条件建索引带cookie的跨域请求失败origin配置为*检查cors配置指定准确origin并打开credentials6. 关于AI辅助编程的四条原则这次的辅导项目结束后A同学问我如果要用几句话总结这次AI辅助编程实践的最核心经验我会怎么说。我给了他一共四条原则基本上是这次实践的浓缩第一条AI是“快译员”不是“架构师”。你可以让AI帮你把想法快速翻译成代码但项目的整体架构——模块边界、接口设计、数据流转——必须你自己想清楚。AI生成的一大坨代码看着能用实际上可能缺少合理的分层后续扩展时就是你自己的债。第二条提示词的信息密度决定输出质量。不要指望AI“猜”你的项目上下文。把依赖列表、目录结构、接口协议、数据模型这些信息都放进提示词里AI的输出质量会有质的飞跃。配套的做法是在项目里维护一份ARCHITECTURE.md每次写提示词时直接从里面复制相关段落。第三条AI生成的代码必须过“三道关”。一查安全用户输入是否校验、权限是否校验二查约束字段类型、唯一性、外键是否符合业务三查状态业务状态何时创建、何时流转、何时更新。每一步都要亲手检查不能因为代码是AI写的就掉以轻心。第四条工具永远在变但排查思路是通用的。这次选用的AI编程工具、框架版本、依赖库可能过半年就会迭代换代。但“先看Network面板再看后端日志最后看数据库数据”这样的问题定位路径是长期不变的。最值得花时间学习的恰恰是这些底层的排查能力和建模思维。我在实际辅导过程中还有一个感受AI编程最大的价值不是让资深开发者写得快而是让像A同学这样的初学者具备了“独立完成一个真实项目”的信心。过去他面对空白项目时无从下手现在他学会了把需求拆成页面清单把页面清单变成数据结构把数据结构交给AI生成代码再通过联调把模块拼接起来。这一整套能力比任何单一工具技巧都更值得长期拥有。最后再分享一个小技巧每次给AI写完提示词后花30秒把“你希望它怎么组织返回结果”也写清楚比如“请先输出文件路径说明再给出完整代码最后列出运行时注意事项”。这样AI的回复会天然形成一份配套文档后查起来会方便很多。