首页 / 资讯中心 / 文章详情

Java+小程序+MySQL健康管理系统:从部署到联调实战

Java+小程序+MySQL健康管理系统:从部署到联调实战 ★ FEATURED ARTICLE
简介这是一套面向高校学生以及初、中级开发者的个人健康管理系统小程序完整源码涵盖Java后端、微信小程序前端与MySQL数据库适合用于毕业设计或课程设计。项目实现了个人健康信息的展示、增删改查及基础服务逻辑前后端代码与数据库脚本齐全配合环境说明即可在Eclipse/IDEA、Tomcat7及微信开发者工具中部署运行。资源包共包含1569个文件压缩后约35.62MB核心类型包括Java源码、Vue页面、小程序wxml/wxss、JS/JSON配置、SQL数据库脚本及docx/doc说明文档文件类型覆盖前后端开发各环节。目前已有199人学习下载适合需要完整参考项目的小程序开发与Java后端学习者。通过阅读该项目可掌握前后端协同开发、数据库表结构设计、小程序页面搭建等技能配套的部署文档和表结构说明有助于快速复现并理解项目架构是一份实用且可扩展的学习资料。1. 拆开这套 java小程序mysql 源码先认清目录结构和数据流向如果手里刚拿到《基于小程序的个人健康管理系统小程序源代码java小程序mysqlLW.zip》第一反应多半不是去看代码而是担心源码缺文档、数据库没脚本、跑不起来。这类压缩包在毕设和公司内部项目里都很常见结构通常是三份东西微信小程序端负责录入和展示java 后端一般用 Spring Boot 提供接口MySQL 存用户档案、运动记录和饮食数据LW 则是配套的论文/设计说明里面通常有 ER 图和用例图部署前先翻它能少走很多弯路。这套系统的核心价值是把个人体重、运动、饮食、睡眠这些零散健康数据收拢成可查询、可趋势分析的记录适合正准备交毕设的学生也适合用小程序做健康类 MVP 后端的 Java 工程师。下面从数据库和后端开始讲因为小程序能不能打开数据完全取决于前两步有没有对齐。2. 搭建开发环境MySQL 5.7 初始化与 Spring Boot 后端的启动命令2.1 先把 MySQL 装好5.7 还是 8.0初始化脚本怎么执行个人健康管理系统最大的坑往往不在代码而在刚开始的 MySQL 环境。很多毕业设计源码下载包里的 sql 是用 MySQL 5.7 导出的而你现在电脑上装的可能是 MySQL 8.0。这两者在默认认证插件上不兼容5.7 默认 mysql_native_password8.0 默认 caching_sha2_password老版 mysql-connector-java 连 8.0 会直接报 Public Key Retrieval is not allowed。所以我建议先统一到 5.7除非你愿意把驱动升级到 8.0.33。不管用哪个版本都是先建库、再导入脚本。假设源码根目录下带了一个 health.sql最稳妥的导入方式是mysql -uroot -p CREATE DATABASE IF NOT EXISTS health DEFAULT CHARACTER SET utf8mb4; USE health; SOURCE /path/to/health.sql; SHOW TABLES;这里SOURCE是 MySQL 命令行自带指令适合导入中等体量的 .sql比用 Navicat 可视化导入更不容易出现编码问题。一定要把库字符集指定成utf8mb4因为有些用户会在小程序里填写带表情的健康备注例如“今天跑了 5km”如果表是 latin1 或 utf8这些表情会变成问号。SHOW TABLES用来确认表是否导入成功正常会看到 user、health_record、diet_record 之类的表。如果导入时提示Unknown database说明没有先USE health如果提示Duplicate entry说明你之前导过一次可以先DROP TABLE相关表再重新导入。这里有个技巧导入前先看一眼 health.sql 开头有没有CREATE DATABASE有些脚本会自带建库语句这时不要重复建库直接source /path/to/health.sql即可。提示Linux 服务器上用 rpm 方式装 MySQL 时记得先初始化/var/lib/mysql目录权限否则 mysqld 起不来。Windows 上装 5.7 则要注意安装包是否自动创建了 Windows 服务没创建的话后面连接会报Access denied。2.2 配置 Spring Boot 数据源application.yml 里的 5 个必调参数后端是 java 工程常见是 Spring Boot Maven。启动前要改的 core 文件是src/main/resources/application.yml。我给一个最小可用的配置server: port: 8080 address: 0.0.0.0 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/health?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: Asia/Shanghai mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true这里真正需要动的是 5 个位置server.port是小程序要对接的接口端口一般 8080 不用改server.address必须写成0.0.0.0否则真机调试时手机访问不到url里的127.0.0.1:3306/health对应 MySQL 地址和库名username/password改成你自己的 MySQL 账号密码driver-class-name要跟 mysql-connector-java 版本一致8.x 用com.mysql.cj.jdbc.Driver5.x 用com.mysql.jdbc.Driver。如果出现加载不到驱动直接去 pom.xml 看版本。url 里那段参数每次都不能少useUnicodetruecharacterEncodingutf8解决中文乱码useSSLfalse避免本地调试时的证书警告serverTimezoneAsia/Shanghai解决日期和时间差八小时的问题。jackson.date-format是给前端返回时间的格式后端开发里常纠结这里不配的话体重表里的record_date可能序列化成2025-06-01T00:00:00.00000:00小程序解析时很别扭。配置完之后在启动类上确认有没有MapperScan(com.xxx.health.mapper)或者每个 Mapper 接口上有没有Mapper。这两个缺一个启动时就会报Invalid bound statement (not found)。2.3 启动后端Maven 打包与 java -jar 的最小命令调整完配置就可以构建了。cd 后端目录 mvn clean package -DskipTests java -jar target/*.jar-DskipTests表示跳过单元测试避免因为测试类里连不上测试库而构建失败。打包后target/*.jar在 Linux 和 Mac 下会自动展开成实际构建出来的 jar 包Windows PowerShell 不支持*通配符需要换成target下真实的 jar 文件名。如果你的电脑没装 Maven也可以直接在 IDEA 里运行启动类的main方法效果一样。第一次构建会下载大量依赖等日志里出现BUILD SUCCESS再看下一步。后端启动成功的标志是日志里出现Tomcat started on port 8080或者你能访问到http://localhost:8080/下的某个接口。很多源码会提供一个健康检查接口比如/api/health/check用 curl 验证最快curl http://localhost:8080/api/health/check如果返回 JSON 而不是 404说明 Spring Boot 已经起来了。此时再打开 LW 里的数据库设计章节对照表结构确认接口用的表名和你导入的脚本一致。个人健康管理系统的数据一般围绕 user、health_record、exercise_record 展开如果发现有的表在脚本里没有就按 LW 的 ER 图补建这是常见操作。3. 小程序端登录与健康数据接口wx.request 请求链路与手机号登录3.1 开发期先绕过合法域名为什么小程序会连不上本地后端微信小程序对wx.request的域名要求是必须是 HTTPS、且在小程序后台配置的合法域名。本地开发时后端是 HTTP所以开发者工具默认会拦截所有请求页面数据加载不出来报url not in domain list。这时要去开发者工具右上角「详情」-「本地设置」勾选「不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书」。勾选后还要注意开发者工具里用 localhost 能通真机预览不通。原因很简单手机上的小程序不能把localhost理解为你电脑它只知道自己的回环地址。你需要把BASE_URL改成你电脑的局域网 IP比如http://192.168.1.100:8080。同时第 2 章里server.address: 0.0.0.0就是为这一步准备的否则后端只监听 127.0.0.1局域网 IP 就连不上。这里有一个容易被忽略的细节微信开发者工具默认模拟器能访问宿主机 localhost但 Android 真机预览时部分源代码里写死的http://localhost:8080不会跟着环境变化。遇到这种问题全局搜一下代码里的localhost和127.0.0.1改成常量BASE_URL。提示开发者工具勾选“不校验合法域名”只对工具内模拟器生效真机预览依然会校验域名。真正要零门槛联调可以用“真机调试”方式前提是代码里配的也是局域网地址生产环境则必须用 HTTPS 域名。3.2 微信小程序登录获取手机号wx.login 与 getPhoneNumber 的配合个人健康管理系统一般要先登录才能把健康记录关联到用户。最常用的做法是用户打开小程序用wx.login拿到临时 code后端拿 code 去微信的jscode2session接口换 openid然后返回一个自定义 token 给小程序端。这个 token 以后每个接口都带着用来识别“你是谁”。下面这段是登录流程的最小实现const login () { return new Promise((resolve, reject) { wx.login({ success: async (res) { if (!res.code) return reject(res) const { data } await new Promise((r, j) { wx.request({ url: http://192.168.1.100:8080/api/user/login, method: POST, data: { code: res.code }, header: { Content-Type: application/json }, success: r, fail: j }) }) if (data.code 0) { wx.setStorageSync(token, data.data.token) resolve(data.data) } else { reject(data) } } }) }) }这段代码的逻辑是先调wx.login拿到 code再从后端换 token。之所以不用wx.getUserProfile拿头像昵称因为健康记录只需要知道用户身份头像昵称可以后面在“个人档案”页补甚至后端直接给默认昵称。这里的code是一次性的后端换到 openid 之后会失效所以不要在业务页面里重复调wx.login。如果你需要手机号登录现在微信的推荐做法是button open-typegetPhoneNumber把手机号授权给小程序。按钮回调里拿到的e.detail.code不是手机号本身而是后端换手机号的一次性凭证button open-typegetPhoneNumber bindgetphonenumberonGetPhoneNumber手机号登录/buttonasync onGetPhoneNumber(e) { if (e.detail.errMsg ! getPhoneNumber:ok) return const res await request(/api/user/phone, POST, { code: e.detail.code }) if (res.code 0) { this.setData({ hasPhone: true }) } }后端拿这个 code 后需要调用微信服务端接口phonenumber.getPhoneNumber换取真实手机号这个过程是服务端到服务端的不要在客户端做。AppSecret 一旦塞进小程序代码就等于把钥匙交给了别人。关于这里的细节可以将“微信小程序登录获取手机号”作为关键词去翻官方更新日志最新规则以你开发时的官方文档为准。3.3 封装 wx.request把 token 注入到每个健康数据接口登录之后健康记录、趋势查询、修改个人资料都要在请求头里带上 token。如果不做封装每个页面都要写一遍Authorization很容易漏。我一般会建一个utils/request.jsconst BASE_URL http://192.168.1.100:8080 const request (path, method, data) { return new Promise((resolve, reject) { wx.request({ url: ${BASE_URL}${path}, method, data, header: { Content-Type: application/json, Authorization: Bearer ${wx.getStorageSync(token) || } }, success(res) { if (res.statusCode 401) { wx.removeStorageSync(token) wx.navigateTo({ url: /pages/login/login }) return reject(res) } resolve(res.data) }, fail(err) { wx.showToast({ title: 网络异常, icon: none }) reject(err) } }) }) } module.exports { request }这个封装把BASE_URL作为唯一需要改的地方页面里调request(/api/health/record, POST, { ... })就能写数据。关键在Authorization: Bearer ...后端拿到后解析出 userId再执行后续的插入或查询。如果后端不支持 Bearer 前缀就按源码里约定的 key 来例如X-Token: ...但大多数 Spring Boot 拦截器都认Bearer。封装完以后可以先在首页模拟一次体重记录插入然后去 MySQL 里查一下是否写进去了。如果返回正常但数据库没数据大概率是事务没提交检查 Service 方法上有没有Transactional。4. 健康数据的 MySQL 表设计与 SQL 写法让趋势统计不拖慢页面4.1 先定表结构用户表、健康记录表和扩展表个人健康管理系统听起来功能多但核心就几条记录个人基本资料记录每天体重/运动/饮食/睡眠按时间维度看趋势。后端建议不要一上来就搞 20 张表先围绕 3 张主表设计user、health_record、exercise_record。diet 可以和 health_record 合并字段或者用一张可扩展的 detail 表。用户表最简单CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT, openid varchar(64) NOT NULL, nickname varchar(50) DEFAULT NULL, phone varchar(20) DEFAULT NULL, height_cm decimal(5,1) DEFAULT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_openid (openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;用户表的openid必须唯一这是微信身份的唯一标识。height_cm放在用户表而不是健康记录表因为它不经常变化BMI 计算要同时用到身高和体重体重在记录表身高在用户表后端查询时做一次关联即可。注意这里没有物理外键只保留逻辑上的 user_id原因是不想让每次插入都触发外键检查也方便以后分表。健康记录表是整套系统的核心推荐这样建CREATE TABLE health_record ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, record_date date NOT NULL, weight_kg decimal(4,1) DEFAULT NULL, steps_count int(11) DEFAULT NULL, exercise_minutes int(11) DEFAULT NULL, diet_type varchar(20) DEFAULT NULL, sleep_hours decimal(3,1) DEFAULT NULL, bmi_value decimal(4,1) DEFAULT NULL, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_date (user_id, record_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;record_date是业务日期不是create_time。两者分开的目的是用户可以补录昨天甚至上周的数据如果统一用创建时间趋势图就会乱。idx_user_date是查询最关键的索引后面所有“按用户按时间范围”的查询都会走它。diet_type可以用字符串比如breakfast/lunch/dinner/snack也可以在客户端做中文映射避免把“早餐午餐”这种中文字面量直接存进数据库给后续统计带来编码和一致性问题。如果你需要记录运动详情比如跑步、骑行、游泳可以把运动时长和运动类型放进exercise_record表通过user_id record_date和主表关联。我见过一些实现把大量字段塞进一张宽表最后查是快了但动态表单扩展时很痛苦。个人健康管理系统建议用“核心宽表 少量扩展表”的组合别过度设计。4.2 按日期统计的 SQL 写法DATE_FORMAT 与 GROUP BY健康系统的高频页面是“趋势”比如近 7 天体重曲线、每月总步数。小程序端要的数据不是明细而是按日或按月聚合后的值。最常用的汇总 SQL 是这样SELECT record_date, weight_kg, steps_count FROM health_record WHERE user_id #{userId} AND record_date BETWEEN #{startDate} AND #{endDate} ORDER BY record_date ASC;这个查询直接返回某段时间内每天的体重和步数前端拿数组去画折线图。BETWEEN ... AND ...是闭区间所以在传入结束日期时要么传2025-06-30要么传2025-07-01然后改用。我在源码里见过的是用BETWEEN那么日期格式化就很重要容易出现“最后一天少一条”的假数据问题。如果做月度汇总要用到DATE_FORMAT和GROUP BYSELECT DATE_FORMAT(record_date, %Y-%m) AS month, AVG(weight_kg) AS avg_weight, SUM(steps_count) AS total_steps, MAX(record_date) AS last_record_day FROM health_record WHERE user_id #{userId} AND record_date #{startDate} GROUP BY DATE_FORMAT(record_date, %Y-%m) ORDER BY month ASC;DATE_FORMAT(record_date, %Y-%m)把日期变成本月字符串比如2025-06AVG(weight_kg)取当月平均体重SUM(steps_count)汇总当月总步数。ORDER BY month ASC保证月份从早到晚返回否则前端拿到乱序月份画出来的曲线就是乱的。这里有一个容易误用的点不要为了“month”好看就在WHERE里写DATE_FORMAT(record_date, %Y-%m) 2025-06这会让索引失效正确写法是record_date 2025-06-01 AND record_date 2025-07-01。提示这里#{userId}是 MyBatis 的占位符如果你用的是 JPA就改成?占位参数SQL 本身不变。很多源码里会混用排查时要清楚自己工程用的是哪套。4.3 让趋势接口变快的两个 MySQL 技巧索引与排序健康管理系统上线后用户多的场景下趋势接口最容易慢。慢的原因不是 SQL 多难而是全表扫描和排序。技巧一是联合索引(user_id, record_date)已经建在表上了。这个索引能同时覆盖 WHERE 条件和 ORDER BY 排序让查询免去 filesort。你可以用EXPLAIN验证EXPLAIN SELECT record_date, weight_kg FROM health_record WHERE user_id 1 AND record_date BETWEEN 2025-06-01 AND 2025-06-30 ORDER BY record_date ASC;看执行计划里的key是不是idx_user_dateExtra是不是Using index condition如果出现Using temporary; Using filesort说明排序没有完全走索引。常见原因是排序字段和索引顺序不一致或者查询里 SELECT 了索引之外的字段导致回表。对单表几万条记录来说问题不大但如果页面卡顿优先看这里。技巧二是排序字段保持一致。我见过一个翻车写法先GROUP BY record_date再ORDER BY record_date DESC然后在 SELECT 里没有带record_date本身。MySQL 5.7 里这条 SQL 的排序结果会不稳定特别是月份边界。解决办法是让ORDER BY和GROUP BY字段一致或者用聚合函数比如ORDER BY MIN(record_date) DESC。另外小程序端要做的是分页加载而不是一次拉半年数据。接口设计里建议带page和pageSizeSQL 加LIMIT #{offset}, #{pageSize}。健康趋势图如果只需要最近 30 天后端接口直接限制最多返回 90 条避免用户在弱网环境等太久。5. 联调避坑记录健康管理系统最常见的 5 个翻车点这些坑是我照着这种 java小程序mysql 源码复现时最常见的每个都按现象、原因、解决说清楚。5.1 后端启动报 Access denied问题不在代码在 MySQL 用户权限现象Spring Boot 启动日志反复报Access denied for user rootlocalhost或者Communications link failure。原因密码不匹配最常见第二多的是 MySQL 8.0 默认认证插件 caching_sha2_password而源码里的 mysql-connector-java 还是 5.x。解决先确认 application.yml 里 password 是否和数据库一致再用本机命令行试mysql -uroot -p。如果确实要兼容老驱动把认证改回 mysql_native_passwordALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456; FLUSH PRIVILEGES;如果是 MySQL 8.0也可以升级 pom.xml 里的 mysql-connector-java 到 8.0.33并在 JDBC url 加allowPublicKeyRetrievaltrue。两种办法选一个别同时在两处改否则会自我怀疑。5.2 中文乱码数据能写进去但显示是问号现象小程序录入了“今天跑步 5 公里”小程序显示正常后端的日志也没乱但用 MySQL 查出来成了???。原因数据库或表字符集不是 utf8mb4连接串没带characterEncodingutf8也有可能是导入 SQL 时建表语句里的 CHARSET 被覆盖成 latin1。解决建库时强制DEFAULT CHARACTER SET utf8mb4连接串带useUnicodetruecharacterEncodingutf8已经写坏的数据只能先清掉再改表字符集ALTER TABLE health_record CONVERT TO CHARACTER SET utf8mb4;注意utf8mb4是 MySQL 字符集JDBC 参数写utf8就行不必写成utf8mb4因为 Java 侧的 encoding 概念和 MySQL 字符集不完全一致。改完之后重新插入再查一次如果还乱就看 health.sql 里建表语句是否写了DEFAULT CHARSETutf8mb4有些老脚本是DEFAULT CHARSETutf8需要手动改。5.3 真机预览连不上后端小程序报了 500日志却是“连接被拒绝”现象开发者工具里所有接口正常点击“真机调试”后请求全部失败Network 面板显示-1或 timeout后端日志一点请求都没有。原因真机访问不了localhost:8080源码里 BASE_URL 写的是 localhost后端也只听 127.0.0.1。解决后端application.yml里server.address: 0.0.0.0小程序端把 BASE_URL 改成电脑局域网 IP比如http://192.168.1.100:8080保证手机和电脑连的是同一个路由器网络。如果改完还不通关掉电脑防火墙再试或者在防火墙入站规则里放行 8080 端口。这一步完成后先用手机浏览器访问一下http://192.168.1.100:8080/api/health/check能通再回小程序能快速区分是网络问题还是小程序问题。5.4 趋势接口数据顺序乱套GROUP BY 之后 ORDER BY 失效现象小程序健康趋势页返回的月份是2025-03、2025-01、2025-02折线图开了一个大回环。原因SQL 里GROUP BY DATE_FORMAT(record_date, %Y-%m)然后ORDER BY record_date但record_date不在分组字段中MySQL 5.7 不会对这个排序做保证产生的临时表顺序不稳定。解决排序字段和分组字段保持一致。用别名排序SELECT DATE_FORMAT(record_date, %Y-%m) AS month, ... GROUP BY month ORDER BY month ASC;MySQL 8.0 里ORDER BY month是对别名的引用不会报错MySQL 5.7 里也可以这么写。如果你要在分组结果里取最早日期就写ORDER BY MIN(record_date)不要直接ORDER BY record_date。这算是 mysql 排序里很典型的一个坑接口层看不出只有画图才暴露。5.5 Docker 装 MySQL 失败端口占用和挂载目录权限现象照着docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 mysql:5.7执行容器秒退或者宿主机访问 3306 被拒绝。原因第一种是 3306 端口已经被本机 MySQL 或其他容器占用第二种是挂载目录没有权限mysqld 初始化失败第三种是没指定-e MYSQL_ROOT_PASSWORD容器直接退出。解决先docker ps -a看所有容器有残留的docker rm -f掉换用-p 3307:3306把宿主机端口改成 3307后端 JDBC url 也改成3307想用自动删除就用--rm。如果使用挂载目录-v $PWD/mysql-data:/var/lib/mysql之前先chmod -R 777 mysql-data或者直接改用命名卷-v mysql-data:/var/lib/mysql避免权限问题。用 Docker 跑 MySQL 不是必须的本地装一个 5.7 更简单很多人在这个阶段卡住后面就放弃了。6. 发布前的进阶自查用 Charles 抓包微信小程序验证接口和敏感数据6.1 用 Charles 抓包微信小程序看全请求参数和响应体小程序页面能跑通只是第一步发布前要考虑真实用户会带什么网络环境。这里我习惯用 Charles 把接口从头到尾抓一遍。做法是电脑和手机连同一个 Wi-Fi手机网络设置里把 HTTP 指向电脑的 IP 和 8888 端口Charles 上会立刻出现来自小程序的请求。如果后端是开发期的 HTTP不需要装根证书就能看到明文如果已经切到 HTTPS需要先在 Charles 的 SSL Proxying Settings 里添加*:443并在手机上信任 Charles 根证书。抓包的目的是确认两件事token 有没有带在 Header 上请求参数和响应字段有没有暴露手机号、openid 这类敏感数据。Charles 里重点看/api/user/login、/api/health/record、/api/health/trend三个请求。登录接口响应里的 token 不应该包含 openid健康记录请求的 body 应该在序列化里没有多余字段响应里如果是体重趋势列表应该能明显看到 record_date、weight_kg、steps_count 而不是大段 explanation 或 debug 字段。平时代码里看不到的“黑匣子”抓包时一眼就看穿了。6.2 自查清单从录数据到看趋势的闭环抓包之外我把发布前自查做成一个固定动作后端接口要做幂等健康记录点两次“保存”数据库里不能插两条。常见做法是在(user_id, record_date, diet_type)上加唯一索引或者后端先去查一次再插。小程序每个页面的标题要动态设置用wx.setNavigationBarTitle根据当前日期改成“6 月 24 日的健康记录”不要所有页面都叫“健康管理”。列表类的健康建议用onReachBottom触发下一页加载用page/pageSize分页不要一次返回全部分类。一个实用的验证场景清空缓存退出登录重新打开小程序录一条体重 70.5kg、步数 8000 的记录然后去趋势页看 7 天曲线、去个人页看 BMI 是不是 22.3假设身高 175cm。再连一次数据库用SELECT ... WHERE user_id ... AND record_date CURDATE()对比接口返回值是否一致。如果这三处数字都对上了说明前后端数据闭环成功。我之前有一个版本所有接口都没有 token抓包时看到 openid 直接出现在请求路径里等于把用户身份暴露给了网络里的每一个节点。后来统一改成 Authorization 头后端拦截器解析 userId顺便在日志里对手机号打码。这个习惯我一直保留。希望帮到你少走一点我走过的弯路。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站