
如果你也是计算机专业的学生最近正在为毕业设计选题发愁或者已经在网上看到过不少“基于微信小程序的闲置物品交易平台【源码文档调试】”这类内容那你大概率已经感受到源码、文档、调试这三个词几乎就是毕设项目的全部交付物。但很多同学拿到手之后依然跑不起来、讲不明白、改不动代码最后答辩现场被老师一问就卡壳。这篇文章我就结合自己做闲置交易类小程序的实际开发经验从选题逻辑、架构设计、功能拆解、踩坑调试到文档撰写把这类项目从头到尾讲透给准备做微信小程序方向的同学一个真正能落地参考的完整路径。1. 为什么“闲置物品交易”是毕设/课设的稳妥之选1.1 业务场景真实答辩时容易讲清楚价值每年毕设选题微信小程序方向永远是大热门。但热门也分两种一种是烂大街的图书借阅、备忘录、记账本另一种是像闲置物品交易这种“有真实商业参考对象”的项目。后者的优势在于——它的业务逻辑并不复杂但场景极其真实你随时可以拿闲鱼来类比答辩老师一听就知道这个系统是干什么的、解决了什么问题。闲置物品交易的核心痛点是什么家里堆积的旧书、二手电子产品、用不上的小家电扔了可惜放在二手平台又担心流程太重。而基于微信小程序的交易平台天然契合“轻量、即时、社交”的属性用户不需要下载额外App扫码即用发布商品、浏览商品、联系卖家一条链路走完。这种“需求—方案”的对应关系在开题报告和答辩PPT里几乎是白送分的内容。1.2 技术栈覆盖恰到好处该有的都有我看了很多同学选这个题目最担心的其实是“技术含量够不够”。这里可以明确说这个题目覆盖的技术点一点都不少而且每一样都能在答辩时讲出东西来。小程序端WXML/WXSS/JavaScript自定义组件页面生命周期本地缓存wx.request 网络请求wx.uploadFile 上传文件wx.login 登录流程。后端接口设计、鉴权token / session、文件存储、业务逻辑分层。用 Spring Boot MyBatis Plus 是最主流的组合也是 Java 课程设计案例里最常见的方案如果你更熟悉 Node.js用 Express 或 Egg.js 也能实现同等效果。数据库MySQL 表结构设计、多表关联查询、分页查询、索引设计。用户表、商品表、图片表、收藏表、订单表五张核心表足够覆盖全部业务。联调与调试开发者工具模拟调试、真机预览、接口测试、日志排查。这正好对应标题里的“源码 文档 调试”三件套源码解决实现问题文档解决设计问题调试解决落地问题。三者凑齐一个毕设该有的完整度就出来了。1.3 MVP功能边界怎么划扩展点怎么留做毕设最忌讳“什么功能都想做”所以我一般建议第一版只做MVP把核心链路打通剩下的作为扩展亮点写进论文里。以一个闲置交易平台为例我可以给你一张功能分级表功能模块MVP必做扩展亮点时间充裕再做用户登录微信授权登录、用户信息维护管理员后台、用户信用分商品模块发布商品、商品列表、分类筛选、关键词搜索、商品详情商品推荐、浏览记录、多图轮播、视频展示交易模块收藏、联系卖家复制微信号/拨打电话在线下单、买卖双方评价、订单状态机个人中心我发布的、我收藏的、我卖出的、我买到的数据统计、消息通知、举报机制注意我特意把“在线支付”放在扩展区之外甚至不建议做。原因很简单个人主体的小程序无法开通微信支付而且带有交易闭环的平台在公司主体资质审核上也有严格限制。毕设阶段把核心价值聚焦在“信息撮合 沟通联系”上反而逻辑更顺、审核风险更小。这个取舍你必须在文档里写清楚答辩时它就是你的“业务边界分析”。2. 整体架构设计三层结构怎么划分各自承担什么2.1 小程序的工程结构规划拿到这类项目源码之后第一步不是急着点运行而是先看懂目录结构。一个典型的小程序闲置交易平台前端工程结构大概是这样的miniprogram ├── app.js # 全局逻辑登录态判断 ├── app.json # 页面路由、窗口配置、tabBar ├── app.wxss # 全局样式 ├── utils │ ├── request.js # wx.request 二次封装统一携带token │ └── util.js # 工具函数比如格式化时间 ├── components │ ├── good-card # 商品卡片组件首页/列表复用 │ └── empty-page # 空状态占位组件 └── pages ├── index # 首页商品信息流 分类筛选 搜索 ├── release # 发布页表单 图片上传 ├── detail # 详情页轮播图、卖家信息、收藏/联系 ├── category # 分类页可选 └── user # 个人中心我发布的、我收藏的、我买到的这个结构最大的好处是“复用”和“解耦”。商品卡片组件在首页推荐流、搜索结果页、我发布的列表里都能用request.js 封装了统一的 baseURL、token 注入、错误提示后续所有页面请求都走这同一个入口。要是你拿到的源码没有做这层封装建议你自己加上文档里也能多写一个“前端工程化设计”的亮点。2.2 后端接口怎么划分才规范后端我以 Spring Boot 为例来说。接口模块按照业务边界拆不要一个 Controller 里堆几百行。核心接口清单列出来就是一张很好的接口文档表模块接口路径功能说明请求方式登录鉴权/api/auth/login接收 wx.login 返回的 code换取 openid 并签发 tokenPOST用户信息/api/user/update更新昵称、头像等PUT商品发布/api/good/release提交商品表单数据POST图片上传/api/upload/image接收图片文件返回URLPOST商品列表/api/good/list分页查询支持搜索、分类、排序GET商品详情/api/good/detail/{id}查询详情浏览量1GET收藏操作/api/favorite/toggle收藏/取消收藏POST我的发布/api/good/my查询当前用户发布的商品GET我的收藏/api/favorite/list查询当前用户收藏的商品GET订单确认/api/order/create买家标记“已成交”POST我建议接口路径保持全小写 中划线风格返回统一 JSON 结构code、message、data这样不管前端还是后端同学协作或者你自己调试都能少掉很多沟通成本。2.3 数据库表结构设计五张核心表怎么建数据库是整个系统的地基直接决定后续开发的顺畅度。拿good商品表举例建表语句大致长这样CREATE TABLE good ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL COMMENT 发布者用户ID, category_id int(11) DEFAULT NULL COMMENT 分类ID, title varchar(100) NOT NULL COMMENT 商品标题, description text COMMENT 商品描述, price decimal(10,2) NOT NULL COMMENT 售价, original_price decimal(10,2) DEFAULT NULL COMMENT 原价选填, cover_image varchar(500) DEFAULT NULL COMMENT 封面图URL, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 状态0在售1已售出2下架, view_count int(11) NOT NULL DEFAULT 0 COMMENT 浏览量, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_id (user_id), KEY idx_category_id (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT闲置物品商品表;这里有几个容易忽略的细节cover_image单独存主图URL而多图通过good_image子表单独关联存储idx_user_id和idx_category_id加索引因为“我的发布”“按分类浏览”是最高频的查询之一status用数字枚举而不是字符串查询更快也更方便代码里做映射。表结构设计得好后面写 mapper 多表查询时能省不少事。3. 核心功能模块拆解每个模块的难点与实现思路3.1 微信登录与token机制最容易出问题的一环登录是几乎所有小程序功能的入口也是很多同学跑通源码后最先报错的地方。微信小程序的登录流程其实是一个固定的“三步走”前端调用wx.login()拿到一个临时凭证code。前端把code发送给后端后端拿这个code去微信接口jscode2session换取openid用户唯一标识和session_key。后端生成业务 token 返回给前端前端存入wx.setStorageSync(token, xxx)后续每次请求放Authorization头里。后端核心代码大致是这样的PostMapping(/api/auth/login) public Result login(RequestBody LoginRequest req) { // 1. 使用 code 换取 openid String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code req.getCode() grant_typeauthorization_code; // 2. 请求微信接口解析 openid String openid wechatClient.getOpenid(url); // 3. 查用户表不存在则自动注册 User user userMapper.selectByOpenid(openid); if (user null) { user new User(openid); userMapper.insert(user); } // 4. 生成 token可用JWT也可用UUID存Redis String token UUID.randomUUID().toString(); redis.set(token, user.getId(), 7 * 24 * 3600); return Result.success(token); }这里有一个关键点很多人第一次接触会犯错code是一次性的一般只能使用一次且有效期只有几分钟。所以不管前端还是后端不能把这个 code 缓存起来重复使用。调试登录问题时如果后端一直报invalid code先检查是不是同一份 code 被测试工具或浏览器缓存反复触发。token 的存储我推荐用 Redis 带过期时间而不是简单把用户ID传回前端因为 Redis 方案支持做“强制下线”和“修改密码后失效”等扩展逻辑也更方便《详细设计》里写“无状态登录鉴权”。3.2 商品发布与图片上传从临时文件到正式URL发布闲置物品核心是两个动作先传图片再提交表单。顺序不能反——先提交表单再传图片商品记录已经生成了万一图片传失败就会产生“有商品没图片”的脏数据。正确做法是用户选择图片wx.chooseMedia获取本地临时文件路径。前端逐张调wx.uploadFile将文件上传到后端/api/upload/image。后端接收 MultipartFile按日期生成存储路径保存到本地磁盘或OSS返回完整URL。前端把所有图片URL拿到手后连同商品表单数据一起POST /api/good/release。前端上传图片的核心代码大致是这样wx.chooseMedia({ count: 9, mediaType: [image], success(res) { const tempFiles res.tempFiles; // 这里需要循环上传并收集返回的URL tempFiles.forEach(file { wx.uploadFile({ url: ${baseUrl}/api/upload/image, filePath: file.tempFilePath, name: file, header: { Authorization: Bearer ${token} }, success(uploadRes) { const data JSON.parse(uploadRes.data); imageUrls.push(data.data.url); } }); }); } });存储方案怎么选如果后端部署在云服务器上我建议用云存储阿里云OSS / 腾讯云COS可以避免自己处理磁盘满、备份、公网访问等问题但如果是毕设演示场景后端本地目录存储也无伤大雅只是要注意配置一个静态资源映射否则上传完的图片在小程序端访问不到。Spring Boot 里加一段 WebMvcConfigurer 配置即可Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String uploadPath file: System.getProperty(user.dir) /upload/; registry.addResourceHandler(/upload/**).addResourceLocations(uploadPath); }3.3 商品列表与搜索分页、筛选、排序的一次性到位商品信息流是用户的“门面”也是后端查询逻辑最集中的地方。大部分毕设源码会用PageHelper或者 MyBatis Plus 的IPage做分页前端配合onReachBottom触底加载下一页。列表查询的请求参数通常是这些pageNum页码默认1 pageSize每页数量默认10 keyword搜索关键词按标题模糊匹配 categoryId分类ID sortBy排序方式latest最新 / price_asc价格升序 / price_desc价格降序后端 Service 层拼接查询条件时注意模糊搜索要防注入——用 MyBatis Plus 的 LambdaQueryWrapper 而不是自己拼字符串LambdaQueryWrapperGood wrapper new LambdaQueryWrapper(); if (StringUtils.hasText(keyword)) { wrapper.like(Good::getTitle, keyword); } if (categoryId ! null) { wrapper.eq(Good::getCategoryId, categoryId); } // 排序 if (price_asc.equals(sortBy)) { wrapper.orderByAsc(Good::getPrice); } else { wrapper.orderByDesc(Good::getCreateTime); }前端首页信息流要注意图片懒加载——image标签加lazy-load属性否则首屏等待时间会长到让人想卸载。另外详情页浏览完之后返回列表要保证滚动位置不丢失这一步在小程序里需要配合页面的onSaveExamineState或使用自定义组件模板消息很多初版源码都忽略了但实际体验差异很大。3.4 交易流程的关键设计没有支付怎么定义“成交”这个模块是很多人觉得“最难做”的因为一提到交易下意识就会想到支付。但前面说了毕设项目受小程序类目限制在线支付链路很难完整跑通所以成熟的做法是把平台定位为“信息撮合工具”成交动作放在线下或者通过“确认成交”的轻量状态机来模拟闭环。我的方案是引入订单表order_info字段包含买家ID、卖家ID、商品ID、状态待联系 / 已成交 / 已关闭。流程可以简单描述为买家在详情页点“联系卖家”平台展示卖家微信号或跳转客服会话业务上记录一次“有意向”。买家线下沟通完成后在该订单上点击“确认成交”后端校验买家身份后把商品状态置为“已售出”同时给卖家加一条成交记录。如果长期未成交用户可在“我发布的”里手动下架或标记售出。这样设计的好处是完整表达了“交易”这个概念但又绕开了支付资质限制。你在《需求分析》里可以专门写一段“为什么不做线上支付”表述成“平台聚焦于供求信息匹配支付与交付环节由用户双方自行完成”答辩老师完全能接受甚至会觉得你有业务敏感度。4. 从0到1跑通项目环境搭建、源码导入与首次联调4.1 环境准备清单拿到标题里的“全套源码文档”之后第一步就是装环境。我整理了一份最小环境清单缺一不可工具说明注意事项微信开发者工具小程序前端开发和调试需要注册小程序账号拿 AppIDJDK 8 / IDEA后端运行环境如果后端是 Spring BootJDK8 或 17 都行MySQL 5.7 / 8.0数据库建议 8.0注意字符集选 utf8mb4Navicat / DataGrip数据库客户端用来执行 SQL 脚本、查看数据Redis可选token 存储如果源码用 Redis必须先启动服务Postman / Apifox接口自测强烈建议联调前先把后端接口测通这里有个非常容易被忽略的坑后端配置文件application.yml 或 application.properties里的数据库密码、Redis 密码、小程序 AppSecret一定要确认是不是你本机的配置。很多源码拿到手直接启动提示连不上数据库原因不是代码有问题而是配置文件里还是原作者本机的localhost和密码。4.2 导入源码后的目录对照后端项目解开后常见的结构是server ├── src/main/java │ └── com/example/xx │ ├── controller # 接口层 │ ├── service # 业务层 │ ├── mapper # 数据访问层 │ ├── entity # 实体类 │ ├── config # 配置类拦截器、跨域、资源映射 │ └── utils # 工具类jwt、md5等 ├── src/main/resources │ ├── application.yml # 配置文件 │ └── mapper # XML文件如果用MyBatis XML └── sql └── init.sql # 数据库初始化脚本前端小程序目录前面已经列过。拿到源码后建议顺序阅读先看app.json再看utils/request.js然后挑一个典型页面比如首页 index从头到尾读一遍。这样你能最快理解“请求从哪个页面发起经过哪个接口落到哪张表”这个理解过程对后面改代码和答辩讲解都特别重要。4.3 启动顺序与首次跑通跑项目最忌讳“所有东西一起启动报错不知道看哪头”。我的建议是严格按照以下顺序操作启动 MySQL执行sql/init.sql确认表都建好。启动 Redis如果项目用到用redis-cli ping确认返回 PONG。启动后端先在 IDEA 里编译跑一次确认没有编译错误。用 Postman 直接测后端接口比如调用“商品列表”接口确认能返回数据。最后才是打开微信开发者工具导入小程序前端配置 AppID。在开发者工具的“详情—本地设置”里勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”仅本地调试时开启。运行小程序先看首页能否加载出商品列表。整个链路里最值得提醒的是第6步。如果你在开发者工具里看到的报错是request:fail url not in domain list99%就是这个设置没勾或者是app.js里 baseURL 配错了。这一步在文档的《部署手册》里也要用醒目字标注因为所有第一次跑项目的人都会在这个地方卡一次。4.4 真机预览时的网络配置开发者工具能跑通之后你肯定会想让小程序在手机上跑一下——毕竟毕设答辩现在很多要求演示真机。真机和开发者工具最大的区别在于网络开发者工具里localhost默认指向你电脑本机所以后端 baseURL 写成http://localhost:8080没问题。真机上这个地址指向的是手机自己根本访问不到电脑。解决办法是改成电脑在局域网里的IP比如http://192.168.1.100:8080。每次换网络环境这个IP可能都会变所以在代码里把 baseURL 抽成一个变量写到config.js会省去很多重复劳动module.exports { baseUrl: http://192.168.1.100:8080/api, };真机预览还有一个很实际的坑上传图片时如果用本地存储图片URL也是局域网IP。手机和电脑必须连同一个Wi-Fi否则图片打不开。如果是从线上买来的源码往往自带线上的文件存储服务OSS/COS这种情况反而不存在这个问题但你要先确认后端配置里的 AK/SK、Bucket 信息是否有效——很多过期源码这里就是坏的需要换成自己的。5. 调试实战我在真机调试中遇到的高频问题5.1 登录时报 invalid code 的完整排查链路先描述一个最典型的场景前端wx.login成功拿到 code调后端登录接口结果返回errcode: 40029, errmsg: invalid code。很多同学到这个报错就懵了其实这个问题的排查链路非常固定先确认 code 是否被使用两次。小程序端如果开了“自动登录”又手动调了一次登录接口第二个请求铁定失败。解决方法是登录态做好标记不要重复请求。再确认后端 appid 和 secret 是否正确。尤其是从别人源码拿来的经常是原作者的 AppID 对应的 secret和自己的小程序账号不匹配。微信接口对于“AppID secret code”三者不匹配会直接判为 invalid code。最后确认有没有改过wx.login的调用时机。把 code 传给后端之前先console.log出来在后端接口入口打日志看是不是请求根本没到达后端。如果后端用了缓存还要检查 Redis 里是否存了旧 code 或者 token 过期逻辑导致误判。这个排查思路在文档的《调试与测试》章节里建议用“表格 日志截图”的方式记录下来这不只是解决一个问题更是向答辩老师展示“你具备独立排错能力”的证明。5.2 图片上传失败不能只看报错信息图片上传是第二个高频翻车点。报错通常有两种uploadFile:fail socket timeout和uploadFile:fail url not in domain list。后者比较直白就是域名校验没过。真机调试时不能用开发者工具那个“不校验域名”的开关你必须在小程序后台的“开发管理—服务器域名”里把上传接口的域名加到uploadFile合法域名里而且要求是 HTTPS。这就是为什么很多毕设演示用局域网IP能跑但一上真机就废——因为个人开发不能用 IP 作为合法域名。前者socket timeout通常不是网络问题而是大文件上传时后端没及时响应。比如用户一次性选了9张原图每张可能5-10MB后端如果没有做文件大小限制处理起来就会很慢甚至超时。解决思路前端选图时用sizeType: [compressed]让微信先压缩再上传。后端限制文件大小Spring Boot 里spring.servlet.multipart.max-file-size5MBmax-request-size50MB。前端做并发控制不要一次性9个请求全发出去用队列或Promise.all控制并发的数量一次同时传3张避免把服务端连接打满。这个问题的排查过程我自己当时花了大半天最后才发现是后端没配 multipart 大小限制。这类“文档里不会写”的细节就是调试经验的真正价值。5.3 自定义导航栏在不同机型上的适配很多闲置交易平台的小程序为了好看首页会自定义顶部导航栏而不是用微信默认的。自定义一时爽适配火葬场——iPhone 刘海屏、安卓全面屏、iPad 小程序状态栏高度完全不一样。正确做法是使用微信提供的wx.getWindowInfo()旧版是wx.getSystemInfoSync()获取状态栏高度动态给自定义导航栏留出空间const info wx.getWindowInfo(); this.setData({ statusBarHeight: info.statusBarHeight, navBarHeight: 44 info.statusBarHeight });这段代码建议直接封装在app.js里全局只算一次所有页面都能拿。千万别写死数值不然换台手机就错位。这类细节在《测试报告》里可以作为“兼容性测试”的典型案例写进去有截图、有测试机型报告会充实很多。5.4 本地缓存溢出与页面栈超限小程序wx.setStorageSync单条数据有1MB限制整个缓存总上限是10MB很多源码在存商品详情数据时会把整条详情塞进缓存做所谓“优化”实际上非常容易踩上限。还有页面栈问题小程序页面栈最多10层如果用户从首页不断点进详情、详情里又跳别的商品详情超过10层之后wx.navigateTo会直接失败。正确习惯是推荐流点击进详情用navigateTo但从详情返回列表后再次进入同一详情页考虑用redirectTo或switchTab去做页面栈控制。这些点很细微但都是用户真实使用中一定会遇到的问题也是资深开发者和新手的明显分水岭。6. 文档编写与答辩准备把三件套的价值发挥到最大6.1 文档结构怎么安排才不会被老师挑刺标题里的“文档”两个字很多同学以为就是把代码注释打印出来这是大错特错。毕设文档应该是一套完整的工程化说明一般包含这几部分需求分析系统定位、用户角色、功能需求、非功能需求性能、安全、可用性。概要设计系统架构图、技术选型理由、模块划分、数据库ER图。详细设计每个模块的核心流程、关键接口定义、数据库表结构说明。测试报告功能测试用例表、兼容性测试记录、问题排查记录。部署手册环境要求、启动步骤、常见问题FAQ。我强烈建议文档里“技术选型理由”和“遇到的问题与解决方案”这两个部分不要敷衍这往往是答辩老师最感兴趣的内容。比如你已经踩过的 code 过期、图片上传超时、真机域名校验直接写成“问题现象—排查过程—解决方案”三段式非常有说服力。6.2 先跑通代码再写文档还是先写文档再跑代码我的经验是“代码为先文档同步记录”。完全跑通之后再补文档很多实现细节和踩坑点早就忘了写出来全是套话。比较好的节奏是第一天先把自己当成使用者把完整功能跑一遍同时写一篇简单的“试跑笔记”。然后带着问题去读源码每读通一个模块就在文档里记一个模块的设计和实现。最后统一整理成标准格式的毕设文档。这样做还有一个附带好处你可以把“试跑笔记”写成《日志》形式附在测试报告后显得工作量特别饱满。6.3 答辩演示的演示路径设计答辩现场演示环节通常只有5-10分钟最忌“当场查数据库、当场改代码”。我建议提前设计一条黄金演示路径打开小程序首页信息流秒开证明启动性能正常。从首页搜索“自行车”搜出结果展示分类筛选效果。点进商品详情展示轮播图和联系卖家入口。演示一次收藏操作然后进个人中心展示收藏列表同步更新。最后演示“我发布的”页面展示用户自己发布的商品列表。这条路径走完用户、商品、收藏、个人中心四大模块全部覆盖而且不需要登录态切换。每个动作之间不要停顿太长时间尽量提前演练五遍以上。至于登录模块如果现场演示真机会因为网络问题卡壳甚至可以直接口头说明“登录逻辑已用 Postman 验证通过这里有测试截图”不必强行演示。6.4 几个高频答辩问题提前准备起来结合我带毕业设计的经验这类题目老师大概率会问这几个问题为什么选微信小程序而不是App或H5回答方向低门槛、免安装、社交传播优势、开发维护成本更低。你这个平台和闲鱼有什么区别回答方向聚焦校园/社区场景、轻量化、功能边界明确不做复杂推荐算法。不做在线支付交易闭环怎么保证回答方向定位信息撮合线下沟通与确认成交避免支付资质风险。如果用户量增加你觉得哪个模块性能会先成为瓶颈回答方向商品列表查询和图片存储然后提出使用缓存、云存储、加索引等优化思路。这几个问题不用背标准答案关键是把文档里写过的设计思路用自己的话讲一遍。记住答辩考察的不是代码写得多高级而是“你对这个系统的理解是不是完整的”。7. 关于“调试”这件事我想再多说两句很多人把“调试”单纯理解为“修Bug”但我更愿意把它看作“逐步建立对系统掌控感”的过程。拿到一份源码先让它跑起来再故意制造一个错误再顺着日志把它找出来反复几轮之后你会发现自己对整个项目的理解远超预期。这种能力不只能应付答辩它就是一个合格软件工程师的基本功。如果你也准备做或正在做这个题目的毕设我的建议是不要急着在原文上大改功能先复现它的登录流程再复现商品发布流程等这两条链路都刻进脑子了再去动代码加新功能。很多拿到源码就一顿乱改的同学最终面对的是一堆不知道哪里来的新Bug。另外强烈建议把console.log和后端日志想办法串起来看前端看到一个报错先记下时间再去后端日志里搜同一时间段的记录绝大多数问题几秒钟就能定位。这篇内容覆盖了从选题、架构、功能、跑通、调试到文档撰写的一条龙经验希望能帮你少走一些弯路。如果你在实际操作中遇到这里没写到的新问题不妨停下来先理一理排除链路再决定下一步动哪里。毕竟调试的真功夫一半靠资料另一半靠你自己在日志和代码之间来回穿梭的耐心。