
简介面向数据库课程设计与企业人事管理信息化场景的完整设计报告PDF涵盖系统规划、需求分析、概念设计、逻辑设计、物理设计到实现维护全流程。报告以SQL Server Java为技术选型围绕员工信息、考勤、部门、薪资、调动与评价等模块展开并配有数据流图、数据字典、E-R图和规范化处理说明适合正在完成课程设计或初步接触企业级人事管理系统的读者参考。资源为1个PDF文件压缩包大小仅1.83MB内容清晰、目录完整可直接用于对照撰写报告、梳理数据库设计思路或准备答辩。目前已有2182人浏览学习。通过学习这份PDF可快速理解人事管理系统从可行性分析、功能需求到关系模型转换、表结构设计的关键步骤提升数据库课程设计的完整性与规范性。1. 企业人事管理系统数据库课程设计里最容易被扣分的一环拿到「企业人事管理系统(数据库课程设计).pdf」这个题目大多数人的第一反应是赶紧去写界面、调按钮等到答辩前几天才熬夜建表。实际上这类课设的评分重心从来不在界面上而在数据库设计——老师翻看你的文档和现场演示时最常追问的就是“为什么这张表这样拆”“这个字段为什么冗余”“删除部门报外键错误你怎么处理”如果项目里只有一张员工表和一张部门表状态字段用字符串乱飘日期全塞 varchar基本就是送分题变送命题。这篇笔记我把人事系统背后最核心的数据库设计路径讲透从实体拆解、建库约束、增删改查到避坑排查照着做就能交付一个敢现场演示、敢回答追问的课程设计作品。适合正在做课设的学生也适合想补关系型数据库落地能力的开发新手。2. 人事业务怎么拆成表实体识别与三大范式取舍2.1 先画 E-R 图6 个核心实体与它们的关系数据库课程设计最先做的不是写 SQL而是把业务场景抽象成实体和关系。企业人事管理系统看上去功能很多裁剪到课程设计能讲清楚的范围核心实体就是 6 张表部门、岗位、员工、考勤记录、薪资记录、系统用户账号。别一上来就加“培训记录”“奖惩记录”表太多反而让关系图失控答辩时也讲不全。实体关系有两种必须画清楚。第一种是 1:N一个部门有多个员工一个岗位有多个员工一个员工有多条考勤记录、多条薪资记录。第二种是 1:1一个员工账号只对应一个员工。这里有个高频错误有人把考勤记录和薪资记录直接做成员工表的多个字段比如 employee 表里加 attendance_date1、attendance_date2…… 这是典型的“一张表装天下”思维违反第一范式后面统计月报、计算薪资时完全没法写 SQL。正确做法是把“每次发生”的数据独立成表用外键关联回员工表。画 E-R 图时还要定好主键策略。我建议员工表用自增代理主键 emp_id同时保留业务编号 emp_no工号并加唯一索引。原因很实战员工离职后工号可能被重新分配如果用 emp_no 当主键历史考勤和薪资记录的外键引用会跟着失效代理主键稳定不变emp_no 只是查询条件。这个细节在答辩时主动讲出来比背概念加分得多。2.2 表结构定稿从 E-R 图到 MySQL 建表语句实体关系确认后直接把表结构落到 DDL。以下是我在课程设计里常用的 MySQL 8.0 建表方案去掉注释也方便你抄改。CREATE TABLE department ( dept_id INT AUTO_INCREMENT PRIMARY KEY COMMENT 部门ID, dept_name VARCHAR(50) NOT NULL UNIQUE COMMENT 部门名称, manager_id INT NULL COMMENT 部门负责人员工ID, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT部门表;逻辑说明manager_id 一般指向 employee 表的 emp_id但这会造成两表互相引用建表时要先建 employee 再加外键或者干脆不建物理外键只在应用层维护。课程设计阶段建议先建 department、position再建 employee最后用 ALTER TABLE 补外键避免循环依赖。CREATE TABLE position ( position_id INT AUTO_INCREMENT PRIMARY KEY, position_name VARCHAR(50) NOT NULL UNIQUE, salary_band DECIMAL(10,2) NULL COMMENT 岗位薪资区间下限 ); CREATE TABLE employee ( emp_id INT AUTO_INCREMENT PRIMARY KEY, emp_no VARCHAR(20) NOT NULL UNIQUE COMMENT 工号, emp_name VARCHAR(30) NOT NULL, gender CHAR(1) NOT NULL, birth_date DATE NULL, dept_id INT NOT NULL, position_id INT NOT NULL, hire_date DATE NOT NULL, phone VARCHAR(20) NULL, email VARCHAR(100) NULL, status TINYINT NOT NULL DEFAULT 1 COMMENT 1在职 0离职, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_emp_dept FOREIGN KEY (dept_id) REFERENCES department(dept_id), CONSTRAINT fk_emp_pos FOREIGN KEY (position_id) REFERENCES position(position_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;参数说明要留意三点gender 用 CHAR(1) 而不是 VARCHAR(10)节省空间且便于加 CHECK 约束status 用 TINYINT 做“在职/离职”逻辑删除标志这是后面处理部门删除、员工查询的关键create_time 用 DEFAULT CURRENT_TIMESTAMP 自动填充减少应用层代码。考勤表和薪资表是事务型表它们的字段设计决定了报表好不好写CREATE TABLE attendance ( att_id INT AUTO_INCREMENT PRIMARY KEY, emp_id INT NOT NULL, att_date DATE NOT NULL, clock_in TIME NULL COMMENT 上班打卡, clock_out TIME NULL COMMENT 下班打卡, status TINYINT NOT NULL DEFAULT 0 COMMENT 0正常 1迟到 2早退 3缺勤, UNIQUE KEY uk_emp_date (emp_id, att_date), CONSTRAINT fk_att_emp FOREIGN KEY (emp_id) REFERENCES employee(emp_id) ); CREATE TABLE salary ( salary_id INT AUTO_INCREMENT PRIMARY KEY, emp_id INT NOT NULL, pay_month CHAR(7) NOT NULL COMMENT 格式2024-06, base_salary DECIMAL(10,2) NOT NULL, bonus DECIMAL(10,2) DEFAULT 0, deduction DECIMAL(10,2) DEFAULT 0, final_salary DECIMAL(10,2) GENERATED ALWAYS AS (base_salary bonus - deduction) STORED, UNIQUE KEY uk_emp_month (emp_id, pay_month), CONSTRAINT fk_sal_emp FOREIGN KEY (emp_id) REFERENCES employee(emp_id) );这里最关键的参数是两个联合唯一索引attendance 表的 uk_emp_date 保证一个员工一天只能有一条考勤salary 表的 uk_emp_month 保证一个员工一个月只能有一条薪资。没有这两个约束重复数据就只能在代码里查一遍再插一遍纯属给自己挖坑。final_salary 用了 MySQL 8.0 的生成列自动计算实发工资比在 Java 或 C# 里算了再存更可靠。2.3 范式与反范式薪资表要不要冗余部门名称三大范式是课程设计文档里必须写的理论但落地时要有取舍。第一范式要求属性原子化所以不要出现“phone1,phone2”这种列一张表专注一类实体。第二范式要求消除部分依赖薪资表的主键是 salary_idemp_id 只是普通字段这样 emp_id 就不存在对联合主键的部分依赖。第三范式要求消除传递依赖员工表里不存部门名称只存 dept_id部门名称通过 JOIN 拿到。但反范式同样重要。salary 表里我故意保留了 base_salary、bonus、deduction 这三列的快照而不是 JOIN 岗位表的 salary_band 去算。为什么因为薪资属于历史事实员工调岗、调薪后历史月份的工资不能跟着变。如果每次查询都去读当前岗位工资往年报表会全部算错。这就是一个典型的“用冗余换正确性”的反范式设计答辩时可以主动讲我保留了薪资快照字段虽然违反了一点冗余原则但保证了历史数据不可变。另一个可选的冗余点是在 salary 表加 department_name便于做部门维度汇总。但课程设计阶段我建议不加因为 JOIN 部门表成本很低多冗余一列反而要维护同步更新得不偿失。3. 建库与完整性约束把规则交给数据库而不是代码3.1 创建数据库字符集一步错后面全盘乱建表之前先建库但建库这一步就埋着最经典的坑——字符集。很多教材示例用的是CREATE DATABASE hr_system;不带任何参数安装 MySQL 时默认字符集是 latin1 的话插入中文姓名直接变问号。CREATE DATABASE hr_system DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci;参数说明utf8mb4 是完整的 UTF-8 编码能存中文、生僻字和 Emojiutf8mb4_unicode_ci 是排序规则ci 表示大小写不敏感。这里要特别强调MySQL 里的 utf8 其实只是 utf8mb3最长 3 字节遇到特殊字符会报“Incorrect string value”错误所以从 8.0 开始官方都推荐直接上 utf8mb4。连接串同样不能漏字符集参数。以 Java JDBC 为例String url jdbc:mysql://localhost:3306/hr_system ?useUnicodetruecharacterEncodingutf8 useSSLfalseserverTimezoneAsia/Shanghai;这段配置里 useUnicode 和 characterEncodingutf8 共同保证应用层和数据库之间传输中文不乱码serverTimezone 指定东八区否则 Java 8 以上连 MySQL 会报时区错误这也是数据库课程设计里非常常见的一个“玄学”启动报错。3.2 外键、唯一索引与 CHECK 约束哪些该加哪些别被坑建表时约束加得好不好直接决定后续数据是否会被搞脏。我的经验是分三类处理。外键约束课程设计中建议在子表上加物理外键比如 attendance.emp_id、employee.dept_id因为演示删除员工、归档数据时能直接展示外键的 RESTRICT 行为。但要注意外键不是越多越好尤其不要给 status、gender 这种字段建外键到字典表——字典表会被锁住业务一忙就成瓶颈。唯一索引必须加在业务编号上emp_no、dept_name、position_name 都要 UNIQUE这是防止重复数据的最后一道防线。只靠应用层先 SELECT 再 INSERT永远有并发漏洞。CHECK 约束要分清版本。MySQL 8.0.16 之后 CHECK 才真正强制执行。下面是员工表的示例ALTER TABLE employee ADD CONSTRAINT chk_gender CHECK (gender IN (男,女)), ADD CONSTRAINT chk_status CHECK (status IN (0,1));逻辑说明gender 字段限制只能录入‘男’或‘女’status 限制只能录入 0 或 1。如果你用的是 MySQL 5.7这两条约束写了也会被忽略等于没有。课程设计环境是 5.7 的话要么升级 8.0要么在代码层校验别指望数据库兜底。这个版本差异在答辩时被老师问起的概率极高建议提前确认自己的环境。3.3 三个常用视图让答辩演示不用现写长 SQL视图不是必须项但它是课设文档里很好用的加分项。以下三个视图分别解决“员工信息查起来太繁琐”“考勤报表统计复杂”“薪资记录要同时看员工信息”三个高频场景。CREATE VIEW v_emp_dept_pos AS SELECT e.emp_id, e.emp_no, e.emp_name, e.gender, d.dept_name, p.position_name, e.hire_date, e.status FROM employee e JOIN department d ON e.dept_id d.dept_id JOIN position p ON e.position_id p.position_id;逻辑说明这是最基础的三表 JOIN 视图把员工、部门、岗位信息拼成一张宽表界面上的员工列表直接SELECT * FROM v_emp_dept_pos WHERE status1就能拿到。CREATE VIEW v_attendance_month AS SELECT emp_id, DATE_FORMAT(att_date, %Y-%m) AS month, COUNT(*) AS work_days, SUM(CASE WHEN clock_in 09:00:00 THEN 1 ELSE 0 END) AS late_days FROM attendance GROUP BY emp_id, DATE_FORMAT(att_date, %Y-%m);参数说明DATE_FORMAT(att_date, %Y-%m) 把日期格式化成年月字符串GROUP BY 用同一个表达式才能正确分组。这里埋了一个索引失效的隐患第 5 章会细说。视图的最大价值是让答辩演示变得干净老师问“这个月迟到最多的员工是谁”一条 SQL 就能答不用现场拼 20 行 JOIN。4. 人事系统的增删改查从单表到跨表事务4.1 员工信息 CRUD参数化查询为什么是必选项企业人事管理系统最核心的数据库操作就是员工表的增删改查这也是“数据库增删改查”这类热词背后的实际需求。先看一个最常规的新增员工操作public int addEmployee(Employee emp) { String sql INSERT INTO employee (emp_no, emp_name, gender, birth_date, dept_id, position_id, hire_date, phone, email, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?); try (PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, emp.getEmpNo()); ps.setString(2, emp.getEmpName()); ps.setString(3, emp.getGender()); ps.setDate(4, emp.getBirthDate()); ps.setInt(5, emp.getDeptId()); ps.setInt(6, emp.getPositionId()); ps.setDate(7, emp.getHireDate()); ps.setString(8, emp.getPhone()); ps.setString(9, emp.getEmail()); ps.setInt(10, emp.getStatus()); return ps.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(新增员工失败, e); } }逻辑说明PreparedStatement 的占位符?替代字符串拼接SQL 结构和数据分离。这样写有两个直接好处第一SQL 注入路径被堵死用户输入带单引号或注释符也只会被当作普通字符串第二数据库可以对 SQL 做预编译和缓存循环插入一千个员工时性能明显好于 Statement 拼接。注意 emp_no、emp_name 这类字段在 setString 和 setInt 之间不能搞错类型否则插入时 MySQL 会做隐式转换轻则数据异常重则直接报错。连接资源管理这里必须用 try-with-resources 或 finally 关闭结果集、Statement、连接。课程设计里最常见的翻车现场是连接忘了 close跑几次后报 “Too many connections”。项目里如果引入连接池HikariCP 或 Druid连接关闭就只是归还池子但即便如此也必须调用 close()否则连接池最终也会被耗尽。这个“连接耗尽”问题在答辩演示连续刷新页面时最容易暴露。查询员工列表时一定记得带筛选条件并分页SELECT * FROM v_emp_dept_pos WHERE emp_name LIKE ? AND status ? ORDER BY emp_id DESC LIMIT ?, ?;LIMIT 的两个参数分别是偏移量和页大小。需要注意 MySQL 的 LIMIT 不能像 SQL Server 那样写 OFFSET 0 ROWS写错语法整个 SQL 报错。排序字段必须明确不加 ORDER BY 时 MySQL 不保证返回顺序这会导致分页时数据翻页错乱。4.2 考勤月报与部门统计GROUP BY 和 JOIN 的常见坑人事系统绕不开报表统计。最常见的需求是统计某月各部门的平均工资、迟到次数排行。先看一个容易写错的例子-- 错误示范先 JOIN 再 GROUP BY但 GROUP BY 字段带函数导致索引失效 SELECT e.dept_id, COUNT(*) AS emp_count FROM employee e GROUP BY e.dept_id;这个简单语句没问题真正的问题是很多人习惯在 GROUP BY 之前不加 JOIN 和 WHERE。正确写法是统计“某月各部门实发工资总额”SELECT d.dept_name, SUM(s.final_salary) AS total_salary, AVG(s.final_salary) AS avg_salary, COUNT(DISTINCT s.emp_id) AS emp_count FROM salary s JOIN employee e ON s.emp_id e.emp_id JOIN department d ON e.dept_id d.dept_id WHERE s.pay_month 2024-06 GROUP BY d.dept_id, d.dept_name ORDER BY total_salary DESC;这里必须理解 GROUP BY 的语义分组字段和聚合函数共同决定结果的粒度。如果你只 GROUP BY d.dept_idSELECT 里的 dept_name 在 SQL 严格模式ONLY_FULL_GROUP_BY下会直接报错这正是 MySQL 5.7 之后默认开启严格模式带来的变化。解决方法是把 dept_name 也加进 GROUP BY或者对 dept_name 用 ANY_VALUE() 包装。WHERE 和 HAVING 的分工也常被搞混。WHERE 在分组之前过滤原始行HAVING 在分组之后过滤聚合结果。比如“筛选出平均工资超过一万的部门”条件里有 AVG(s.final_salary)只能写在 HAVING 里写在 WHERE 会直接报“Invalid use of group function”。4.3 批量调薪事务隔离级别与死锁排查人事系统每月初要批量调薪或批量发工资这类操作必须以事务为单位要么全部成功要么全部回滚。一个标准的批量调薪事务如下START TRANSACTION; UPDATE salary SET bonus bonus 200 WHERE emp_id IN (SELECT emp_id FROM employee WHERE dept_id 2); UPDATE employee SET update_time NOW() WHERE dept_id 2; COMMIT; -- 异常时执行 ROLLBACK;逻辑说明两条 UPDATE 必须在一个事务里第一条改薪资第二条留操作痕记中途任何一条失败都要回滚否则会出现工资变了但修改时间没变的脏状态。实际项目中不应在应用层手动拼这种多行 SQL而是用 Spring 的 Transactional 注解或服务层事务管理器包裹 JDBC 操作。这里要重点讲 InnoDB 的行锁机制。执行UPDATE ... WHERE dept_id 2时InnoDB 会锁住所有匹配的行如果另一个事务同时在更新同一张表里 dept_id 3 的行两边互不干扰但如果有事务先更新 dept_id 2 再更新 dept_id 3另一个事务反着来两者就会在各自持有部分锁、等待对方锁时进入死锁。MySQL 会自动检测并回滚其中一个事务但你的程序如果没处理好异常用户会看到莫名的报错。规避死锁最常见的手段是固定操作顺序所有事务里都按同一个字段升序处理比如每次都按 emp_id 从小到大做批量更新。事务还要短不要在事务里做远程调用或循环查库锁持有时间越短冲突的概率越低。对于课程设计用下面这条命令能直接查看最近一次死锁的完整日志SHOW ENGINE INNODB STATUS;查看结果里 LATEST DETECTED DEADLOCK 段落会列出两个事务各自持有哪些锁、等待哪个锁据此调整更新顺序即可。这个排查方法同样适用于“数据库并发锁”其他场景不只是人事系统。5. 数据库课程设计避坑乱码、外键与索引失效5.1 中文乱码建库少了 utf8mb4后面全崩现象界面输入“张三”插入数据库变成“???”或者从数据库读出中文显示成问号。原因建库时没指定字符集MySQL 默认 latin1也可能是连接串缺了 characterEncodingutf8应用层按系统默认编码传字节流。解决建库时显式指定DEFAULT CHARACTER SET utf8mb4连接串加useUnicodetruecharacterEncodingutf8。如果数据库已经建成 latin1不要一个个表去改用ALTER DATABASE hr_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;后再把每张表ALTER TABLE xxx CONVERT TO CHARACTER SET utf8mb4;最后验证SHOW CREATE TABLE employee;是否显示 utf8mb4。5.2 外键删除被拒先处理子表还是做逻辑删除现象执行DELETE FROM department WHERE dept_id 2;报错 “Cannot delete or update a parent row”。原因employee 表里还有员工引用 dept_id 2外键约束 RESTRICT 拒绝了删除。解决两条路线。一是物理删除路线先把该部门下员工调走或删除再删部门二是逻辑删除路线给 department 表加一个 status 字段删除只是UPDATE department SET status 0 WHERE dept_id 2;员工数据完好报表也能保留历史。企业真实系统几乎都用逻辑删除课程设计建议直接做逻辑删除并在答辩时说明“为了保留历史数据我不做物理删除”这是加分的点。如果一定要物理删除并验证级联行为可以在外键上加 ON DELETE CASCADE 或 ON DELETE SET NULL但要在文档中写明这样做的风险。5.3 索引失效隐式类型转换与函数包裹现象员工表 emp_no 有唯一索引查询WHERE emp_no 1001却走全表扫描考勤表按日期查询时也使用不上索引。原因emp_no 是 VARCHAR条件里却传了整数 1001MySQL 把字段隐式转换成数值类型比较DATE_FORMAT(att_date, %Y-%m) 对字段做函数运算索引无法直接匹配。解决查询条件与字段类型保持一致WHERE emp_no 1001按月查询尽量写成范围条件WHERE att_date BETWEEN 2024-06-01 AND 2024-06-30而不是用 DATE_FORMAT 包字段。验证方式用EXPLAIN SELECT * FROM employee WHERE emp_no 1001;查看结果里的 type 和 key 字段type 为 const 或 ref、key 不为空代表走索引type 为 ALL 就是全表扫描。这条技巧在“数据库优化”和面试里都是高频考点五分钟能验证一个索引到底用没用上。5.4 死锁两个事务更新顺序相反现象批量调薪时同一时间两个人部门调薪一个从 A 部门到 B 部门另一个从 B 到 A日志报 “Deadlock found when trying to get lock”。原因两个事务都持有一部分行锁接着申请对方已持有的锁死锁形成。InnoDB 自动回滚其中一个事务但程序如果没有重试机制用户就看到了报错。解决统一更新顺序所有事务按 dept_id 升序处理事务尽量短不要在事务里查询大量数据后再更新。如果无法避免互斥场景应用层捕获死锁异常后重试 1~3 次每次重试前随机等待 20~50 毫秒避免同时重试再次碰撞。这里谈不上优雅但确实是工程上最实用的兜底手段。5.5 答辩追问为什么不用存储过程包办一切现象有人为了演示“高级功能”把整个增删改查写进存储过程程序只调用一个 CALL 语句。答辩时老师问“这个转岗逻辑如果需求变了怎么改”答不上来。原因存储过程调试难、版本管理难、数据库迁移难MySQL 的存储过程在达梦、Oracle 上语法差异巨大课程设计本来要展示数据库基础过度堆存储过程反而踩坑。解决把存储过程留给两类场景——定时统计月度工资汇总、考勤归档和复杂报表计算常规业务校验放在应用层。课程设计里写一到两个存储过程用于自动生成工资单即可例如CALL sp_generate_salary(2024-06)批量生成当月工资记录既能展示流程控制能力又不会把业务逻辑全锁死在数据库里。6. 让系统从“能跑”到“能答辩”审计表与验证技巧6.1 员工薪资被改你怎么追溯答辩必问的一道题是员工信息或工资被误改了你怎么恢复空口说“有日志”没用直接演示一张审计表更实在。CREATE TABLE audit_log ( log_id INT AUTO_INCREMENT PRIMARY KEY, operator_id INT NOT NULL COMMENT 操作人用户ID, table_name VARCHAR(50) NOT NULL, record_id INT NOT NULL COMMENT 被修改记录主键, action_type VARCHAR(10) NOT NULL COMMENT INSERT/UPDATE/DELETE, old_value TEXT NULL, new_value TEXT NULL, operate_time DATETIME DEFAULT CURRENT_TIMESTAMP );应用层在每次写操作前构造一条审计记录把修改前后的数据快照存进去。不需要触发器避免所有操作都写日志导致事务膨胀。面试或答辩时演示流程是先查某员工工资UPDATE 一次再查 audit_log展示 old_value 和 new_value 的差异这一套下来比任何口头解释都有说服力。6.2 用执行计划验证系统“真的没问题”把 EXPLAIN 作为一个门禁动作写进验证脚本。打开命令行依次执行EXPLAIN SELECT * FROM v_emp_dept_pos WHERE emp_no 1001; SHOW INDEX FROM employee;第一句看是否走唯一索引第二句确认约束是否齐全。课程设计文档里附上这三行输出截图能直观证明你做过验证而不是截图看效果。我推荐的最终验证脚本是新增员工 → 查视图确认关联信息正确 → 修改薪资 → 查审计表 → 删除部门走逻辑删除→ 确认员工列表不受影响。五个步骤走完基本能覆盖讲演示的所有关键路径。6.3 保留一个自选动作把工号交给数据库维护如果还想再加亮点把 emp_no 的生成规则写成一个函数每次插入员工时由数据库生成带年份的工号。例如EMP YEAR 四位流水号这样新员工录入后工号立即统一应用层少写一段编号逻辑演示也更像真实系统。注意用完函数加唯一索引兜底并发插入时要处理流水号冲突课程设计可以接受先按事务串行生成。我做课设那会儿最遗憾的就是没做审计表被老师当场问“这条工资改动是谁操作的”时完全答不上来。后来在项目里补上那一张表整个系统的可解释性立刻不一样。这个方向不复杂值得你花半天时间加上希望帮到你。本文还有配套的精品资源点击获取