简介这是一份基于SpringBoot的二手物品交易系统毕业设计源码包面向计算机专业毕业生、Java学习者和需要课程设计或期末大作业的人群可帮助快速搭建具备商品交易功能的完整项目。资源包共包含633个文件涵盖73个Java后端源文件、50个FreeMarker页面模板、178个JavaScript脚本以及MySQL数据库脚本、项目说明和开发工具配置文件类型从前端样式、图片图标到后端逻辑、SQL脚本均覆盖整体压缩后仅18.27MB。系统采用SpringBoot作为后台框架结合MySQL持久化并引入Bootstrap等前端组件代码经严格调试可在JDK与IDEA环境下直接运行。目前已有293人学习下载作为导师指导通过的高分项目随包提供的数据库脚本和说明文档能帮助读者理解用户、商品、订单等核心模块的设计思路节省从零搭建与排错的时间适合直接用于毕设或作为二次开发基础。1. 二手物品交易系统源码包先搞懂它是什么再决定要不要跑每年毕业设计提交截止前两周总有人从网上下载一个名为“java毕业设计-基于springboot的二手物品交易系统项目源码数据库.zip”的压缩包解压后却连启动界面都打不开。这套东西本质上是一个典型的 Spring Boot 课程设计/毕业设计项目后端用 Spring Boot 写 REST 接口和页面渲染数据库用 MySQL 存用户、商品、订单和留言再配一个后台管理模块。它能解决的核心问题是让你在有限时间内拿到一套结构完整、能讲清楚业务逻辑、能演示给老师看的电商类信息管理系统而不是从零搭框架。适合三类人要交毕设答辩的学生、刚学完 Java Web 想做综合练习的初学者、以及想快速复现一套二手交易流程的转型开发者。但要注意这种包最大的坑不是代码本身而是 JDK 版本、MySQL 版本和配置文件把这个理顺了剩下的事都不难。2. 拆开springboot二手交易系统分层架构、核心模块与选型理由2.1 源码数据库.zip内到底有什么目录结构与每个包的职责拿到压缩包先别急着解压看一下文件清单。这种毕设包的目录结构高度相似基本逃不出下面这套布局我按常见做法拆给你看secondhand/ ├── src/main/java/com/example/secondhand/ │ ├── controller/ # 控制层接收请求 │ ├── service/ # 业务层处理逻辑 │ ├── mapper/ # 数据访问层接口 │ ├── entity/ # 实体类对应数据表 │ ├── config/ # 配置类、拦截器 │ └── SecondhandApplication.java # SpringBoot启动类 ├── src/main/resources/ │ ├── application.yml # 核心配置 │ ├── mapper/ # MyBatis的XML映射文件 │ ├── static/ # CSS/JS/图片 │ └── templates/ # 页面模板 ├── sql/ │ └── secondhand.sql # 建库建表初始数据 └── README.txt # 运行说明这里最容易忽视的是sql/目录。很多新手把代码导入 IDEA 就开始等依赖下载完全不管数据库脚本结果启动成功却登录不上因为表根本不存在。经验是先建库再改配置最后才启动代码。controller 层直接对应前端请求service 层是业务规则集中的地方mapper 层配合 XML 文件执行 SQL。如果包里有config类通常放着登录拦截器和跨域配置答辩时老师特别喜欢问这个。另外注意resources/mapper目录它是 MyBatis 的 SQL 所在地。如果这个目录是空的说明项目用的是注解 SQL 或者 MyBatis-Plus读取方式不一样。两种写法都能跑通但排错路径完全不同后面第四章会细说。2.2 买家/卖家/管理员三条业务主线表与接口怎么对起来二手交易系统和普通商品系统的核心区别在于“角色双身份”普通用户既是买家也是卖家管理员只做审核和管理。我一般会按这三条线去读源码效率比顺着文件列表读高很多。买家链路是这样的注册登录 → 浏览商品列表 → 看详情 → 下单购买 → 确认收货 → 评价。卖家链路登录后进入个人中心 → 发布商品 → 管理上下架 → 看到订单 → 发货。管理员链路登录后台 → 审核商品 → 管理用户 → 处理举报或留言 → 查看统计数据。对应到代码里controller 层一般有三个分组GoodsController负责商品接口OrderController负责下单和订单状态变更AdminController负责后台功能。这是订单实体最常见的写法你可以从任意一个毕设包里找到类似结构public class Order { private Integer id; // 订单id private String orderNo; // 订单编号 private Integer buyerId; // 买家用户id private Integer goodsId; // 商品id private Integer status; // 0待付款 1待发货 2待收货 3已完成 4已取消 private BigDecimal amount; // 订单金额 private Date createTime; }status字段是整个交易系统的核心状态机。为什么用数字而不是字符串因为数字可扩展、查询效率高、状态流转清楚而且答辩时老师一问“订单状态怎么设计”你就能直接回答出一整条流程下单时状态为 0卖家点击发货变成 1买家确认收货变成 2交易完成是 3超时或取消是 4。订单编号生成方式也是高频问题常见做法是时间戳加随机数防止并发下重复。2.3 为什么选springbootmybatismysql给答辩用选型理由选型逻辑是答辩必问项你心里得有一笔明白账为什么是这个组合而不是 SSM或者 Spring Boot JPA。我的理解是这样Spring Boot 的价值在“自动配置 内嵌 Tomcat”不用再去 tomcat 的 webapp 目录里扔 war 包一个java -jar就能跑头部成本和部署成本都低。MyBatis 的价值在“SQL 和控制权”比起 JPA 那种完全由框架生成 SQL 的方式MyBatis 的 XML 里每一条 SQL 都看得见对于毕设这种需要单独讲“某条复杂查询”的场景特别有用。MySQL 就不多说了免费、资料多、Navicat 图形化操作出现问题随便一搜就有答案。三个技术拼在一起正好覆盖“框架能跑、SQL 可控、数据可靠”三个诉求。这套组合和 SSM 的差别值得单独说。SSM 是 Spring SpringMVC MyBatis 的经典组合Spring Boot 本质上还是 Spring只是省掉了大量 XML 配置。如果老师问“你和 SSM 的项目有什么区别”正确答法是Spring Boot 简化了配置和部署底层 Spring 容器、SpringMVC 请求流转、MyBatis 数据访问这套核心机制没有变所以项目里依然能看到Controller、Service、Mapper这些注解。这就是分层架构的意义换壳不换核业务代码不用重写。3. 数据库脚本落地表结构设计、导入mysql与连接配置3.1 读懂sql脚本users、goods、orders三张核心表的字段设计把 sql 文件用记事本或 Navicat 打开别急着一次执行。先看建表语句二手交易系统的核心表基本是三张用户表、商品表、订单表外加分类表、收藏表、留言表作为辅助。用户表一般包含id, username, password, nickname, phone, avatar, role其中的role字段用来区分普通用户和管理员常见取值是 0 和 1。这里有一个常见隐患很多毕设包的密码字段是明文存储如果老师追问“安全性怎么保证”你要能答出“生产环境要用 MD5/BCrypt 加盐这里是教学简化版”才算过关。商品表是字段最多的一张表常用写法如下CREATE TABLE goods ( id int(11) NOT NULL AUTO_INCREMENT, title varchar(100) NOT NULL COMMENT 商品标题, price decimal(10,2) NOT NULL COMMENT 价格, description text COMMENT 产品描述, seller_id int(11) NOT NULL COMMENT 卖家id, status tinyint(4) DEFAULT 0 COMMENT 0上架 1下架 2已售, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;三个细节值得注意价格用decimal(10,2)而不是float避免浮点运算精度丢失状态字段注释里写明白每个数字的含义这不只是给维护者看的答辩展示口碑会好很多字符集用utf8mb4支持表情符号也能兼容旧数据乱码问题。最后那行ENGINEInnoDB也很重要只有 InnoDB 支持外键和事务MyISAM 不支持而订单下单流程通常要开事务。外键和硬编码问题也要早看清。不少毕设包为了省事建表时根本不加FOREIGN KEY而是靠 Java 代码在 service 层检查关联关系。这不算错但对新手来说如果你发现orders表里有goods_id却没有外键约束只能说设计者把完整性控制放在了应用层。答辩被问到就如实说“应用层保证数据一致数据库不做强约束”这是很多教学项目的常见手法。3.2 导入数据库用命令行还是Navicat两分钟建好测试库导入方式看个人习惯两种都是常见做法我一般先用命令行验证脚本本身没问题再拿 Navicat 做检查。先打开终端进到 sql 文件所在目录执行mysql -u root -p CREATE DATABASE IF NOT EXISTS secondhand DEFAULT CHARSET utf8mb4; exit mysql -u root -p secondhand secondhand.sql逻辑很简单第一步建库第二步把 sql 文件里的建表语句和数据导入到该库。这里有一个必然遇到的坑有的 sql 脚本文件开头已经写了CREATE DATABASE和USE如果你先手动建库再导一次会报“数据库已存在”。解决办法是看前几行如果有USE就直接执行mysql -u root -p secondhand.sql不用手动建库如果没有才按上面的命令走。MySQL 8.x 和 5.x 的差异也在这个阶段暴露。如果你的脚本里有ENGINEInnoDB DEFAULT CHARSETutf8mb4两边都能跑但如果你用了or开头的旧工具导出 SQL文件里可能有TYPEMyISAM这种老语法在 MySQL 8.x 里直接报错。这时候的处理不是改数据库而是把 SQL 文件里的TYPEMyISAM批量替换成ENGINEInnoDB。Navicat 可视化操作的话右键“运行 SQL 文件”选中脚本即可但同样要提前建好目标库再运行否则容易导错库。导入成功后重点看两个信号控制台有没有报错行以及目标库里的表数量和你预期对不对得上。有的 sql 文件只建了表但没有初始数据登录进去是空的不影响功能但演示效果差。如果包里自带README.txt通常会在最后一段写明默认管理员账号密码比如admin/admin123这种初始数据是埋进 sql 文件里的导入成功才能登录后台。3.3 application.yml里的连接配置把root密码改成你的数据库导完接下来动src/main/resources/application.yml。这个文件是 Spring Boot 项目的中枢几乎 80% 的启动失败都能在这里找到原因。大多数毕设包只有一个 application.yml也有分application-dev.yml和application-prod.yml多环境配置的原理一样改数据源那段就可以server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/secondhand?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.secondhand.entity logging: level: com.example.secondhand.mapper: debug四个参数必须按你的环境改url里的数据库名secondhand要和 3.2 建的库名一致username和password改成你的 MySQL 账号密码默认 root 但密码每个人都有差异driver-class-name在 MySQL 8.x 里固定是com.mysql.cj.jdbc.Driver如果你用的是 MySQL 5.x则要改回com.mysql.jdbc.Driver写反会直接提示找不到驱动类。serverTimezoneAsia/Shanghai这一项不能删删了之后 MySQL 8.x 经常报“服务器时区无法识别”之类的时区错误。mybatis.mapper-locations指明 XML 映射文件路径如果你的 XML 不在这个路径下启动时候 MyBatis 扫不到 SQL运行时会报Invalid bound statement异常。type-aliases-package是实体类所在包配了它之后 XML 里写resultTypeOrder可以直接用类名。logging.level那两行是排错神器配好之后控制台会打印每一条执行的 SQL后面第五章排错全靠它。如果包用的是 MyBatis-Plus这段配置会变成mybatis-plus.mapper-locations前缀原理一样别照着写岔了。这里补一句很多包在pom.xml里同时引了 MySQL 5.x 和 8.x 的驱动依赖这是制作人为了兼容不同环境留下的“后悔药”依赖冲突时编译会报红请在 pom 里只保留你当前 MySQL 版本对应的那一份。4. 用IDEA把springboot工程跑起来启动步骤与验证清单4.1 打开工程前先定JDK和Maven镜像依赖下载不出错这一步是新手和本项目之间最大的一道坎。绝大多数这类源码包基于 Spring Boot 2.x 编写对应要求是JDK 8 及以上、Maven 3.6 左右。如果你用 IDEA 默认的 JDK 17 甚至 21 去跑大概率会碰到编译错误因为源码里的javax.*包和 JDK 17 不兼容。正确做法是打开File - Project Structure - Project SDK选 JDK 8如果没有先通过 IDEA 的 Add SDK 下载一个JDK 1.8然后确认 Maven 的配置。Maven 是依赖管理工具pom.xml里声明的 springboot 框架、mysql 驱动、mybatis 依赖都是从远程仓库下载的。国内直连中央仓库常常超时或卡死所以要在settings.xml里加一个国内镜像仓库避免依赖下载阻塞整个构建。找到 Maven 安装目录下的conf/settings.xml在mirrors标签里加入mirror idaliyunmaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/central/url /mirrorIDEA 中路径是File - Settings - Build Tools - Maven把 User settings file 指向你改好的settings.xml然后在右侧 Maven 面板点刷新让它重新读取依赖。首次构建下载量往往几千个文件耗时几分钟都属正常如果日志里反复出现“Downloading…”却一直不动再去检查远程仓库地址。还有一个小技巧IDEA 底部 Maven 面板能切换离线模式依赖下载完以后勾上 Offline后面每次启动构建都会更快避免反复联网校验。4.2 启动主类与内嵌Tomcat从控制台日志判断是否成功一切配置就绪后找到src/main/java下带SpringBootApplication注解的类类名一般是SecondhandApplication在它的main方法上右键直接 Run。这是整套系统的入口main方法只有一行但背后做的事不少SpringBootApplication public class SecondhandApplication { public static void main(String[] args) { SpringApplication.run(SecondhandApplication.class, args); } }SpringApplication.run()做的事情可以拆成三步加载自动配置、创建 Spring 容器、启动内嵌 Tomcat。所以第一次启动时你会看到控制台刷出一大串日志眼花的判断标准只有两个关键行。第一行是 Tomcat 启动日志类似Tomcat started on port(s): 8080 (http)出现这一行说明 Web 服务器起来了第二行是Started SecondhandApplication in x seconds出现这一行说明整个 Spring 容器初始化完毕。两者缺一启动都算失败。启动失败时先看错误堆栈最顶部的Caused by那才是根因。常见的三个根因都和环境有关数据库连接失败、端口被占用、Mapper 接口扫描不到。这些都不是代码逻辑问题不用动业务代码按第五章逐个排查。启动成功且没有报警日志后浏览器访问http://localhost:8080如果看到登录页或首页这一套就算真正跑通了。这里也给一个血泪经验不要因为在 IDEA 里启动了就去改server.port。如果你口子上写着 8080访问却用 8081必然白屏。改端口只发生在 8080 被占时而且改完要重启整个项目才生效热部署并不总是管用。4.3 功能验证清单登录、发布、下单、后台各跑一遍启动成功不等于系统可用。我要求每个拿到这种包的人先按功能清单走一遍把问题暴露在演示之前而不是答辩现场翻车。下面是精简版的验证清单照着执行走完基本能确认主干功能完备功能模块操作路径预期结果涉及数据表注册首页 - 注册跳转登录页库中新增一条用户记录users登录用户端登录进入商品列表页users发布商品个人中心 - 发布商品提交后状态为“上架”列表可见goods下单购买商品详情 - 立即购买生成待付款订单orders卖家发货卖家个人中心 - 订单管理订单状态变为“待收货”orders确认收货买家个人中心 - 我的订单订单状态变为“已完成”orders后台管理/admin或入口按钮能看见用户数和商品列表users, goods商品搜索首页搜索框输入关键词返回标题匹配的商品goods其中最容易挂掉的是“发布商品”和“下单购买”因为它们涉及两张表的写操作后台一报错八成是 SQL 字段对不上列名比如实体里写userId表中字段叫user_id。此时控制台如果打印了 SQL第四章 4.1 配的 debug 日志一眼就能看出来。整个清单走完不超过十分钟却能让答辩演示阶段从容很多。如果某个功能点不通先把该模块和日志信息记下来放到下一步排查不要继续往后走。5. 启动与部署避坑这五个现场最容易翻车5.1 端口8080被占用报错信息、定位进程与换端口现象启动日志里出现Port 8080 was already in use或者更直接的描述是Web server failed to start项目启动失败。原因几乎总是你机器上某个进程占了 8080常见的“罪魁祸首”是之前没关掉的旧 Java 进程、Oracle 相关服务或者另一个 IDE 正在调试项目。解决方法是先找到占用进程再决定是杀掉它还是换个端口。Windows 下打开 CMD执行下面两条命令先查后杀netstat -ano | findstr 8080 taskkill /PID 12345 /Fnetstat输出的最后一列就是进程 PID拿到数字后替换到taskkill命令里即可强制结束。Linux 或 Mac 的环境一行搞定lsof -i:8080查 PIDkill -9 12345杀掉。不想杀进程就去application.yml里把server.port改成 8081然后重启项目访问地址同步换成http://localhost:8081。注意项目里如果写死了跳转链接比如某个登录成功后的redirect:/index此类相对路径不受端口影响但如果代码里存在写死的http://localhost:8080绝对路径那就要全局搜索替换。5.2 springboot版本太高导致的javax报错现象导入项目后大量 Java 文件报红错误集中在javax.servlet、javax.persistence这类包名全划线编译直接失败。这是你拿到的是 Spring Boot 2.x 项目但用了 JDK 17 或更高版本在跑导致的命名空间冲突。Spring Boot 3.x 从 JDK 17 开始把javax.*迁移到了jakarta.*而旧的 2.x 系源码里用的全是javax两个体系互不兼容纯属版本代沟。解决思路有两条路你按实际情况选一条。第一条也是推荐的把 IDE 的 Project SDK 切到 JDK 1.8同时确认pom.xml里java.version是 1.8大多数 Spring Boot 2.x 项目在这两个版本一致后即可编译通过。第二条如果你电脑上实在没有 JDK 8也没法装那就升级源码到 Spring Boot 3.x但这不是改一个版本号就完事的得批量替换javax.servlet为jakarta.servlet有些第三方依赖还得换新版本工作量明显更大。所以尽量走第一条省时间。判断项目到底基于哪个大版本直接看pom.xml里的spring-boot-starter-parent版本号2.x 开头就是上面的处理方式。5.3 mysql连接失败Access denied与link failure的两种改法现象应用启动到一半报错一种信息是Access denied for user rootlocalhost (using password: YES)另一种是Communications link failure或者Cannot create PoolableConnectionFactory。前者是登录认证失败后者是压根没连上 MySQL 服务两个原因不同解决路径也不同。Access denied的根因就一个application.yml里的password和实际 MySQL 密码不一致或者username拼写错误。把它改成你能在 Navicat/命令行里正常登录的那套账号密码重启项目即可。这里有个细节如果 MySQL 是用sudo mysql免密登录的那你的 root 用户可能根本没设密码密码留空字符串就行但有的驱动不允许空密码连接需要先去 MySQL 里给 root 设置一个密码。Communications link failure则先确认 MySQL 服务有没有启动Windows 在服务管理器里看MySQL服务状态Ubuntu 等 Linux 环境用systemctl status mysql。服务没启动配置写得再对也白搭。另外 MySQL 8.x 默认端口是 3306如果你把端口改成了 3307url里的 3306 也要同步改这种细节最容易被忽略。5.4 接口返回500但控制台没日志把mybatis的sql打出来现象前端页面上点“发布商品”或者“提交订单”直接跳到 500 错误页IDEA 控制台却干干净净几乎没有任何异常输出。这种情况最容易让新手慌因为“黑匣子”一样摸不着头脑。原因多半不是没异常而是日志级别把它吞了要么 MyBatis 的 SQL 没打印要么异常被全局处理器吃掉了没输出出来。我一般会做的第一件事在application.yml里把 mapper 包的日志级别调到 debug也就是第四章写过的这一行logging: level: com.example.secondhand.mapper: debug配完后重启再重复刚才的操作控制台会把每一条预处理 SQL 和参数列表打出来例如 Preparing: SELECT * FROM goods WHERE title ?和 Parameters: 手机(String)。这时错误往往就清楚了你一半。常见的情况是 SQL 写错字段名日志显示Unknown column xxx in field list去resources/mapper/*.xml里把字段名和数据库表结构对齐就能解决。还有一种“没日志”的玄学场景启动时 IDEA 控制台窗口被误关了或者日志被输出到项目根目录的logs文件里而不是控制台。打开根目录找一找有没有logs文件夹里面的spring.log或类似文件记录了完整堆栈直接翻那个文件比瞎猜高效得多。5.5 登录后跳转404、css/js全丢静态资源路径与拦截器放行现象登录页能打开但输入账号密码后跳转到一个 404 页面或者页面能出来但完全没有样式HTML 是纯文本堆在一起。这两类问题指向的是同一个根因静态资源或页面模板没有按 Spring Boot 的默认规则放对位置。Spring Boot 对静态资源有约定的目录规则src/main/resources/static下的文件直接映射到根路径src/main/resources/templates下的是模板页面。有些毕设包当年做的时候是前后端分离的前端用 Vue 打包后生成一个dist目录制作人把dist整个塞进了static里。把 Vue 打包放进 springboot 里的做法本身没问题但打包后的 index.html 里引用的 JS/CSS 是绝对路径恰好和static根路径冲突就会导致样式全丢。解决方法是把static下的文件解包、把静态文件散开放置而不是保留dist嵌套结构。如果你看到拦截器相关代码比如LoginInterceptor或WebMvcConfigurer里注册了拦截排查重点就是路径放行。常见错误是拦截器把/css/**、/js/**、/img/**也拦了导致登录页面引用静态资源全部被挡。在拦截器的excludePathPatterns里显式放行静态资源路径或者干脆只拦/admin/**后台路径是最省事且符合场景的做法。登录后跳转 404 的情况还要检查页面模板里跳转用的是相对路径还是绝对路径很多跳转的 controller 方法不存在或者方法名拼错就会落到 404。6. 把二手交易系统改成你的毕设小改造、自测清单与答辩话术6.1 成本最低的两个功能改造按商品名模糊搜索与订单导出拿到包之后完全不动代码直接用老师一眼就能看出是同款项目。我建议做两个低成本、高展示度的改造第一是商品模糊搜索第二是订单导出。模糊搜索的改动很小很适合拿来讲“自己独立完成了查询优化”。先在GoodsService里加一个方法然后到对应的 Mapper 接口和 XML 各补一段public ListGoods searchByTitle(String keyword) { return goodsMapper.searchByTitle(keyword); }select idsearchByTitle resultTypeGoods SELECT * FROM goods WHERE title LIKE CONCAT(%, #{keyword}, %) AND status 0 ORDER BY create_time DESC /select这段代码的亮点在于两个细节LIKE拼接用的是CONCAT(%, #{keyword}, %)而不是直接%${keyword}%这能防止 SQL 注入答辩被问安全问题时这就是加分点status 0过滤只查上架商品体现你考虑了业务状态。前端的搜索框把输入参数传过来就完成了闭环。订单导出给老师留下的印象最深但不建议动复杂报表框架写一个把订单列表输出成 CSV 的接口就够实用。核心思路是查询订单列表把每条记录的字段用逗号拼接设置application/octet-stream响应头让浏览器下载代码量二十行以内能完整讲清楚“什么是流式输出”。6.2 答辩提问清单对着这些代码准备好答案毕业设计答辩本质上是自证不是发明创造准备好以下四个高频问题的答案通过率会大幅提升。第一个是“为什么选 springboot 而不是 ssm”对着pom.xml里的spring-boot-starter-parent讲自动配置和内嵌 Tomcat说“不用再配置 web.xml 和 Spring XML 文件”就够。第二个是“下单流程事务怎么控制的”去 service 层找Transactional注解下单要同时扣库存、创建订单任一步失败都要回滚这就是事务控制的价值。第三个是“权限是怎么做的”去config包找拦截器普通用户和管理员分别拦哪些路径回答“没有用的单点登录框架而是基于 session 的角色判断”。第四个是“密码为什么不加密”诚实地回答“教学项目为了展示注册登录流程做了简化生产环境会用安全框架做加密和会话管理”比硬编一个加密逻辑却被追问漏洞要好得多。我平时拿到任何一套 Java 毕设源码第一件事永远不是读代码而是先把 sql 脚本导进 MySQL库建不起来后面全是空中楼阁库起来之后才改配置、跑主类、按功能清单走一遍。这三步走完项目能不能用、值不值得继续投入心里早就有了答案。把它当成一套可以动手拆的实验环境每个报错都是一个具体的、可解决的题而不是玄学。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?