ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

职工信息管理系统数据库课程设计:六表结构与避坑要点

职工信息管理系统数据库课程设计:六表结构与避坑要点 简介一份完整的职工信息管理系统数据库课程设计文档面向计算机相关专业学生和数据库入门者帮助其掌握从需求分析到数据库实施的全流程设计方法。文档围绕企业职工管理场景展开覆盖基本信息、奖罚、培训、薪资、部门信息等业务模块依次完成需求分析、数据流程图绘制、数据字典构建、概念结构设计、逻辑结构设计、物理结构设计以及数据库实施等环节并配以创建数据库和创建数据表的SQL语句示例最后附有课程设计心得。压缩包内共1个doc文件整体仅154KB内容紧凑、结构完整既可作为课程设计报告模板也可作为数据库实践入门参考。该资源已有48人学习浏览特别适合正在完成类似课题、需要完整案例和规范开发流程参照的高校学生使用。1. 职工信息管理系统数据库课程设计一份能直接用的六表设计但有两个坑要先填拿到这份职工信息管理系统数据库课程设计文档第一反应是它把数据库设计的完整生命周期走了一遍从需求分析、数据字典、E-R 图一直到建库建表 SQL 都给全了这在课程设计里属于少见的完整素材。整套设计围绕职工、部门、奖罚、培训、薪资、登录信息六个对象展开用 SQL Server 2012 落地前端 Java 访问六张表的主键、字段类型、长度全部给了具体值照着敲就能跑通一个能增删改查的员工管理系统。但如果你打算直接拿建表语句去建库会踩到两个隐蔽的字段矛盾一个在奖罚表一个在培训表。这份资源适合正在做数据库课程设计、需要参考完整设计文档或需要改造成真实管理系统的学生和入门开发者。2. 需求分析与数据字典六个模块对应六张表先看处理对象再动手建表2.1 从需求文档里提炼出六个处理对象需求分析阶段最容易犯的错是上来就画表跳过对象梳理。这份文档的优点是先明确了软件处理对象职工系统登录信息、在职员工基本信息、职工奖罚信息、职工培训信息、薪资信息、部门信息。这六个对象后来直接映射成六张表模块边界很清楚。先看模块拆分系统管理负责用户密码管理、添加用户、修改密码、退出系统职工基本信息模块管编号、姓名、出生日期、性别、婚姻状态、职务、转正时间、学历、就职状态奖罚信息模块管职工编号、姓名、奖罚时间、地点、原因和备注培训信息模块管培训编号、培训天数、培训费用、培训内容薪资信息模块管基本工资、福利、奖金、薪资计算方式、实发工资部门信息模块管部门编号、部门名称、部门人数。这六个模块的划分直接决定了表结构后面所有设计都围绕它们展开。我在做类似系统时一般会多走一步把每个模块的输入输出列一遍再定表比如奖罚信息是谁录入的、谁查询的、按什么条件查询这些都会影响字段设计。文档里没有细化到这个程度但对课程设计来说模块划分已经足够支撑后续的 E-R 图和建表。2.2 六张表的字段和主键设计通过数据字典可以得到六张表的完整定义。职工基本信息表 EmployeeInformation 有 E_Number 到 E_Remark 共 13 个字段覆盖了一名在职员工从入职到转正的核心信息奖罚表 EncouragementPunishInformation 有 EP_Number、EP_Name、EP_Date、EP_Address、EP_Causation、EP_Remark 六个字段培训表 TrainInformation 有 T_Number、T_Content、T_Name、T_Date、T_Money 五个字段薪资表 WageInformation 有 W_Number、W_Name、W_BasicWage、W_Boon、W_Bonus、W_CountMethod、W_FactWage 七个字段部门表只有三个字段用户表 UserInformation 有用户编号、用户名、密码、权限四个字段。字段类型上有几个值得注意的选择所有日期字段都用 varchar(30) 而不是 SQL Server 2012 自带的 date 或 datetime 类型薪资和培训费用用 int姓名用 varchar(20) 或 varchar(30)备注给到 varchar(500)。这种设计在课程设计里很常见因为 Java 端处理 varchar 不需要做类型转换插入时直接传字符串即可。但从数据库规范角度讲日期字段用 varchar 会丢失日期类型的约束和比较能力这个问题的具体影响在后面物理设计和避坑章节详细展开。设备参数字典里 EP_Number 的说明是“员工编号”但建表语句里它被定义成了自增主键这是一个必须在实施前解决的矛盾稍后专门讲。2.3 数据流程图和业务流程图文档里的两幅图传达了哪些信息文档给出了系统业务流程图和总数据流图。业务流程图展示的是用户登录后分管理员和普通员工两个端口管理员能管理职工信息普通员工只能查询和修改自己的密码。这个流程决定了 UserInformation 表要有权限字段也决定了登录模块要有权限判断。数据流图则展示了数据如何流动录登录信息、录入员工档案、员工奖惩查询、公司部门设置、考勤记录查询等都在一个闭环里。这张图最大的价值是明确了系统的数据源头和流向——员工档案数据来自录入奖惩数据来自记录部门数据来自设置登录数据来自用户注册。看流程图时我一般会顺手标注哪些是静态数据哪些是动态数据文档里也提到了这一点静态表和动态表分开设计六张表里 UserInformation 和 DepartmentInformation 相对静态奖罚、培训、薪资是典型的动态表。3. 概念结构与逻辑结构设计从 E-R 图到关系模式的转换细节3.1 总 E-R 图里隐藏的三个关系归属、获得、进行概念结构设计阶段文档给出了总 E-R 图和六个分 E-R 图。总 E-R 图里的实体包括部门、职工、奖罚、培训、薪资联系包括职工属于部门、职工获得薪资、职工受到奖罚、职工进行培训。把这些联系转换成关系模式时有一条最基本的规则实体变表联系看类型。一对多联系把一方主键放进多方表作外键多对多联系需要单独建一张关联表。在这套设计里部门和职工是一对多联系一个部门有多个职工转换时把部门编号放入职工表即可。职工和奖罚、培训、薪资都是一对多联系职工一条记录对应多条奖罚记录或多条薪资记录转换时在奖罚表、培训表、薪资表里保留职工编号字段但由于文档中的建表语句把 EP_Number 和 T_Number 设计成了自增主键这个关联关系实际上被架空了原文建表 SQL 里没有体现出任何一个外键关系。真正符合规范的做法是奖罚表的 EP_Number 改为 E_Number并设置外键约束。3.2 分 E-R 图的属性检查登录取名其余取编号查看各分 E-R 图时我有一个发现薪资信息表分 E-R 图里列出了 W_Number、W_Name、W_BasicWage、W_Boon、W_Bonus、W_CountMethod、W_FactWage其中 W_Name 是职工姓名W_Number 是职工编号。奖罚表同样如此EP_Number 是职工编号EP_Name 是职工姓名。这意味着这几张表里同时存了职工编号和职工姓名从数据库第三范式角度看属于冗余存储姓名应该通过编号关联从职工信息表查出而不是冗余到每一张表中。但在实际的小型管理系统中这种冗余是刻意为之的——查询奖罚列表时如果每次都要 join 职工表开发量和查询成本都会上升而冗余姓名字段让单表查询就能直接显示。一个值得注意的细节是分 E-R 图里系统登录信息实体用的是 User_ID、User_Name、Password、Popedom 四个属性这和建表语句 UserInformation 表的结构一致但登录信息实体的 User_ID 到底对应职工编号还是独立的自增编号在文档中没有明确说明。从需求角度看每个职工在建立时默认为其分配一个用户名和密码那么这个 User_ID 应该与 E_Number 对应但从建表语句看 User_ID 是独立自增主键并没有和职工表建立关联。这是文档中另一个隐蔽的坑会在避坑章节展开。3.3 从 E-R 图到关系模式的转换规则三条可直接套用的经验E-R 图转关系模式有固定的套路把文档中的设计归纳成三条规则实体转表实体的属性转字段一对多联系将“一”方主键并入“多”方表多对多联系新建关联表关联表包含双方主键。这套设计的六个实体转换结果如下UserInformation(User_ID, User_Name, Password, Popedom)DepartmentInformation(D_Number, D_Name, D_Count)EmployeeInformation(E_Number, E_Name, E_Sex, E_BornDate, E_Marriage, E_PoliticsVisage, E_SchoolAge, E_EnterDate, E_InDueFormDate, E_Department, E_Headship, E_Estate, E_Remark)TrainInformation(T_Number, T_Content, T_Name, T_Date, T_Money)EncouragementPunishInformation(EP_Number, EP_Name, EP_Date, EP_Address, EP_Causation, EP_Remark)WageInformation(W_Number, W_Name, W_BasicWage, W_Boon, W_Bonus, W_CountMethod, W_FactWage)这套关系模型可以用但人工识别两个隐患一是薪资表的 W_FactWage实发工资是可计算字段理论上应通过基本工资加福利加奖金减去扣款计算得出文档虽然设计了 W_CountMethod 字段用于记录薪资计算方式但并没有把计算逻辑落实到 SQL 约束或存储过程层面导致实发工资只能靠 Java 端计算后写入二是部门表 D_Count 字段存了部门人数这个值同样可以通过统计 EmployeeInformation 得出单独存储需要人工维护一致性部门人员变动时如果忘记更新会出现数据不一致。4. 物理设计和数据库实施建库建表 SQL 落地与 JDBC 连接的实操配置4.1 物理结构设计索引策略和存储设置物理结构设计阶段文档明确说使用了索引法在经常需要搜索的列和主关键字上建立唯一索引。具体到这个系统主键上的聚集索引由 identity(1,1) primary key 自动创建不需要额外处理。需要手工考虑的索引应该加在频繁查询的列上职工姓名 E_Name、部门名称 D_Name、奖罚原因 EP_Causation 这类经常作为查询条件的字段都值得加非聚集索引。数据文件和日志文件的存放位置取决于安装 SQL Server 2012 的电脑配置默认路径一般是 C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA。如果是在自己电脑上做课程设计保持默认即可生产环境则建议把数据文件和日志文件分盘存放日志文件放独立磁盘可以有效避免日志增长拖累数据读写性能。4.2 建库建表 SQL照着敲之前先解决 identity 与业务编号的矛盾实施阶段文档只给出了建库和一个简化版建表语句需要补完整。先看建库语句CREATE DATABASE EmployeeInformationMS;这个命令会创建名为 EmployeeInformationMS 的数据库。SQL Server 2012 中执行后可以接着用 USE EmployeeInformationMS 切换上下文后续建表语句都在这个库下执行。我一般会习惯在建库语句后用 GO 分隔批处理避免上下文切换失败。然后是完整的建表语句。这里有一个细节需要特别注意文档里的原始建表语句在几个表中使用了 identity(1,1) 作为主键但如果某个字段在数据字典里被定义为“员工编号”它就不应该是自增值而应该是对应 EmployeeInformation.E_Number 的外键。建议按如下方式修正后建表CREATE TABLE UserInformation ( User_ID INT IDENTITY(1,1) PRIMARY KEY, User_Name VARCHAR(20) NOT NULL, Password VARCHAR(20) NOT NULL, Popedom VARCHAR(20) NOT NULL ); CREATE TABLE DepartmentInformation ( D_Number INT IDENTITY(1,1) PRIMARY KEY, D_Name VARCHAR(20), D_Count VARCHAR(20) ); CREATE TABLE EmployeeInformation ( E_Number INT IDENTITY(1,1) PRIMARY KEY, E_Name VARCHAR(20) NOT NULL, E_Sex VARCHAR(2), E_BornDate VARCHAR(30), E_Marriage VARCHAR(4), E_PoliticsVisage VARCHAR(20), E_SchoolAge VARCHAR(20), E_EnterDate VARCHAR(30), E_InDueFormDate VARCHAR(30), E_Department VARCHAR(20), E_Headship VARCHAR(20), E_Estate VARCHAR(20), E_Remark VARCHAR(500) );以上是职工表和用户表的核心建表语句后面几个表按文档的字段列表补全即可。这里我做了两个修正一是把 NOT NULL 约束显式写出原文档里所有字段都标了 NOT NULL建表时如果不加约束程序端就必须非空判断兜底二是保留了 identity(1,1) 作为主键但注意这个自增编号是表中记录编号不是业务意义上的员工编号。在奖罚表、培训表和薪资表中应该使用普通整数存放员工编号并建立外键关联而不是也设置成 identity这一点在本章后面专门说明。4.3 Java 连接 SQL Server 2012驱动、URL 和登录验证文档声明前端用 Java后台用 SQL Server 2012但没有给出 Java 连接数据库的代码。课程设计场景下最常用的是 JDBC 直连方式代码如下import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class DBUtil { private static final String URL jdbc:sqlserver://localhost:1433;DatabaseNameEmployeeInformationMS; private static final String USER sa; private static final String PASSWORD 123456; public static Connection getConnection() throws Exception { Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); return DriverManager.getConnection(URL, USER, PASSWORD); } public static void main(String[] args) { String sql SELECT User_Name, Popedom FROM UserInformation WHERE User_Name ? AND Password ?; try (Connection conn getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, admin); ps.setString(2, 123456); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { System.out.println(rs.getString(User_Name) - rs.getString(Popedom)); } } } catch (Exception e) { e.printStackTrace(); } } }这段代码做了登录验证根据用户名和密码参数查询 UserInformation 表返回用户权限字段。使用 PreparedStatement 而不是拼 SQL 字符串是因为拼接方式在用户输入密码包含单引号时会直接报 SQL 语法错误而防止 SQL 注入是顺手的事。需要说明的是 driver 类名 com.microsoft.sqlserver.jdbc.SQLServerDriver 对应 Microsoft JDBC Driver 4.x 版本如果用的是更高版本驱动包名不变但需要将 sqljdbc4.jar 或 mssql-jdbc-*.jar 放到项目的 classpath 中。URL 中的 1433 是 SQL Server 默认端口如果你的 SQL Server 实例用了命名实例或改了端口需要同步修改这一行。sa 是系统管理员账号课程设计环境通常直接使用生产环境建议单独建一个最小权限的数据库用户。4.4 补充增删改查系统管理模块和职工信息模块的常用操作文档对六个模块的功能描述比较全面但没有给出任何 Java 实现代码。课程设计答辩时增删改查是必考环节这里补一个职工信息表的基础操作模板覆盖添加职工、按编号查询、修改职务和删除记录四种典型操作public class EmployeeDao { // 添加职工 public int insertEmployee(Employee emp) { String sql INSERT INTO EmployeeInformation (E_Name, E_Sex, E_BornDate, E_Marriage, E_PoliticsVisage, E_SchoolAge, E_EnterDate, E_InDueFormDate, E_Department, E_Headship, E_Estate, E_Remark) VALUES (?,?,?,?,?,?,?,?,?,?,?,?); // try-with-resources 获取连接并执行返回受影响行数 } // 按编号查询 public Employee findById(int number) { String sql SELECT * FROM EmployeeInformation WHERE E_Number ?; // 查询结果集映射到 Employee 对象 } // 修改职务 public int updateHeadship(int number, String newHeadship) { String sql UPDATE EmployeeInformation SET E_Headship ? WHERE E_Number ?; // 返回更新行数 } // 按编号删除 public int deleteById(int number) { String sql DELETE FROM EmployeeInformation WHERE E_Number ?; // 返回删除行数 } }这套 DAO 模板把查询条件全部参数化增删改查四条路径都走 PreparedStatement。有一点需要提醒删除职工前要先确认该职工是否有级联的奖罚、培训、薪资记录否则会出现孤儿数据。原文档里没有外键约束所以这种一致性问题只能靠 Java 端逻辑兜底。5. 避坑指南字段矛盾、日期乱用和缺失的外键约束5.1 奖罚表的 EP_Number 到底是员工编号还是自增主键现象按文档数据字典的描述EP_Number 字段类型是 int说明是“员工编号”但按文档建表语句执行后EP_Number 变成了自增主键插入第一条奖罚记录时它自动变为 1如果这个职工的 E_Number 恰好是 1001奖罚记录和职工记录根本对不上。原因数据字典和建表语句由文档作者分阶段完成概念设计阶段把 EP_Number 设计成员工编号物理设计阶段又图省事给它加上了 identity(1,1)两个阶段的口径没有对齐。解决确定业务关联键。正确设计是奖罚表用独立自增主键 EP_ID 作为记录编号另外设置 EP_Number 或 E_Number 作为员工编号外键关联 EmployeeInformation(E_Number)。修改后的建表语句应该是CREATE TABLE EncouragementPunishInformation ( EP_ID INT IDENTITY(1,1) PRIMARY KEY, E_Number INT NOT NULL, EP_Name VARCHAR(30), EP_Date VARCHAR(30), EP_Address VARCHAR(50), EP_Causation VARCHAR(200), EP_Remark VARCHAR(500), CONSTRAINT FK_EP_Employee FOREIGN KEY (E_Number) REFERENCES EmployeeInformation(E_Number) );EP_Name 字段的冗余设计保留因为它承载了列表页直接展示的功能需求。加外键约束后删职工时如果该职工存在奖罚记录SQL Server 默认会阻止删除需要程序先处理奖罚记录或设置级联删除。课程设计里我更推荐在 Java 端先删子表再删主表不推荐数据库级联删除因为级联删除一旦误触发数据恢复成本极高。5.2 培训表用培训员工姓名字段做关联没有唯一性保证现象培训表 TrainInformation 的字段是 T_Number、T_Content、T_Name、T_Date、T_Money其中 T_Name 是“培训员工姓名”整张表只有 T_Number 自增主键和这一个姓名字段能和职工关联。当公司有两个同名职工时培训记录无法确定到底属于哪一个人。原因设计者为了让培训表能单表查询出员工姓名直接把姓名冗余进表且没有同时冗余员工编号这是一个常见的课程设计错误。姓名不是唯一键不能作为关联字段。解决培训表增加 E_Number 字段与 EmployeeInformation 建立外键。查询培训记录时如果需要显示姓名通过 join 职工表获取或者保留 T_Name 作为冗余展示字段但关联判断一律使用 E_Number。原则是展示字段可以冗余关联字段必须使用编号。5.3 日期字段全部用 varchar(30)区间查询只能字符串比较现象E_BornDate、E_EnterDate、E_InDueFormDate、EP_Date 都是 varchar(30)。按入职年份查询职工时如果年份存在 2024 和 2025 两种值用 BETWEEN 做字符串比较得到的结果不一定符合日期语义。原因设计时图 Java 端插入方便所有日期统一用字符串。但字符串比较是按字典序进行的只要日期格式统一为 yyyy-MM-dd字典序恰好等于时间序不会出问题怕的是录入格式不一致一条是 2024-3-5另一条是 2024-03-05排序和比较都会乱。解决如果允许修改表结构建议把日期字段改为 date 或 datetime 类型Java 端用 java.time.LocalDate 配合 PreparedStatement 的 setObject 方法写入。如果表结构不允许动至少要在 Java 端统一日期格式用 SimpleDateFormat 或 DateTimeFormatter 格式化成 yyyy-MM-dd 再入库数据库端对这种固定格式的 varchar 做字符串比较就是安全的。这个坑我在实际项目中见过多次varchar 存日期给查询带来的风险不是立刻爆发的而是等系统跑了大半年、数据量上来之后突然有一天有人要查某个月的所有记录时才发现格式早乱了。5.4 六张表之间零外键约束删部门后职工表残留孤立部门名现象部门信息表里删除了某个部门后职工基本信息表里还有员工的 E_Department 指向这个已经不存在的部门名称查询员工列表时显示一个空部门。原因表设计阶段没有建立任何外键关系部门信息只以名称形式存进职工表数据库层面无法感知部门与职工之间的引用关系。这和文档在概念设计阶段画的“职工属于部门”联系是矛盾的。解决两种方案。方案一是在建表时给 EmployeeInformation 的 E_Department 增加外键约束引用 DepartmentInformation(D_Name)但部门名称本身不是主键需要在部门表先给 D_Name 加唯一约束才能被引用。方案二更简单Java 端在做删除部门操作前先执行一条 UPDATE 语句把该部门下所有职工的 E_Department 改为空或“待分配”再执行部门删除。课程设计答辩时被问到数据一致性能说清楚这一步就足够了。5.5 薪资表没有唯一约束同一个员工可以插入多条薪资记录现象WageInformation 表主键 W_Number 是自增编号员工编号 W_Number 仅仅是普通字段同一员工可以在表中存在多条基本工资记录无法区分哪条是当前有效薪资。原因薪资表的插入动作由 Java 端调用每次提交工资时都执行 INSERT表本身对员工编号没有唯一约束也没有“生效时间”字段。解决最贴近课程设计场景的做法是加一条 Java 端逻辑每次插入薪资记录前先执行“UPDATE WageInformation SET W_FactWage 0 WHERE W_Number 当前员工编号”使历史记录失效然后再插入新记录。更进一步的做法是给薪资表增加生效日期字段 W_EffectDate用日期来区分历史薪资和当前薪资主键改为 (W_Number, W_EffectDate) 联合主键。这一条在原文档里完全没有覆盖建议自己动手补上答辩时很加分。提示以上五个避坑点不是修改建议而是这份资源直接投入复现前必须处理的前提问题。其中 5.1 和 5.2 是字段语义冲突不解决会导致数据错乱5.3 到 5.5 是设计规范问题不解决会导致运营期数据质量下降。6. 用三条 SQL 验证设计质量并顺手完成一次索引体检拿到任何一份数据库课程设计我第一个习惯是先跑三条验证性 SQL确认表结构与设计文档一致再确认系统功能真正可用。第一条验证系统登录功能是否可用也就是用户按账号密码查询权限SELECT User_Name, Popedom FROM UserInformation WHERE User_Name admin;这条语句验证的是登录模块的数据通路。如果返回空结果说明用户表里还没有初始化管理员账号需要在实施阶段插入一条默认管理员数据。我一般会在建完表后立刻执行一条 INSERT 语句初始化管理员账号避免程序端首次登录直接撞空表。第二条验证员工、部门、薪资三表联查能否跑通这条 SQL 能模拟“按部门统计职工薪资总额”的真实业务场景SELECT d.D_Name, COUNT(e.E_Number) AS emp_count, SUM(w.W_FactWage) AS total_wage FROM DepartmentInformation d LEFT JOIN EmployeeInformation e ON d.D_Number e.E_Department LEFT JOIN WageInformation w ON e.E_Number w.W_Number GROUP BY d.D_Name;这里因为原表设计没有外键e.E_Department 存的是部门名称字符串而 d.D_Number 是部门编号实际执行时需要把关联条件改成 e.E_Department d.D_Name或者在建表时就把职工表的部门字段设计为部门编号。我在拆这份资源时实际是把职工表的 E_Department 改成了 D_Number 才能让这条 SQL 顺畅执行。第三条验证索引策略是否合理。在职工信息管理系统中按姓名查询是最常见的操作之一检查一下 E_Name 上有没有索引SELECT name, type_desc FROM sys.indexes WHERE object_id OBJECT_ID(EmployeeInformation);如果结果里只有主键索引说明姓名字段还没有辅助索引。对小数据量的课程设计来说影响不大但如果要演示查询性能优化给 E_Name 加一个非聚集索引是很好的切入点CREATE NONCLUSTERED INDEX IX_Employee_Name ON EmployeeInformation(E_Name);加完索引后再跑一遍按姓名查询的语句观察执行计划是否走索引查找而不是表扫描。这一步做完整个系统从设计到调优就形成了闭环答辩时可以明确说出每个模块用什么索引支撑。进阶建议方面如果想把这份课程设计从“能跑”提升到“经得起追问”有三个值得动手的点一是把薪资计算逻辑落成 SQL Server 的触发器或存储过程让 W_FactWage 自动计算二是把登录权限判断从简单的字符串相等升级为基于角色的权限表设计三是给所有表增加创建时间和更新时间字段用 DEFAULT GETDATE() 自动维护。回过头看这份文档它真正的价值不在建表语句本身而在于把数据库设计的六步流程完整演示了一遍。数据字典和 E-R 图部分尤其值得精读这两块通常是课程设计里最容易被敷衍的部分而它们恰恰是后续所有设计的依据。我从文档里踩到的两个字段矛盾说起再到外键缺失和日期类型乱用都是在提醒一件事设计阶段的口径不一致最后都会变成实施阶段的改表成本。从那以后我每拆一份数据库课程设计都会先做一次字段语义核查确认数据字典和建表语句对同一字段的描述完全一致再开始动手建库。这套流程值得你在自己的项目里也强制走一遍希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进