GitHub: https://github.com/csushl/imooc-oa
涉及技术
MySQL、MyBatis、Alibaba Druid、Servlet、Vue、Element Plus.
项目亮点
项目基于MVC模式进行开发,通过MVC的设计使得各层之间有效解藕。
使用了Vue3、Element Plus前端技术。
本项目主要是请假流程的模块,针对于请假流程,设计了process flow任务流进行处理,这是底层设计的亮点.
对于MVC的理解
基于MVC的软件分层设计
每一层各司其职,从后往前依次推进(不允许出现夸层调用):
- 最底层是数据持久层,使用MyBatis的mapper完成数据库的增删改查。
- 业务逻辑层是负责处理响应业务逻辑的地方,并且是完成业务的主体方法。
- 控制层:接收前端传来的数据、根据前端传来的数据调用相应的业务逻辑、最后将业务逻辑返回的数据进行包装,返回给前端。
- 视图层指责为:向Servlet提交数据、从Servlet接收相应数据显示出来,前端进行渲染。
RBAC的实现原理
基于角色进行权限控制
RBAC的核心是角色,角色是进行数据绑定核心。
工作流程设计
请假流程
- 部门经理只允许批准本部门员工申请
- 部门经理请假需直接由总经理审批
- 总经理提起请假申请,系统自动批准通过
设计约束
- 每个请假单位对应一个审批流程
- 请假单创建后,按业务规则生成部门经理、总经理审批任务
- 审批任务的经办人只能审批自己辖区内的请假申请
- 所有审批任务“通过”,代表请假已经批准
- 任意审批任务“驳回”操作,其余审批任务取消,请假申请被驳回
- 请假流程中任意节点产生的操作都要生成对应的系统通知
数据库设计
RBAC表设计
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 80016 Source Host : localhost:3306 Source Schema : imooc_oa Target Server Type : MySQL Target Server Version : 80016 File Encoding : 65001 Date: 12/06/2021 18:14:52 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;
sys_node 系统功能定义表
DROP TABLE IF EXISTS `sys_node`;
CREATE TABLE `sys_node` (
`node_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'节点编号\',
`node_type` int(255) NOT NULL COMMENT \'节点类型 1-模块 2-功能\',
`node_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'节点名称\',
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT \'功能地址\',
`node_code` int(255) NOT NULL COMMENT \'节点编码,用于排序\',
`parent_id` bigint(20) NULL DEFAULT NULL COMMENT \'上级节点编号\',
PRIMARY KEY (`node_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_node
-- ----------------------------
INSERT INTO `sys_node` VALUES (1, 1, \'行政审批\', NULL, 1000000, NULL);
INSERT INTO `sys_node` VALUES (2, 2, \'通知公告\', \'/notice.html\', 1000001, 1);
INSERT INTO `sys_node` VALUES (3, 2, \'请假申请\', \'/leave_form.html\', 1000002, 1);
INSERT INTO `sys_node` VALUES (4, 2, \'请假审批\', \'/audit.html\', 1000003, 1);
sys_role 系统角色表
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`role_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'角色编号\',
`role_description` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'角色描述\',
PRIMARY KEY (`role_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES (1, \'业务岗角色\');
INSERT INTO `sys_role` VALUES (2, \'管理岗角色\');
sys_role_node 系统角色功能表
DROP TABLE IF EXISTS `sys_role_node`;
CREATE TABLE `sys_role_node` (
`rn_id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_id` bigint(20) NOT NULL,
`node_id` bigint(20) NOT NULL,
PRIMARY KEY (`rn_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_role_node
-- ----------------------------
INSERT INTO `sys_role_node` VALUES (1, 1, 1);
INSERT INTO `sys_role_node` VALUES (2, 1, 2);
INSERT INTO `sys_role_node` VALUES (3, 1, 3);
INSERT INTO `sys_role_node` VALUES (4, 2, 1);
INSERT INTO `sys_role_node` VALUES (5, 2, 2);
INSERT INTO `sys_role_node` VALUES (6, 2, 3);
INSERT INTO `sys_role_node` VALUES (7, 2, 4);
sys_role_user 系统角色用户表
DROP TABLE IF EXISTS `sys_role_user`;
CREATE TABLE `sys_role_user` (
`ru_id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_id` bigint(20) NOT NULL,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`ru_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_role_user
-- ----------------------------
INSERT INTO `sys_role_user` VALUES (1, 2, 1);
INSERT INTO `sys_role_user` VALUES (2, 2, 2);
INSERT INTO `sys_role_user` VALUES (3, 1, 3);
INSERT INTO `sys_role_user` VALUES (4, 1, 4);
INSERT INTO `sys_role_user` VALUES (5, 1, 5);
INSERT INTO `sys_role_user` VALUES (6, 2, 6);
INSERT INTO `sys_role_user` VALUES (7, 1, 7);
INSERT INTO `sys_role_user` VALUES (8, 1, 8);
INSERT INTO `sys_role_user` VALUES (9, 1, 9);
INSERT INTO `sys_role_user` VALUES (10, 1, 10);
sys_user 系统用户表
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'用户编号\',
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'用户名\',
`password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'密码\',
`employee_id` bigint(20) NOT NULL COMMENT \'员工编号\',
`salt` int(255) NOT NULL COMMENT \'盐值\',
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES (1, \'m8\', \'f57e762e3fb7e1e3ec8ec4db6a1248e1\', 1, 188);
INSERT INTO `sys_user` VALUES (2, \'t7\', \'dcfa022748271dccf5532c834e98ad08\', 2, 189);
INSERT INTO `sys_user` VALUES (3, \'t6\', \'76ce11f8b004e8bdc8b0976b177c620d\', 3, 190);
INSERT INTO `sys_user` VALUES (4, \'t5\', \'11f04f04054772bc1a8fdc41e70c7977\', 4, 191);
INSERT INTO `sys_user` VALUES (5, \'t4\', \'8d7713848189a8d5c224f94f65d18b06\', 5, 192);
INSERT INTO `sys_user` VALUES (6, \'s7\', \'044214e86e07d96c97de79a2222188cd\', 6, 193);
INSERT INTO `sys_user` VALUES (7, \'s6\', \'ecbd2f592ee65838328236d06ce35252\', 7, 194);
INSERT INTO `sys_user` VALUES (8, \'s5\', \'846ecc83bba8fe420adc38b39f897201\', 8, 195);
INSERT INTO `sys_user` VALUES (9, \'s4\', \'c1e523cd2daa02f6cf4b98b2f26585fd\', 9, 196);
INSERT INTO `sys_user` VALUES (10, \'s3\', \'89e89f369e07634fbb2286efffb9492b\', 10, 197);
SET FOREIGN_KEY_CHECKS = 1;
adm_department 部门表
DROP TABLE IF EXISTS `adm_department`;
CREATE TABLE `adm_department` (
`department_id` bigint(20) NOT NULL AUTO_INCREMENT,
`department_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
PRIMARY KEY (`department_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of adm_department
-- ----------------------------
INSERT INTO `adm_department` VALUES (1, \'总裁办\');
INSERT INTO `adm_department` VALUES (2, \'研发部\');
INSERT INTO `adm_department` VALUES (3, \'市场部\');
adm_employee 员工表
DROP TABLE IF EXISTS `adm_employee`;
CREATE TABLE `adm_employee` (
`employee_id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`department_id` bigint(20) NOT NULL,
`title` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`level` int(255) NOT NULL,
PRIMARY KEY (`employee_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of adm_employee
-- ----------------------------
INSERT INTO `adm_employee` VALUES (1, \'张晓涛\', 1, \'总经理\', 8);
INSERT INTO `adm_employee` VALUES (2, \'齐紫陌\', 2, \'部门经理\', 7);
INSERT INTO `adm_employee` VALUES (3, \'王美美\', 2, \'高级研发工程师\', 6);
INSERT INTO `adm_employee` VALUES (4, \'宋彩妮\', 2, \'研发工程师\', 5);
INSERT INTO `adm_employee` VALUES (5, \'欧阳峰\', 2, \'初级研发工程师\', 4);
INSERT INTO `adm_employee` VALUES (6, \'张世豪\', 3, \'部门经理\', 7);
INSERT INTO `adm_employee` VALUES (7, \'王子豪\', 3, \'大客户经理\', 6);
INSERT INTO `adm_employee` VALUES (8, \'段峰\', 3, \'客户经理\', 5);
INSERT INTO `adm_employee` VALUES (9, \'章雪峰\', 3, \'客户经理\', 4);
INSERT INTO `adm_employee` VALUES (10, \'李莉\', 3, \'见习客户经理\', 3);
请假流程中的表设计
adm_leave_form 请假申请表
DROP TABLE IF EXISTS `adm_leave_form`;
CREATE TABLE `adm_leave_form` (
`form_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'请假单编号\',
`employee_id` bigint(20) NOT NULL COMMENT \'员工编号\',
`form_type` int(255) NOT NULL COMMENT \'请假类型 1-事假 2-病假 3-工伤假 4-婚假 5-产假 6-丧假\',
`start_time` datetime(0) NOT NULL COMMENT \'请假起始时间\',
`end_time` datetime(0) NOT NULL COMMENT \'请假结束时间\',
`reason` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'请假事由\',
`create_time` datetime(0) NOT NULL COMMENT \'创建时间\',
`state` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'processing-正在审批 approved-审批已通过 refused-审批被驳回\',
PRIMARY KEY (`form_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 40 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
adm_process_flow 执行流程表
DROP TABLE IF EXISTS `adm_process_flow`;
CREATE TABLE `adm_process_flow` (
`process_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'处理任务编号\',
`form_id` bigint(20) NOT NULL COMMENT \'表单编号\',
`operator_id` bigint(20) NOT NULL COMMENT \'经办人编号\',
`action` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'apply-申请 audit-审批\',
`result` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT \'approved-同意 refused-驳回\',
`reason` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT \'审批意见\',
`create_time` datetime(0) NOT NULL COMMENT \'创建时间\',
`audit_time` datetime(0) NULL DEFAULT NULL COMMENT \'审批时间\',
`order_no` int(11) NOT NULL COMMENT \'任务序号\',
`state` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT \'ready-准备 process-正在处理 complete-处理完成 cancel-取消\',
`is_last` int(255) NOT NULL COMMENT \'是否最后节点,0-否 1-是\',
PRIMARY KEY (`process_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 96 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
sys_notice 消息通知表
DROP TABLE IF EXISTS `sys_notice`;
CREATE TABLE `sys_notice` (
`notice_id` bigint(20) NOT NULL AUTO_INCREMENT,
`receiver_id` bigint(20) NOT NULL,
`content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
`create_time` datetime(0) NOT NULL,
PRIMARY KEY (`notice_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 29 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
敏感数据加密
使用MD5加盐设计。MD5可以产生出128的散列值,可以唯一标识原数据。
MD5特点:
- 压缩性,MD5生成的摘要长度固定
- 抗修改,源数据哪怕有一个字节变化,MD5也会有巨大差异
- 不可逆,无法通过MD5反向推算源数据
项目中应用:
/**
* 对源数据加盐混淆后生成MD5摘要
* @param source 源数据
* @param salt 盐值
* @return MD5摘要
*/
public static String md5Digest(String source,Integer salt){
char[] chars = source.toCharArray();
for (int i= 0 ; i< chars.length ; i++){
chars[i] = (char) (chars[i] + salt);
}
String target = new String(chars);
//System.out.println(target);
String md5 = DigestUtils.md5Hex(target);
return md5;
}