news 2026/10/8 5:54:28

旅游小程序源码落地指南:Spring Boot后端与MySQL联调避坑全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
旅游小程序源码落地指南:Spring Boot后端与MySQL联调避坑全解析

简介:面向计算机专业毕业设计或课程设计场景,这套基于微信小程序的旅游服务软件完整实现了客户端与后端联动。后端采用Java与SSM框架,前端为微信小程序,开发者使用IDEA与微信开发者工具分别导入工程并安装MySQL8.0即可直接运行,无需额外改配置。功能上覆盖旅游攻略、旅游资讯、景点信息、搜索查询、酒店信息、论坛中心、门票预订、酒店预订、推荐路线、用户发帖及用户管理等多个模块,从信息浏览到在线预订形成闭环。资源包共包含22个文件,大小约61.15MB,其中有19张PNG界面截图、2个ZIP源码压缩包以及1个SQL数据库脚本,分别对应效果展示、前后端代码和数据库初始化数据。目前已有2604人学习下载,适合需要快速搭建可演示项目或借鉴模块设计的学生与开发者。

1. 拿到一套旅游小程序源码,先别急着跑前端

很多团队第一次接触带源码的旅游服务小程序项目,都以为最难的是前端页面,实际上手才发现,黑匣子全在后端和数据库。我见过不止一个小组拿到“基于微信小程序旅游服务软件设计与实现(项目源码+数据库文件)后端java开发”这类交付物后,卡在同一个地方:数据库文件导不进去、Java后端启动报错、小程序请求接口连不通——三天没跑出一套能演示的系统。这篇文章就围绕这套交付物讲清楚三件事:后端Java工程怎么落地、数据库文件怎么处理、小程序和后端联调有哪些坑。适合毕业设计、课设团队,也适合第一次接前后端分离小程序外包的开发者;熟悉 Spring Boot 的老手可以直接跳到第 5 章看联调避坑清单。

2. 三端一库:这套旅游服务软件的架构到底怎么拆

“微信小程序旅游服务软件”这个名字听起来像一个完整产品,但拆开看,它其实是三个独立部件:微信小程序前端、Java 后端、MySQL 数据库文件。搞明白这三块怎么协同,后面跑通才有方向。

2.1 交付物里通常躺着三块内容:前端工程、后端工程与数据库文件

按照常见的交付形态,你会拿到一个压缩包或一个 Git 仓库,打开后大致是这个结构:

travel-miniapp/ # 微信小程序前端 ├── pages/ │ ├── index/ # 首页:景区列表、轮播图 │ ├── scenic/ # 景区详情、地图定位 │ ├── order/ # 门票/导游订单 │ └── mine/ # 个人中心、收藏、登录 ├── utils/ # 请求封装、工具函数 ├── app.js / app.json # 小程序入口与全局配置 └── project.config.json # 开发者工具项目配置 travel-server/ # Java 后端(Spring Boot) ├── src/main/java/com/... │ ├── controller/ # REST 接口层 │ ├── service/ # 业务逻辑层 │ ├── mapper/ # MyBatis-Plus 数据访问层 │ ├── entity/ # 实体类 │ ├── config/ # 跨域、拦截器、全局配置 │ └── TravelApplication.java ├── src/main/resources/ │ ├── application.yml # 数据源、端口、MyBatis 配置 │ └── mapper/ # XML 文件(如果走 XML 方式) └── pom.xml travel-db/ └── travel.sql # 数据库脚本:建库建表 + 初始数据

这段目录结构不是某个固定模板,而是这类交付最常见的工程组织。前端和后端是两个独立工程,靠 HTTP 接口通信,这就是所谓的前后端分离项目实战。数据库脚本单独放一个目录,是因为后端启动前必须先把它导进 MySQL,否则一运行就会因为找不到表直接翻车。

2.2 为什么这样选:原生小程序、Spring Boot 与 MySQL 的取舍

先聊技术选型。旅游服务类小程序,前端用原生微信小程序就够了,页面量级一般在十个左右:首页、景区列表、详情、下单、订单列表、个人中心。原生小程序渲染性能好、调试顺手,没有必要在这类项目里引入 uniapp 再做一层打包;如果你未来要把同一套代码发到支付宝小程序,再考虑 uniapp 也不迟。

后端用 Java 和 Spring Boot,是这个行业里最不冒险的选择。Spring Boot 把配置简化了一大截,内嵌 Tomcat,一个 main 方法就能起服务,对“拿到源码要快速跑起来”的场景特别友好。数据访问层常见做法是用 MyBatis-Plus,因为这类项目全是标准的单表增删改查,MyBatis-Plus 的 BaseMapper 直接给你把 insert、update、selectById 都实现好了,少写大量样板代码。

数据库用 MySQL,理由就更直接了:交付的数据库文件绝大多数是 .sql 脚本,换成别的库还得改方言。旅游业务里有地理位置字段,MySQL 的 DECIMAL 存经纬度足够,真的需要按距离排序时再用空间函数也来得及。地图展示一般是在小程序端集成腾讯地图或天地图组件,后端只需要把景区的经纬度字段返回给前端——这是旅游类小程序和普通商城类小程序最不一样的业务点。

2.3 请求链路过一遍:小程序到后端到数据库的调用关系

把三块串起来看,一次完整的“查看景区列表”请求是这样的:

微信小程序页面 ↓ wx.request(携带 token) 后端 Controller 接收请求 ↓ 校验登录态 + 参数 Service 层业务处理 ↓ 调用 Mapper MyBatis-Plus 执行 SQL ↓ MySQL 返回结果 → 逐层封装 → 小程序渲染

为了让这条链路稳定,接口设计上有个约定俗成的规范:所有后端接口统一以 /api 开头,返回体固定为 JSON 结构:

{ "code": 0, "msg": "success", "data": { "list": [], "total": 58 } }

code 为 0 表示业务成功,非 0 表示业务失败;data 里放业务数据。小程序端封装请求时,只需要统一判断 code 就能处理所有成功和失败分支。后端如果用了 Result 泛型类,代码里会经常看到 Result.success(...) 和 Result.error(...),后面第 4 章的接口示例会再展示。

3. 让数据库文件落地:导入SQL脚本与核心表设计拆解

数据库文件是整套系统的地基。很多新手拿到 .sql 文件的第一反应是双击打开、复制粘贴到 Navicat 里执行,结果报错一串。原因通常是字符集不一致或数据库没先创建好。正确处理方式是先建库、再导脚本。

3.1 导入SQL文件:命令行与可视化工具两条路

先在 MySQL 里创建一个空库,再导入 SQL 脚本。命令行方式最省事:

mysql -uroot -p CREATE DATABASE travel_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE travel_db; SOURCE /path/to/travel.sql;

前两步手动完成,关键在于字符集:数据库必须用 utf8mb4。原因很直接,微信小程序用户昵称里带 emoji 是常态,而 emoji 是四字节字符,utf8 存不下,导入或写入时会报Incorrect string value: '\xF0\x9F\x98\x80'...这种错。utf8mb4 是 utf8 的超集,能覆盖四字节字符,排序规则用 utf8mb4_unicode_ci 对中文排序也更合理。

如果你习惯用 Navicat,操作路径是:新建数据库 travel_db,字符集选 utf8mb4,创建完成后右键该库,选择“运行 SQL 文件”,选中 travel.sql 执行。这里有个细节:Navicat 运行 SQL 文件时,如果脚本里已经包含了 CREATE DATABASE 和 USE 语句,你也可以直接在 root 连接上运行整个脚本,但很多交付脚本不写这两句,所以我还是建议先手工建库再导。

3.2 核心表结构拆解:用户、景区、订单、评论怎么建

旅游服务软件的表不会太多,核心就四张:用户表、景区表、订单表、评论表。读懂这几张表,你就读懂了整个系统的业务骨架。下面是简化后的建表结构:

CREATE TABLE `user` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `openid` VARCHAR(64) NOT NULL COMMENT '微信openid,唯一标识', `nickname` VARCHAR(64) DEFAULT NULL COMMENT '昵称', `avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL', `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号', `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_openid` (`openid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; CREATE TABLE `scenic` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `name` VARCHAR(128) NOT NULL COMMENT '景区名称', `cover` VARCHAR(255) DEFAULT NULL COMMENT '封面图URL', `images` TEXT COMMENT '详情图片,JSON数组或逗号分隔', `description` TEXT COMMENT '景区介绍', `address` VARCHAR(255) DEFAULT NULL COMMENT '地址', `latitude` DECIMAL(10,7) DEFAULT NULL COMMENT '纬度', `longitude` DECIMAL(10,7) DEFAULT NULL COMMENT '经度', `price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '门票价格', `stock` INT DEFAULT 0 COMMENT '当日剩余票数', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='景区表'; CREATE TABLE `orders` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `order_no` VARCHAR(32) NOT NULL COMMENT '订单编号', `user_id` BIGINT NOT NULL COMMENT '下单用户ID', `scenic_id` BIGINT NOT NULL COMMENT '景区ID', `quantity` INT DEFAULT 1 COMMENT '购买数量', `total_amount` DECIMAL(10,2) DEFAULT 0.00 COMMENT '订单金额', `status` TINYINT DEFAULT 0 COMMENT '0待支付 1已支付 2已取消', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间', PRIMARY KEY (`id`), KEY `idx_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; CREATE TABLE `comment` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `user_id` BIGINT NOT NULL, `scenic_id` BIGINT NOT NULL, `content` VARCHAR(500) DEFAULT NULL, `rating` TINYINT DEFAULT 5 COMMENT '1-5星', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_scenic_id` (`scenic_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论表';

注意几个设计细节。openid 是微信用户的唯一标识,每次 wx.login 都会返回同一个 openid,用它做唯一键能防止同一个用户重复注册。订单表特意加了订单号 order_no,而不是直接用自增 id,因为订单号要暴露给用户和小程序,用时间戳加随机数生成的业务编号,既安全又方便对账。景区表里 images 用 TEXT 存 JSON 字符串,是这类项目的常见做法——小程序端解析 JSON 数组即可,没必要为图片列表单独建一张表。

经纬度用 DECIMAL(10,7),可以精确到小数点后 7 位,大约厘米级精度,对景区定位绰绰有余。price 用 DECIMAL(10,2) 而不是 FLOAT,是因为浮点数在金额计算上会有精度丢失,这是做支付相关表时的基本要求。

3.3 初始数据与开发态账号:导入后先做这三步验证

SQL 脚本里除了建表语句,一般还会带一批 INSERT 初始数据,这是让项目“开箱即演示”的关键。导入完成后,别急着启动后端,先执行三条验证语句:

USE travel_db; SHOW TABLES; SELECT COUNT(*) FROM scenic; SELECT id, nickname, phone FROM user LIMIT 5;

SHOW TABLES 确认四张核心表都建出来了;COUNT(*) 看景区表有没有数据,如果返回 0,说明脚本里没附初始数据,后端接口能通但页面是空的;查 user 表是为了确认手机号字段结构对不对,方便后面调试登录。

这里最容易忽视的是开发态账号。交付的脚本里通常会有一个或多个测试用户,openid 是类似test_openid_001的占位字符串。为什么要这样设计?因为真用户必须在微信开发者工具里通过 wx.login 才能拿到真实 openid。开发阶段你写的 SQL 查询、手工构造的订单数据,都得挂在一个固定的 openid 下,才能用测试账号在小程序里看到效果。

4. 后端Java工程:从配置启动到接口跑通的完整链路

数据库就绪后,接下来把 Java 后端跑起来。这一章我会按环境准备、配置文件、接口实现三个层面讲,每一层都有具体的操作步骤和失败时的观察点。

4.1 环境准备:JDK、Maven、IDEA 与 Lombok 插件

后端工程是 Maven 项目,环境要求一般是 JDK 8 或 11,Maven 3.6 以上。如果前一个人用的是 JDK 8 开发的,而你本机装了 JDK 17,最好在 IDEA 里把 Project SDK 切到 8 或 11,避免编译报错。这里的 java 基础问题经常会卡住新手:Spring Boot 版本和 JDK 版本有对应关系,老版本的 Spring Boot 2.x 在 JDK 17 下运行会有兼容隐患。

还有一个高频翻车点:工程里用了 Lombok。交付源码里实体类常见这样的写法:

@Data public class User { private Long id; private String openid; private String nickname; }

@Data 注解会在编译时自动生成 getter、setter、toString,但如果 IDEA 没装 Lombok 插件,编译会直接报“找不到符号 getNickname()”之类的错误。这不是代码问题,是环境问题。装好插件后,还要在 IDEA 设置里开启 Annotation Processing,否则插件不生效。我一般拿到工程第一件事就是确认这两个设置,能省半小时的无谓排查。

4.2 配置application.yml:数据源、端口与MyBatis-Plus

后端启动前必须改对配置文件。打开 src/main/resources/application.yml,核心内容长这样:

server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/travel_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml configuration: map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0

大概需要改三处:端口、数据库账号密码、时区参数。serverTimezone=Asia/Shanghai 必须有,MySQL 8 驱动默认要求显式时区,不加会报The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized。driver-class-name 用 com.mysql.cj.jdbc.Driver,这是 8.x 驱动的类名;老版本驱动类是 com.mysql.jdbc.Driver,如果工程的 pom.xml 里引的是 mysql-connector-java 8.x,却写了老驱动名,启动时同样会失败。

mybatis-plus.map-underscore-to-camel-case 这个配置是 MyBatis-Plus 自动把数据库的 create_time 映射成 Java 属性 createTime,必须设成 true,否则第 5 章会讲到字段全为 null 的坑。

启动方式是标准的两种:IDEA 里直接运行 TravelApplication 的 main 方法,或者命令行执行:

mvn spring-boot:run

看到Started TravelApplication in x.xx seconds就说明启动成功。启动失败的日志里如果出现Access denied for user 'root'@'localhost',就是账号密码配错了;出现Unknown database 'travel_db',说明第 3 章的建库步骤没有执行。

4.3 接口分层与小程序请求封装:REST规范落地

后端工程按 Controller、Service、Mapper 三层分包。拿景区列表接口做例子,Controller 层长这样:

@RestController @RequestMapping("/api/scenic") public class ScenicController { private final ScenicService scenicService; public ScenicController(ScenicService scenicService) { this.scenicService = scenicService; } @GetMapping("/list") public Result<IPage<Scenic>> list(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size) { return Result.success(scenicService.pageList(page, size)); } @GetMapping("/{id}") public Result<Scenic> detail(@PathVariable Long id) { return Result.success(scenicService.getById(id)); } }

这里用构造器注入而非 @Autowired 字段注入,是 Spring 官方推荐的方式,好处是依赖关系清晰,测试时可以直接 new 一个 Controller 传入 mock Service。分页参数 page 和 size 都有默认值,防止前端没传参时接口报 NPE。返回类型统一用 Result ,这个类在工程里的 common 包下,通常包含 code、msg、data 三个字段,它的静态方法 success 和 error 负责封装统一返回结构。

Service 层和 Mapper 层在 MyBatis-Plus 下非常薄,往往就是继承一个 ServiceImpl:

@Service public class ScenicServiceImpl extends ServiceImpl<ScenicMapper, Scenic> implements ScenicService { public IPage<Scenic> pageList(Integer page, Integer size) { return this.page(new Page<>(page, size)); } }

小程序端对应的请求封装,是所有页面共用的工具:

const BASE_URL = 'http://localhost:8080/api'; function request(path, method = 'GET', data = {}) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + path, method, data, header: { 'Content-Type': 'application/json' }, success: (res) => { if (res.data.code === 0) { resolve(res.data.data); } else { wx.showToast({ title: res.data.msg, icon: 'none' }); reject(res.data); } }, fail: (err) => reject(err) }); }); } module.exports = { request };

这段封装把“业务失败”和“网络失败”做了区分:code 不等于 0 时弹 toast,reject 出去;网络不通时走 fail 回调。页面里调用时就只管拿数据,不用每个页面都写 toast 逻辑。BASE_URL 是联调时最常改的地方:本地跑后端就写 localhost,真机调试要换成电脑的局域网 IP,上线后换 HTTPS 域名。后面第 5 章会细说这个切换的坑。

5. 联调与部署避坑:后端Java和小程序对接的5个常见问题

这一章写的都是我见过无数次的现场翻车。每条都按“现象 → 原因 → 解决”来讲,你对照着排查就行。

5.1 真机预览连不上后端:localhost 的幻觉

现象:微信开发者工具里请求接口一切正常,一到真机预览,所有列表加载不出来,Network 面板显示请求超时。

原因:小程序开发者工具运行时,localhost 指向的是你的电脑;真机上 localhost 指向的是手机自己。手机根本访问不到电脑上的 8080 端口。

解决:把 BASE_URL 里的 localhost 换成电脑的局域网 IP,比如http://192.168.1.5:8080/api,并保证手机和电脑连同一个 WiFi。另外,在开发者工具的“详情 → 本地设置”里勾选“不校验合法域名、web-view(业务域名)”,这是调试阶段必备选项,否则连 localhost 也会被拦。这里需要提醒:这个勾选只用于本地开发和真机调试,上线版本必须去掉。体验版和正式版要求所有请求域名在微信公众平台配置为合法域名且走 HTTPS,这是微信的强制规则,逃不掉。真机预览时如果手机浏览器能打开http://192.168.1.5:8080/api/scenic/list但小程序里不通,九成是 WiFi 隔离或防火墙挡了端口。

5.2 数据库连接启动报错:时区与驱动名

现象:后端启动,控制台抛Cannot create PoolableConnectionException,Caused by 里有一行时区相关的错误,或者ClassNotFoundException: com.mysql.jdbc.Driver。

原因:MySQL 连接串里没带 serverTimezone,或者驱动类名和依赖版本不匹配。MySQL 8.x 驱动强制要求时区,老驱动类名在新驱动里已经被移除了。

解决:照抄第 4.2 节的配置,url 末尾加上serverTimezone=Asia/Shanghai,驱动类名换成com.mysql.cj.jdbc.Driver。如果还报Public Key Retrieval is not allowed,在 url 里追加allowPublicKeyRetrieval=true即可,这是 MySQL 8 使用 caching_sha2_password 认证时的已知行为。

5.3 接口通了但字段全空:驼峰映射没开

现象:调用景区列表接口,HTTP 200 返回了,但每条记录的 createTime、userName 这类多单词字段全是 null,单单词字段正常。

原因:数据库字段是下划线风格 create_time,Java 实体是驼峰风格 createTime,MyBatis 默认不自动转换,需要开启 map-underscore-to-camel-case。

解决:确认 application.yml 里mybatis-plus.configuration.map-underscore-to-camel-case: true。如果配置没问题,再检查实体类字段上有没有 @TableField 注解覆盖了映射规则。还有一种隐蔽情况:实体类用了 @Data 但字段名拼写和数据库不一致,比如数据库是 scenic_id,Java 写了 scencId,这种只能靠人工逐个核对。

5.4 登录与手机号获取:token 会话的两个坑

现象:小程序端登录成功后,过一会儿再请求接口就报“未登录”;或者 getUserInfo 能拿到昵称头像,但 wx.getPhoneNumber 换手机号时后端一直报解密失败。

原因:很多简单项目没有做 token 机制,每次请求只传 openid;而手机号获取依赖 session_key,session_key 在每次 wx.login 之后会失效。如果你先调了 wx.login 又调 wx.getPhoneNumber,两次登录会刷新 session_key,后端拿旧的 session_key 解密手机号必然失败。

解决:登录流程按下面这条路走。首先用 wx.login 拿 code,后端拿着 code 去微信接口换 openid 和 session_key;接着后端生成自己的 token(比如 UUID)存到 Redis 或数据库,并把这个 token 返回给小程序;小程序把 token 存进 storage,后续所有请求在 header 里带Authorization: token。后端通过拦截器校验 token,而不是每次拿 openid 现查。这样既避免频繁查库,也让会话过期可控。

wx.getPhoneNumber 的正确调用姿势,是在用户点击“手机号快速验证”按钮时把按钮上的 code 传给后端,后端用当前会话的 session_key 解密。千万别在调 wx.login 之后再取手机号,这是血泪经验。项目代码里如果用的是“先 wx.login 再 getPhoneNumber”的错误顺序,那就得改掉。

5.5 上线后白屏与图片加载失败:域名校验与 HTTPS

现象:本地演示一切都好,提交体验版之后,页面白屏,或者景区图片全部裂开。

原因:两个问题叠加。白屏通常是请求被微信拦截——wx.request、wx.uploadFile 等接口的域名必须在微信公众平台配置为合法域名,且必须是 HTTPS。图片裂开是第二个问题:如果图片地址是 http 或者 IP 地址,小程序同样会拒绝加载。

解决:正规做法是准备一个已备案的域名,配好 SSL 证书,然后通过 Nginx 把/路径请求转发到后端的 8080 端口。很多树莓派和国内服务器用户直接用宝塔面板操作,面板里配站点、装 SSL、做转发都可视化了,比手写 Nginx 配置省事不少。后端自身的跨域配置也要检查:Spring Boot 里写一个 WebMvcConfigurer 的 CORS 配置,允许https://你的域名来源,否则浏览器环境里调试 H5 页面时会报跨域错误——小程序本身没有跨域限制,但如果这个系统以后要加管理后台网页端,跨域配置就得提前留好。

6. 从能跑到能交付:接口自测清单与上线检查项

系统在本地能跑通,离“能交付”还有距离。我的习惯是,打开小程序之前,先做一轮纯后端自测。

6.1 先别打开小程序:Postman 接口自测清单

按业务主流程列一份接口自测顺序:获取景区列表、查看景区详情、登录换 token、创建订单、查询订单列表、发表评论、查看评论列表。每测一个接口,同时看两处:响应码是否 0,data 里关键字段是否完整。发现字段为 null 或列表为空,优先查数据库数据和 mapper 映射,别急着改小程序端。Postman 里可以先把 token 存在环境变量里,这样测订单、评论这类需要鉴权的接口时,不用每次手动填 Authorization 头。

6.2 自定义导航栏适配:顶部导航栏高度动态计算

旅游类小程序首页喜欢做沉浸式头部,把景区大图延伸到导航栏底下,这就涉及自定义导航栏。这里的经典坑是:不同机型顶部安全区高度不一样,刘海屏和普通屏差了 20 多个像素。常见做法是在小程序启动时读取胶囊按钮位置,动态计算导航栏高度:

const menu = wx.getMenuButtonBoundingClientRect(); const statusBarHeight = wx.getSystemInfoSync().statusBarHeight; const navBarHeight = (menu.top - statusBarHeight) * 2 + menu.height;

这段代码把状态栏高度和胶囊按钮位置结合起来,得出来的 navBarHeight 就是自定义导航栏的实际高度。写死在样式里只能适配你手头那台测试机,一换 iPhone 14 Pro 就露馅。放在全局 app.js 或者独立工具文件里,所有页面都能复用。

顺着这个思路,交付前最后做一遍这三件事:换一台不是自己日常用的手机跑真机预览;关掉开发者工具的“不校验合法域名”选项模拟体验版环境;把数据库里的测试账号密码改成空白并输入你自己的账号密码,确认别人拿到源码后能在 10 分钟内按 README 跑起来。我自己的习惯是每次交付都把 README 里的启动步骤从零执行一遍,专治“我机器上能跑”的玄学问题。这套流程走下来,希望你少踩我当年踩过的坑,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 5:53:30

多厂商AI额度查询工具:一站式管理智谱、OpenCode Go、火山方舟、阿里Token Plan、DeepSeek官方额度,TaoToken统一Key接入实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 5:53:27

用Trae编辑器写一个Trae的AI对话记录导出脚本:把settings改到TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 5:52:09

换季的时候车子要做检查吗?按流程一步步来

换季的时候车子需要做检查&#xff0c;但项目应当按季节变化筛选&#xff0c;不必做全车大项。温度与湿度交替变化时&#xff0c;影响最直接的是制动系统、轮胎状态与电气系统的稳定性&#xff1b;其余项目按里程和上次施工时间判断即可。宁波博捷汽车在季节交替前后接待的检测…

作者头像 李华