基于springboot实现OA办公管理系统

作者主页:编程指南针

 简介: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标签库封装组件的开源框架。

项目特点:

  1. 开箱即用,节省开发时间,提高开发效率
  2. 代码全部开源,持续更新,共同维护
  3. 支持分布式部署,session统一由redis进行管理
  4. 基于SpringBoot,简化了大量项目配置和maven依赖,让您更专注于业务开发
  5. 使用分层设计,分为dao,service,Controller,view层,层次清楚,低耦合,高内聚
  6. 提供了诸多的UI组件
  7. 友好的代码结构及注释,便于阅读及二次开发
  8. 灵活的权限控制, 整合shiro,可控制到页面或按钮,满足绝大部分的权限需求,优化权限注解方便权限配置
  9. 日志记录采用aop(LogAop类)方式,可对用户所有操作进行记录
  10. 数据统计报表:丰富的报表统计功能
  11. 集成jsp页面,采用标准JSTL标签库对常用组件进行封装,便于将传统项目过度到springboot
  12. 组件库丰富,对常用页面组件进行了代码封装,提高开发效率
  13. 前端页面简洁优美,支持移动端

系统功能较为全面,可根据需求删减相关功能实现。

二,项目展示

部分功能展示如下:

用户管理

部门管理

菜单管理

角色管理

数据字典管理

日志管理

个人办公-系统消息

会议管理

日报管理

日程管理

任务管理

目标管理

人力资源模块:包含档案管理、考勤管理、薪资管理、招聘管理、培训管理几大模块,不再一一展示。

三,核心代码

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<SysDicValueEntity> 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<String, Object> map = new HashMap<String, Object>();
				//获取部门信息
				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<String, Object> map = new HashMap<String, Object>();
				//获取岗位信息
				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<OaHrJobEntity> 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<OaHrUserOverTimeModel> 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<OaHrOverTimeEntity> queryWrapper = QueryUtils.installQueryWrapper(oaHrOverTimeEntity, request.getParameterMap(), dataGrid);
		//执行查询
		IPage<OaHrOverTimeEntity> lstResult = oaHrOverTimeService.page(new Page<OaHrOverTimeEntity>(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 <= 0) {
				j.setMsg("请选择用户!");
				j.setSuccess(false);
				return j;
			}
			
			if(StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime) || StringUtils.isEmpty(hours)) {
				j.setSuccess(false);
				j.setMsg("请填写完整的时间");
				return j;
			}
			
			Date startDate = DateUtils.str2Date(startTime, DateUtils.SDF_YYYY_MM_DD_HH_MM);
			Date endDate = DateUtils.str2Date(endTime, DateUtils.SDF_YYYY_MM_DD_HH_MM);
			
			Double d = Double.valueOf(hours);
			
			List<OaHrOverTimeEntity> lstTimes = new ArrayList<OaHrOverTimeEntity>();
			for(String id : UList) {
				OaHrUserEntity user = oaHrUserService.getById(id);
				if(null == user) {
					continue;
				}
				
				OaHrOverTimeEntity time = new OaHrOverTimeEntity();
				time.setUserName(user.getRealName());
				time.setUserId(user.getId());
				
				//获取部门信息
				SysDeptEntity depart = sysDeptService.getById(user.getDeptId());
				time.setDepartCode(depart.getDeptNo());
				time.setDepartName(depart.getName());
				time.setDepartId(depart.getId());
				time.setOptType(GlobalConstant.OPT_TYPE_ADD); //增加
				time.setStartTime(startDate);
				time.setEndTime(endDate);
				time.setType(type);
				time.setHours(d);
				time.setMemo(memo);
				
				lstTimes.add(time);
			}
			//批量保存
			oaHrOverTimeService.saveBatch(lstTimes);
			
		}catch(Exception e){
			j.setSuccess(false);
			j.setMsg("保存加班数据错误");
			log.error("保存加班数据错误,错误原因:{}", e.getMessage());
		}
		
		return j;
	}
	
	
	/**
	 * 保存加班数据
	 * @param request
	 * @return
	 */
	@RequestMapping("/saveEdit")
	@ResponseBody
	public AjaxJson saveEdit(String id, String type, String startTime, String endTime, String hours, String memo, HttpServletRequest request) {
		AjaxJson j = new AjaxJson();
		try{
			
			if(StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime) || StringUtils.isEmpty(hours)) {
				j.setSuccess(false);
				j.setMsg("请填写完整的时间");
				return j;
			}
			
			Date startDate = DateUtils.str2Date(startTime, DateUtils.SDF_YYYY_MM_DD_HH_MM);
			Date endDate = DateUtils.str2Date(endTime, DateUtils.SDF_YYYY_MM_DD_HH_MM);
			
			Double d = Double.valueOf(hours);
			
			OaHrOverTimeEntity time = oaHrOverTimeService.getById(id);
			time.setType(type);
			time.setStartTime(startDate);
			time.setEndTime(endDate);
			time.setHours(d);
			time.setMemo(memo);
			oaHrOverTimeService.saveOrUpdate(time);
			
		}catch(Exception e){
			j.setSuccess(false);
			j.setMsg("保存加班数据错误");
			log.error("保存加班数据错误,错误原因:{}", e.getMessage());
		}
		
		return j;
	}
	
	/**
	 * 删除加班数据
	 * @param request
	 * @return
	 */
	@RequestMapping("/del")
	@ResponseBody
	public AjaxJson del(String id, HttpServletRequest request) {
		AjaxJson j = new AjaxJson();
		try{
			
			if(StringUtils.isNotEmpty(id)) {
				//删除
				oaHrOverTimeService.removeById(id);
			}
			
		}catch(Exception e){
			j.setSuccess(false);
			j.setMsg("删除加班数据错误");
			log.error("删除加班数据错误,错误原因:{}", e.getMessage());
		}
		
		return j;
	}
}

四,项目总结

本系统功能完整,全面,可做商业应用,也可根据需求调整进行删减,做毕业设计使用。

通过明确的分析,对本文的组织结构做了以下概括:

第一部分是绪论:在这一部分,主要分析了文珺OA系统的研究背景以及意义,对文珺OA系统目前应用现状进行分析,以及最新发展概况,并且介绍了本文的研究内容以及结构安排。

第二部分是相关技术分析:这一部分主要介绍了设计和开发文珺OA系统所涉及的相关技术。重点介绍了J2EE相关技术、MySQL数据库技术、Gradle技术、Bootstrap技术,以及MVC分层结构的优缺点,后面关于系统的实现都会运用到这些技术。

第三部分是需求分析:通过相关人员的共同参与,在进行充分的探讨和调研后,确定系统的需求,并且加以整理,通过UML用例图,ER结构图以及数据库表格的方式,突出明显也更加直观的描述系统需求。

第四部分是系统设计:首先根据需求分析,系统的整体设计,分为几个重要板块,其次是系统的各种功能模块的设计,最后是数据库的设计包括了视图设计、数据表的设计,详细介绍了开发过程中系统支持的各项技术。

第五部分是系统实现:针对上面提出的每个部分进行具体的代码实现,得到最终的结果。

第六部分是系统测试:本章主要是对已经完成的文珺OA系统进行功能上的测试,看是否满足需求分析以及是否存在一些未知的Bug。

  • 7
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Web开发是为Internet(World Wide Web)或Intranet(私有网络)开发网站所涉及的工作。Web开发的范围可以从开发简单的纯文本单个静态页面到复杂的基于WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源。 Internet上供外界访问的Web资源分为: 静态web资源(如html 页面):指web页Web的Internet应用程序(Web应用程序)。 面中供人们浏览的数据始终是不变。 动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。 静态web资源开发技术:Html 常用动态web资源开发技术:JSP/Servlet、ASP、PHP等 在Java中,动态web资源开发技术统称为Javaweb。+ WEB应用程序指供浏览器访问的程序,通常也简称为web应用。例如有a.html 、b.html…..多个web资源,这多个web资源用于对外提供服务,此时应把这多个web资源放在一个目录中,以组成一个web应用(或web应用程序) Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程指南针

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值