作者主页:编程指南针
简介:Java领域优质创作者、CSDN博客专家 Java项目、简历模板、学习资料、面试题库、技术互助
文末获取源码
项目编号:BS-XX-003
前言:
当今互联网技术发展的非常迅速,而以往的定点办公模式已经不能满足现代人们的需要,迫切地需要我们设计一款办公自动化的OA系统才可以解决目前日益突出的问题。本系统采用了Java开发工具IntelliJ IDEA,数据库MySQL和轻量级框架SpringMVC,Hibernate,Spring开发出基于JavaEE的文珺OA系统。本课题主要实现了用户,部门,岗位等模块的增删改查,请假流程的审批,公共相册管理,个人信息管理,公告管理等功能。其中岗位管理中实现了对不同用户角色的权限管理,根据不同用户的角色授权登录系统而划分不同的功能模块。核心工作流采用自主设计的方式实现,无风险控制流程管理,解决了定点办公方式的局限性,最终实现信息以无线的方式进行流转,对提高人们的办公效率和改善企业的办公生产能力,减少企业运营成本有着重大的意义。
一,项目介绍
本系统基于springboot+ssm+shiro来进行开发实现,数据库采用mysql,开发工具为IDEA或Eclipse.利用redis进行数据缓存存储处理,使用 quartz来进行定时任务执行处理。
于SpingBoot2.0轻量级的java快速开发框架。以Spring Framework为核心容器, Spring MVC为模型视图控制器,Mybatis Plus为数据访问层, Apache Shiro为权限授权层, Redis为分布式缓存,Quartz为分布式集群调度,JSP作为前端页面引擎, 采用JSTL标签库封装组件的开源框架。
项目特点:
开箱即用,节省开发时间,提高开发效率代码全部开源,持续更新,共同维护支持分布式部署,session统一由redis进行管理基于SpringBoot,简化了大量项目配置和maven依赖,让您更专注于业务开发使用分层设计,分为dao,service,Controller,view层,层次清楚,低耦合,高内聚提供了诸多的UI组件友好的代码结构及注释,便于阅读及二次开发灵活的权限控制, 整合shiro,可控制到页面或按钮,满足绝大部分的权限需求,优化权限注解方便权限配置日志记录采用aop(LogAop类)方式,可对用户所有操作进行记录数据统计报表:丰富的报表统计功能集成jsp页面,采用标准JSTL标签库对常用组件进行封装,便于将传统项目过度到springboot组件库丰富,对常用页面组件进行了代码封装,提高开发效率前端页面简洁优美,支持移动端
系统功能较为全面,可根据需求删减相关功能实现。
二,项目展示
部分功能展示如下:
![](https://img-blog.csdnimg.cn/20201028141311348.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
用户管理
![](https://img-blog.csdnimg.cn/20201028141320187.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
部门管理
![](https://img-blog.csdnimg.cn/20201028141331814.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
菜单管理
![](https://img-blog.csdnimg.cn/20201028141331866.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
角色管理
![](https://img-blog.csdnimg.cn/20201028141342963.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
数据字典管理
![](https://img-blog.csdnimg.cn/2020102814134346.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
日志管理
![](https://img-blog.csdnimg.cn/20201028141354467.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
个人办公-系统消息
![](https://img-blog.csdnimg.cn/20201028141354440.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
会议管理
![](https://img-blog.csdnimg.cn/20201028141405471.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
日报管理
![](https://img-blog.csdnimg.cn/20201028141405497.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
日程管理
![](https://img-blog.csdnimg.cn/20201028141417975.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
任务管理
![](https://img-blog.csdnimg.cn/2020102814141833.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
目标管理
![](https://img-blog.csdnimg.cn/20201028141427734.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
人力资源模块:包含档案管理、考勤管理、薪资管理、招聘管理、培训管理几大模块,不再一一展示。
![](https://img-blog.csdnimg.cn/20201028141427732.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3doaXJsd2luZDUyNg==,size_16,color_FFFFFF,t_70)
三,核心代码
package com.active4j.hr.hr.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.active4j.hr.base.controller.BaseController;
import com.active4j.hr.common.constant.SysConstant;
import com.active4j.hr.core.model.AjaxJson;
import com.active4j.hr.system.entity.SysDeptEntity;
import com.active4j.hr.system.entity.SysDicValueEntity;
import com.active4j.hr.system.service.SysDeptService;
import com.active4j.hr.system.util.SystemUtils;
import lombok.extern.slf4j.Slf4j;
/**
* @title OaHrDepartController.java
* @description
oa 部门管理
* @time 2022年4月9日 上午9:10:55
* @author znz
* @version 1.0
*/
@Controller
@RequestMapping("/oa/hr/depart")
@Slf4j
public class OaHrDepartController extends BaseController {
@Autowired
private SysDeptService sysDeptService;
/**
*
* @description
* 组织架构-部门信息跳转
* @params
* @return ModelAndView
* @author guyp
* @time 2020年4月9日 上午9:47:20
*/
@RequestMapping("/oadepart")
public ModelAndView oaDepart(HttpServletRequest req) {
//查询数据字典
List types = SystemUtils.getDictionaryLst(SysConstant.DIC_DEPART_TYPE);
req.setAttribute("types", types);
return new ModelAndView("oa/hr/organization/oadepart");
}
/**
*
* @description
* 获取部门信息
* @params
* @return AjaxJson
* @author guyp
* @time 2020年4月9日 下午2:27:43
*/
@RequestMapping("/getDepart")
@ResponseBody
public AjaxJson getDepart(String id, HttpServletRequest request) {
AjaxJson j = new AjaxJson();
try{
if(StringUtils.isNotEmpty(id)) {
Map map = new HashMap();
//获取部门信息
SysDeptEntity depart = sysDeptService.getById(id);
map.put("depart", depart);
//获取父部门信息
if(null != depart.getParentId()){
SysDeptEntity parent = sysDeptService.getById(depart.getParentId());
map.put("parentName", parent.getName());
map.put("parentId", parent.getId());
}
j.setAttributes(map);
}
}catch(Exception e) {
log.error("获取部门信息报错,错误信息:{}", e.getMessage());
j.setSuccess(false);
j.setMsg("获取部门信息错误");
e.printStackTrace();
}
return j;
}
}
package com.active4j.hr.hr.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.active4j.hr.base.controller.BaseController;
import com.active4j.hr.core.annotation.Log;
import com.active4j.hr.core.beanutil.MyBeanUtils;
import com.active4j.hr.core.model.AjaxJson;
import com.active4j.hr.core.model.LogType;
import com.active4j.hr.hr.entity.OaHrJobEntity;
import com.active4j.hr.hr.service.OaHrJobService;
import lombok.extern.slf4j.Slf4j;
/**
*
* @title OaHrJobController.java
* @description
oa 岗位管理
* @time 2022年4月9日 下午3:46:44
* @author znz
* @version 1.0
*/
@Controller
@RequestMapping("/oa/hr/job")
@Slf4j
public class OaHrJobController extends BaseController {
@Autowired
private OaHrJobService oaHrJobService;
/**
*
* @description
* 组织架构-部门信息跳转
* @params
* @return ModelAndView
* @author guyp
* @time 2020年4月9日 上午9:47:20
*/
@RequestMapping("/oajob")
public ModelAndView oaJob(HttpServletRequest req) {
return new ModelAndView("oa/hr/organization/oajob");
}
/**
*
* @description
* 获取岗位信息
* @params
* @return AjaxJson
* @author guyp
* @time 2020年4月9日 下午2:27:43
*/
@RequestMapping("/getJob")
@ResponseBody
public AjaxJson getJob(String id, HttpServletRequest request) {
AjaxJson j = new AjaxJson();
try{
if(StringUtils.isNotEmpty(id)) {
Map map = new HashMap();
//获取岗位信息
OaHrJobEntity job = oaHrJobService.getById(id);
map.put("job", job);
//获取父岗位信息
if(null != job.getParentId()){
OaHrJobEntity parent = oaHrJobService.getById(job.getParentId());
map.put("parentName", parent.getJobName());
map.put("parentId", parent.getId());
}
j.setAttributes(map);
}
}catch(Exception e) {
log.error("获取岗位信息报错,错误信息:{}", e.getMessage());
j.setSuccess(false);
j.setMsg("获取岗位信息错误");
e.printStackTrace();
}
return j;
}
/**
*
* @description
* 岗位保存
* @params
* @return AjaxJson
* @author guyp
* @time 2020年4月9日 下午4:18:11
*/
@RequestMapping("/save")
@ResponseBody
@Log(type = LogType.save, name = "保存部门信息", memo = "新增或编辑保存了部门信息")
public AjaxJson save(OaHrJobEntity job, HttpServletRequest request) {
AjaxJson j = new AjaxJson();
try {
if(StringUtils.isEmpty(job.getParentId())) {
job.setLevel(0);
job.setParentId(null);
}else {
OaHrJobEntity parent = oaHrJobService.getById(job.getParentId());
job.setLevel(parent.getLevel() + 1);
}
if(StringUtils.isNotEmpty(job.getParentId()) && StringUtils.equals(job.getParentId(), job.getId())) {
j.setSuccess(false);
j.setMsg("上级岗位不能选择自己,请重新选择");
return j;
}
if (StringUtils.isNotEmpty(job.getId())) {
//编辑保存
OaHrJobEntity tmp = oaHrJobService.getById(job.getId());
MyBeanUtils.copyBeanNotNull2Bean(job, tmp);
if(StringUtils.isEmpty(job.getParentId())) {
tmp.setParentId(null);
}
oaHrJobService.saveOrUpdate(tmp);
}else {
//新增保存
oaHrJobService.save(job);
}
}catch(Exception e) {
log.error("保存岗位信息报错,错误信息:" + e.getMessage());
j.setSuccess(false);
j.setMsg("保存岗位错误");
e.printStackTrace();
}
return j;
}
/**
*
* @description
* 删除岗位
* @params
* @return AjaxJson
* @author guyp
* @time 2020年4月9日 下午4:16:54
*/
@RequestMapping("/del")
@ResponseBody
@Log(type = LogType.del, name = "删除岗位信息", memo = "删除了岗位信息")
public AjaxJson del(OaHrJobEntity job, HttpServletRequest request) {
AjaxJson j = new AjaxJson();
try {
if(StringUtils.isNotEmpty(job.getId())) {
List lstJobs = oaHrJobService.getChildJobsByJobId(job.getId());
if(null != lstJobs && lstJobs.size() > 0) {
j.setSuccess(false);
j.setMsg("该岗位下存在子岗位,不能直接删除");
return j;
}
//删除岗位
oaHrJobService.removeById(job.getId());
}
}catch(Exception e) {
log.error("删除岗位信息报错,错误信息:" + e.getMessage());
j.setSuccess(false);
j.setMsg("删除岗位错误");
e.printStackTrace();
}
return j;
}
}
package com.active4j.hr.hr.controller;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.active4j.hr.base.controller.BaseController;
import com.active4j.hr.common.constant.GlobalConstant;
import com.active4j.hr.core.model.AjaxJson;
import com.active4j.hr.core.query.QueryUtils;
import com.active4j.hr.core.util.DateUtils;
import com.active4j.hr.core.util.ResponseUtil;
import com.active4j.hr.core.web.tag.model.DataGrid;
import com.active4j.hr.hr.domain.OaHrUserOverTimeModel;
import com.active4j.hr.hr.entity.OaHrOverTimeEntity;
import com.active4j.hr.hr.entity.OaHrUserEntity;
import com.active4j.hr.hr.service.OaHrOverTimeService;
import com.active4j.hr.hr.service.OaHrUserService;
import com.active4j.hr.system.entity.SysDeptEntity;
import com.active4j.hr.system.service.SysDeptService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
/**
*
* @title OaHrOverTimeController.java
* @description
加班维护管理
* @time 2022年4月24日 上午10:00:39
* @author znz
* @version 1.0
*/
@Slf4j
@Controller
@RequestMapping("/oa/hr/overtime")
public class OaHrOverTimeController extends BaseController{
@Autowired
private OaHrOverTimeService oaHrOverTimeService;
@Autowired
private OaHrUserService oaHrUserService;
@Autowired
private SysDeptService sysDeptService;
private static final String prefix_page = "oa/hr/overtime/";
/**
* 加班记录
* @param request
* @return
*/
@RequestMapping("/list")
public ModelAndView list(HttpServletRequest request) {
ModelAndView view = new ModelAndView(prefix_page + "overtimelist");
return view;
}
/**
* 加班统计界面
* @param request
* @return
*/
@RequestMapping("/statlist")
public ModelAndView statlist(HttpServletRequest request) {
ModelAndView view = new ModelAndView(prefix_page + "overtimestatlist");
List lstResult = oaHrOverTimeService.queryOverTimeModel();
view.addObject("lstResult", lstResult);
return view;
}
/**
* 查询数据
* @param user
* @param request
* @param response
* @param dataGrid
*/
@RequestMapping("/datagrid")
public void datagrid(OaHrOverTimeEntity oaHrOverTimeEntity, String deptId, HttpServletRequest request, HttpServletResponse response, DataGrid dataGrid) {
oaHrOverTimeEntity.setDepartId(deptId);
//拼接查询条件
QueryWrapper queryWrapper = QueryUtils.installQueryWrapper(oaHrOverTimeEntity, request.getParameterMap(), dataGrid);
//执行查询
IPage lstResult = oaHrOverTimeService.page(new Page(dataGrid.getPage(), dataGrid.getRows()), queryWrapper);
//结果处理,直接写到客户端
ResponseUtil.writeJson(response, dataGrid, lstResult);
}
/**
* 跳转到新增页面
* @param request
* @return
*/
@RequestMapping("/add")
public ModelAndView add(HttpServletRequest request){
ModelAndView view = new ModelAndView(prefix_page + "overtimeadd");
//查询按用户分配权限使用的树形结构
String userTreeStr = oaHrUserService.getCompanyOfOaUser(null);
view.addObject("userTreeStr", userTreeStr);
return view;
}
/**
* 跳转到编辑页面
* @param request
* @return
*/
@RequestMapping("/edit")
public ModelAndView edit(String id, HttpServletRequest request){
ModelAndView view = new ModelAndView(prefix_page + "overtimeedit");
if(StringUtils.isNotEmpty(id)) {
//获取加班实体
OaHrOverTimeEntity time = oaHrOverTimeService.getById(id);
view.addObject("time", time);
}
return view;
}
/**
* 保存加班数据
* @param request
* @return
*/
@RequestMapping("/saveAdd")
@ResponseBody
public AjaxJson saveAdd(String[] UList, String type, String startTime, String endTime, String hours, String memo, HttpServletRequest request) {
AjaxJson j = new AjaxJson();
try{
if(null == UList || UList.length |