简介一份面向数据库课程设计与考勤管理系统开发的规范设计文档适合计算机专业学生、数据库初学者及相关项目开发者参考。其以员工考勤管理为业务场景围绕员工基本信息、部门、考勤类型、员工考勤记录及系统用户五类核心实体给出从逻辑表结构到功能需求实现的完整设计思路。文档为单份DOC格式大小约57KB包含五张核心数据表的字段定义与主外键约束说明如员工编号、部门编号、考勤日期等同时梳理了系统登录、增删改查、按员工/部门/时间段查询以及按月按部门统计考勤次数与罚金等九类功能需求并附有员工考勤表和罚金统计表的样式参考。已有262人学习浏览内容精炼实用可直接迁移用于课程设计文档撰写或考勤模块的数据库原型搭建。1. 员工考勤管理系统数据库设计先想清楚这张表要回答的三个问题拿到「员工考勤管理系统数据库设计.doc」这个标题多数人第一反应是写几张表员工表、打卡表、请假表。但真正做过考勤系统的人都知道数据库设计能不能过关不看表多不多而看你能不能回答这三个问题某个人某天应该几点上班、实际几点来、最后算出来是正常还是迟到。考勤系统所有的业务规则——排班、打卡、请假、加班、补卡、统计——最终都要落到这三问上。这个文档要解决的核心就是把「考勤规则」这种容易撕扯的抽象约定翻译成一张张结构清晰、不产生歧义的数据表。适合谁如果你在做毕设、给小微企业搭一套人事考勤、或者要把Excel打卡记录升成正经系统这篇就是照着画表和写SQL的底稿。我见过太多考勤项目翻车不是败在业务复杂而是败在把「打卡」和「出勤结果」混在一张表里最后统计口径改一次、数据改三天。下面按我习惯的落地顺序展开先定模型再写DDL再写统计SQL最后列踩坑。2. 考勤数据模型怎么搭从业务规则到ER图的四张核心表考勤系统的数据模型核心不是「员工表」而是「事件表」。员工、部门、班次属于主数据变化频率低打卡记录、请假审批、补卡申请才是每天高频写入的事件流。设计时要把主数据和事件流分开否则一张大表既扛不住写入又没法做灵活的统计。2.1 员工与排班考勤的「主数据」从哪来员工表是所有业务表的锚点但考勤系统关心的不是员工的通讯录字段而是他的考勤属性。常见做法是单独做一张employee员工表再加一张shift班次表和一张employee_schedule排班表。这样做的理由是一个公司很可能有多个班次早班、晚班、倒班同一个员工的排班也可能每周变化如果把班次时间直接写死在员工表里后续调班就得改员工记录既没有操作留痕也没法处理「周一到周五早班、周末晚班」这类规则。员工表的最小字段一般是员工号工号、姓名、部门、入职日期、状态。其中工号建议用业务工号而不是自增ID做主键因为外部打卡设备、HR系统都用工号做关联自增ID只适合内部关联。班次表则要包含班次名、上班时间、下班时间、是否跨天。特别注意「是否跨天」这个字段后面统计迟到早退时全靠它。排班表是员工和班次的关联表字段建议为员工号、排班日期、班次ID。排班表的存在让「查询某人某天上的是什么班」变成一条普通索引查询而不是去解析复杂的排班规则表达式。别把排班规则做成字符串存储再写程序解析那会给统计SQL制造巨大麻烦。我一般会预留一个effective_date字段表示这条排班从哪天开始生效方便月末批量调整下一周期的班次。2.2 打卡与审批流水把一次出勤拆成不可再分的事件打卡记录表attendance_record是考勤系统的核心流水表。它的语义非常单纯从打卡机上收到一条原始记录就插入一行。字段至少包含记录ID、员工号、打卡时间、设备编号、打卡类型上班/下班/加班/休息日打卡。这里最容易踩的坑是「打卡类型」不能人工可信——很多打卡机只给时间不给类型类型是靠与排班时间比对推断出来的。所以设计时打卡类型字段要允许为空或存「未知」等后续统计程序回填。审批流水表attendance_approval用于记录请假、加班、补卡、外勤这几类会改变考勤结果的事件。为什么不用一张单独的请假表因为除了请假还有审批状态待定、驳回、撤销等流程动作用一个统一的审批表加类型字段比给每种审批单独建表更容易扩展。例如新增「居家办公」类型只需要加一个枚举值不必加一张新表。我见过有些设计把打卡记录和审批记录混在一起加一个type字段区分「打卡」还是「请假」。这样看起来省了表实际查询时非常痛苦「某员工某天打卡了几次、请假几小时」得在同一条SQL里做条件分支。正确做法是职责分离打卡表只管原始事件审批表只管人为变更最后在统计层做合并。2.3 用ER图串起表之间的关系外键与基数画ER图时关系是这样定的employee到employee_schedule是一对多一个员工有多条排班记录employee_schedule到shift是多对一多条排班指向同一个班次employee到attendance_record是一对多attendance_approval与employee也是一对多。外键怎么建我的建议是员工号在流水表里建普通索引即可不一定要物理外键约束。考勤系统高频写入如果打卡记录表插入时每次都要去校验员工号外键是否存在会拖慢写入速度。更重要的是打卡机可能在员工未建档时就先传了记录严格外键会导致入库失败。所以关联关系仅通过索引实现靠业务代码保证员工号有效性。但ER图上仍要把一对多关系明确画出因为这是后续写统计JOIN的依据。最后要生成一份数据字典文档这是「.doc」类设计文档的标配。每一张表列出字段名、类型、允许为空、默认值、说明。数据字典不需要写进数据库注释里但文档里必须有一张字段清单表否则评审时一眼就能看出设计没做完。3. 把ER图落成MySQL建表语句字段类型、默认值与索引设计模型定好后下一步是写CREATE TABLE。这一节给出一个可以直接改用的建表脚本并在注释里说明每个字段为什么要这样设。3.1 员工表与排班表的DDL写法-- 员工主数据表 CREATE TABLE employee ( emp_id VARCHAR(20) NOT NULL COMMENT 工号考勤设备的唯一标识, emp_name VARCHAR(50) NOT NULL COMMENT 姓名, dept_id VARCHAR(20) NULL COMMENT 部门ID关联部门表, hire_date DATE NULL COMMENT 入职日期, status TINYINT NOT NULL DEFAULT 1 COMMENT 1在职 0离职 2停用, PRIMARY KEY (emp_id), KEY idx_dept (dept_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT员工表; -- 班次定义表 CREATE TABLE shift ( shift_id INT AUTO_INCREMENT PRIMARY KEY, shift_name VARCHAR(30) NOT NULL COMMENT 早班/晚班/行政班, on_duty_time TIME NOT NULL COMMENT 本班次上班时间, off_duty_time TIME NOT NULL COMMENT 本班次下班时间, is_next_day TINYINT NOT NULL DEFAULT 0 COMMENT 0当天结束 1跨天班次, work_hours DECIMAL(4,2) NULL COMMENT 标准工时如8.00 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT班次表; -- 排班表 CREATE TABLE employee_schedule ( schedule_id INT AUTO_INCREMENT PRIMARY KEY, emp_id VARCHAR(20) NOT NULL, work_date DATE NOT NULL COMMENT 具体出勤日期, shift_id INT NOT NULL, effective_date DATE NULL COMMENT 生效日期当月调整用, UNIQUE KEY uk_emp_date (emp_id, work_date) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT员工排班表;逻辑说明员工表主键直接用VARCHAR工号避免打卡机导数据时做一次ID映射status用TINYINT而不是CHAR因为条件筛选时数字范围判断更快而且「离职员工的历史考勤」仍然需要保留不能物理删除。班次表把上下班时间设为TIME类型因为班次是每天重复的规律不依赖具体日期。is_next_day是关键字段晚班的off_duty_time是第二天凌晨的2点存TIME类型时并不包含日期信息统计时必须结合is_next_day判断实际下班日期这个细节在排班表里也要保留。排班表的UNIQUE KEY uk_emp_date (emp_id, work_date)保证一个员工一天只能有一条排班这是业务刚需。如果没有这个唯一约束程序重复调用排班接口就会产生两条排班统计时就会出现两倍数据。参数说明里值得注意的还有employee_schedule.effective_date。有些团队把这个字段做成「生效日期」但真正查某天的班次时应该先用work_date精确匹配。实际上effective_date只用于后台批量生成排班时标记批次前端展示和统计都应该走work_date。这两个日期如果你不加注释三个月后自己回来看也会混淆。3.2 打卡表和审批表的DDL写法以及为什么datetime比timestamp更稳-- 考勤打卡记录流水表 CREATE TABLE attendance_record ( rec_id BIGINT AUTO_INCREMENT PRIMARY KEY, emp_id VARCHAR(20) NOT NULL, punch_time DATETIME NOT NULL COMMENT 打卡时间精确到秒, device_id VARCHAR(20) NULL COMMENT 打卡机编号, punch_type TINYINT NULL COMMENT 1上班卡 2下班卡 3休息日加班卡由程序推断, is_valid TINYINT NOT NULL DEFAULT 1 COMMENT 1有效 0异常/作废, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY idx_emp_time (emp_id, punch_time), KEY idx_time (punch_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT打卡流水表; -- 考勤审批流水表请假/加班/补卡/外勤 CREATE TABLE attendance_approval ( approval_id BIGINT AUTO_INCREMENT PRIMARY KEY, emp_id VARCHAR(20) NOT NULL, approval_type TINYINT NOT NULL COMMENT 1事假 2病假 3加班 4补卡 5外勤, start_time DATETIME NOT NULL COMMENT 事件开始时间, end_time DATETIME NOT NULL COMMENT 事件结束时间, duration_hours DECIMAL(4,2) NULL COMMENT 审批时长, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待审 1通过 2驳回 3撤销, remark VARCHAR(200) NULL, KEY idx_emp_start (emp_id, start_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT审批流水表;逻辑说明打卡时间用DATETIME而不是TIMESTAMP。原因有两点第一TIMESTAMP的范围到2038年系统只要用到2038年以后就得改造第二考勤系统常需要处理跨时区或服务器时间偏移DATETIME存的是字面时间不受数据库时区影响统计时用程序统一转换。如果你需要显示「这个打卡发生在UTC还是本地时间」建议用TIMESTAMP或额外加一个时区字段但大多数国内考勤系统只关心本地时间DATETIME是更稳的选择。attendance_record上建了两个索引idx_emp_time (emp_id, punch_time)和idx_time (punch_time)。前者服务「查某员工某时段记录」后者服务「按天全量统计」。千万记得在后端跑月度统计时若只按punch_time范围查不会走emp_id那组索引所以单独建时间索引是必要的。这个双索引设计是我通常会写进开发规范里的。审批表单独看好像没有和打卡表直接关联但统计时需要「某员工某天有请假那么当天缺勤或迟到要豁免」。因此approval表必须有start_time和end_time不要只存日期。只存日期会导致半天请假没法计算时长也无法判断请假时段与上下班时间重叠多少。3.3 状态字段用tinyint还是varchar我的习惯考勤表里到处都是状态员工在职状态、打卡有效无效、审批状态。这几种字段我统一用TINYINT不用VARCHAR。理由很实际代码里if (status 1)比if (approved.equals(status))强健而且索引长度更短排序更快。用TINYINT的代价是代码里需要维护枚举常量。我的做法是在Java后端写一个枚举类把1、2、3映射成有意义的名称在MySQL里则用COMMENT写清楚每个数字的含义例如COMMENT 1在职 0离职 2停用。如果不写注释一年后维护的人一定会问「status2到底是什么」这是我踩过的最不值当的坑。布尔类字段例如is_next_day、is_valid用TINYINT(1)就够不需要BIT类型。BIT在ORM映射时容易出奇奇怪怪的类型转换TINYINT则各家驱动都支持得好。另外所有表都要有create_time打卡表还建议加一个update_time用于排查数据被修正的情况。4. 考勤统计的SQL写法迟到早退缺勤是如何算出来的模型和DDL只是骨架真正体现数据库设计水平的是统计SQL。考勤统计的难点不是单表查询而是把「一次打卡行为」还原成「某天某班次的结果」。下面给出三段我常用的可复现SQL。4.1 用打卡时间反推上下班先合并打卡对考勤机只负责记时间不负责告诉你那一笔是上班还是下班。常规做法是按天分组取当天按排班日期边界最早和最晚的打卡时间分别作为上班和下班。但如果只按自然日0点到24点分组跨天班次就会出错所以我们先把排班日期换算成「班次起始日」-- 统计视角把打卡记录归属到每个班次日期 SELECT r.emp_id, r.punch_time, -- 如果是跨天班次下班时间是次日所以归属日期要修正 CASE WHEN s.is_next_day 1 AND r.punch_time DATE_ADD(s.work_date, INTERVAL 12 HOUR) THEN s.work_date ELSE s.work_date END AS calc_date FROM attendance_record r JOIN employee_schedule es ON r.emp_id es.emp_id AND r.punch_time es.work_date AND r.punch_time DATE_ADD(es.work_date, INTERVAL 1 DAY) JOIN shift s ON es.shift_id s.shift_id;逻辑说明DATE_ADD(s.work_date, INTERVAL 1 DAY)的时间边界用的是00:00:00。如果是晚间班次上班时间在晚上20点下班在次日凌晨2点这条SQL会把work_date那天的两次打卡都归属到正确日期。但如果是21点上班、次日5点下班那么次日凌晨的记录仍然落在work_date 1的区间里CASE里加INTERVAL 12 HOUR的条件其实不严谨——正确判断跨天班次的归属应该以排班当天12点为分界而不是00点。这里的参数INTERVAL 12 HOUR就是一个可调阈值。如果你们有下午班14点上班、22点下班12点分界没问题如果有上午10点上班、次日凌晨1点下班就必须把分界往前调。这种班次必须在shift表里加一个boundary_time字段否则不同班次没法通用。从这段SQL能看到为什么打卡表必须建idx_emp_timeJOIN条件里emp_id和punch_time的等值加范围查询正好走这个联合索引是全表扫描和秒出的分水岭。4.2 关联排班后算迟到早退一条UPDATE或SELECT搞定拿到某个员工某天的最早上班卡和最晚下班卡之后就可以和班次时间比较。下面的SQL直接输出迟到早退明细-- 按员工班次日期计算迟到早退 WITH base AS ( SELECT r.emp_id, DATE(r.punch_time) AS att_date, MIN(r.punch_time) AS first_punch, MAX(r.punch_time) AS last_punch FROM attendance_record r JOIN employee_schedule es ON r.emp_id es.emp_id AND DATE(r.punch_time) es.work_date WHERE r.is_valid 1 GROUP BY r.emp_id, DATE(r.punch_time) ) SELECT b.emp_id, b.att_date, s.on_duty_time, s.off_duty_time, s.is_next_day, -- 迟到分钟数实际打卡晚于应到时间且打卡时间在中午12点前 GREATEST(TIMESTAMPDIFF(MINUTE, CONCAT(b.att_date, , s.on_duty_time), b.first_punch), 0) AS late_minutes, -- 早退分钟数实际下班打卡早于应离时间 GREATEST(TIMESTAMPDIFF(MINUTE, b.last_punch, CONCAT(b.att_date, , s.off_duty_time)), 0) AS early_leave_minutes FROM base b JOIN employee_schedule es ON b.emp_id es.emp_id AND b.att_date es.work_date JOIN shift s ON es.shift_id s.shift_id;逻辑说明GREATEST(x, 0)把「早到」变成0避免出现负数迟到。这里有一个很关键的假设first_punch作为上班打卡。但员工中午才来、晚上加班到很晚这个算法会把下午的第一次打卡当成上班卡导致「上班时间」出现在下午而误判。改进方案是用排班时间的某个容忍窗口来判断哪次打卡属于上班卡例如「上班时间前4小时到后2小时」内的第一次打卡才算上班。遇到这种情况我建议先做一个punch_type回填程序再跑统计而不是直接在统计SQL里处理因为回填逻辑放SQL里会变成一个大泥球。TIMESTAMPDIFF(MINUTE, time1, time2)的计算规则是time2 - time1。所以迟到算的是(排班上班时刻, 实际上班卡)差值正为迟到早退算的是(实际下班卡, 排班下班时刻)插值正为早退。注意跨天班次这里仍然没处理如果off_duty_time是次日02:00CONCAT(b.att_date, , s.off_duty_time)得到的其实是当天02:00而不是次日02:00。正确做法是在拼接时给日期加一天CONCAT(DATE_ADD(b.att_date, INTERVAL s.is_next_day DAY), , s.off_duty_time)。这个坑在第5章还会细说。4.3 请假加班怎么抵扣先算明细再汇总考勤统计最忌讳一步到位的汇总SQL。正确路径是先算出每日明细正常/迟到/早退/请假/加班再按员工月份汇总。明细表可以用临时表或者定期落一张daily_attendance_result表。-- 生成每日考勤结果表简化版 INSERT INTO daily_attendance_result (emp_id, att_date, work_status, late_minutes, early_minutes, leave_minutes, overtime_minutes) SELECT emp_id, att_date, CASE WHEN first_punch IS NULL THEN 缺勤 WHEN leave_minutes 480 THEN 请假 WHEN late_minutes 0 AND early_minutes 0 THEN 正常 ELSE 异常 END AS work_status, late_minutes, early_minutes, leave_minutes, overtime_minutes FROM detail_calc; -- detail_calc 是前面SQL封装成的视图或子查询逻辑说明这里演示的是「先有明细后汇总」不要把CASE WHEN嵌套到对attendance_record的GROUP BY里。每日明细表以emp_id, att_date为唯一键之后月报统计就变成对这张表的SUM查询速度远大于直接扫原始打卡表。审批数据怎么合进来在生成detail_calc时应该用attendance_approval表的start_time/end_time与当天的班次时间段做重叠计算。重叠小时数就是请假抵扣小时。这个计算通常在程序里做不在SQL里做因为SQL写区间重叠条件很绕且难以调试。我推荐的做法是先把审批表拉到内存按员工和时间段排序再在Java或Python里计算与排班的重叠然后把结果写回daily_attendance_result表。数据库只负责存取复杂业务规则交给应用层这是考勤系统DB设计的另一个原则。5. 考勤系统数据库设计的避坑指南这五个问题我至少踩过三回从打卡机到统计报表中间至少埋伏着五个大坑。这些问题在数据模型上留了隐患后面调试时才会暴露。每一条都是「现象 → 原因 → 解决」的结构都是我实际维护过的系统里反复出现的。5.1 现象跨天班次被当成两天统计第二天深夜打卡算成缺勤原因shift表里的off_duty_time只存了TIME类型比如02:00没有存「这是次日02:00」的语义。统计SQL用DATE(punch_time) es.work_date做关联导致次日凌晨的打记录被归到新的一天而新一天并没有排班于是那晚的加班和下班卡全部丢失员工第二天还会被算成缺勤。解决统计时一定要基于is_next_day做日期偏移。比如排班日期是2024-06-01班次是晚班下班到次日02:00那么punch_time在2024-06-01 12:00到2024-06-02 12:00都归属2024-06-01。更稳妥的做法是在shift表加一个boundary_time字段默认12:00表示从此时间之后开始的打卡才属于当日晚班。这样即使有下午班/晚班混合也能统一处理。5.2 现象同一个人同一分钟打两次卡统计出现迟到早退同时成立原因门禁考勤一体机可能重复上传数据或者在1秒内员工刷了两次指纹。如果程序没有对打卡记录去重MIN(first_punch)和MAX(last_punch)可能取了不同来源的重复记录甚至因为重复记录导致“上班卡”被取成下午那次。解决在attendance_record上做应用层去重以emp_id, punch_time为唯一键重复写入时忽略。如果怕合法情况同一秒打两次卡比如一次是进门一次是出门那就在punch_type里做区分统计时按punch_type分组而不是简单MIN/MAX。我给打卡表增加了一个source_batch_id字段用来标记导入批次按批次做幂等处理。5.3 现象请假审批中改先状态统计数据对不上员工被算成缺勤原因审批表里status有「待审/通过/驳回」三种状态统计SQL只过滤status1通过但业务上存在「先填报补卡审批还在走流程月底算薪时又截止」的场景更常见的是审批通过后HR手工改了打卡记录例如补卡但attendance_record的is_valid仍为1统计时把补卡时间和原始打卡都算进去导致一天出现了两次上班卡。解决补卡操作不要直接改attendance_record而是通过审批流新增一条approval_type4的补卡记录再在统计阶段用一条UPDATE attendance_record SET is_valid 0标记原异常卡或者给补卡记录维护一个「覆盖关系」统计时优先取补卡结果。我推荐前者因为考勤流水应该只追加、不修改修改原始打卡记录会让审计无从谈起。如果确实需要修改也要用update_time和操作人字段记录谁改的、什么时候改的。5.4 现象时区或夏令时切换打卡时间错乱原因考勤机用的UTC时间数据库用的北京时间或者部署的服务器时区被改成UTC查询时ORM自动做转换导致DATETIME显示与打卡机原始记录差8小时。国内通常没有夏令时但跨国企业或云端部署容易踩到。TIMESTAMP类型受时区设置影响DATETIME不受影响但如果程序端在写入时已经做了时区转换那错误在源头就埋下了。解决统一约定数据库连接串里serverTimezoneAsia/Shanghai所有时间字段存DATETIME后端程序也统一用上海时区解析。如果打卡机只能输出UTC时间就在采集服务里做显式转换后再写入不要依赖数据库自动转。另外考勤机的时间同步周期要缩短到每天一次否则机器时钟飘移会直接造成迟到早退误判。5.5 现象打卡表数据量一大按月统计从秒级变分钟级原因很多设计只在attendance_record建了emp_id punch_time联合索引但统计SQL是按punch_time范围查询所有员工用不上联合索引或者统计时多次JOINemployee_schedule每次都扫一遍排班表。当打卡记录到千万级时这种SQL基本跑不动。解决按月份做分区表。在 MySQL 里用PARTITION BY RANGE (YEAR(punch_time)*100MONTH(punch_time))每个分区对应一个月。这样统计时只扫描对应月分区而不是全表。如果业务上需要保留多年数据同时定期归档到冷存储。归档后热表只保留最近3个月历史月报走归档表再配合daily_attendance_result宽表查询十几秒的问题就基本消失了。6. 进阶给考勤表加一个归档策略和一张月报宽表让报表查询快10倍如果你已经把前面5章做完系统能跑通下一步就该考虑性能和长期维护了。这里分享一个我用了很多次的组合拳月度宽表 数据归档。月度宽表是区别于流水表的一张“结果表”字段直接是员工号、月份、应出勤天数、实际出勤天数、迟到次数、早退次数、请假小时数、加班小时数、缺勤天数。这张表的存在意义是把复杂的逐日计算收敛成一行。月底最后一天跑一次存储过程或定时任务从daily_attendance_result聚合出数据写入宽表。日常查询“张三这个月迟到几次”就变成单行主键查询几乎零延迟。归档策略要区分两类表。attendance_record流水表只保留当前自然年和前一年更早的数据移入attendance_record_archive表并按年分区。employee_schedule排班表同样归档到历史表不过保留周期可以长一些因为排班数据量小。归档本身不改变业务代码只需要在查询服务上做一个“当前表查不到就去归档表”的兜底逻辑。我习惯在归档时不删原表而是用ALTER TABLE ... RENAME TO把热表换成归档表再新建一张空的热表避免在业务高峰期做DELETE大批量数据。验证方法也值得说一下每个月末用一份独立的核对SQL对比attendance_record的原始打卡次数和daily_attendance_result里的正常迟到早退缺勤记录数是否对得上。对不上就说明有五类问题中的某一类重复记录、跨天归属错误、审批状态不完整、补卡覆盖漏判、归档边界拖了数据。这个核对脚本是我每次升级考勤系统后必跑的跑一次能安心一个月。我自己的习惯是第一次做完这套系统后故意拿一段有跨天班次、有重复打卡、有请假重叠的数据去跑结果总能逼出几个没考虑到的分支。别怕改表结构刚上线前两周就是拿来折腾的等报表数据稳定了再锁结构。这一套做完考勤系统数据库基本能支撑上千人的公司平稳跑两年以上。如果你正准备写那份「员工考勤管理系统数据库设计.doc」建议先照第2章画ER图再照第3章建表跑通第4章的统计SQL最后把第5章的几个坑写进文档的“设计约束”里文档的说服力会强很多。希望帮到你。本文还有配套的精品资源点击获取