├── file ├── 277e41bceb435b833a6f.txt ├── 50c3cd7ced46abbe4093.jpg ├── 646cec1d674c5fa595a5.png ├── 64a85e1a3c4dfb83d267.jpg ├── 693c2156904974a5734f.jpg ├── 6e2a56b137425e87f0b9.jpg ├── 7318a077ab4e8499e8b9.jpg ├── 826f7fffbd435284d3c7.jpg ├── 83fcdbcb4b450da4390e.png ├── b2f66ce7ec4b54a0fea7.png ├── cf27a645464dafa957ff.png ├── fdc2f2fd3e42779c4ca1.jpg ├── 11daf7f3aa4fbfaf876c.xlsx ├── 5dcc0999734b09b08aee.xlsx ├── 75bf86e97c43c88f2fa5.xlsx └── 90b02643334e5aa802c3.xlsx ├── vue-elementui-hrm ├── src │ ├── assets │ │ ├── less │ │ │ ├── _variable.scss │ │ │ ├── index.less │ │ │ ├── table.less │ │ │ ├── common.less │ │ │ ├── home.less │ │ │ └── reset.less │ │ ├── logo.png │ │ └── images │ │ │ ├── 404.png │ │ │ ├── avatar.png │ │ │ └── favicon.ico │ ├── views │ │ ├── system │ │ │ └── index.vue │ │ ├── money │ │ │ └── index.vue │ │ ├── performance │ │ │ └── index.vue │ │ ├── permission │ │ │ └── index.vue │ │ ├── error │ │ │ └── index.vue │ │ └── Main.vue │ ├── store │ │ ├── modules │ │ │ ├── token.js │ │ │ ├── permission.js │ │ │ ├── menu.js │ │ │ ├── staff.js │ │ │ └── tag.js │ │ ├── getters.js │ │ └── index.js │ ├── directive │ │ ├── index.js │ │ └── permission │ │ │ └── permission.js │ ├── utils │ │ ├── validateCode.js │ │ ├── avatar.js │ │ ├── docs.js │ │ └── request.js │ ├── App.vue │ ├── api │ │ ├── login.js │ │ ├── overtime.js │ │ ├── salaryDeduct.js │ │ ├── leave.js │ │ ├── home.js │ │ ├── salary.js │ │ ├── city.js │ │ ├── dept.js │ │ ├── menu.js │ │ ├── role.js │ │ ├── attendance.js │ │ ├── docs.js │ │ ├── insurance.js │ │ ├── staffOvertime.js │ │ ├── staff.js │ │ └── staffLeave.js │ ├── main.js │ ├── components │ │ ├── Tag.vue │ │ └── Aside.vue │ └── router │ │ └── index.js ├── .browserslistrc ├── public │ ├── favicon.ico │ └── index.html ├── .env ├── .editorconfig ├── babel.config.js ├── vue.config.js ├── .eslintrc.js └── package.json ├── 加班数据导入样例.xlsx ├── 考勤数据导入样例.xlsx ├── hrm └── src │ └── main │ ├── java │ └── com │ │ └── qiujie │ │ ├── mapper │ │ ├── CityMapper.java │ │ ├── RoleMenuMapper.java │ │ ├── OvertimeMapper.java │ │ ├── StaffRoleMapper.java │ │ ├── SalaryDeductMapper.java │ │ ├── RoleMapper.java │ │ ├── LeaveMapper.java │ │ ├── DocsMapper.java │ │ ├── DeptMapper.java │ │ ├── MenuMapper.java │ │ ├── StaffOvertimeMapper.java │ │ ├── AttendanceMapper.java │ │ ├── SalaryMapper.java │ │ ├── StaffLeaveMapper.java │ │ └── InsuranceMapper.java │ │ ├── config │ │ ├── HolidayConfig.java │ │ ├── MybatisPlusConfig.java │ │ ├── RedisConfig.java │ │ └── SwaggerConfig.java │ │ ├── enums │ │ ├── BaseEnum.java │ │ ├── GenderEnum.java │ │ ├── OvertimeEnum.java │ │ ├── DeductEnum.java │ │ ├── OvertimeStatusEnum.java │ │ ├── LeaveEnum.java │ │ ├── AuditStatusEnum.java │ │ ├── AttendanceStatusEnum.java │ │ └── BusinessStatusEnum.java │ │ ├── HrmApplication.java │ │ ├── exception │ │ ├── ServiceException.java │ │ └── BaseExceptionHandler.java │ │ ├── annotation │ │ └── ExcelColumn.java │ │ ├── util │ │ ├── WebUtil.java │ │ ├── DatetimeUtil.java │ │ ├── ValidateCodeUtil.java │ │ ├── JwtUtil.java │ │ └── CodeGenerateUtil.java │ │ ├── entity │ │ ├── StaffDetails.java │ │ ├── RoleMenu.java │ │ ├── StaffRole.java │ │ ├── Role.java │ │ ├── ValidateCode.java │ │ ├── SalaryDeduct.java │ │ ├── Leave.java │ │ ├── Docs.java │ │ ├── StaffLeave.java │ │ ├── Overtime.java │ │ ├── Menu.java │ │ ├── Staff.java │ │ ├── Insurance.java │ │ ├── Attendance.java │ │ ├── Salary.java │ │ └── Dept.java │ │ ├── handler │ │ ├── AccessDeniedExceptionHandler.java │ │ └── AuthenticationEntryPointHandler.java │ │ ├── controller │ │ ├── LoginController.java │ │ ├── HomeController.java │ │ ├── OvertimeController.java │ │ ├── SalaryDeductController.java │ │ ├── LeaveController.java │ │ ├── SalaryController.java │ │ ├── CityController.java │ │ ├── DeptController.java │ │ └── InsuranceController.java │ │ ├── vo │ │ ├── OvertimeMonthVO.java │ │ ├── StaffOvertimeVO.java │ │ ├── StaffAttendanceVO.java │ │ ├── StaffDocsVO.java │ │ ├── AttendanceMonthVO.java │ │ ├── StaffLeaveVO.java │ │ ├── StaffDeptVO.java │ │ ├── StaffInsuranceVO.java │ │ └── StaffSalaryVO.java │ │ ├── service │ │ ├── StaffRoleService.java │ │ ├── RoleMenuService.java │ │ ├── StaffDetailsService.java │ │ ├── SalaryDeductService.java │ │ ├── LoginService.java │ │ ├── LeaveService.java │ │ └── OvertimeService.java │ │ ├── dto │ │ ├── Response.java │ │ └── ResponseDTO.java │ │ ├── listener │ │ ├── HrApproveListener.java │ │ └── ManagerApproveListener.java │ │ └── filter │ │ └── JwtAuthenticationFilter.java │ └── resources │ ├── application.yml │ └── templates │ ├── controller.java.vm │ └── service.java.vm └── .gitignore /file/277e41bceb435b833a6f.txt: -------------------------------------------------------------------------------- 1 | 你好✌ -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/less/_variable.scss: -------------------------------------------------------------------------------- 1 | $theme-color: #33aef0; -------------------------------------------------------------------------------- /vue-elementui-hrm/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /加班数据导入样例.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/加班数据导入样例.xlsx -------------------------------------------------------------------------------- /考勤数据导入样例.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/考勤数据导入样例.xlsx -------------------------------------------------------------------------------- /file/50c3cd7ced46abbe4093.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/50c3cd7ced46abbe4093.jpg -------------------------------------------------------------------------------- /file/646cec1d674c5fa595a5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/646cec1d674c5fa595a5.png -------------------------------------------------------------------------------- /file/64a85e1a3c4dfb83d267.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/64a85e1a3c4dfb83d267.jpg -------------------------------------------------------------------------------- /file/693c2156904974a5734f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/693c2156904974a5734f.jpg -------------------------------------------------------------------------------- /file/6e2a56b137425e87f0b9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/6e2a56b137425e87f0b9.jpg -------------------------------------------------------------------------------- /file/7318a077ab4e8499e8b9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/7318a077ab4e8499e8b9.jpg -------------------------------------------------------------------------------- /file/826f7fffbd435284d3c7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/826f7fffbd435284d3c7.jpg -------------------------------------------------------------------------------- /file/83fcdbcb4b450da4390e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/83fcdbcb4b450da4390e.png -------------------------------------------------------------------------------- /file/b2f66ce7ec4b54a0fea7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/b2f66ce7ec4b54a0fea7.png -------------------------------------------------------------------------------- /file/cf27a645464dafa957ff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/cf27a645464dafa957ff.png -------------------------------------------------------------------------------- /file/fdc2f2fd3e42779c4ca1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/fdc2f2fd3e42779c4ca1.jpg -------------------------------------------------------------------------------- /file/11daf7f3aa4fbfaf876c.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/11daf7f3aa4fbfaf876c.xlsx -------------------------------------------------------------------------------- /file/5dcc0999734b09b08aee.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/5dcc0999734b09b08aee.xlsx -------------------------------------------------------------------------------- /file/75bf86e97c43c88f2fa5.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/75bf86e97c43c88f2fa5.xlsx -------------------------------------------------------------------------------- /file/90b02643334e5aa802c3.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/file/90b02643334e5aa802c3.xlsx -------------------------------------------------------------------------------- /vue-elementui-hrm/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/vue-elementui-hrm/public/favicon.ico -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/vue-elementui-hrm/src/assets/logo.png -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/vue-elementui-hrm/src/assets/images/404.png -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/vue-elementui-hrm/src/assets/images/avatar.png -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fo11ow-me/hrm/HEAD/vue-elementui-hrm/src/assets/images/favicon.ico -------------------------------------------------------------------------------- /vue-elementui-hrm/.env: -------------------------------------------------------------------------------- 1 | # 主机地址 2 | VUE_APP_HOST = 'http://localhost' 3 | 4 | # 后端项目端口 5 | VUE_APP_PORT = 8888 6 | 7 | VUE_APP_BASE_API = '/dev' 8 | 9 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/less/index.less: -------------------------------------------------------------------------------- 1 | @import "./common.less"; 2 | @import "./home.less"; 3 | @import "./reset.less"; 4 | @import "./table.less"; 5 | -------------------------------------------------------------------------------- /vue-elementui-hrm/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/views/system/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/views/money/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/views/performance/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/views/permission/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/less/table.less: -------------------------------------------------------------------------------- 1 | .common-table { 2 | height: calc(100% - 62px); 3 | background-color: white; 4 | position: relative; 5 | .pager { 6 | position: absolute; 7 | bottom: 20px; 8 | right: 20px; 9 | } 10 | } -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/less/common.less: -------------------------------------------------------------------------------- 1 | .manage { 2 | height: 90%; 3 | padding-bottom: 20px; 4 | overflow: hidden; 5 | &-header { 6 | display: flex; 7 | justify-content: space-between; 8 | align-items: flex-start; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/views/error/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 12 | -------------------------------------------------------------------------------- /vue-elementui-hrm/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ], 5 | plugins: [ // 按需引入 6 | [ 7 | 'component', 8 | { 9 | libraryName: 'element-ui', 10 | styleLibraryName: 'theme-chalk' 11 | } 12 | ] 13 | ] 14 | 15 | } 16 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/modules/token.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | token: localStorage.getItem('token') || '' 5 | }, 6 | mutations: { 7 | SET_TOKEN (state, token) { 8 | state.token = token 9 | localStorage.setItem('token', token) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/directive/index.js: -------------------------------------------------------------------------------- 1 | import permission from './permission/permission' 2 | import Vue from 'vue' 3 | 4 | const install = function (Vue) { 5 | Vue.directive('permission', permission) 6 | } 7 | 8 | if (window.Vue) { 9 | window.permission = permission 10 | Vue.use(install) 11 | } 12 | export default install 13 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/getters.js: -------------------------------------------------------------------------------- 1 | export const getters = { 2 | menuList: state => state.menu.menuList, 3 | isCollapsed: state => state.menu.isCollapsed, 4 | permissionList: state => state.permission.permissionList, 5 | staff: state => state.staff.staff, 6 | tagList: state => state.tag.tagList, 7 | token: state => state.token.token 8 | } 9 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/modules/permission.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | permissionList: [] 5 | }, 6 | mutations: { 7 | SET_PERMISSION (state, list) { 8 | state.permissionList = list.map(item => item.permission) 9 | console.log('我有的权限:', state.permissionList) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/utils/validateCode.js: -------------------------------------------------------------------------------- 1 | import { getValidateCode } from '@/api/login' 2 | 3 | export const setValidateCode = (img) => { 4 | getValidateCode().then(response => { 5 | img.src = window.URL.createObjectURL(new Blob([response.data])) 6 | img.onload = () => { 7 | URL.revokeObjectURL(img.src) 8 | } 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/CityMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.City; 5 | 6 | /** 7 | *

8 | * Mapper 接口 9 | *

10 | * 11 | * @author qiujie 12 | * @since 2022-03-23 13 | */ 14 | public interface CityMapper extends BaseMapper { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vue-elementui-hrm/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | lintOnSave: false, // 关闭语法检查 3 | devServer: { 4 | proxy: { 5 | '/dev': { 6 | // 请求前缀 7 | target: process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT, 8 | pathRewrite: { '^/dev': '' }, 9 | changeOrigin: true // 用于控制请求头中的host值 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 25 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/RoleMenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.RoleMenu; 5 | 6 | /** 7 | *

8 | * Mapper 接口 9 | *

10 | * 11 | * @author qiujie 12 | * @since 2022-02-28 13 | */ 14 | public interface RoleMenuMapper extends BaseMapper { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/OvertimeMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.Overtime; 5 | 6 | /** 7 | *

8 | * 加班表 Mapper 接口 9 | *

10 | * 11 | * @author qiujie 12 | * @since 2022-03-28 13 | */ 14 | 15 | public interface OvertimeMapper extends BaseMapper { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/StaffRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.qiujie.entity.StaffRole; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | 6 | /** 7 | *

8 | * Mapper 接口 9 | *

10 | * 11 | * @author qiujie 12 | * @since 2022-02-28 13 | */ 14 | 15 | 16 | public interface StaffRoleMapper extends BaseMapper { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/SalaryDeductMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.SalaryDeduct; 5 | 6 | /** 7 | *

8 | * 工资扣除表 Mapper 接口 9 | *

10 | * 11 | * @author qiujie 12 | * @since 2022-03-27 13 | */ 14 | 15 | 16 | public interface SalaryDeductMapper extends BaseMapper { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/login.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | // 登录 4 | export const login = (data) => { 5 | return request({ 6 | url: '/login/' + data.validateCode, 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | export const getValidateCode = () => { 13 | return request({ 14 | url: '/validate/code', 15 | method: 'get', 16 | responseType: 'blob' 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.qiujie.entity.Role; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | 7 | /** 8 | *

9 | * Mapper 接口 10 | *

11 | * 12 | * @author qiujie 13 | * @since 2022-01-27 14 | */ 15 | public interface RoleMapper extends BaseMapper { 16 | 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /vue-elementui-hrm/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | 'plugin:vue/essential', 8 | '@vue/standard' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/config/HolidayConfig.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.config; 2 | 3 | 4 | import lombok.Data; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @Component 12 | @ConfigurationProperties // 指明前缀,因为没有前缀,所以不用指明,默认为”“即可 13 | public class HolidayConfig { 14 | private List holidays; 15 | } 16 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import tag from './modules/tag' 4 | import menu from './modules/menu' 5 | import staff from './modules/staff' 6 | import token from './modules/token' 7 | import permission from './modules/permission' 8 | import { getters } from '@/store/getters' 9 | 10 | Vue.use(Vuex) 11 | 12 | export default new Vuex.Store({ 13 | modules: { 14 | tag, menu, staff, token, permission 15 | }, 16 | getters 17 | }) 18 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/BaseEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 通用枚举接口 7 | * 8 | * @Author qiujie 9 | * @Date 2022/3/21 10 | * @Version 1.0 11 | */ 12 | 13 | public interface BaseEnum extends Serializable { 14 | /** 15 | * 获取编码 16 | * 17 | * @return 18 | */ 19 | 20 | Integer getCode(); 21 | 22 | /** 23 | * 消息内容 24 | * 25 | * @return 26 | */ 27 | String getMessage(); 28 | } 29 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/LeaveMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.Leave; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * 请假表 Mapper 接口 13 | *

14 | * 15 | * @author qiujie 16 | * @since 2022-03-27 17 | */ 18 | 19 | public interface LeaveMapper extends BaseMapper { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/overtime.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/overtime' 4 | 5 | // 得到 6 | export const queryByDeptIdAndTypeNum = (deptId, typeNum) => { 7 | return request({ 8 | url: url + '/' + deptId + '/' + typeNum 9 | }) 10 | } 11 | 12 | export const setOvertime = (data) => { 13 | return request({ 14 | url: url + '/set', method: 'post', data 15 | }) 16 | } 17 | 18 | // 查询所有加班类型 19 | export const queryAll = () => { 20 | return request({ 21 | url: url + '/all' 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/salaryDeduct.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/salary-deduct' 4 | 5 | // 得到 6 | export const queryByDeptIdAndTypeNum = (deptId, typeNum) => { 7 | return request({ 8 | url: url + '/' + deptId + '/' + typeNum 9 | }) 10 | } 11 | 12 | export const setSalaryDeduct = (data) => { 13 | return request({ 14 | url: url + '/set', 15 | method: 'post', 16 | data 17 | }) 18 | } 19 | 20 | // 获得所有 21 | export const queryAll = () => { 22 | return request({ 23 | url: url + '/all' 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/GenderEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import org.apache.poi.ss.formula.functions.T; 8 | 9 | @Getter 10 | @AllArgsConstructor 11 | public enum GenderEnum implements BaseEnum{ 12 | 13 | MALE(0,"男"), 14 | FEMALE(1,"女"); 15 | 16 | @EnumValue 17 | private final Integer code; 18 | @JsonValue 19 | private final String message; 20 | } 21 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/HrmApplication.java: -------------------------------------------------------------------------------- 1 | package com.qiujie; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.transaction.annotation.EnableTransactionManagement; 7 | 8 | 9 | @MapperScan("com.qiujie.mapper") 10 | @SpringBootApplication 11 | @EnableTransactionManagement // 事务 12 | public class HrmApplication { 13 | public static void main(String[] args) { 14 | SpringApplication.run(HrmApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import ElementUI from 'element-ui' // 按需引入element-ui 4 | import 'element-ui/lib/theme-chalk/index.css' // 全局引入element-ui的css文件 5 | import './assets/less/index.less' 6 | import store from './store' 7 | import router from './router' // 引入vue路由 8 | import directive from '@/directive' 9 | 10 | Vue.config.productionTip = false 11 | 12 | // 全局注入element-ui,会引入全部的组件,增大了项目的体积 13 | Vue.use(ElementUI, { size: 'mini' }) 14 | Vue.use(directive) 15 | 16 | new Vue({ 17 | store, 18 | router, 19 | render: (h) => h(App) 20 | }).$mount('#app') 21 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/exception/ServiceException.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.exception; 2 | 3 | import com.qiujie.enums.BaseEnum; 4 | import lombok.Getter; 5 | import org.apache.poi.ss.formula.functions.T; 6 | 7 | /** 8 | * 自定义异常 9 | * @author 10 | * @date 11 | */ 12 | @Getter 13 | public class ServiceException extends RuntimeException { 14 | private final int code; 15 | 16 | public ServiceException(int code,String message){ 17 | super(message); 18 | this.code = code; 19 | } 20 | 21 | public ServiceException(BaseEnum e){ 22 | super(e.getMessage()); 23 | this.code = e.getCode(); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/leave.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/leave' 4 | 5 | // 得到 6 | export const queryByDeptIdAndTypeNum = (deptId, typeNum) => { 7 | return request({ 8 | url: url + '/' + deptId + '/' + typeNum 9 | }) 10 | } 11 | 12 | export const setLeave = (data) => { 13 | return request({ 14 | url: url + '/set', 15 | method: 'post', 16 | data 17 | }) 18 | } 19 | 20 | // 得到 21 | export const queryByDeptId = (deptId) => { 22 | return request({ 23 | url: url + '/dept/' + deptId 24 | }) 25 | } 26 | 27 | // 查询所有请假类型 28 | export const queryAll = () => { 29 | return request({ 30 | url: url + '/all' 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /vue-elementui-hrm/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/annotation/ExcelColumn.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @Author qiujie 10 | * @Date 2022/3/29 11 | * @Version 1.0 12 | */ 13 | 14 | /** 15 | * 声明该注解类的生命周期 16 | * RUNTIME表示注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。 17 | */ 18 | @Retention(RetentionPolicy.RUNTIME) 19 | // 定义注解作用的元素类型 20 | @Target(ElementType.FIELD) 21 | public @interface ExcelColumn { 22 | 23 | /** 24 | * 列的名称 25 | * 26 | * @return 27 | */ 28 | String value() default ""; 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/util/WebUtil.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.util; 2 | 3 | import javax.servlet.http.HttpServletResponse; 4 | import java.io.IOException; 5 | 6 | public class WebUtil { 7 | 8 | /** 9 | * 渲染字符串到前端 10 | * 11 | * @param response 12 | * @param str 13 | */ 14 | public static void renderString(HttpServletResponse response, String str){ 15 | try{ 16 | response.setStatus(200); 17 | response.setContentType("application/json"); 18 | response.setCharacterEncoding("utf-8"); 19 | response.getWriter().print(str); 20 | } catch (IOException e) { 21 | throw new RuntimeException(e); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/utils/avatar.js: -------------------------------------------------------------------------------- 1 | import { getAvatar } from '@/api/docs' 2 | import store from '../store' 3 | import defaultAvatar from '../assets/images/avatar.png' 4 | 5 | export const setAvatar = (img) => { 6 | const avatar = store.getters.staff.avatar 7 | if (avatar != null && avatar !== '') { // 当没有头像时,使用默认头像 8 | getAvatar(avatar).then(response => { 9 | // 如果头像不存在使用默认头像 10 | if (response.data.size > 0) { 11 | img.src = window.URL.createObjectURL(new Blob([response.data])) 12 | } else { 13 | img.src = defaultAvatar 14 | } 15 | }) 16 | } else { 17 | img.src = defaultAvatar 18 | } 19 | img.onload = () => { 20 | URL.revokeObjectURL(img.src) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/OvertimeEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.EnumValue; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import org.apache.poi.ss.formula.functions.T; 9 | 10 | 11 | @Getter 12 | @AllArgsConstructor 13 | public enum OvertimeEnum implements BaseEnum { 14 | 15 | WORKDAY_OVERTIME(0, "工作日加班",1.5), 16 | HOLIDAY_OVERTIME(1, "节假日加班",3.0), 17 | DAY_OFF_OVERTIME(2, "休息日加班",2.0); 18 | 19 | @EnumValue 20 | private final Integer code; 21 | 22 | @JsonValue 23 | private final String message; 24 | 25 | // 基本工资倍数下限 26 | private final Double lowerLimit; 27 | } 28 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/utils/docs.js: -------------------------------------------------------------------------------- 1 | import ElementUI from 'element-ui' 2 | 3 | // 将后端传来的文件流写入文件 4 | export const write = (response, filename) => { 5 | if (response.data.size > 0) { 6 | const url = window.URL.createObjectURL(new Blob([response.data])) 7 | const link = document.createElement('a') 8 | link.href = url 9 | link.setAttribute('download', filename) 10 | document.body.appendChild(link) 11 | link.click() 12 | setTimeout(function () { 13 | // 移除内存中的临时文件路径和为下载而创建的a标签 14 | window.URL.revokeObjectURL(url) 15 | link.remove() 16 | }, 10000) 17 | } else { 18 | ElementUI.Message({ 19 | message: '文件不存在!', 20 | type: 'error', 21 | duration: 5 * 1000 22 | }) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/DeductEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import org.apache.poi.ss.formula.functions.T; 8 | 9 | @Getter 10 | @AllArgsConstructor 11 | public enum DeductEnum implements BaseEnum{ 12 | LATE_DEDUCT(0, "迟到扣款",50), 13 | LEAVE_EARLY_DEDUCT(1, "早退扣款",50), 14 | ABSENTEEISM_DEDUCT(2, "旷工扣款",100), 15 | LEAVE_DEDUCT(3, "休假扣款",80); 16 | 17 | 18 | @EnumValue 19 | private final Integer code; 20 | @JsonValue 21 | private final String message; 22 | 23 | // 默认的扣款金额 24 | private final Integer defaultValue; 25 | } 26 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/home.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/home' 4 | 5 | export const queryStaff = () => { 6 | return request({ 7 | url: url + '/staff' 8 | }) 9 | } 10 | 11 | // 获取统计数据 12 | export const queryCount = () => { 13 | return request({ 14 | url: url + '/count' 15 | }) 16 | } 17 | 18 | // 获取城市社保数据 19 | export const queryCity = () => { 20 | return request({ 21 | url: url + '/city' 22 | }) 23 | } 24 | 25 | // 统计各部门员工人数 26 | export const queryDepartment = () => { 27 | return request({ 28 | url: url + '/department' 29 | }) 30 | } 31 | 32 | // 获取员工考勤数据 33 | export const queryAttendance = (params) => { 34 | return request({ 35 | url: url + '/attendance', 36 | params 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/OvertimeStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.EnumValue; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import org.apache.poi.ss.formula.functions.T; 9 | 10 | /** 11 | * @Author qiujie 12 | * @Date 2022/3/31 13 | * @Version 1.0 14 | */ 15 | 16 | @Getter 17 | @AllArgsConstructor 18 | public enum OvertimeStatusEnum implements BaseEnum { 19 | 20 | NORMAL(0, "正常","success"), 21 | OVERTIME(1, "加班",""), 22 | TIME_OFF(2, "调休","info"); 23 | 24 | @EnumValue 25 | private final Integer code; 26 | @JsonValue 27 | private final String message; 28 | 29 | private final String tagType; 30 | } 31 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/LeaveEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import org.apache.poi.ss.formula.functions.T; 8 | 9 | /** 10 | * 休假枚举类 11 | */ 12 | 13 | @Getter 14 | @AllArgsConstructor 15 | public enum LeaveEnum implements BaseEnum { 16 | PERSONAL_LEAVE(0, "事假"), 17 | MATERNITY_LEAVE(1, "产假"), 18 | SICK_LEAVE(2, "病假"), 19 | MARRIAGE_LEAVE(3, "婚假"), 20 | HOME_LEAVE(4, "探亲假"), 21 | PATERNITY_LEAVE(5, "陪产假"), 22 | TIME_OFF(6, "调休"); 23 | 24 | @EnumValue 25 | private final Integer code; 26 | @JsonValue 27 | private final String message; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/AuditStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | import com.baomidou.mybatisplus.annotation.EnumValue; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import org.apache.poi.ss.formula.functions.T; 8 | 9 | /** 10 | * @Author qiujie 11 | * @Date 2022/4/7 12 | * @Version 1.0 13 | */ 14 | 15 | @Getter 16 | @AllArgsConstructor 17 | public enum AuditStatusEnum implements BaseEnum { 18 | 19 | UNAUDITED(0, "待审核","info"), 20 | APPROVE(1, "审核通过","success"), 21 | REJECT(2, "驳回","danger"), 22 | CANCEL(3, "撤销",""), 23 | AUDITING(4,"审核中","warning"); 24 | 25 | @EnumValue 26 | private final Integer code; 27 | @JsonValue 28 | private final String message; 29 | 30 | private final String tagType; 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | 25 | test/ 26 | target/ 27 | !.mvn/wrapper/maven-wrapper.jar 28 | !**/src/main/**/target/ 29 | !**/src/test/**/target/ 30 | 31 | ### STS ### 32 | .apt_generated 33 | .classpath 34 | .factorypath 35 | .project 36 | .settings 37 | .springBeans 38 | .sts4-cache 39 | 40 | ### IntelliJ IDEA ### 41 | *.iws 42 | *.iml 43 | *.ipr 44 | *.rdb 45 | 46 | ### NetBeans ### 47 | /nbproject/private/ 48 | /nbbuild/ 49 | /dist/ 50 | /nbdist/ 51 | /.nb-gradle/ 52 | build/ 53 | !**/src/main/**/build/ 54 | !**/src/test/**/build/ 55 | 56 | ### VS Code ### 57 | .vscode/ 58 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/exception/BaseExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.exception; 2 | 3 | import com.qiujie.dto.Response; 4 | import com.qiujie.dto.ResponseDTO; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.web.bind.annotation.ControllerAdvice; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | 11 | @ControllerAdvice 12 | public class BaseExceptionHandler { 13 | 14 | private static final Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class); 15 | 16 | @ExceptionHandler(ServiceException.class) 17 | @ResponseBody 18 | public ResponseDTO handle(ServiceException exception){ 19 | logger.info(exception.getMessage()); 20 | return Response.error(exception.getCode(),exception.getMessage()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/modules/menu.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | // 首页是所有员工都可访问的 5 | menuList: [ 6 | { 7 | id: 0, 8 | code: 'home', 9 | name: '首页', 10 | icon: 's-home', 11 | path: '/home', 12 | children: [] 13 | } 14 | ], 15 | isCollapsed: false // 是否水平折叠收起菜单 16 | }, 17 | mutations: { 18 | SET_MENU (state, menuList) { 19 | state.menuList = menuList 20 | }, 21 | CLEAR_MENU (state) { 22 | state.menuList = [ 23 | { 24 | id: 0, 25 | code: 'home', 26 | name: '首页', 27 | icon: 's-home', 28 | path: '/home', 29 | children: [] 30 | } 31 | ] 32 | }, 33 | COLLAPSE_MENU (state) { 34 | state.isCollapsed = !state.isCollapsed 35 | } 36 | }, 37 | actions: { 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/AttendanceStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | 4 | import com.baomidou.mybatisplus.annotation.EnumValue; 5 | import com.fasterxml.jackson.annotation.JsonValue; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import org.apache.poi.ss.formula.functions.T; 9 | 10 | /** 11 | * @Author qiujie 12 | * @Date 2022/3/31 13 | * @Version 1.0 14 | */ 15 | 16 | @Getter 17 | @AllArgsConstructor 18 | public enum AttendanceStatusEnum implements BaseEnum { 19 | 20 | NORMAL(0, "正常","success"), 21 | LATE(1, "迟到",""), 22 | LEAVE_EARLY(2, "早退","warning"), 23 | ABSENTEEISM(3, "旷工","danger"), 24 | LEAVE(4, "休假","info"), 25 | TIME_OFF(5,"调休","info"); 26 | 27 | 28 | @EnumValue 29 | private final Integer code; 30 | @JsonValue 31 | private final String message; 32 | 33 | private final String tagType; 34 | } 35 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/enums/BusinessStatusEnum.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.enums; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import org.apache.poi.ss.formula.functions.T; 6 | import org.springframework.http.HttpStatus; 7 | 8 | @Getter 9 | @AllArgsConstructor 10 | public enum BusinessStatusEnum implements BaseEnum { 11 | 12 | SUCCESS(200, "成功"), 13 | ERROR(300, "失败"), 14 | STAFF_NOT_EXIST(400,"没有此员工,请重新登录"), 15 | STAFF_STATUS_ERROR(500, "状态异常,请联系管理员"), 16 | FILE_NOT_EXIST(600, "文件不存在"), 17 | FILE_READ_ERROR(700, "文件读取失败"), 18 | FILE_WRITE_ERROR(800, "文件写入失败"), 19 | FILE_UPLOAD_ERROR(900, "文件上传失败"), 20 | DATA_IMPORT_ERROR(1000, "数据导入失败"), 21 | BATCH_DELETE_ERROR(1100, "批量删除失败"), 22 | UNAUTHORIZED(1200,"认证失败,请重新登录"), 23 | FORBIDDEN(1300,"不好意思,你没有此权限"); 24 | 25 | private final Integer code; 26 | private final String message; 27 | } 28 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.config; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 分页插件 12 | */ 13 | @Configuration 14 | @MapperScan("com.qiujie.mapper") 15 | public class MybatisPlusConfig { 16 | 17 | // 最新版 18 | @Bean 19 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 20 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 21 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); 22 | return interceptor; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/DocsMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.qiujie.entity.Docs; 6 | import com.qiujie.vo.StaffDocsVO; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | /** 11 | *

12 | * Mapper 接口 13 | *

14 | * 15 | * @author qiujie 16 | * @since 2022-02-24 17 | */ 18 | public interface DocsMapper extends BaseMapper { 19 | 20 | @Select("select sd.*,ss.name staff_name from sys_staff ss left join sys_docs sd on ss.id = sd.staff_id " + 21 | "where sd.is_deleted = 0 and sd.old_name like concat('%',#{oldName},'%') and ss.name like concat('%',#{staffName},'%')") 22 | IPage listStaffDocsVO(IPage config, @Param("oldName") String oldName, @Param("staffName") String staffName); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/StaffDetails.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.qiujie.vo.StaffDeptVO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.io.Serial; 11 | import java.io.Serializable; 12 | import java.util.Collection; 13 | 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class StaffDetails implements UserDetails, Serializable { 18 | 19 | 20 | @Serial 21 | private static final long serialVersionUID = 1L; 22 | 23 | private String username; 24 | private String password; 25 | private Collection authorities; 26 | private boolean accountNonExpired; 27 | private boolean accountNonLocked; 28 | private boolean credentialsNonExpired; 29 | private boolean enabled; 30 | } 31 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/directive/permission/permission.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | 3 | function checkPermission (el, binding) { 4 | const { value } = binding 5 | // 已拥有的权限 6 | const hasPermission = store.getters && store.getters.permissionList 7 | if (value && value instanceof Array) { 8 | if (value.length > 0) { 9 | // 需要的权限 10 | const requiredPermission = value 11 | // 如果已有权限中存在至少一条需要的权限,就授权 12 | const flag = hasPermission.some(item => { 13 | return requiredPermission.includes(item) 14 | }) 15 | if (!flag) { 16 | // el.parentNode && el.parentNode.removeChild(el) 17 | el.disabled = true 18 | el.style.opacity = 0.6 19 | // el.style.cursor = 'not-allowed' 20 | el.style['pointer-events'] = 'none' 21 | } 22 | } 23 | } else { 24 | throw new Error('请指定权限字符串!') 25 | } 26 | } 27 | 28 | export default { 29 | inserted (el, binding) { 30 | checkPermission(el, binding) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/modules/staff.js: -------------------------------------------------------------------------------- 1 | import router, { resetRouter } from '../../router' 2 | 3 | export default { 4 | namespaced: true, 5 | state: { 6 | staff: JSON.parse(localStorage.getItem('staff')) 7 | }, 8 | mutations: { 9 | SET_STAFF (state, staff) { 10 | state.staff = staff 11 | localStorage.setItem('staff', JSON.stringify(staff)) // 存储用户信息到浏览器 12 | }, 13 | SET_AVATAR (state, avatar) { 14 | state.staff.avatar = avatar 15 | localStorage.setItem('staff', JSON.stringify(state.staff)) // 存储用户信息到浏览器 16 | } 17 | }, 18 | actions: { 19 | // 退出登录 20 | logout ({ commit }) { 21 | // 清除本地缓存 22 | localStorage.clear() 23 | // 清除vuex中的菜单数据 24 | commit('menu/CLEAR_MENU', null, { root: true }) 25 | // 清除vuex中的标签数据 26 | commit('tag/CLEAR_TAG', null, { root: true }) 27 | // 重置路由 28 | resetRouter() 29 | router.push({ name: 'login' }).then(() => { 30 | }) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/views/Main.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 37 | 38 | 47 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/handler/AccessDeniedExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.enums.BusinessStatusEnum; 6 | import com.qiujie.util.WebUtil; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | 16 | 17 | @Component 18 | public class AccessDeniedExceptionHandler implements AccessDeniedHandler { 19 | @Override 20 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { 21 | String str = JSON.toJSONString(new ResponseDTO(BusinessStatusEnum.FORBIDDEN)); 22 | // 给出异常提示信息 23 | WebUtil.renderString(response, str); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/handler/AuthenticationEntryPointHandler.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.handler; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.enums.BusinessStatusEnum; 6 | import com.qiujie.util.WebUtil; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.web.AuthenticationEntryPoint; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | 16 | 17 | @Component 18 | public class AuthenticationEntryPointHandler implements AuthenticationEntryPoint { 19 | @Override 20 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) { 21 | String str = JSON.toJSONString(new ResponseDTO(BusinessStatusEnum.UNAUTHORIZED)); 22 | // 给出异常提示信息 23 | WebUtil.renderString(response, str); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/store/modules/tag.js: -------------------------------------------------------------------------------- 1 | export default { 2 | namespaced: true, 3 | state: { 4 | tagList: JSON.parse(localStorage.getItem('tagList')) || [{ 5 | id: 0, 6 | name: '首页', 7 | path: '/home', 8 | code: 'home' 9 | }] 10 | }, 11 | mutations: { 12 | // 添加标签 13 | ADD_TAG (state, menu) { 14 | // 判断当前点击的是否是首页 15 | if (menu.code !== 'home') { 16 | // 判断tag是否存在,若存在就不添加 17 | const result = state.tagList.findIndex( 18 | item => item.code === menu.code 19 | ) 20 | if (result === -1) { 21 | state.tagList.push(menu) 22 | } 23 | } 24 | localStorage.setItem('tagList', JSON.stringify(state.tagList)) 25 | }, 26 | // 关闭标签 27 | CLOSE_TAG (state, menu) { 28 | state.tagList = state.tagList.filter(item => item.code !== menu.code) 29 | localStorage.setItem('tagList', JSON.stringify(state.tagList)) 30 | }, 31 | // 清空标签 32 | CLEAR_TAG (state) { 33 | state.tagList = [{ 34 | id: 0, 35 | name: '首页', 36 | path: '/home', 37 | code: 'home' 38 | }] 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/DeptMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.qiujie.entity.Dept; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | *

13 | * Mapper 接口 14 | *

15 | * 16 | * @author qiujie 17 | * @since 2022-03-07 18 | */ 19 | public interface DeptMapper extends BaseMapper { 20 | 21 | @Select("select * from sys_dept where is_deleted = 0 and parent_id = 0 and name like concat('%',#{name},'%')") 22 | IPage listParentDept(IPage config, @Param("name") String name); 23 | 24 | /** 25 | * 查找所有子部门 26 | * 27 | */ 28 | @Select("select * from sys_dept where is_deleted = 0 and parent_id != 0") 29 | List queryAllSub(); 30 | 31 | /** 32 | * 查找员工所在的部门 33 | */ 34 | @Select("select sd.* from sys_dept sd right join sys_staff ss on sd.id = ss.dept_id where ss.is_deleted = 0 and ss.id = #{id} ") 35 | Dept queryByStaffId(@Param("id") Integer id); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.dto.Response; 4 | import com.qiujie.entity.Staff; 5 | import com.qiujie.dto.ResponseDTO; 6 | import com.qiujie.service.LoginService; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.annotation.Resource; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * 登录注册接口 17 | * 18 | * @Author : qiujie 19 | * @Date : 2022/1/30 20 | */ 21 | @RestController 22 | public class LoginController { 23 | 24 | @Autowired 25 | private LoginService loginService; 26 | 27 | @PostMapping("/login/{validateCode}") 28 | public ResponseDTO login(@RequestBody Staff staff, @PathVariable String validateCode) { 29 | return this.loginService.login(staff, validateCode); 30 | } 31 | 32 | @GetMapping("/validate/code") 33 | public void getValidateCode(HttpServletResponse response) throws IOException { 34 | this.loginService.getValidateCode(response); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/OvertimeMonthVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @Author qiujie 11 | * @Date 2022/4/7 12 | * @Version 1.0 13 | */ 14 | 15 | @Data 16 | public class OvertimeMonthVO implements Serializable { 17 | 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @ApiModelProperty("员工id") 22 | private Integer staffId; 23 | 24 | @ApiModelProperty("部门id") 25 | private Integer deptId; 26 | 27 | @ExcelColumn("员工工号") 28 | @ApiModelProperty("员工工号") 29 | private String code; 30 | 31 | @ExcelColumn("员工姓名") 32 | @ApiModelProperty("员工姓名") 33 | private String name; 34 | 35 | @ExcelColumn("电话") 36 | @ApiModelProperty("电话") 37 | private String phone; 38 | 39 | @ExcelColumn("地址") 40 | @ApiModelProperty("地址") 41 | private String address; 42 | 43 | @ExcelColumn("部门") 44 | @ApiModelProperty("部门") 45 | private String deptName; 46 | 47 | @ExcelColumn("加班次数") 48 | private Integer overtimeTimes; 49 | 50 | @ExcelColumn("调休天数") 51 | private Integer timeOffDays; 52 | } 53 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffOvertimeVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | 11 | /** 12 | * @Author qiujie 13 | * @Date 2022/3/31 14 | * @Version 1.0 15 | */ 16 | 17 | @Data 18 | public class StaffOvertimeVO implements Serializable { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | @ApiModelProperty("员工id") 23 | private Integer staffId; 24 | 25 | @ApiModelProperty("部门id") 26 | private Integer deptId; 27 | 28 | @ExcelColumn("员工工号") 29 | @ApiModelProperty("员工工号") 30 | private String code; 31 | 32 | @ExcelColumn("员工姓名") 33 | @ApiModelProperty("员工姓名") 34 | private String name; 35 | 36 | @ExcelColumn("电话") 37 | @ApiModelProperty("电话") 38 | private String phone; 39 | 40 | @ExcelColumn("地址") 41 | @ApiModelProperty("地址") 42 | private String address; 43 | 44 | @ExcelColumn("部门") 45 | @ApiModelProperty("部门") 46 | private String deptName; 47 | 48 | @ApiModelProperty("员工加班数据") 49 | private List> overtimeList; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffAttendanceVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | 11 | /** 12 | * @Author qiujie 13 | * @Date 2022/3/31 14 | * @Version 1.0 15 | */ 16 | 17 | @Data 18 | public class StaffAttendanceVO implements Serializable { 19 | 20 | private static final long serialVersionUID = 1L; 21 | 22 | @ApiModelProperty("员工id") 23 | private Integer staffId; 24 | 25 | @ApiModelProperty("部门id") 26 | private Integer deptId; 27 | 28 | @ExcelColumn("员工工号") 29 | @ApiModelProperty("员工工号") 30 | private String code; 31 | 32 | @ExcelColumn("员工姓名") 33 | @ApiModelProperty("员工姓名") 34 | private String name; 35 | 36 | @ExcelColumn("电话") 37 | @ApiModelProperty("电话") 38 | private String phone; 39 | 40 | @ExcelColumn("地址") 41 | @ApiModelProperty("地址") 42 | private String address; 43 | 44 | @ExcelColumn("部门") 45 | @ApiModelProperty("部门") 46 | private String deptName; 47 | 48 | @ApiModelProperty("员工考勤数据") 49 | private List> attendanceList; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffDocsVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.sql.Timestamp; 9 | @Data 10 | public class StaffDocsVO implements Serializable { 11 | 12 | private static final long serialVersionUID = 1L; 13 | 14 | private Integer id; 15 | 16 | @ApiModelProperty("文件名称") 17 | private String name; 18 | 19 | @ApiModelProperty("员工姓名") 20 | private String staffName; 21 | 22 | @ApiModelProperty("文件类型") 23 | private String type; 24 | 25 | @ApiModelProperty("文件原名称") 26 | private String oldName; 27 | 28 | @ApiModelProperty("文件md5信息") 29 | private String md5; 30 | 31 | @ApiModelProperty("文件大小kB") 32 | private Long size; 33 | 34 | @ApiModelProperty("文件上传者id") 35 | private Integer staffId; 36 | 37 | @ApiModelProperty("备注") 38 | private String remark; 39 | 40 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 41 | @ApiModelProperty("创建时间") 42 | private Timestamp createTime; 43 | 44 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 45 | @ApiModelProperty("修改时间") 46 | private Timestamp updateTime; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /vue-elementui-hrm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-elementui-hrm", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.25.0", 12 | "cache-loader": "^4.1.0", 13 | "core-js": "^3.6.5", 14 | "echarts": "^5.3.0", 15 | "element-ui": "^2.15.7", 16 | "less": "^4.1.2", 17 | "less-loader": "^6.0.0", 18 | "mockjs": "^1.1.0", 19 | "moment": "^2.30.1", 20 | "qs": "^6.10.3", 21 | "vue": "^2.6.11", 22 | "vue-router": "^3.2.0", 23 | "vuex": "^3.6.2" 24 | }, 25 | "devDependencies": { 26 | "@vue/cli-plugin-babel": "~4.5.0", 27 | "@vue/cli-plugin-eslint": "~4.5.0", 28 | "@vue/cli-plugin-router": "~4.5.0", 29 | "@vue/cli-service": "~4.5.0", 30 | "@vue/eslint-config-standard": "^5.1.2", 31 | "babel-eslint": "^10.1.0", 32 | "babel-plugin-component": "^1.1.1", 33 | "eslint": "^6.7.2", 34 | "eslint-plugin-import": "^2.20.2", 35 | "eslint-plugin-node": "^11.1.0", 36 | "eslint-plugin-promise": "^4.2.1", 37 | "eslint-plugin-standard": "^4.0.0", 38 | "eslint-plugin-vue": "^6.2.2", 39 | "sass": "^1.49.9", 40 | "vue-template-compiler": "^2.6.11" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/salary.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/salary' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, method: 'post', data 13 | }) 14 | } 15 | 16 | /** 17 | * 逻辑删除 18 | * @param id 19 | * @returns {AxiosPromise} 20 | */ 21 | export const del = (id) => { 22 | return request({ 23 | url: url + '/' + id, method: 'delete' 24 | }) 25 | } 26 | 27 | export const deleteBatch = (ids) => { 28 | return request({ 29 | url: url + '/batch/' + ids, method: 'delete' 30 | }) 31 | } 32 | 33 | export const edit = (data) => { 34 | return request({ 35 | url: url, method: 'put', data 36 | }) 37 | } 38 | 39 | export const list = (params) => { 40 | return request({ 41 | url: url, method: 'get', params 42 | }) 43 | } 44 | 45 | export const setSalary = (data) => { 46 | return request({ 47 | url: url + '/set', method: 'post', data 48 | }) 49 | } 50 | 51 | export const exp = (month, filename) => { 52 | return request({ 53 | url: url + '/export/' + month + '/' + filename, 54 | method: 'get', 55 | responseType: 'blob' 56 | }) 57 | } 58 | 59 | // 数据导入 60 | export const getImportApi = () => { 61 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 62 | } 63 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/RoleMenu.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableLogic; 7 | import com.baomidou.mybatisplus.annotation.TableName; 8 | 9 | import java.io.Serial; 10 | import java.io.Serializable; 11 | import java.sql.Timestamp; 12 | 13 | import com.fasterxml.jackson.annotation.JsonFormat; 14 | import io.swagger.annotations.ApiModel; 15 | import io.swagger.annotations.ApiModelProperty; 16 | import lombok.Getter; 17 | import lombok.Setter; 18 | import lombok.experimental.Accessors; 19 | 20 | /** 21 | *

22 | * 23 | *

24 | * 25 | * @author qiujie 26 | * @since 2022-02-28 27 | */ 28 | @Getter 29 | @Setter 30 | @Accessors(chain = true) 31 | @TableName("per_role_menu") 32 | @ApiModel(value = "RoleMenu对象", description = "") 33 | public class RoleMenu implements Serializable { 34 | 35 | @Serial 36 | private static final long serialVersionUID = 1L; 37 | 38 | @TableId(value = "id", type = IdType.AUTO) 39 | private Integer id; 40 | 41 | @ApiModelProperty("角色id") 42 | @TableField("role_id") 43 | private Integer roleId; 44 | 45 | @ApiModelProperty("菜单id") 46 | @TableField("menu_id") 47 | private Integer menuId; 48 | } 49 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/StaffRole.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableLogic; 7 | import com.baomidou.mybatisplus.annotation.TableName; 8 | 9 | import java.io.Serial; 10 | import java.io.Serializable; 11 | import java.sql.Timestamp; 12 | 13 | import com.fasterxml.jackson.annotation.JsonFormat; 14 | import io.swagger.annotations.ApiModel; 15 | import io.swagger.annotations.ApiModelProperty; 16 | import lombok.Getter; 17 | import lombok.Setter; 18 | import lombok.experimental.Accessors; 19 | 20 | /** 21 | *

22 | * 23 | *

24 | * 25 | * @author qiujie 26 | * @since 2022-02-28 27 | */ 28 | @Getter 29 | @Setter 30 | @Accessors(chain = true) 31 | @TableName("per_staff_role") 32 | @ApiModel(value = "StaffRole对象", description = "") 33 | public class StaffRole implements Serializable { 34 | 35 | @Serial 36 | private static final long serialVersionUID = 1L; 37 | 38 | @TableId(value = "id", type = IdType.AUTO) 39 | private Integer id; 40 | 41 | @ApiModelProperty("员工id") 42 | @TableField("staff_id") 43 | private Integer staffId; 44 | 45 | @ApiModelProperty("角色id") 46 | @TableField("role_id") 47 | private Integer roleId; 48 | } 49 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/StaffRoleService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.qiujie.enums.BusinessStatusEnum; 6 | import com.qiujie.dto.Response; 7 | import com.qiujie.dto.ResponseDTO; 8 | import com.qiujie.entity.StaffRole; 9 | import com.qiujie.exception.ServiceException; 10 | import com.qiujie.mapper.StaffRoleMapper; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * @Author qiujie 18 | * @Date 2022/3/1 19 | * @Version 1.0 20 | */ 21 | 22 | @Service 23 | public class StaffRoleService extends ServiceImpl { 24 | 25 | @Transactional 26 | public ResponseDTO setRole(Integer staffId, List roleIds) { 27 | remove(new QueryWrapper().eq("staff_id", staffId)); 28 | for (Integer roleId : roleIds) { 29 | save(new StaffRole().setStaffId(staffId).setRoleId(roleId)); 30 | } 31 | return Response.success(); 32 | } 33 | 34 | public ResponseDTO queryByStaffId(Integer staffId) { 35 | List list = list(new QueryWrapper().eq("staff_id",staffId)); 36 | return Response.success(list); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/MenuMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.Menu; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | *

12 | * Mapper 接口 13 | *

14 | * 15 | * @author qiujie 16 | * @since 2022-02-28 17 | */ 18 | public interface MenuMapper extends BaseMapper { 19 | 20 | @Select(""" 21 | select distinct pm.* from per_menu pm\s 22 | left join per_role_menu prm on pm.id = prm.menu_id\s 23 | left join per_role pr on prm.role_id = pr.id\s 24 | left join per_staff_role psr on pr.id = psr.role_id where psr.staff_id = #{id} and pm.status = 1 and pm.level < 2 and pm.is_deleted = 0""") 25 | List queryByStaffId(@Param("id") Integer id); 26 | 27 | 28 | /** 29 | * 查询当前员工的权限 30 | * @param id 员工id 31 | */ 32 | @Select(""" 33 | select distinct pm.* from per_menu pm\s 34 | left join per_role_menu prm on pm.id = prm.menu_id\s 35 | left join per_role pr on prm.role_id = pr.id\s 36 | left join per_staff_role psr on pr.id = psr.role_id where psr.staff_id = #{id} and pm.status = 1 and pm.level > 0 and pm.is_deleted = 0""") 37 | List queryPermission(@Param("id") Integer id); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import ElementUI from 'element-ui' 3 | import store from '../store' 4 | 5 | const instance = axios.create({ 6 | baseURL: process.env.VUE_APP_BASE_API, 7 | timeout: 10000 // 超时设置 8 | }) 9 | 10 | /** 11 | * request 拦截器 12 | */ 13 | instance.interceptors.request.use(config => { 14 | config.headers['Content-Type'] = 'application/json;charset=utf-8' 15 | config.headers.Authorization = 'Bearer ' + store.getters.token 16 | return config 17 | }, error => { 18 | return Promise.reject(error) 19 | }) 20 | 21 | /** 22 | * response 拦截器 23 | */ 24 | instance.interceptors.response.use(response => { 25 | const res = response.data 26 | // 文件特殊处理 27 | if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') { 28 | return response 29 | } 30 | // 用户不存在、状态异常、认证失败,直接退出登录 31 | if (res.code === 400 || res.code === 500 || res.code === 1200) { 32 | ElementUI.Message({ 33 | message: res.message, 34 | type: 'error', 35 | duration: 5 * 1000 36 | }) 37 | store.dispatch('staff/logout').then(() => { 38 | return Promise.reject(res.message) 39 | }) 40 | } else { 41 | return res 42 | } 43 | }, error => { 44 | ElementUI.Message({ 45 | message: error.message, 46 | type: 'error', 47 | duration: 5 * 1000 48 | }) 49 | return Promise.reject(error) 50 | }) 51 | 52 | export default instance 53 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/city.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/city' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, method: 'post', data 13 | }) 14 | } 15 | 16 | /** 17 | * 逻辑删除 18 | * @param id 19 | * @returns {AxiosPromise} 20 | */ 21 | export const del = (id) => { 22 | return request({ 23 | url: url + '/' + id, method: 'delete' 24 | }) 25 | } 26 | 27 | export const deleteBatch = (ids) => { 28 | return request({ 29 | url: url + '/batch/' + ids, method: 'delete' 30 | }) 31 | } 32 | 33 | export const edit = (data) => { 34 | return request({ 35 | url: url, method: 'put', data 36 | }) 37 | } 38 | 39 | // 条件查询 40 | export const list = (params) => { 41 | return request({ 42 | url: url, method: 'get', params 43 | }) 44 | } 45 | 46 | // 查询所有 47 | export const queryAll = () => { 48 | return request({ 49 | url: url + '/all' 50 | }) 51 | } 52 | 53 | // 得到一条数据 54 | export const query = (id) => { 55 | return request({ 56 | url: url + '/' + id 57 | }) 58 | } 59 | 60 | export const exp = (filename) => { 61 | return request({ 62 | url: url + '/export/' + filename, 63 | method: 'get', 64 | responseType: 'blob' 65 | }) 66 | } 67 | 68 | // 数据导入 69 | export const getImportApi = () => { 70 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 71 | } 72 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/AttendanceMonthVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @Author qiujie 11 | * @Date 2022/4/7 12 | * @Version 1.0 13 | */ 14 | 15 | @Data 16 | public class AttendanceMonthVO implements Serializable { 17 | 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @ApiModelProperty("员工id") 22 | private Integer staffId; 23 | 24 | @ApiModelProperty("部门id") 25 | private Integer deptId; 26 | 27 | @ExcelColumn("员工工号") 28 | @ApiModelProperty("员工工号") 29 | private String code; 30 | 31 | @ExcelColumn("员工姓名") 32 | @ApiModelProperty("员工姓名") 33 | private String name; 34 | 35 | @ExcelColumn("电话") 36 | @ApiModelProperty("电话") 37 | private String phone; 38 | 39 | @ExcelColumn("地址") 40 | @ApiModelProperty("地址") 41 | private String address; 42 | 43 | @ExcelColumn("部门") 44 | @ApiModelProperty("部门") 45 | private String deptName; 46 | 47 | @ExcelColumn("迟到次数") 48 | private Integer lateTimes; 49 | 50 | @ExcelColumn("早退次数") 51 | private Integer leaveEarlyTimes; 52 | 53 | @ExcelColumn("旷工次数") 54 | private Integer absenteeismTimes; 55 | 56 | @ExcelColumn("休假天数") 57 | private Integer leaveDays; 58 | 59 | @ExcelColumn("调休天数") 60 | private Integer timeOffDays; 61 | } 62 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/dept.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/dept' 4 | /** 5 | * 添加 6 | * @param data 7 | * @returns {AxiosPromise} 8 | */ 9 | export const add = (data) => { 10 | return request({ 11 | url: url, 12 | method: 'post', 13 | data 14 | }) 15 | } 16 | 17 | /** 18 | * 逻辑删除 19 | * @param id 20 | * @returns {AxiosPromise} 21 | */ 22 | export const del = (id) => { 23 | return request({ 24 | url: url + '/' + id, 25 | method: 'delete' 26 | }) 27 | } 28 | 29 | export const deleteBatch = (ids) => { 30 | return request({ 31 | url: url + '/batch/' + ids, 32 | method: 'delete' 33 | }) 34 | } 35 | 36 | export const edit = (data) => { 37 | return request({ 38 | url: url, 39 | method: 'put', 40 | data 41 | }) 42 | } 43 | 44 | // 分页条件查询 45 | export const list = (params) => { 46 | return request({ 47 | url: url, method: 'get', params 48 | }) 49 | } 50 | 51 | // 查询所有 52 | export const queryAll = () => { 53 | return request({ 54 | url: url + '/all' 55 | }) 56 | } 57 | 58 | // 得到一条数据 59 | export const query = (id) => { 60 | return request({ 61 | url: url + '/' + id 62 | }) 63 | } 64 | 65 | export const exp = (filename) => { 66 | return request({ 67 | url: url + '/export/' + filename, 68 | method: 'get', 69 | responseType: 'blob' 70 | }) 71 | } 72 | 73 | // 数据导入 74 | export const getImportApi = () => { 75 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 76 | } 77 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/util/DatetimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.util; 2 | 3 | import cn.hutool.core.date.DateUtil; 4 | import com.qiujie.config.HolidayConfig; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.sql.Date; 9 | 10 | /** 11 | * @Author qiujie 12 | * @Date 2022/4/12 13 | * @Version 1.0 14 | */ 15 | 16 | @Component 17 | public class DatetimeUtil { 18 | 19 | @Autowired 20 | private HolidayConfig holidayConfig; 21 | 22 | /** 23 | * 获取月份的日期字符串数据组如,['20220101','20220102','20220103',........] 24 | * 25 | * @param month yyyyMM 26 | * @return 27 | */ 28 | public String[] getMonthDayList(String month) { 29 | int monthSize = DateUtil.lengthOfMonth(Integer.valueOf(month.substring(4)), DateUtil.isLeapYear(Integer.valueOf(month.substring(0, 4)))); 30 | String[] monthDayList = new String[monthSize]; 31 | for (int i = 0; i < monthSize; i++) { 32 | if (i < 9) { 33 | monthDayList[i] = month + "0" + (i + 1); 34 | } else { 35 | monthDayList[i] = month + (i + 1); 36 | } 37 | } 38 | return monthDayList; 39 | } 40 | 41 | 42 | /** 43 | * 判断当前日期是否是节假日 44 | * 45 | * @param date 46 | * @return 47 | */ 48 | public boolean isHoliday(Date date) { 49 | String str = DateUtil.format(date, "yyyy-MM-dd"); 50 | return holidayConfig.getHolidays().contains(str); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffLeaveVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.qiujie.enums.AuditStatusEnum; 5 | import com.qiujie.enums.LeaveEnum; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.sql.Date; 11 | import java.sql.Timestamp; 12 | 13 | /** 14 | * @Author qiujie 15 | * @Date 2022/4/5 16 | * @Version 1.0 17 | */ 18 | 19 | @Data 20 | public class StaffLeaveVO implements Serializable { 21 | 22 | private static final long serialVersionUID = 1L; 23 | 24 | private Integer id; 25 | 26 | @ApiModelProperty("工号") 27 | private String code; 28 | 29 | @ApiModelProperty("员工姓名") 30 | private String name; 31 | 32 | @ApiModelProperty("部门") 33 | private String deptName; 34 | 35 | @ApiModelProperty("电话") 36 | private String phone; 37 | 38 | 39 | @ApiModelProperty("员工id") 40 | private Integer staffId; 41 | 42 | @ApiModelProperty("请假的天数") 43 | private Integer days; 44 | 45 | @ApiModelProperty("请假类型") 46 | private LeaveEnum typeNum; 47 | 48 | @ApiModelProperty("请假的起始日期") 49 | private Date startDate; 50 | 51 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 52 | private Timestamp createTime; 53 | 54 | @ApiModelProperty("0未审核,1审核通过,2驳回,3撤销") 55 | private AuditStatusEnum status; 56 | 57 | @ApiModelProperty("审批意见") 58 | private String auditRemark; 59 | 60 | private String remark; 61 | } 62 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.dto.ResponseDTO; 4 | import com.qiujie.service.HomeService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import javax.annotation.Resource; 12 | 13 | /** 14 | * @Author qiujie 15 | * @Date 2022/2/27 16 | * @Version 1.0 17 | */ 18 | 19 | @RestController 20 | @RequestMapping("/home") 21 | public class HomeController { 22 | 23 | @Autowired 24 | private HomeService homeService; 25 | 26 | @GetMapping("/staff") 27 | public ResponseDTO queryStaff() { 28 | return this.homeService.queryStaff(); 29 | } 30 | 31 | @GetMapping("/count") 32 | public ResponseDTO queryCount() { 33 | return this.homeService.queryCount(); 34 | } 35 | 36 | @GetMapping("/city") 37 | public ResponseDTO queryCity() { 38 | return this.homeService.queryCity(); 39 | } 40 | 41 | @GetMapping("/attendance") 42 | public ResponseDTO queryAttendance(@RequestParam Integer id, String month) { 43 | return this.homeService.queryAttendance(id, month); 44 | } 45 | @GetMapping("/department") 46 | public ResponseDTO queryDepartment() { 47 | return this.homeService.queryDepartment(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/dto/Response.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.dto; 2 | 3 | import com.qiujie.enums.BaseEnum; 4 | import com.qiujie.enums.BusinessStatusEnum; 5 | import org.apache.poi.ss.formula.functions.T; 6 | 7 | /** 8 | * 请求响应数据 9 | */ 10 | public class Response { 11 | 12 | public static ResponseDTO success(){ 13 | return new ResponseDTO(BusinessStatusEnum.SUCCESS); 14 | } 15 | 16 | public static ResponseDTO success(String message){ 17 | return new ResponseDTO(BusinessStatusEnum.SUCCESS.getCode(), message); 18 | } 19 | 20 | public static ResponseDTO success(Object data){ 21 | return new ResponseDTO(BusinessStatusEnum.SUCCESS,data); 22 | } 23 | 24 | public static ResponseDTO success(Object data,String token){ 25 | return new ResponseDTO(BusinessStatusEnum.SUCCESS,data,token); 26 | } 27 | 28 | public static ResponseDTO success(String message, Object data){ 29 | return new ResponseDTO(BusinessStatusEnum.SUCCESS.getCode(),message,data); 30 | } 31 | 32 | public static ResponseDTO error(String message){ 33 | return new ResponseDTO(BusinessStatusEnum.ERROR.getCode(), message); 34 | } 35 | 36 | public static ResponseDTO error(){ 37 | return new ResponseDTO(BusinessStatusEnum.ERROR); 38 | } 39 | 40 | public static ResponseDTO error(Integer code, String message){ 41 | return new ResponseDTO(code,message); 42 | } 43 | 44 | public static ResponseDTO error(BaseEnum e) { 45 | return new ResponseDTO(e); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/components/Tag.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 52 | 53 | 64 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.sql.Timestamp; 11 | 12 | /** 13 | *

14 | * 15 | *

16 | * 17 | * @author qiujie 18 | * @since 2022-01-27 19 | */ 20 | @Data 21 | @TableName("per_role") 22 | @ApiModel(value = "Role对象", description = "") 23 | public class Role implements Serializable { 24 | 25 | private static final long serialVersionUID = 1L; 26 | 27 | @ApiModelProperty("角色id") 28 | @TableId(value = "id", type = IdType.AUTO) 29 | private Integer id; 30 | 31 | @ApiModelProperty("角色编码") 32 | @TableField("code") 33 | private String code; 34 | 35 | @ApiModelProperty("角色名称") 36 | @TableField("name") 37 | private String name; 38 | 39 | @ApiModelProperty("角色备注") 40 | @TableField("remark") 41 | private String remark; 42 | 43 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 44 | @ApiModelProperty("创建时间") 45 | @TableField("create_time") 46 | private Timestamp createTime; 47 | 48 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 49 | @ApiModelProperty("更新时间") 50 | @TableField("update_time") 51 | private Timestamp updateTime; 52 | 53 | @TableField("is_deleted") 54 | @TableLogic 55 | private Integer deleteFlag; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/ValidateCode.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.time.LocalDateTime; 5 | 6 | public class ValidateCode { 7 | 8 | private BufferedImage image; 9 | 10 | private String code; 11 | 12 | private LocalDateTime expireTime; 13 | 14 | public ValidateCode(BufferedImage image, String code, int expireIn) { 15 | this.image = image; 16 | this.code = code; 17 | this.expireTime = LocalDateTime.now().plusSeconds(expireIn); 18 | } 19 | 20 | public ValidateCode(BufferedImage image, String code) { 21 | this.image = image; 22 | this.code = code; 23 | } 24 | 25 | public ValidateCode(BufferedImage image, String code, LocalDateTime expireTime) { 26 | this.image = image; 27 | this.code = code; 28 | this.expireTime = expireTime; 29 | } 30 | 31 | boolean isExpire() { 32 | return LocalDateTime.now().isAfter(expireTime); 33 | } 34 | 35 | public BufferedImage getImage() { 36 | return image; 37 | } 38 | 39 | public void setImage(BufferedImage image) { 40 | this.image = image; 41 | } 42 | 43 | public String getCode() { 44 | return code; 45 | } 46 | 47 | public void setCode(String code) { 48 | this.code = code; 49 | } 50 | 51 | public LocalDateTime getExpireTime() { 52 | return expireTime; 53 | } 54 | 55 | public void setExpireTime(LocalDateTime expireTime) { 56 | this.expireTime = expireTime; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/StaffOvertimeMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.qiujie.entity.Attendance; 6 | import com.qiujie.entity.StaffOvertime; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | import java.math.BigDecimal; 11 | 12 | /** 13 | *

14 | * 员工加班表 Mapper 接口 15 | *

16 | * 17 | * @author qiujie 18 | * @since 2024-03-20 19 | */ 20 | public interface StaffOvertimeMapper extends BaseMapper { 21 | 22 | @Select("select * from att_staff_overtime where is_deleted = 0 and staff_id = #{id} and date_format(overtime_date,'%Y%m%d') = #{day}") 23 | StaffOvertime queryByStaffIdAndDate(@Param("id") Integer id, @Param("day") String day); 24 | 25 | 26 | /** 27 | * 统计员工加班次数、获得的调休天数 28 | * 29 | * @param id 员工id 30 | * @param status 状态 31 | * @param month 月份 32 | */ 33 | @Select("select count(*) from att_staff_overtime where is_deleted = 0 and staff_id = #{id} and status = #{status} and date_format(overtime_date,'%Y%m') = #{month} ") 34 | Integer countTimes(@Param("id") Integer id, @Param("status") Integer status, @Param("month") String month); 35 | 36 | 37 | /** 38 | * 合计员工当前月的加班工资 39 | */ 40 | @Select("select sum(overtime_salary) from att_staff_overtime WHERE is_deleted = 0 and staff_id = #{id} and date_format(overtime_date,'%Y%m') = #{month}") 41 | BigDecimal sumMonthOvertimeSalary(@Param("id") Integer id, @Param("month") String month); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/dto/ResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.dto; 2 | 3 | import com.qiujie.enums.BaseEnum; 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | import org.apache.poi.ss.formula.functions.T; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @ApiModel(value = "数据传输对象", description = "") 15 | public class ResponseDTO { 16 | @ApiModelProperty("状态码") 17 | private int code; 18 | 19 | @ApiModelProperty("响应消息") 20 | private String message; 21 | 22 | @ApiModelProperty("响应数据") 23 | private Object data; 24 | 25 | @ApiModelProperty("token") 26 | private String token; 27 | 28 | public ResponseDTO(int code, String message){ 29 | this.code = code; 30 | this.message = message; 31 | } 32 | 33 | public ResponseDTO(int code,String message,Object data){ 34 | this.code = code; 35 | this.message = message; 36 | this.data = data; 37 | } 38 | 39 | public ResponseDTO(BaseEnum e){ 40 | this.code = e.getCode(); 41 | this.message = e.getMessage(); 42 | } 43 | 44 | public ResponseDTO(BaseEnum e, Object data){ 45 | this.code = e.getCode(); 46 | this.message = e.getMessage(); 47 | this.data = data; 48 | } 49 | 50 | public ResponseDTO(BaseEnum e, Object data, String token){ 51 | this.code = e.getCode(); 52 | this.message = e.getMessage(); 53 | this.data = data; 54 | this.token = token; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/AttendanceMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.qiujie.entity.Attendance; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | import java.sql.Date; 9 | import java.util.List; 10 | 11 | /** 12 | *

13 | * Mapper 接口 14 | *

15 | * 16 | * @author qiujie 17 | * @since 2022-03-29 18 | */ 19 | 20 | public interface AttendanceMapper extends BaseMapper { 21 | 22 | 23 | @Select("select * from att_attendance where is_deleted = 0 and staff_id = #{id} and date_format(attendance_date,'%Y%m%d') = #{day}") 24 | Attendance queryByStaffIdAndDate(@Param("id") Integer id, @Param("day") String day); 25 | 26 | /** 27 | * 统计员工迟到、早退、旷工的次数 28 | * 29 | * @param id 员工id 30 | * @param status 31 | * @param month 月份 32 | * @return 33 | */ 34 | @Select("select count(*) from att_attendance where is_deleted = 0 and staff_id = #{id} and status = #{status} and date_format(attendance_date,'%Y%m') = #{month} ") 35 | Integer countTimes(@Param("id") Integer id, @Param("status") Integer status, @Param("month") String month); 36 | 37 | 38 | /** 39 | * 查找员工休假的日期 40 | * 41 | * @param id 42 | * @param month 43 | * @return 44 | */ 45 | @Select("select attendance_date from att_attendance where is_deleted = 0 and staff_id = #{id} and status=#{status} and date_format(attendance_date,'%Y%m') = #{month} ") 46 | List queryLeaveDate(@Param("id") Integer id, @Param("status") Integer status, @Param("month") String month); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/less/home.less: -------------------------------------------------------------------------------- 1 | .home { 2 | .user { 3 | display: flex; 4 | align-items: center; 5 | padding-bottom: 20px; 6 | margin-bottom: 20px; 7 | border-bottom: 1px solid #ccc; 8 | img { 9 | width: 150px; 10 | height: 150px; 11 | border-radius: 50%; 12 | margin-right: 40px; 13 | } 14 | &info { 15 | .name { 16 | font-size: 32px; 17 | margin-bottom: 10px; 18 | } 19 | .access { 20 | color: #999999; 21 | } 22 | } 23 | } 24 | .login-info { 25 | p { 26 | line-height: 28px; 27 | font-size: 14px; 28 | color: #999999; 29 | span { 30 | color: #666666; 31 | margin-left: 60px; 32 | } 33 | } 34 | } 35 | .num { 36 | display: flex; 37 | flex-wrap: wrap; 38 | justify-content: space-between; 39 | .el-card { 40 | width: 32%; 41 | margin-bottom: 20px; 42 | } 43 | .icon { 44 | font-size: 30px; 45 | width: 80px; 46 | height: 80px; 47 | text-align: center; 48 | line-height: 80px; 49 | color: #fff; 50 | } 51 | .detail { 52 | margin-left: 15px; 53 | display: flex; 54 | flex-direction: column; 55 | justify-content: center; 56 | .num { 57 | font-size: 30px; 58 | margin-bottom: 10px; 59 | } 60 | .txt { 61 | font-size: 14px; 62 | text-align: center; 63 | color: #999999; 64 | } 65 | } 66 | } 67 | .graph { 68 | margin-top: 20px; 69 | display: flex; 70 | justify-content: space-between; 71 | .el-card { 72 | width: 48%; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/menu.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/menu' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, 13 | method: 'post', 14 | data 15 | }) 16 | } 17 | 18 | /** 19 | * 逻辑删除 20 | * @param id 21 | * @returns {AxiosPromise} 22 | */ 23 | export const del = (id) => { 24 | return request({ 25 | url: url + '/' + id, 26 | method: 'delete' 27 | }) 28 | } 29 | 30 | export const deleteBatch = (ids) => { 31 | return request({ 32 | url: url + '/batch/' + ids, 33 | method: 'delete' 34 | }) 35 | } 36 | 37 | export const edit = (data) => { 38 | return request({ 39 | url: url, 40 | method: 'put', 41 | data 42 | }) 43 | } 44 | 45 | // 分页条件查询 46 | export const list = (params) => { 47 | return request({ 48 | url: url, 49 | method: 'get', 50 | params 51 | }) 52 | } 53 | 54 | // 查询所有 55 | export const queryAll = () => { 56 | return request({ 57 | url: url + '/all' 58 | }) 59 | } 60 | 61 | // 获取员工的菜单 62 | export const queryByStaffId = (id) => { 63 | return request({ 64 | url: url + '/staff/' + id 65 | }) 66 | } 67 | 68 | export const queryPermission = (id) => { 69 | return request({ 70 | url: url + '/permission/' + id 71 | }) 72 | } 73 | 74 | export const exp = (filename) => { 75 | return request({ 76 | url: url + '/export/' + filename, 77 | method: 'get', 78 | responseType: 'blob' 79 | }) 80 | } 81 | 82 | // 数据导入 83 | export const getImportApi = () => { 84 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 85 | } 86 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/RoleMenuService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.qiujie.entity.RoleMenu; 6 | import com.qiujie.entity.StaffRole; 7 | import com.qiujie.enums.BusinessStatusEnum; 8 | import com.qiujie.exception.ServiceException; 9 | import com.qiujie.mapper.RoleMenuMapper; 10 | import com.qiujie.dto.Response; 11 | import com.qiujie.dto.ResponseDTO; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | *

19 | * 服务类 20 | *

21 | * 22 | * @author qiujie 23 | * @since 2022-02-28 24 | */ 25 | @Service 26 | public class RoleMenuService extends ServiceImpl { 27 | 28 | /** 29 | * 为角色设置菜单 30 | * 31 | * @param roleId 32 | * @param menuIds 33 | * @return 34 | */ 35 | @Transactional 36 | public ResponseDTO setMenu(Integer roleId, List menuIds) { 37 | remove(new QueryWrapper().eq("role_id", roleId)); 38 | for (Integer menuId : menuIds) { 39 | save(new RoleMenu().setRoleId(roleId).setMenuId(menuId)); 40 | } 41 | return Response.success(); 42 | } 43 | 44 | /** 45 | * 获取角色的菜单 46 | * 47 | * @param roleId 48 | * @return 49 | */ 50 | public ResponseDTO queryByRoleId(Integer roleId) { 51 | List list = list(new QueryWrapper().eq("role_id", roleId)); 52 | return Response.success(list); 53 | } 54 | 55 | 56 | } 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/role.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/role' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, 13 | method: 'post', 14 | data 15 | }) 16 | } 17 | 18 | /** 19 | * 逻辑删除 20 | * @param id 21 | * @returns {AxiosPromise} 22 | */ 23 | export const del = (id) => { 24 | return request({ 25 | url: url + '/' + id, 26 | method: 'delete' 27 | }) 28 | } 29 | 30 | export const deleteBatch = (ids) => { 31 | return request({ 32 | url: url + '/batch/' + ids, 33 | method: 'delete' 34 | }) 35 | } 36 | 37 | export const edit = (data) => { 38 | return request({ 39 | url: url, 40 | method: 'put', 41 | data 42 | }) 43 | } 44 | 45 | export const list = (params) => { 46 | return request({ 47 | url: url, 48 | method: 'get', 49 | params 50 | }) 51 | } 52 | 53 | // 查询所有 54 | export const queryAll = () => { 55 | return request({ 56 | url: url + '/all' 57 | }) 58 | } 59 | 60 | // 为角色设置菜单 61 | export const setMenu = (id, data) => { 62 | return request({ 63 | url: url + '/set/' + id, 64 | method: 'post', 65 | data 66 | }) 67 | } 68 | 69 | // 获取角色的菜单 70 | export const queryByRoleId = (id) => { 71 | return request({ 72 | url: url + '/role/' + id 73 | }) 74 | } 75 | 76 | export const exp = (filename) => { 77 | return request({ 78 | url: url + '/export/' + filename, 79 | method: 'get', 80 | responseType: 'blob' 81 | }) 82 | } 83 | 84 | // 数据导入 85 | export const getImportApi = () => { 86 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 87 | } 88 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffDeptVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import com.qiujie.enums.GenderEnum; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.Data; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serializable; 10 | import java.sql.Date; 11 | 12 | /** 13 | * @Author qiujie 14 | * @Date 2022/4/9 15 | * @Version 1.0 16 | */ 17 | 18 | @Data 19 | @Accessors(chain = true) 20 | public class StaffDeptVO implements Serializable { 21 | 22 | private static final long serialVersionUID = 1L; 23 | 24 | @ApiModelProperty("员工id") 25 | private Integer id; 26 | 27 | @ExcelColumn("工号") 28 | @ApiModelProperty("员工编码") 29 | private String code; 30 | 31 | @ExcelColumn("姓名") 32 | @ApiModelProperty("员工姓名") 33 | private String name; 34 | 35 | @ExcelColumn("年龄") 36 | @ApiModelProperty("员工年龄") 37 | private Integer age; 38 | 39 | @ApiModelProperty("性别,0男,1女,默认0") 40 | private GenderEnum gender; 41 | 42 | @ExcelColumn("地址") 43 | @ApiModelProperty("员工家庭住址") 44 | private String address; 45 | 46 | @ApiModelProperty("部门id") 47 | private Integer deptId; 48 | 49 | @ExcelColumn("部门") 50 | @ApiModelProperty("部门") 51 | private String deptName; 52 | 53 | @ApiModelProperty("员工头像") 54 | private String avatar; 55 | 56 | @ExcelColumn("生日") 57 | @ApiModelProperty("员工生日") 58 | private Date birthday; 59 | 60 | @ExcelColumn("电话") 61 | @ApiModelProperty("员工电话") 62 | private String phone; 63 | 64 | @ExcelColumn("备注") 65 | @ApiModelProperty("员工备注") 66 | private String remark; 67 | 68 | 69 | @ApiModelProperty("员工状态,0异常,1正常") 70 | private Integer status; 71 | } 72 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/attendance.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/attendance' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, method: 'post', data 13 | }) 14 | } 15 | 16 | /** 17 | * 逻辑删除 18 | * @param id 19 | * @returns {AxiosPromise} 20 | */ 21 | export const del = (id) => { 22 | return request({ 23 | url: url + '/' + id, method: 'delete' 24 | }) 25 | } 26 | 27 | export const deleteBatch = (ids) => { 28 | return request({ 29 | url: url + '/batch/' + ids, method: 'delete' 30 | }) 31 | } 32 | 33 | export const edit = (data) => { 34 | return request({ 35 | url: url, method: 'put', data 36 | }) 37 | } 38 | 39 | // 查询所有 40 | export const queryAll = () => { 41 | return request({ 42 | url: url + '/all' 43 | }) 44 | } 45 | 46 | // 得到一条数据 47 | export const query = (id) => { 48 | return request({ 49 | url: url + '/' + id 50 | }) 51 | } 52 | 53 | export const queryByStaffIdAndDate = (id, date) => { 54 | return request({ 55 | url: url + '/' + id + '/' + date 56 | }) 57 | } 58 | 59 | // 查询 60 | export const list = (params) => { 61 | return request({ 62 | url: url, method: 'get', params 63 | }) 64 | } 65 | 66 | export const setAttendance = (data) => { 67 | return request({ 68 | url: url + '/set', method: 'put', data 69 | }) 70 | } 71 | export const exp = (month, filename) => { 72 | return request({ 73 | url: url + '/export/' + month + '/' + filename, 74 | method: 'get', 75 | responseType: 'blob' 76 | }) 77 | } 78 | 79 | // 得到一条数据 80 | // 数据导入 81 | export const getImportApi = () => { 82 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 83 | } 84 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/docs.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/docs' 4 | /** 5 | * 添加 6 | * @param data 7 | * @returns {AxiosPromise} 8 | */ 9 | export const add = (data) => { 10 | return request({ 11 | url: url, 12 | method: 'post', 13 | data 14 | }) 15 | } 16 | 17 | /** 18 | * 逻辑删除 19 | * @param id 20 | * @returns {AxiosPromise} 21 | */ 22 | export const del = (id) => { 23 | return request({ 24 | url: url + '/' + id, 25 | method: 'delete' 26 | }) 27 | } 28 | 29 | export const deleteBatch = (ids) => { 30 | return request({ 31 | url: url + '/batch/' + ids, 32 | method: 'delete' 33 | }) 34 | } 35 | 36 | export const edit = (data) => { 37 | return request({ 38 | url: url, 39 | method: 'put', 40 | data 41 | }) 42 | } 43 | 44 | export const list = (params) => { 45 | return request({ 46 | url: url, 47 | method: 'get', 48 | params 49 | }) 50 | } 51 | 52 | export const download = (filename) => { 53 | return request({ 54 | url: url + '/download/' + filename, 55 | method: 'get', 56 | responseType: 'blob' 57 | }) 58 | } 59 | 60 | export const getAvatar = (filename) => { 61 | return request({ 62 | url: url + '/avatar/' + filename, 63 | method: 'get', 64 | responseType: 'blob' 65 | }) 66 | } 67 | 68 | export const exp = (filename) => { 69 | return request({ 70 | url: url + '/export/' + filename, 71 | method: 'get', 72 | responseType: 'blob' 73 | }) 74 | } 75 | 76 | // 数据导入 77 | export const getImportApi = () => { 78 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 79 | } 80 | 81 | // 文件上传 82 | export const getUploadApi = (id) => { 83 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/upload/' + id 84 | } 85 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/insurance.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/insurance' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, 13 | method: 'post', 14 | data 15 | }) 16 | } 17 | 18 | /** 19 | * 逻辑删除 20 | * @param id 21 | * @returns {AxiosPromise} 22 | */ 23 | export const del = (id) => { 24 | return request({ 25 | url: url + '/' + id, 26 | method: 'delete' 27 | }) 28 | } 29 | 30 | export const deleteBatch = (ids) => { 31 | return request({ 32 | url: url + '/batch/' + ids, 33 | method: 'delete' 34 | }) 35 | } 36 | 37 | export const edit = (data) => { 38 | return request({ 39 | url: url, 40 | method: 'put', 41 | data 42 | }) 43 | } 44 | 45 | // 分页条件查询 46 | export const list = (params) => { 47 | return request({ 48 | url: url, method: 'get', params 49 | }) 50 | } 51 | 52 | // 得到一条数据 53 | export const query = (id) => { 54 | return request({ 55 | url: url + '/' + id 56 | }) 57 | } 58 | 59 | // 得到一条数据 60 | export const queryByStaffId = (id) => { 61 | return request({ 62 | url: url + '/staff/' + id 63 | }) 64 | } 65 | 66 | // 查询所有 67 | export const queryAll = () => { 68 | return request({ 69 | url: url + '/all' 70 | }) 71 | } 72 | 73 | // 设置社保 74 | export const setInsurance = (data) => { 75 | return request({ 76 | url: url + '/set', 77 | method: 'post', 78 | data 79 | }) 80 | } 81 | 82 | export const exp = (filename) => { 83 | return request({ 84 | url: url + '/export/' + filename, 85 | method: 'get', 86 | responseType: 'blob' 87 | }) 88 | } 89 | 90 | // 数据导入 91 | export const getImportApi = () => { 92 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 93 | } 94 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/SalaryDeduct.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import com.qiujie.enums.DeductEnum; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | import java.io.Serializable; 12 | import java.sql.Timestamp; 13 | 14 | /** 15 | *

16 | * 工资扣除表 17 | *

18 | * 19 | * @author qiujie 20 | * @since 2022-03-27 21 | */ 22 | @Getter 23 | @Setter 24 | @TableName("sal_salary_deduct") 25 | @ApiModel(value = "SalaryDeduct对象", description = "工资扣除表") 26 | public class SalaryDeduct implements Serializable { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | @TableId(value = "id", type = IdType.AUTO) 31 | private Integer id; 32 | 33 | @ApiModelProperty("部门id") 34 | @TableField("dept_id") 35 | private Integer deptId; 36 | 37 | @ApiModelProperty("扣款类型,0迟到,1早退,2旷工,3休假") 38 | @TableField("type_num") 39 | private DeductEnum typeNum; 40 | 41 | @ApiModelProperty("每次扣款金额") 42 | @TableField("deduct") 43 | private Integer deduct; 44 | 45 | @ApiModelProperty("备注") 46 | @TableField("remark") 47 | private String remark; 48 | 49 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 50 | @ApiModelProperty("创建时间") 51 | @TableField("create_time") 52 | private Timestamp createTime; 53 | 54 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 55 | @ApiModelProperty("修改时间") 56 | @TableField("update_time") 57 | private Timestamp updateTime; 58 | 59 | @ApiModelProperty("0未删除,1已删除,默认为0") 60 | @TableField("is_deleted") 61 | @TableLogic 62 | private Integer deleteFlag; 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/assets/less/reset.less: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, iframe, 2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 3 | a, abbr, acronym, address, big, cite, code, 4 | del, dfn, em, img, ins, kbd, q, s, samp, 5 | small, strike, strong, sub, sup, tt, var, 6 | b, u, i, center, 7 | dl, dt, dd, ol, ul, li, 8 | fieldset, form, label, legend, 9 | table, caption, tbody, tfoot, thead, tr, th, td, 10 | article, aside, canvas, details, embed, 11 | figure, figcaption, footer, header, hgroup, 12 | menu, nav, output, ruby, section, summary, 13 | time, mark, audio, video { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font-size: 100%; 18 | font: inherit; 19 | vertical-align: baseline; 20 | box-sizing: border-box; 21 | } 22 | /* HTML5 display-role reset for older browsers */ 23 | article, aside, details, figcaption, figure, 24 | footer, header, hgroup, menu, nav, section { 25 | display: block; 26 | } 27 | body { 28 | line-height: 1; 29 | } 30 | ol, ul { 31 | list-style: none; 32 | } 33 | blockquote, q { 34 | quotes: none; 35 | } 36 | blockquote:before, blockquote:after, 37 | q:before, q:after { 38 | content: ''; 39 | content: none; 40 | } 41 | a, a:hover{ 42 | color: inherit; 43 | text-decoration: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | html, body { 50 | width: 100%; 51 | height: 100%; 52 | background-color: #f5f5f5; 53 | font-family: 'PingFangSC-Light', 'PingFang SC', 'STHeitiSC-Light', 'Helvetica-Light', 'Arial', 'sans-serif'; 54 | } 55 | 56 | // 公共样式 57 | .fl{ 58 | float: left; 59 | } 60 | .fr{ 61 | float: right; 62 | .button-group-item{ 63 | padding-left: 3px; 64 | } 65 | } 66 | //清除浮动 67 | .clearfix{ 68 | zoom:1; 69 | &:after{ 70 | display:block; 71 | clear:both; 72 | content:""; 73 | visibility: hidden; 74 | height:0; 75 | } 76 | } -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Leave.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import com.qiujie.enums.LeaveEnum; 6 | 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | import java.io.Serializable; 13 | import java.sql.Timestamp; 14 | 15 | /** 16 | *

17 | * 请假表 18 | *

19 | * 20 | * @author qiujie 21 | * @since 2022-03-27 22 | */ 23 | @Getter 24 | @Setter 25 | @TableName("att_leave") 26 | @ApiModel(value = "Leave对象", description = "请假表") 27 | public class Leave implements Serializable { 28 | 29 | private static final long serialVersionUID = 1L; 30 | 31 | @TableId(value = "id", type = IdType.AUTO) 32 | private Integer id; 33 | 34 | @ApiModelProperty("休假类型") 35 | @TableField("type_num") 36 | private LeaveEnum typeNum; 37 | 38 | @ApiModelProperty("部门id") 39 | @TableField("dept_id") 40 | private Integer deptId; 41 | 42 | @ApiModelProperty("休假天数") 43 | @TableField("days") 44 | private Integer days; 45 | 46 | @ApiModelProperty("0禁用,1正常,默认1") 47 | @TableField("status") 48 | private Integer status; 49 | 50 | @TableField("remark") 51 | private String remark; 52 | 53 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 54 | @ApiModelProperty("创建时间") 55 | @TableField("create_time") 56 | private Timestamp createTime; 57 | 58 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 59 | @ApiModelProperty("更新时间") 60 | @TableField("update_time") 61 | private Timestamp updateTime; 62 | 63 | @ApiModelProperty("逻辑删除,0未删除,1删除") 64 | @TableField("is_deleted") 65 | @TableLogic 66 | private Integer deleteFlag; 67 | 68 | } 69 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/staffOvertime.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/staff-overtime' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, method: 'post', data 13 | }) 14 | } 15 | 16 | /** 17 | * 逻辑删除 18 | * @param id 19 | * @returns {AxiosPromise} 20 | */ 21 | export const del = (id) => { 22 | return request({ 23 | url: url + '/' + id, method: 'delete' 24 | }) 25 | } 26 | 27 | export const deleteBatch = (ids) => { 28 | return request({ 29 | url: url + '/batch/' + ids, method: 'delete' 30 | }) 31 | } 32 | 33 | export const edit = (data) => { 34 | return request({ 35 | url: url, method: 'put', data 36 | }) 37 | } 38 | 39 | // 分页条件查询 40 | export const list = (params) => { 41 | return request({ 42 | url: url, method: 'get', params 43 | }) 44 | } 45 | 46 | // 查询所有 47 | export const queryAll = () => { 48 | return request({ 49 | url: url + '/all' 50 | }) 51 | } 52 | 53 | // 得到一条数据 54 | export const query = (id) => { 55 | return request({ 56 | url: url + '/' + id 57 | }) 58 | } 59 | 60 | export const queryByStaffIdAndDate = (id, date) => { 61 | return request({ 62 | url: url + '/' + id + '/' + date 63 | }) 64 | } 65 | 66 | export const queryTimeOffDaysByStaffId = (id) => { 67 | return request({ 68 | url: url + '/time/off/' + id 69 | }) 70 | } 71 | 72 | // 设置 73 | export const setOvertime = (data) => { 74 | return request({ 75 | url: url + '/set', method: 'post', data 76 | }) 77 | } 78 | 79 | export const exp = (month, filename) => { 80 | return request({ 81 | url: url + '/export/' + month + '/' + filename, 82 | method: 'get', 83 | responseType: 'blob' 84 | }) 85 | } 86 | 87 | // 数据导入 88 | export const getImportApi = () => { 89 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 90 | } 91 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/SalaryMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.qiujie.entity.Salary; 6 | import com.qiujie.vo.StaffSalaryVO; 7 | import io.swagger.models.auth.In; 8 | import org.apache.ibatis.annotations.Param; 9 | import org.apache.ibatis.annotations.Select; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | *

15 | * Mapper 接口 16 | *

17 | * 18 | * @author qiujie 19 | * @since 2022-04-06 20 | */ 21 | public interface SalaryMapper extends BaseMapper { 22 | 23 | 24 | @Select("select ss.id staff_id,ss.dept_id,ss.code,ss.name,ss.phone,ss.address,sd.name dept_name,si.per_social_pay social_pay,si.per_house_pay house_pay " + 25 | "from sys_staff ss inner join sys_dept sd on ss.dept_id = sd.id left join soc_insurance si on ss.id = si.staff_id where ss.is_deleted = 0") 26 | List queryStaffSalaryVO(); 27 | 28 | 29 | @Select("select ss.id staff_id,ss.dept_id,ss.code,ss.name,ss.phone,ss.address,sd.name dept_name,si.per_social_pay social_pay,si.per_house_pay house_pay " + 30 | "from sys_staff ss inner join sys_dept sd on ss.dept_id = sd.id left join soc_insurance si on ss.id = si.staff_id where ss.is_deleted = 0 and ss.name like concat('%',#{name},'%')") 31 | IPage listStaffSalaryVO(IPage config, @Param("name") String name); 32 | 33 | @Select("select ss.id staff_id,ss.dept_id,ss.code,ss.name,ss.phone,ss.address,sd.name dept_name,si.per_social_pay social_pay,si.per_house_pay house_pay " + 34 | "from sys_staff ss inner join sys_dept sd on ss.dept_id = sd.id left join soc_insurance si on ss.id = si.staff_id where ss.is_deleted = 0 and ss.dept_id = #{deptId} and ss.name like concat('%',#{name},'%')") 35 | IPage listStaffDeptSalaryVO(IPage config, @Param("name") String name, @Param("deptId")Integer deptId); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/listener/HrApproveListener.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.listener; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 4 | import com.qiujie.entity.Staff; 5 | import com.qiujie.entity.StaffLeave; 6 | import com.qiujie.enums.AuditStatusEnum; 7 | import com.qiujie.enums.BusinessStatusEnum; 8 | import com.qiujie.exception.ServiceException; 9 | import com.qiujie.mapper.StaffMapper; 10 | import com.qiujie.service.StaffLeaveService; 11 | import org.activiti.engine.RuntimeService; 12 | import org.activiti.engine.delegate.DelegateExecution; 13 | import org.activiti.engine.delegate.ExecutionListener; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Component; 16 | import org.springframework.transaction.annotation.Transactional; 17 | 18 | import java.util.HashMap; 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.stream.Collectors; 22 | 23 | @Component 24 | public class HrApproveListener implements ExecutionListener { 25 | 26 | @Autowired 27 | private StaffLeaveService staffLeaveService; 28 | 29 | @Autowired 30 | private StaffMapper staffMapper; 31 | 32 | @Autowired 33 | private RuntimeService runtimeService; 34 | 35 | @Override 36 | @Transactional 37 | public void notify(DelegateExecution execution) { 38 | UpdateWrapper updateWrapper = new UpdateWrapper<>(); 39 | updateWrapper.set("status", AuditStatusEnum.UNAUDITED).eq("id", Integer.valueOf(execution.getProcessInstanceBusinessKey())); 40 | if (!this.staffLeaveService.update(updateWrapper)) { 41 | throw new ServiceException(BusinessStatusEnum.ERROR); 42 | } 43 | List staffList = this.staffMapper.queryByRole("manager"); 44 | Map variables = new HashMap<>(); 45 | variables.put("manager", staffList.stream().map(Staff::getCode).collect(Collectors.joining(","))); 46 | runtimeService.setVariables(execution.getId(), variables); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Docs.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Data; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | import java.sql.Timestamp; 12 | 13 | /** 14 | *

15 | * 16 | *

17 | * 18 | * @author qiujie 19 | * @since 2022-02-24 20 | */ 21 | @Data 22 | @Accessors(chain = true) 23 | @TableName("sys_docs") 24 | @ApiModel(value = "Docs对象", description = "文件管理") 25 | public class Docs implements Serializable { 26 | 27 | private static final long serialVersionUID = 1L; 28 | 29 | @TableId(value = "id", type = IdType.AUTO) 30 | private Integer id; 31 | 32 | @ApiModelProperty("文件名称") 33 | @TableField("name") 34 | private String name; 35 | 36 | @ApiModelProperty("文件类型") 37 | @TableField("type") 38 | private String type; 39 | 40 | @ApiModelProperty("文件原名称") 41 | @TableField("old_name") 42 | private String oldName; 43 | 44 | @ApiModelProperty("文件md5信息") 45 | @TableField("md5") 46 | private String md5; 47 | 48 | @ApiModelProperty("文件大小kB") 49 | @TableField("size") 50 | private Long size; 51 | 52 | @ApiModelProperty("文件上传者id") 53 | @TableField("staff_id") 54 | private Integer staffId; 55 | 56 | @ApiModelProperty("员工备注") 57 | @TableField("remark") 58 | private String remark; 59 | 60 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 61 | @ApiModelProperty("创建时间") 62 | @TableField("create_time") 63 | private Timestamp createTime; 64 | 65 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 66 | @ApiModelProperty("修改时间") 67 | @TableField("update_time") 68 | private Timestamp updateTime; 69 | 70 | @ApiModelProperty("0未删除,1已删除,默认为0") 71 | @TableField("is_deleted") 72 | @TableLogic 73 | private Integer deleteFlag; 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/StaffLeave.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import com.qiujie.enums.AuditStatusEnum; 6 | import com.qiujie.enums.LeaveEnum; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | 12 | import java.io.Serializable; 13 | import java.sql.Date; 14 | import java.sql.Timestamp; 15 | 16 | /** 17 | *

18 | * 19 | *

20 | * 21 | * @author qiujie 22 | * @since 2022-04-05 23 | */ 24 | @Getter 25 | @Setter 26 | @TableName("att_staff_leave") 27 | @ApiModel(value = "StaffLeave对象", description = "") 28 | public class StaffLeave implements Serializable { 29 | 30 | private static final long serialVersionUID = 1L; 31 | 32 | @TableId(value = "id", type = IdType.AUTO) 33 | private Integer id; 34 | 35 | @ApiModelProperty("员工id") 36 | @TableField("staff_id") 37 | private Integer staffId; 38 | 39 | @ApiModelProperty("请假的天数") 40 | @TableField("days") 41 | private Integer days; 42 | 43 | @TableField("type_num") 44 | private LeaveEnum typeNum; 45 | 46 | @ApiModelProperty("请假的起始日期") 47 | @TableField("start_date") 48 | private Date startDate; 49 | 50 | @ApiModelProperty("0待审核,1审核通过,2驳回,3撤销,4审核中") 51 | @TableField("status") 52 | private AuditStatusEnum status; 53 | 54 | @ApiModelProperty("审批意见") 55 | @TableField("audit_remark") 56 | private String auditRemark; 57 | 58 | @TableField("remark") 59 | private String remark; 60 | 61 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 62 | @ApiModelProperty("创建时间") 63 | @TableField("create_time") 64 | private Timestamp createTime; 65 | 66 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 67 | @ApiModelProperty("更新时间") 68 | @TableField("update_time") 69 | private Timestamp updateTime; 70 | 71 | @ApiModelProperty("逻辑删除,0未删除,1删除") 72 | @TableField("is_deleted") 73 | @TableLogic 74 | private Integer deleteFlag; 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 | import com.fasterxml.jackson.annotation.PropertyAccessor; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.data.redis.connection.RedisConnectionFactory; 11 | import org.springframework.data.redis.core.RedisTemplate; 12 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 13 | import org.springframework.data.redis.serializer.StringRedisSerializer; 14 | 15 | @Configuration 16 | public class RedisConfig { 17 | 18 | @Bean 19 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 20 | RedisTemplate redisTemplate = new RedisTemplate(); 21 | redisTemplate.setConnectionFactory(factory); 22 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 23 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 24 | ObjectMapper objectMapper = new ObjectMapper(); 25 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 26 | objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); 27 | jackson2JsonRedisSerializer.setObjectMapper(objectMapper); 28 | redisTemplate.setKeySerializer(stringRedisSerializer); // key的序列化类型 29 | redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value的序列化类型 30 | redisTemplate.setHashKeySerializer(stringRedisSerializer); // hash key的序列化类型 31 | redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); // hash value的序列化类型 32 | redisTemplate.afterPropertiesSet(); 33 | return redisTemplate; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Overtime.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import com.qiujie.enums.OvertimeEnum; 6 | import io.swagger.annotations.ApiModel; 7 | import io.swagger.annotations.ApiModelProperty; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | import java.sql.Timestamp; 14 | 15 | /** 16 | *

17 | * 加班表 18 | *

19 | * 20 | * @author qiujie 21 | * @since 2022-03-28 22 | */ 23 | @Getter 24 | @Setter 25 | @TableName("att_overtime") 26 | @ApiModel(value = "Overtime对象", description = "加班表") 27 | public class Overtime implements Serializable { 28 | 29 | private static final long serialVersionUID = 1L; 30 | 31 | @TableId(value = "id", type = IdType.AUTO) 32 | private Integer id; 33 | 34 | @ApiModelProperty("工资倍数,如按照小时计算,就是员工平均小时工资乘以倍数") 35 | @TableField("salary_multiple") 36 | private BigDecimal salaryMultiple; 37 | 38 | @ApiModelProperty("加班奖金") 39 | @TableField("bonus") 40 | private BigDecimal bonus; 41 | 42 | @ApiModelProperty("加班类型") 43 | @TableField("type_num") 44 | private OvertimeEnum typeNum; 45 | 46 | @ApiModelProperty("部门id") 47 | @TableField("dept_id") 48 | private Integer deptId; 49 | 50 | @ApiModelProperty("0小时,1天,默认0,计数加班工资的类型") 51 | @TableField("count_type") 52 | private Integer countType; 53 | 54 | @TableField("remark") 55 | private String remark; 56 | 57 | @ApiModelProperty("0不调休,1调休,默认0") 58 | @TableField("is_time_off") 59 | private Integer timeOffFlag; 60 | 61 | 62 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 63 | @ApiModelProperty("创建时间") 64 | @TableField("create_time") 65 | private Timestamp createTime; 66 | 67 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 68 | @ApiModelProperty("更新时间") 69 | @TableField("update_time") 70 | private Timestamp updateTime; 71 | 72 | @ApiModelProperty("逻辑删除,0未删除,1删除") 73 | @TableField("is_deleted") 74 | @TableLogic 75 | private Integer deleteFlag; 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/StaffLeaveMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.qiujie.entity.StaffLeave; 6 | import com.qiujie.vo.StaffLeaveVO; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | *

14 | * Mapper 接口 15 | *

16 | * 17 | * @author qiujie 18 | * @since 2022-04-05 19 | */ 20 | public interface StaffLeaveMapper extends BaseMapper { 21 | 22 | 23 | @Select("select * from att_staff_leave where is_deleted = 0 and staff_id = #{id}") 24 | IPage listStaffLeaveByStaffId(IPage config, @Param("id") Integer id); 25 | 26 | /** 27 | * 查询组任务以及个人任务 28 | * 29 | * @param config 30 | * @param name 31 | * @param deptId 32 | * @param ids 33 | * @return 34 | */ 35 | @Select("") 54 | IPage listStaffLeaveVO(IPage config, @Param("name") String name, @Param("deptId") Integer deptId, @Param("ids") List ids); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/staff.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/staff' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, 13 | method: 'post', 14 | data 15 | }) 16 | } 17 | 18 | /** 19 | * 逻辑删除 20 | * @param id 21 | * @returns {AxiosPromise} 22 | */ 23 | export const del = (id) => { 24 | return request({ 25 | url: url + '/' + id, 26 | method: 'delete' 27 | }) 28 | } 29 | 30 | export const deleteBatch = (ids) => { 31 | return request({ 32 | url: url + '/batch/' + ids, 33 | method: 'delete' 34 | }) 35 | } 36 | 37 | export const edit = (data) => { 38 | return request({ 39 | url: url, 40 | method: 'put', 41 | data 42 | }) 43 | } 44 | 45 | export const list = (params) => { 46 | return request({ 47 | url: url, 48 | params 49 | }) 50 | } 51 | 52 | // 为员工设置角色 53 | export const setRole = (id, data) => { 54 | return request({ 55 | url: url + '/set/' + id, 56 | method: 'post', 57 | data 58 | }) 59 | } 60 | 61 | // 获取员工的角色 62 | export const queryByStaffId = (id) => { 63 | return request({ 64 | url: url + '/staff/' + id 65 | }) 66 | } 67 | 68 | // 得到一条数据 69 | export const query = (id) => { 70 | return request({ 71 | url: url + '/' + id 72 | }) 73 | } 74 | 75 | // 得到一条数据 76 | export const queryInfo = (id) => { 77 | return request({ 78 | url: url + '/info/' + id 79 | }) 80 | } 81 | 82 | // 检查员工的密码 83 | export const validate = (pwd, id) => { 84 | return request({ 85 | url: url + '/' + pwd + '/' + id 86 | }) 87 | } 88 | 89 | export const reset = (data) => { 90 | return request({ 91 | url: url + '/reset', 92 | method: 'put', 93 | data 94 | }) 95 | } 96 | 97 | export const exp = (filename) => { 98 | return request({ 99 | url: url + '/export/' + filename, 100 | method: 'get', 101 | responseType: 'blob' 102 | }) 103 | } 104 | 105 | // 数据导入 106 | export const getImportApi = () => { 107 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 108 | } 109 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/StaffDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.qiujie.entity.Menu; 5 | import com.qiujie.entity.Staff; 6 | import com.qiujie.entity.StaffDetails; 7 | import com.qiujie.enums.BusinessStatusEnum; 8 | import com.qiujie.exception.ServiceException; 9 | import com.qiujie.mapper.MenuMapper; 10 | import com.qiujie.mapper.StaffMapper; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.security.core.GrantedAuthority; 13 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 14 | import org.springframework.security.core.userdetails.UserDetails; 15 | import org.springframework.security.core.userdetails.UserDetailsService; 16 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 17 | import org.springframework.stereotype.Service; 18 | 19 | import javax.annotation.Resource; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | @Service 24 | public class StaffDetailsService implements UserDetailsService { 25 | 26 | @Autowired 27 | private StaffMapper staffMapper; 28 | 29 | @Autowired 30 | private MenuMapper menuMapper; 31 | 32 | @Override 33 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 34 | Staff staff = this.staffMapper.selectOne(new QueryWrapper().eq("code", username)); 35 | if (staff == null) { 36 | throw new ServiceException(BusinessStatusEnum.STAFF_NOT_EXIST); 37 | } 38 | if (staff.getStatus() == 0){ 39 | throw new ServiceException(BusinessStatusEnum.STAFF_STATUS_ERROR); 40 | } 41 | // 查询员工的权限信息 42 | List menuList = this.menuMapper.queryPermission(staff.getId()); 43 | List list = new ArrayList<>(); 44 | for (Menu menu : menuList) { 45 | SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(menu.getPermission()); 46 | list.add(simpleGrantedAuthority); 47 | } 48 | return new StaffDetails(username, staff.getPassword(), list, 49 | true, true, true, true); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/util/ValidateCodeUtil.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.util; 2 | 3 | import com.qiujie.entity.ValidateCode; 4 | 5 | import java.awt.*; 6 | import java.awt.image.BufferedImage; 7 | import java.time.LocalDateTime; 8 | import java.util.Random; 9 | 10 | public class ValidateCodeUtil { 11 | static int width = 60; // 验证码图片宽度 12 | static int height = 20; // 验证码图片高度 13 | static int length = 4; // 验证码位数 14 | public static int expireIn = 60; // 验证码有效时间 60s 15 | public static ValidateCode generateValidateCode() { 16 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 17 | Graphics g = image.getGraphics(); 18 | Random random = new Random(); 19 | g.setColor(getRandColor(200, 250)); 20 | g.fillRect(0, 0, width, height); 21 | g.setFont(new Font("Times New Roman", Font.ITALIC, 20)); 22 | g.setColor(getRandColor(160, 200)); 23 | for (int i = 0; i < 155; i++) { 24 | int x = random.nextInt(width); 25 | int y = random.nextInt(height); 26 | int xl = random.nextInt(12); 27 | int yl = random.nextInt(12); 28 | g.drawLine(x, y, x + xl, y + yl); 29 | } 30 | StringBuilder sRand = new StringBuilder(); 31 | for (int i = 0; i < length; i++) { 32 | String rand = String.valueOf(random.nextInt(10)); 33 | sRand.append(rand); 34 | g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); 35 | g.drawString(rand, 13 * i + 6, 16); 36 | } 37 | g.dispose(); 38 | return new ValidateCode(image, sRand.toString(),expireIn); 39 | } 40 | 41 | private static Color getRandColor(int fc, int bc) { 42 | Random random = new Random(); 43 | if (fc > 255) 44 | fc = 255; 45 | if (bc > 255) 46 | bc = 255; 47 | int r = fc + random.nextInt(bc - fc); 48 | int g = fc + random.nextInt(bc - fc); 49 | int b = fc + random.nextInt(bc - fc); 50 | return new Color(r, g, b); 51 | } 52 | 53 | public static boolean isExpire(LocalDateTime expireTime) { 54 | return LocalDateTime.now().isAfter(expireTime); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/api/staffLeave.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request' 2 | 3 | const url = '/staff-leave' 4 | 5 | /** 6 | * 添加 7 | * @param data 8 | * @returns {AxiosPromise} 9 | */ 10 | export const add = (data) => { 11 | return request({ 12 | url: url, method: 'post', data 13 | }) 14 | } 15 | 16 | /** 17 | * 逻辑删除 18 | * @param id 19 | * @returns {AxiosPromise} 20 | */ 21 | export const del = (id) => { 22 | return request({ 23 | url: url + '/' + id, method: 'delete' 24 | }) 25 | } 26 | 27 | export const deleteBatch = (ids) => { 28 | return request({ 29 | url: url + '/batch/' + ids, method: 'delete' 30 | }) 31 | } 32 | 33 | export const edit = (data) => { 34 | return request({ 35 | url: url, method: 'put', data 36 | }) 37 | } 38 | 39 | export const list = (params) => { 40 | return request({ 41 | url: url, method: 'get', params 42 | }) 43 | } 44 | 45 | export const queryByStaffId = (params) => { 46 | return request({ 47 | url: url + '/staff', method: 'get', params 48 | }) 49 | } 50 | 51 | // 获得所有 52 | export const queryAll = () => { 53 | return request({ 54 | url: url + '/all' 55 | }) 56 | } 57 | 58 | export const exp = (filename) => { 59 | return request({ 60 | url: url + '/export/' + filename, 61 | method: 'get', 62 | responseType: 'blob' 63 | }) 64 | } 65 | 66 | // 数据导入 67 | export const getImportApi = () => { 68 | return process.env.VUE_APP_HOST + ':' + process.env.VUE_APP_PORT + url + '/import' 69 | } 70 | 71 | // 请假 72 | export const apply = (data, code) => { 73 | return request({ 74 | url: url + '/apply/' + code, method: 'post', data 75 | }) 76 | } 77 | 78 | // 拾取任务 79 | export const claim = (data, code) => { 80 | return request({ 81 | url: url + '/claim/' + code, method: 'post', data 82 | }) 83 | } 84 | 85 | // 归还任务 86 | export const revert = (data, code) => { 87 | return request({ 88 | url: url + '/revert/' + code, method: 'post', data 89 | }) 90 | } 91 | 92 | // 完成任务 93 | export const complete = (data, code) => { 94 | return request({ 95 | url: url + '/complete/' + code, method: 'post', data 96 | }) 97 | } 98 | 99 | // 撤销请假 100 | export const cancel = (data) => { 101 | return request({ 102 | url: url + '/cancel', method: 'post', data 103 | }) 104 | } 105 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.core.env.Environment; 6 | import springfox.documentation.builders.ApiInfoBuilder; 7 | import springfox.documentation.builders.PathSelectors; 8 | import springfox.documentation.builders.RequestHandlerSelectors; 9 | import springfox.documentation.service.ApiInfo; 10 | import springfox.documentation.spi.DocumentationType; 11 | import springfox.documentation.spring.web.plugins.Docket; 12 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 13 | 14 | /** 15 | * 配置Api生成文档 16 | * 17 | * @Author : qiujie 18 | * @Date : 2022/1/30 19 | */ 20 | @Configuration // 标明配置类 21 | @EnableSwagger2 // 开启Swagger功能 22 | public class SwaggerConfig { 23 | 24 | @Bean 25 | public Docket createRestApi(Environment environment) { 26 | // 设置要显示的swagger环境 27 | // Profiles profiles = Profiles.of("dev"); 28 | // 判断是否处在自己设定的环境当中 29 | // boolean flag = environment.acceptsProfiles(profiles); 30 | return new Docket(DocumentationType.SWAGGER_2) // DocumentationType.SWAGGER_2 固定的,代表swagger2 31 | // .groupName("分布式任务系统") // 如果配置多个文档的时候,那么需要配置groupName来分组标识 32 | .apiInfo(apiInfo()) // 用于生成API信息 33 | .enable(true) // 如果为false,则不启动swagger 34 | .select() // select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档 35 | .apis(RequestHandlerSelectors.basePackage("com.qiujie.controller")) // 用于指定扫描哪个包下的接口 36 | /** 37 | * RequestHandlerSelectors: 配置要扫描的包 38 | * any(): 扫描全部 39 | * none(): 不扫描 40 | */ 41 | .paths(PathSelectors.any()) // 选择所有的API,如果你想只为部分API生成文档,可以配置这里 42 | .build(); 43 | } 44 | 45 | /** 46 | * 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本 47 | * 48 | * @return 49 | */ 50 | private ApiInfo apiInfo() { 51 | return new ApiInfoBuilder() 52 | .title("人力资源管理系统API") // 可以用来自定义API的主标题 53 | .description("人力资源管理系统API管理") // 可以用来描述整体的API 54 | .termsOfServiceUrl("") // 用于定义服务的域名 55 | .version("1.0") // 可以用来定义版本。 56 | .build(); // 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /hrm/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8888 3 | 4 | spring: 5 | # 多数据源 6 | datasource: 7 | master: 8 | jdbc-url: jdbc:mysql://127.0.0.1:3306/hrm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2b8 9 | username: root 10 | password: 123456 11 | driver-class-name: com.mysql.cj.jdbc.Driver 12 | type: com.zaxxer.hikari.HikariDataSource 13 | activiti: 14 | jdbc-url: jdbc:mysql://127.0.0.1:3306/hrm_activiti?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2b8 15 | username: root 16 | password: 123456 17 | driver-class-name: com.mysql.cj.jdbc.Driver 18 | type: com.zaxxer.hikari.HikariDataSource 19 | 20 | activiti: 21 | database-schema-update: true # 检查数据库的表是否存在,不存在就创建 22 | history-level: full 23 | db-history-used: true # 是否使用历史记录表 24 | 25 | servlet: 26 | multipart: 27 | enabled: true #默认支持文件上传 28 | max-file-size: 20MB # 最大支持文件大小 29 | max-request-size: 30MB # 最大支持请求大小 30 | 31 | redis: 32 | host: localhost 33 | port: 6379 34 | password: 123456 35 | database: 0 36 | lettuce: 37 | pool: 38 | max-idle: 16 39 | max-active: 32 40 | min-idle: 8 41 | mvc: 42 | path match: 43 | matching-strategy: ant-path-matcher 44 | 45 | main: 46 | allow-bean-definition-overriding: true 47 | 48 | mybatis-plus: 49 | configuration: 50 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 51 | # 扫描通用枚举包 52 | type-enums-package: com.qiujie.enums 53 | mapper-locations: classpath:mapper/*.xml 54 | 55 | 56 | file-path: D:/project/idea/hrm/file/ # 文件存储位置 57 | 58 | # 2024国家法定节假日 59 | holidays: 60 | - 2024-01-01 61 | - 2024-02-10 62 | - 2024-02-11 63 | - 2024-02-12 64 | - 2024-02-13 65 | - 2024-02-14 66 | - 2024-02-15 67 | - 2024-02-16 68 | - 2024-02-17 69 | - 2024-04-04 70 | - 2024-04-05 71 | - 2024-04-06 72 | - 2024-05-01 73 | - 2024-05-02 74 | - 2024-05-03 75 | - 2024-05-04 76 | - 2024-05-05 77 | - 2024-06-08 78 | - 2024-06-09 79 | - 2024-06-10 80 | - 2024-09-15 81 | - 2024-09-16 82 | - 2024-09-17 83 | - 2024-10-01 84 | - 2024-10-02 85 | - 2024-10-03 86 | - 2024-10-04 87 | - 2024-10-05 88 | - 2024-10-06 89 | - 2024-10-07 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Menu.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableLogic; 7 | import com.baomidou.mybatisplus.annotation.TableName; 8 | 9 | import java.io.Serial; 10 | import java.io.Serializable; 11 | import java.sql.Timestamp; 12 | import java.util.List; 13 | 14 | import com.fasterxml.jackson.annotation.JsonFormat; 15 | import io.swagger.annotations.ApiModel; 16 | import io.swagger.annotations.ApiModelProperty; 17 | import lombok.Data; 18 | 19 | /** 20 | *

21 | * 22 | *

23 | * 24 | * @author qiujie 25 | * @since 2022-02-28 26 | */ 27 | @Data 28 | @TableName("per_menu") 29 | @ApiModel(value = "Menu对象", description = "") 30 | public class Menu implements Serializable { 31 | 32 | @Serial 33 | private static final long serialVersionUID = 1L; 34 | 35 | @ApiModelProperty("菜单id") 36 | @TableId(value = "id", type = IdType.AUTO) 37 | private Integer id; 38 | 39 | @ApiModelProperty("菜单编码") 40 | @TableField("code") 41 | private String code; 42 | 43 | @ApiModelProperty("菜单名称") 44 | @TableField("name") 45 | private String name; 46 | 47 | @TableField("icon") 48 | private String icon; 49 | 50 | @ApiModelProperty("权限标识") 51 | @TableField("permission") 52 | private String permission; 53 | 54 | @ApiModelProperty("父菜单id,0代表根菜单") 55 | @TableField("parent_id") 56 | private Integer parentId; 57 | 58 | @ApiModelProperty("0一级菜单,1二级菜单,2权限点") 59 | @TableField("level") 60 | private Integer level; 61 | 62 | @ApiModelProperty("权限点是否启用,0禁用、1正常,默认1") 63 | @TableField("status") 64 | private Integer status; 65 | 66 | @ApiModelProperty("备注") 67 | @TableField("remark") 68 | private String remark; 69 | 70 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 71 | @ApiModelProperty("创建时间") 72 | @TableField("create_time") 73 | private Timestamp createTime; 74 | 75 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 76 | @ApiModelProperty("更新时间") 77 | @TableField("update_time") 78 | private Timestamp updateTime; 79 | 80 | @TableField("is_deleted") 81 | @TableLogic 82 | private Integer deleteFlag; 83 | 84 | @TableField(exist = false) 85 | private List children; 86 | 87 | } 88 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffInsuranceVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * @Author qiujie 12 | * @Date 2022/3/23 13 | * @Version 1.0 14 | */ 15 | 16 | @Data 17 | public class StaffInsuranceVO implements Serializable { 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @ApiModelProperty("员工id") 22 | private Integer staffId; 23 | 24 | @ApiModelProperty("城市id") 25 | private Integer cityId; 26 | 27 | @ApiModelProperty("社保id") 28 | private Integer insuranceId; 29 | 30 | @ExcelColumn("员工工号") 31 | @ApiModelProperty("员工工号") 32 | private String code; 33 | 34 | @ExcelColumn("员工姓名") 35 | @ApiModelProperty("员工姓名") 36 | private String name; 37 | 38 | @ExcelColumn("电话") 39 | @ApiModelProperty("电话") 40 | private String phone; 41 | 42 | @ExcelColumn("地址") 43 | @ApiModelProperty("地址") 44 | private String address; 45 | 46 | @ExcelColumn("部门") 47 | @ApiModelProperty("部门") 48 | private String deptName; 49 | 50 | @ExcelColumn("公积金基数") 51 | @ApiModelProperty("公积金基数") 52 | private BigDecimal houseBase; 53 | 54 | @ExcelColumn("公积金个人缴纳比例") 55 | @ApiModelProperty("公积金个人缴纳比例") 56 | private BigDecimal perHouseRate; 57 | 58 | @ExcelColumn("公积金个人缴纳费用") 59 | @ApiModelProperty("公积金个人缴纳费用") 60 | private BigDecimal perHousePay; 61 | 62 | @ExcelColumn("公积金企业缴纳比例") 63 | @ApiModelProperty("公积金企业缴纳比例") 64 | private BigDecimal comHouseRate; 65 | 66 | @ExcelColumn("公积金企业缴纳费用") 67 | @ApiModelProperty("公积金企业缴纳费用") 68 | private BigDecimal comHousePay; 69 | 70 | @ExcelColumn("公积金备注") 71 | @ApiModelProperty("公积金备注") 72 | private String houseRemark; 73 | 74 | @ExcelColumn("社保基数") 75 | @ApiModelProperty("社保基数") 76 | private BigDecimal socialBase; 77 | 78 | @ExcelColumn("社保企业缴纳费用") 79 | @ApiModelProperty("社保企业缴纳费用") 80 | private BigDecimal comSocialPay; 81 | 82 | @ExcelColumn("社保个人缴纳费用") 83 | @ApiModelProperty("社保个人缴纳费用") 84 | private BigDecimal perSocialPay; 85 | 86 | @ExcelColumn("工伤保险企业缴纳比例") 87 | @ApiModelProperty("工伤保险企业缴纳比例") 88 | private BigDecimal comInjuryRate; 89 | 90 | @ExcelColumn("社保备注") 91 | @ApiModelProperty("社保备注") 92 | private String socialRemark; 93 | 94 | 95 | } 96 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/OvertimeController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.Overtime; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.enums.OvertimeEnum; 6 | import com.qiujie.service.OvertimeService; 7 | import io.swagger.annotations.ApiOperation; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.security.access.prepost.PreAuthorize; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.List; 14 | 15 | 16 | /** 17 | *

18 | * 加班表 前端控制器 19 | *

20 | * 21 | * @author qiujie 22 | * @since 2022-03-28 23 | */ 24 | @RestController 25 | @RequestMapping("/overtime") 26 | public class OvertimeController { 27 | @Autowired 28 | private OvertimeService overtimeService; 29 | 30 | @ApiOperation("新增") 31 | @PostMapping 32 | public ResponseDTO add(@RequestBody Overtime overtime) { 33 | return this.overtimeService.add(overtime); 34 | } 35 | 36 | @ApiOperation("逻辑删除") 37 | @DeleteMapping("/{id}") 38 | public ResponseDTO delete(@PathVariable Integer id) { 39 | return this.overtimeService.delete(id); 40 | } 41 | 42 | @ApiOperation("批量逻辑删除") 43 | @DeleteMapping("/batch/{ids}") 44 | public ResponseDTO deleteBatch(@PathVariable List ids) { 45 | return this.overtimeService.deleteBatch(ids); 46 | } 47 | 48 | @ApiOperation("编辑更新") 49 | @PutMapping 50 | public ResponseDTO edit(@RequestBody Overtime overtime) { 51 | return this.overtimeService.edit(overtime); 52 | } 53 | 54 | @ApiOperation("查询") 55 | @GetMapping("/{id}") 56 | public ResponseDTO query(@PathVariable Integer id) { 57 | return this.overtimeService.query(id); 58 | } 59 | 60 | @ApiOperation("获取") 61 | @GetMapping("/{deptId}/{typeNum}") 62 | public ResponseDTO queryByDeptIdAndTypeNum(@PathVariable Integer deptId, @PathVariable String typeNum) { 63 | return this.overtimeService.queryByDeptIdAndTypeNum(deptId,typeNum); 64 | } 65 | 66 | @ApiOperation("设置加班") 67 | @PostMapping("/set") 68 | @PreAuthorize("hasAnyAuthority('system:department:setting')") 69 | public ResponseDTO setOvertime(@RequestBody Overtime overtime) { 70 | return this.overtimeService.setOvertime(overtime); 71 | } 72 | 73 | @ApiOperation("获取所有") 74 | @GetMapping("/all") 75 | public ResponseDTO queryAll() { 76 | return this.overtimeService.queryAll(); 77 | } 78 | 79 | } 80 | 81 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/components/Aside.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 64 | 65 | 90 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/SalaryDeductController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.SalaryDeduct; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.service.SalaryDeductService; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | 15 | /** 16 | *

17 | * 工资扣除表 前端控制器 18 | *

19 | * 20 | * @author qiujie 21 | * @since 2022-03-27 22 | */ 23 | @RestController 24 | @RequestMapping("/salary-deduct") 25 | public class SalaryDeductController { 26 | @Autowired 27 | private SalaryDeductService salaryDeductService; 28 | 29 | @ApiOperation("新增") 30 | @PostMapping 31 | public ResponseDTO add(@RequestBody SalaryDeduct salaryDeduct) { 32 | return this.salaryDeductService.add(salaryDeduct); 33 | } 34 | 35 | @ApiOperation("逻辑删除") 36 | @DeleteMapping("/{id}") 37 | public ResponseDTO delete(@PathVariable Integer id) { 38 | return this.salaryDeductService.delete(id); 39 | } 40 | 41 | @ApiOperation("批量逻辑删除") 42 | @DeleteMapping("/batch/{ids}") 43 | public ResponseDTO deleteBatch(@PathVariable List ids) { 44 | return this.salaryDeductService.deleteBatch(ids); 45 | } 46 | 47 | @ApiOperation("编辑更新") 48 | @PutMapping 49 | public ResponseDTO edit(@RequestBody SalaryDeduct salaryDeduct) { 50 | return this.salaryDeductService.edit(salaryDeduct); 51 | } 52 | 53 | @ApiOperation("查询") 54 | @GetMapping("/{id}") 55 | public ResponseDTO query(@PathVariable Integer id) { 56 | return this.salaryDeductService.query(id); 57 | } 58 | 59 | @ApiOperation("获取") 60 | @GetMapping("/{deptId}/{typeNum}") 61 | public ResponseDTO queryByDeptIdAndTypeNum(@PathVariable Integer deptId, @PathVariable Integer typeNum) { 62 | return this.salaryDeductService.queryByDeptIdAndTypeNum(deptId, typeNum); 63 | } 64 | 65 | @ApiOperation("设置罚款") 66 | @PostMapping("/set") 67 | @PreAuthorize("hasAnyAuthority('system:department:setting')") 68 | public ResponseDTO setSalaryDeduct(@RequestBody SalaryDeduct salaryDeduct) { 69 | return this.salaryDeductService.setSalaryDeduct(salaryDeduct); 70 | } 71 | 72 | @ApiOperation("获取所有") 73 | @GetMapping("/all") 74 | public ResponseDTO queryAll() { 75 | return this.salaryDeductService.queryAll(); 76 | } 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/mapper/InsuranceMapper.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.qiujie.entity.Insurance; 6 | import com.qiujie.vo.StaffInsuranceVO; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | *

14 | * Mapper 接口 15 | *

16 | * 17 | * @author qiujie 18 | * @since 2022-03-23 19 | */ 20 | public interface InsuranceMapper extends BaseMapper { 21 | 22 | 23 | @Select("select ss.id staff_id,ss.code,ss.name,ss.phone,ss.address,sd.name dept_name," + 24 | "si.id insurance_id,si.city_id,si.social_base,si.per_social_pay,si.com_injury_rate,si.com_social_pay,si.social_remark,si.house_base,si.per_house_rate," + 25 | "si.per_house_pay,si.com_house_rate,si.com_house_pay,si.house_remark from " + 26 | "(sys_staff ss left join sys_dept sd on ss.dept_id = sd.id) left join soc_insurance si on si.staff_id = ss.id " + 27 | "where ss.is_deleted = 0 and ss.name like concat('%',#{name},'%')") 28 | IPage listStaffInsuranceVO(IPage config, @Param("name") String name); 29 | 30 | @Select("select ss.id staff_id,ss.code,ss.name,ss.phone,ss.address,sd.name dept_name," + 31 | "si.id insurance_id,si.city_id,si.social_base,si.per_social_pay,si.com_injury_rate,si.com_social_pay,si.social_remark,si.house_base,si.per_house_rate," + 32 | "si.per_house_pay,si.com_house_rate,si.com_house_pay,si.house_remark from " + 33 | "(sys_staff ss left join sys_dept sd on ss.dept_id = sd.id) left join soc_insurance si on si.staff_id = ss.id " + 34 | "where ss.is_deleted = 0 and ss.dept_id = #{deptId} and ss.name like concat('%',#{name},'%')") 35 | IPage listStaffDeptInsuranceVO(IPage config, @Param("name") String name,@Param("deptId") Integer deptId); 36 | 37 | @Select("select ss.id staff_id,ss.code,ss.name,ss.phone,ss.address,sd.name dept_name," + 38 | "si.id insurance_id,si.city_id,si.social_base,si.per_social_pay,si.com_injury_rate,si.com_social_pay,si.social_remark,si.house_base,si.per_house_rate," + 39 | "si.per_house_pay,si.com_house_rate,si.com_house_pay,si.house_remark from " + 40 | "(sys_staff ss left join sys_dept sd on ss.dept_id = sd.id) left join soc_insurance si on si.staff_id = ss.id " + 41 | "where ss.is_deleted = 0") 42 | List queryStaffInsuranceVO(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/vo/StaffSalaryVO.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.vo; 2 | 3 | import com.qiujie.annotation.ExcelColumn; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | 11 | /** 12 | * @Author qiujie 13 | * @Date 2022/4/8 14 | * @Version 1.0 15 | */ 16 | 17 | @Data 18 | @Accessors(chain = true) 19 | public class StaffSalaryVO implements Serializable { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @ApiModelProperty("员工id") 24 | private Integer staffId; 25 | 26 | @ApiModelProperty("部门id") 27 | private Integer deptId; 28 | 29 | @ExcelColumn("员工工号") 30 | @ApiModelProperty("员工工号") 31 | private String code; 32 | 33 | @ExcelColumn("员工姓名") 34 | @ApiModelProperty("员工姓名") 35 | private String name; 36 | 37 | @ExcelColumn("电话") 38 | @ApiModelProperty("电话") 39 | private String phone; 40 | 41 | @ExcelColumn("地址") 42 | @ApiModelProperty("地址") 43 | private String address; 44 | 45 | @ExcelColumn("部门") 46 | @ApiModelProperty("部门") 47 | private String deptName; 48 | 49 | @ExcelColumn("迟到扣款") 50 | @ApiModelProperty("迟到扣款") 51 | private BigDecimal lateDeduct; 52 | 53 | @ExcelColumn("休假扣款") 54 | @ApiModelProperty("休假扣款") 55 | private BigDecimal leaveDeduct; 56 | 57 | @ExcelColumn("早退扣款") 58 | @ApiModelProperty("早退扣款") 59 | private BigDecimal leaveEarlyDeduct; 60 | 61 | @ExcelColumn("旷工扣款") 62 | @ApiModelProperty("旷工扣款") 63 | private BigDecimal absenteeismDeduct; 64 | 65 | @ExcelColumn("公积金缴纳费用") 66 | @ApiModelProperty("公积金缴纳费用") 67 | private BigDecimal housePay; 68 | 69 | @ExcelColumn("社保缴纳费用") 70 | @ApiModelProperty("社保缴纳费用") 71 | private BigDecimal socialPay; 72 | 73 | @ExcelColumn("基础工资") 74 | @ApiModelProperty("基础工资") 75 | private BigDecimal baseSalary; 76 | 77 | @ExcelColumn("加班费") 78 | @ApiModelProperty("加班费") 79 | private BigDecimal overtimeSalary; 80 | 81 | @ApiModelProperty("备注") 82 | private String remark; 83 | 84 | @ExcelColumn("生活补贴") 85 | @ApiModelProperty("生活补贴") 86 | private BigDecimal subsidy; 87 | 88 | @ExcelColumn("奖金") 89 | @ApiModelProperty("奖金") 90 | private BigDecimal bonus; 91 | 92 | @ApiModelProperty("月份") 93 | private String month; 94 | 95 | @ExcelColumn("最终工资") 96 | @ApiModelProperty("最终工资") 97 | private BigDecimal totalSalary; 98 | 99 | } 100 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/LeaveController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.Leave; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.service.LeaveService; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | 15 | /** 16 | *

17 | * 请假表 前端控制器 18 | *

19 | * 20 | * @author qiujie 21 | * @since 2022-03-27 22 | */ 23 | @RestController 24 | @RequestMapping("/leave") 25 | public class LeaveController { 26 | @Autowired 27 | private LeaveService leaveService; 28 | 29 | @ApiOperation("新增") 30 | @PostMapping 31 | public ResponseDTO add(@RequestBody Leave leave) { 32 | return this.leaveService.add(leave); 33 | } 34 | 35 | @ApiOperation("逻辑删除") 36 | @DeleteMapping("/{id}") 37 | public ResponseDTO delete(@PathVariable Integer id) { 38 | return this.leaveService.delete(id); 39 | } 40 | 41 | @ApiOperation("批量逻辑删除") 42 | @DeleteMapping("/batch/{ids}") 43 | public ResponseDTO deleteBatch(@PathVariable List ids) { 44 | return this.leaveService.deleteBatch(ids); 45 | } 46 | 47 | @ApiOperation("编辑更新") 48 | @PutMapping 49 | public ResponseDTO edit(@RequestBody Leave leave) { 50 | return this.leaveService.edit(leave); 51 | } 52 | 53 | @ApiOperation("查询") 54 | @GetMapping("/{id}") 55 | public ResponseDTO query(@PathVariable Integer id) { 56 | return this.leaveService.query(id); 57 | } 58 | 59 | 60 | @ApiOperation("获取") 61 | @GetMapping("/{deptId}/{typeNum}") 62 | public ResponseDTO queryByDeptIdAndTypeNum(@PathVariable Integer deptId, @PathVariable Integer typeNum) { 63 | return this.leaveService.queryByDeptIdAndTypeNum(deptId, typeNum); 64 | } 65 | 66 | @ApiOperation("设置假期") 67 | @PostMapping("/set") 68 | @PreAuthorize("hasAnyAuthority('system:department:setting')") 69 | public ResponseDTO setLeave(@RequestBody Leave leave) { 70 | return this.leaveService.setLeave(leave); 71 | } 72 | 73 | 74 | @ApiOperation("查询") 75 | @GetMapping("/dept/{id}") 76 | public ResponseDTO queryByDeptId(@PathVariable Integer id) { 77 | return this.leaveService.queryByDeptId(id); 78 | } 79 | 80 | @ApiOperation("获取所有") 81 | @GetMapping("/all") 82 | public ResponseDTO queryAll() { 83 | return this.leaveService.queryAll(); 84 | } 85 | 86 | } 87 | 88 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/filter/JwtAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.filter; 2 | 3 | import com.qiujie.service.StaffDetailsService; 4 | import com.qiujie.util.JwtUtil; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.StringUtils; 12 | import org.springframework.web.filter.OncePerRequestFilter; 13 | 14 | import javax.servlet.FilterChain; 15 | import javax.servlet.ServletException; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | 20 | @Component 21 | public class JwtAuthenticationFilter extends OncePerRequestFilter { 22 | 23 | @Autowired 24 | private StaffDetailsService staffDetailsService; 25 | 26 | @Override 27 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 28 | // 获取认证信息 29 | String authorization = request.getHeader("Authorization"); 30 | String username = ""; 31 | if (StringUtils.hasText(authorization) && authorization.startsWith("Bearer ")) { 32 | String token = authorization.substring(7).trim(); // 截取token 33 | if (StringUtils.hasText(token)) { 34 | // 解析username 35 | try { 36 | username = JwtUtil.extractUsername(token); 37 | } catch (Exception e) { 38 | this.logger.warn(e.getMessage()); 39 | } 40 | } 41 | } 42 | if (StringUtils.hasText(username)) { 43 | // 获取信息 44 | UserDetails userDetails = this.staffDetailsService.loadUserByUsername(username); 45 | if (userDetails != null) { 46 | // 存入SecurityContextHolder中 47 | UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = 48 | new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 49 | usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 50 | SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); 51 | } 52 | } 53 | filterChain.doFilter(request, response); 54 | } 55 | } -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Staff.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import com.qiujie.annotation.ExcelColumn; 6 | import com.qiujie.enums.GenderEnum; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.Data; 10 | import lombok.experimental.Accessors; 11 | 12 | import java.io.Serializable; 13 | import java.sql.Date; 14 | import java.sql.Timestamp; 15 | 16 | /** 17 | *

18 | * 19 | *

20 | * 21 | * @author qiujie 22 | * @since 2022-01-27 23 | */ 24 | @Data 25 | @Accessors(chain = true) 26 | @TableName("sys_staff") 27 | @ApiModel(value = "Staff对象", description = "") 28 | public class Staff implements Serializable { 29 | 30 | private static final long serialVersionUID = 1L; 31 | 32 | @ApiModelProperty("员工id") 33 | @TableId(value = "id", type = IdType.AUTO) 34 | private Integer id; 35 | 36 | @ExcelColumn("工号") 37 | @ApiModelProperty("员工编码") 38 | @TableField("code") 39 | private String code; 40 | 41 | @ExcelColumn("姓名") 42 | @ApiModelProperty("员工姓名") 43 | @TableField("name") 44 | private String name; 45 | 46 | @ApiModelProperty("性别,0男,1女,默认男") 47 | @TableField("gender") 48 | private GenderEnum gender; 49 | 50 | @ExcelColumn("地址") 51 | @ApiModelProperty("员工家庭住址") 52 | @TableField("address") 53 | private String address; 54 | 55 | @ApiModelProperty("员工密码") 56 | @TableField("pwd") 57 | private String password; 58 | 59 | @ApiModelProperty("员工头像") 60 | @TableField("avatar") 61 | private String avatar; 62 | 63 | @ExcelColumn("生日") 64 | @ApiModelProperty("员工生日") 65 | @TableField("birthday") 66 | private Date birthday; 67 | 68 | @ExcelColumn("电话") 69 | @ApiModelProperty("员工电话") 70 | @TableField("phone") 71 | private String phone; 72 | 73 | @ExcelColumn("备注") 74 | @ApiModelProperty("员工备注") 75 | @TableField("remark") 76 | private String remark; 77 | 78 | @ExcelColumn("部门id") 79 | @ApiModelProperty("部门id") 80 | @TableField("dept_id") 81 | private Integer deptId; 82 | 83 | @ApiModelProperty("员工状态,0离职,1在职,2禁用") 84 | @TableField("status") 85 | private Integer status; 86 | 87 | @ExcelColumn("创建时间") 88 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 89 | @ApiModelProperty("创建时间") 90 | @TableField("create_time") 91 | private Timestamp createTime; 92 | 93 | @ExcelColumn("更新时间") 94 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 95 | @ApiModelProperty("更新时间") 96 | @TableField("update_time") 97 | private Timestamp updateTime; 98 | 99 | @ApiModelProperty("逻辑删除,0未删除,1删除") 100 | @TableField("is_deleted") 101 | @TableLogic 102 | private Integer deleteFlag; 103 | } 104 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Insurance.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | import java.io.Serializable; 11 | import java.math.BigDecimal; 12 | import java.sql.Timestamp; 13 | 14 | /** 15 | *

16 | * 17 | *

18 | * 19 | * @author qiujie 20 | * @since 2022-03-24 21 | */ 22 | @Getter 23 | @Setter 24 | @TableName("soc_insurance") 25 | @ApiModel(value = "Insurance对象", description = "员工社保") 26 | public class Insurance implements Serializable { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | @TableId(value = "id", type = IdType.AUTO) 31 | private Integer id; 32 | 33 | @ApiModelProperty("城市id") 34 | @TableField("city_id") 35 | private Integer cityId; 36 | 37 | @ApiModelProperty("员工id") 38 | @TableField("staff_id") 39 | private Integer staffId; 40 | 41 | @ApiModelProperty("公积金基数") 42 | @TableField("house_base") 43 | private BigDecimal houseBase; 44 | 45 | @ApiModelProperty("公积金个人缴纳比例") 46 | @TableField("per_house_rate") 47 | private BigDecimal perHouseRate; 48 | 49 | @ApiModelProperty("公积金个人缴纳费用") 50 | @TableField("per_house_pay") 51 | private BigDecimal perHousePay; 52 | 53 | @ApiModelProperty("公积金企业缴纳比例") 54 | @TableField("com_house_rate") 55 | private BigDecimal comHouseRate; 56 | 57 | @ApiModelProperty("公积金企业缴纳费用") 58 | @TableField("com_house_pay") 59 | private BigDecimal comHousePay; 60 | 61 | @ApiModelProperty("公积金备注") 62 | @TableField("house_remark") 63 | private String houseRemark; 64 | 65 | @ApiModelProperty("社保基数") 66 | @TableField("social_base") 67 | private BigDecimal socialBase; 68 | 69 | @ApiModelProperty("社保企业缴纳费用") 70 | @TableField("com_social_pay") 71 | private BigDecimal comSocialPay; 72 | 73 | @ApiModelProperty("社保个人缴纳费用") 74 | @TableField("per_social_pay") 75 | private BigDecimal perSocialPay; 76 | 77 | @ApiModelProperty("工伤保险企业缴纳比例") 78 | @TableField("com_injury_rate") 79 | private BigDecimal comInjuryRate; 80 | 81 | @ApiModelProperty("社保备注") 82 | @TableField("social_remark") 83 | private String socialRemark; 84 | 85 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 86 | @ApiModelProperty("创建时间") 87 | @TableField("create_time") 88 | private Timestamp createTime; 89 | 90 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 91 | @ApiModelProperty("更新时间") 92 | @TableField("update_time") 93 | private Timestamp updateTime; 94 | 95 | @ApiModelProperty("逻辑删除,0未删除,1删除") 96 | @TableField("is_deleted") 97 | @TableLogic 98 | private Integer deleteFlag; 99 | } 100 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/SalaryDeductService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.qiujie.entity.SalaryDeduct; 6 | import com.qiujie.enums.DeductEnum; 7 | import com.qiujie.mapper.SalaryDeductMapper; 8 | import com.qiujie.dto.Response; 9 | import com.qiujie.dto.ResponseDTO; 10 | import com.qiujie.util.EnumUtil; 11 | import org.springframework.stereotype.Service; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | *

17 | * 工资扣除表 服务类 18 | *

19 | * 20 | * @author qiujie 21 | * @since 2022-03-27 22 | */ 23 | @Service 24 | public class SalaryDeductService extends ServiceImpl { 25 | 26 | 27 | public ResponseDTO add(SalaryDeduct salaryDeduct) { 28 | if (save(salaryDeduct)) { 29 | return Response.success(); 30 | } 31 | return Response.error(); 32 | } 33 | 34 | public ResponseDTO delete(Integer id) { 35 | if (removeById(id)) { 36 | return Response.success(); 37 | } 38 | return Response.error(); 39 | } 40 | 41 | public ResponseDTO deleteBatch(List ids) { 42 | if (removeBatchByIds(ids)) { 43 | return Response.success(); 44 | } 45 | return Response.error(); 46 | } 47 | 48 | 49 | public ResponseDTO edit(SalaryDeduct salaryDeduct) { 50 | if (updateById(salaryDeduct)) { 51 | return Response.success(); 52 | } 53 | return Response.error(); 54 | } 55 | 56 | 57 | public ResponseDTO query(Integer id) { 58 | SalaryDeduct salaryDeduct = getById(id); 59 | if (salaryDeduct != null) { 60 | return Response.success(salaryDeduct); 61 | } 62 | return Response.error(); 63 | } 64 | 65 | public ResponseDTO queryByDeptIdAndTypeNum(Integer deptId, Integer typeNum) { 66 | QueryWrapper queryWrapper = new QueryWrapper<>(); 67 | queryWrapper.eq("dept_id", deptId).eq("type_num", typeNum); 68 | SalaryDeduct salaryDeduct = getOne(queryWrapper); 69 | if (salaryDeduct != null) { 70 | return Response.success(salaryDeduct); 71 | } 72 | return Response.error(); 73 | } 74 | 75 | 76 | public ResponseDTO setSalaryDeduct(SalaryDeduct salaryDeduct) { 77 | QueryWrapper queryWrapper = new QueryWrapper<>(); 78 | queryWrapper.eq("dept_id", salaryDeduct.getDeptId()).eq("type_num", salaryDeduct.getTypeNum()); 79 | if (saveOrUpdate(salaryDeduct, queryWrapper)) { 80 | return Response.success(); 81 | } 82 | return Response.error(); 83 | } 84 | 85 | /** 86 | * 获取所有罚款类型 87 | * @return 88 | */ 89 | public ResponseDTO queryAll() { 90 | return Response.success(EnumUtil.getEnumList(DeductEnum.class)); 91 | } 92 | } 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Attendance.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import com.qiujie.annotation.ExcelColumn; 6 | import com.qiujie.enums.AttendanceStatusEnum; 7 | import io.swagger.annotations.ApiModel; 8 | import io.swagger.annotations.ApiModelProperty; 9 | import lombok.Data; 10 | import lombok.experimental.Accessors; 11 | import org.springframework.format.annotation.DateTimeFormat; 12 | 13 | import java.io.Serializable; 14 | import java.sql.Timestamp; 15 | import java.sql.Date; 16 | 17 | /** 18 | *

19 | * 20 | *

21 | * 22 | * @author qiujie 23 | * @since 2022-03-29 24 | */ 25 | @Data 26 | @Accessors(chain = true) 27 | @TableName("att_attendance") 28 | @ApiModel(value = "Attendance对象", description = "") 29 | public class Attendance implements Serializable { 30 | 31 | private static final long serialVersionUID = 1L; 32 | 33 | @TableId(value = "id", type = IdType.AUTO) 34 | private Integer id; 35 | 36 | @ExcelColumn("员工id") 37 | @ApiModelProperty("员工id") 38 | @TableField("staff_id") 39 | private Integer staffId; 40 | 41 | @ExcelColumn("上午上班时间") 42 | @ApiModelProperty("上午上班时间") 43 | @DateTimeFormat(pattern = "HH:mm") 44 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 45 | @TableField("mor_start_time") 46 | private Timestamp morStartTime; 47 | 48 | @ExcelColumn("上午下班时间") 49 | @ApiModelProperty("上午下班时间") 50 | @DateTimeFormat(pattern = "HH:mm") 51 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 52 | @TableField("mor_end_time") 53 | private Timestamp morEndTime; 54 | 55 | @ExcelColumn("下午上班时间") 56 | @ApiModelProperty("下午上班时间") 57 | @DateTimeFormat(pattern = "HH:mm") 58 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 59 | @TableField("aft_start_time") 60 | private Timestamp aftStartTime; 61 | 62 | @ExcelColumn("下午下班时间") 63 | @ApiModelProperty("下午下班时间") 64 | @DateTimeFormat(pattern = "HH:mm") 65 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 66 | @TableField("aft_end_time") 67 | private Timestamp aftEndTime; 68 | 69 | @ExcelColumn("考勤日期") 70 | @ApiModelProperty("考勤日期") 71 | @TableField("attendance_date") 72 | private Date attendanceDate; 73 | 74 | @ApiModelProperty("0正常,1迟到,2早退,3旷工,4休假") 75 | @TableField("status") 76 | private AttendanceStatusEnum status; 77 | 78 | @TableField("remark") 79 | private String remark; 80 | 81 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 82 | @ApiModelProperty("创建时间") 83 | @TableField("create_time") 84 | private Timestamp createTime; 85 | 86 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 87 | @ApiModelProperty("更新时间") 88 | @TableField("update_time") 89 | private Timestamp updateTime; 90 | 91 | @ApiModelProperty("逻辑删除,0未删除,1删除") 92 | @TableField("is_deleted") 93 | @TableLogic 94 | private Integer deleteFlag; 95 | 96 | } 97 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Salary.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | import java.io.Serializable; 11 | import java.math.BigDecimal; 12 | import java.sql.Timestamp; 13 | 14 | /** 15 | *

16 | * 17 | *

18 | * 19 | * @author qiujie 20 | * @since 2022-04-06 21 | */ 22 | @Getter 23 | @Setter 24 | @TableName("sal_salary") 25 | @ApiModel(value = "Salary对象", description = "") 26 | public class Salary implements Serializable { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | @TableId(value = "id", type = IdType.AUTO) 31 | private Integer id; 32 | 33 | @ApiModelProperty("员工id") 34 | @TableField("staff_id") 35 | private Integer staffId; 36 | 37 | @ApiModelProperty("基础工资") 38 | @TableField("base_salary") 39 | private BigDecimal baseSalary; 40 | 41 | @ApiModelProperty("平均日薪") 42 | @TableField("day_salary") 43 | private BigDecimal daySalary; 44 | 45 | @ApiModelProperty("平均时薪资") 46 | @TableField("hour_salary") 47 | private BigDecimal hourSalary; 48 | 49 | @ApiModelProperty("加班费") 50 | @TableField("overtime_salary") 51 | private BigDecimal overtimeSalary; 52 | 53 | @ApiModelProperty("生活补贴") 54 | @TableField("subsidy") 55 | private BigDecimal subsidy; 56 | 57 | @ApiModelProperty("奖金") 58 | @TableField("bonus") 59 | private BigDecimal bonus; 60 | 61 | @ApiModelProperty("月份") 62 | @TableField("month") 63 | private String month; 64 | 65 | @ApiModelProperty("早退扣款") 66 | @TableField("late_deduct") 67 | private BigDecimal lateDeduct; 68 | 69 | @ApiModelProperty("休假扣款") 70 | @TableField("leave_deduct") 71 | private BigDecimal leaveDeduct; 72 | 73 | @ApiModelProperty("早退扣款") 74 | @TableField("leave_early_deduct") 75 | private BigDecimal leaveEarlyDeduct; 76 | 77 | @ApiModelProperty("旷工扣款") 78 | @TableField("absenteeism_deduct") 79 | private BigDecimal absenteeismDeduct; 80 | 81 | @ApiModelProperty("总工资") 82 | @TableField("total_salary") 83 | private BigDecimal totalSalary; 84 | 85 | @ApiModelProperty("备注") 86 | @TableField("remark") 87 | private String remark; 88 | 89 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 90 | @ApiModelProperty("创建时间") 91 | @TableField("create_time") 92 | private Timestamp createTime; 93 | 94 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 95 | @ApiModelProperty("更新时间") 96 | @TableField("update_time") 97 | private Timestamp updateTime; 98 | 99 | @ApiModelProperty("逻辑删除,0未删除,1删除") 100 | @TableField("is_deleted") 101 | @TableLogic 102 | private Integer deleteFlag; 103 | 104 | 105 | } 106 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/entity/Dept.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import com.fasterxml.jackson.annotation.JsonFormat; 5 | import io.swagger.annotations.ApiModel; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.springframework.format.annotation.DateTimeFormat; 10 | 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | import java.sql.Timestamp; 14 | import java.util.List; 15 | 16 | 17 | /** 18 | *

19 | * 20 | *

21 | * 22 | * @author qiujie 23 | * @since 2022-03-07 24 | */ 25 | 26 | @Getter 27 | @Setter 28 | @TableName("sys_dept") 29 | @ApiModel(value = "Dept对象", description = "部门") 30 | public class Dept implements Serializable { 31 | 32 | private static final long serialVersionUID = 1L; 33 | 34 | @ApiModelProperty("部门id") 35 | @TableId(value = "id", type = IdType.AUTO) 36 | private Integer id; 37 | 38 | @ApiModelProperty("部门编码") 39 | @TableField("code") 40 | private String code; 41 | 42 | @ApiModelProperty("部门名称") 43 | @TableField("name") 44 | private String name; 45 | 46 | @DateTimeFormat(pattern = "HH:mm") 47 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 48 | @ApiModelProperty("上午上班时间") 49 | @TableField("mor_start_time") 50 | private Timestamp morStartTime; 51 | 52 | @DateTimeFormat(pattern = "HH:mm") 53 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 54 | @ApiModelProperty("上午下班时间") 55 | @TableField("mor_end_time") 56 | private Timestamp morEndTime; 57 | 58 | @DateTimeFormat(pattern = "HH:mm") 59 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 60 | @ApiModelProperty("下午上班时间") 61 | @TableField("aft_start_time") 62 | private Timestamp aftStartTime; 63 | 64 | @DateTimeFormat(pattern = "HH:mm") 65 | @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") 66 | @ApiModelProperty("下午下班时间") 67 | @TableField("aft_end_time") 68 | private Timestamp aftEndTime; 69 | 70 | @ApiModelProperty("员工的总工作时长") 71 | @TableField("total_work_time") 72 | private BigDecimal totalWorkTime; 73 | 74 | @ApiModelProperty("部门备注") 75 | @TableField("remark") 76 | private String remark; 77 | 78 | @ApiModelProperty("父级部门id,0根部门") 79 | @TableField("parent_id") 80 | private Integer parentId; 81 | 82 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 83 | @ApiModelProperty("创建时间") 84 | @TableField("create_time") 85 | private Timestamp createTime; 86 | 87 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") 88 | @ApiModelProperty("更新时间") 89 | @TableField("update_time") 90 | private Timestamp updateTime; 91 | 92 | @ApiModelProperty("逻辑删除,0未删除,1删除") 93 | @TableField("is_deleted") 94 | @TableLogic 95 | private Integer deleteFlag; 96 | 97 | @ApiModelProperty("子部门") 98 | @TableField(exist = false) 99 | private List children; 100 | 101 | } 102 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/SalaryController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.Salary; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.service.SalaryService; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import javax.annotation.Resource; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | 18 | /** 19 | *

20 | * 前端控制器 21 | *

22 | * 23 | * @author qiujie 24 | * @since 2022-04-06 25 | */ 26 | @RestController 27 | @RequestMapping("/salary") 28 | public class SalaryController { 29 | 30 | @Autowired 31 | private SalaryService salaryService; 32 | 33 | @ApiOperation("新增") 34 | @PostMapping 35 | public ResponseDTO add(@RequestBody Salary salary) { 36 | return this.salaryService.add(salary); 37 | } 38 | 39 | @ApiOperation("逻辑删除") 40 | @DeleteMapping("/{id}") 41 | public ResponseDTO delete(@PathVariable Integer id) { 42 | return this.salaryService.delete(id); 43 | } 44 | 45 | @ApiOperation("批量逻辑删除") 46 | @DeleteMapping("/batch/{ids}") 47 | public ResponseDTO deleteBatch(@PathVariable List ids) { 48 | return this.salaryService.deleteBatch(ids); 49 | } 50 | 51 | @ApiOperation("编辑更新") 52 | @PutMapping 53 | public ResponseDTO edit(@RequestBody Salary salary) { 54 | return this.salaryService.edit(salary); 55 | } 56 | 57 | @ApiOperation("查询") 58 | @GetMapping("/{id}") 59 | public ResponseDTO query(@PathVariable Integer id) { 60 | return this.salaryService.query(id); 61 | } 62 | 63 | @ApiOperation("分页条件查询") 64 | @GetMapping 65 | @PreAuthorize("hasAnyAuthority('money:salary:list','money:salary:search')") 66 | public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, String name, Integer deptId, String month) { 67 | return this.salaryService.list(current, size, name, deptId, month); 68 | } 69 | 70 | @ApiOperation("数据导出接口") 71 | @GetMapping("/export/{month}/{filename}") 72 | @PreAuthorize("hasAnyAuthority('money:salary:export')") 73 | public void export(HttpServletResponse response, @PathVariable String month,@PathVariable String filename) throws IOException { 74 | this.salaryService.export(response, month,filename); 75 | } 76 | 77 | @ApiOperation("数据导入接口") 78 | @PostMapping("/import") 79 | @PreAuthorize("hasAnyAuthority('money:salary:import')") 80 | public ResponseDTO imp(MultipartFile file) throws IOException { 81 | return this.salaryService.imp(file); 82 | } 83 | 84 | @ApiOperation("设置工资") 85 | @PostMapping("/set") 86 | @PreAuthorize("hasAnyAuthority('money:salary:set')") 87 | public ResponseDTO setSalary(@RequestBody Salary salary) { 88 | return this.salaryService.setSalary(salary); 89 | } 90 | 91 | 92 | } 93 | 94 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/CityController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.City; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.service.CityService; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import javax.annotation.Resource; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | 18 | /** 19 | *

20 | * 前端控制器 21 | *

22 | * 23 | * @author qiujie 24 | * @since 2022-03-23 25 | */ 26 | @RestController 27 | @RequestMapping("/city") 28 | public class CityController { 29 | @Autowired 30 | private CityService cityService; 31 | 32 | @ApiOperation("新增") 33 | @PostMapping 34 | @PreAuthorize("hasAnyAuthority('money:city:add')") 35 | public ResponseDTO add(@RequestBody City city) { 36 | return this.cityService.add(city); 37 | } 38 | 39 | @ApiOperation("逻辑删除") 40 | @DeleteMapping("/{id}") 41 | @PreAuthorize("hasAnyAuthority('money:city:delete')") 42 | public ResponseDTO delete(@PathVariable Integer id) { 43 | return this.cityService.delete(id); 44 | } 45 | 46 | @ApiOperation("批量逻辑删除") 47 | @DeleteMapping("/batch/{ids}") 48 | @PreAuthorize("hasAnyAuthority('money:city:delete')") 49 | public ResponseDTO deleteBatch(@PathVariable List ids) { 50 | return this.cityService.deleteBatch(ids); 51 | } 52 | 53 | @ApiOperation("编辑更新") 54 | @PutMapping 55 | @PreAuthorize("hasAnyAuthority('money:city:edit')") 56 | public ResponseDTO edit(@RequestBody City city) { 57 | return this.cityService.edit(city); 58 | } 59 | 60 | @ApiOperation("查询") 61 | @GetMapping("/{id}") 62 | public ResponseDTO query(@PathVariable Integer id) { 63 | return this.cityService.query(id); 64 | } 65 | 66 | @ApiOperation("查询所有") 67 | @GetMapping("/all") 68 | public ResponseDTO queryAll() { 69 | return this.cityService.queryAll(); 70 | } 71 | 72 | @ApiOperation("条件查询") 73 | @GetMapping 74 | @PreAuthorize("hasAnyAuthority('money:city:list','money:city:search')") 75 | public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, String name) { 76 | return this.cityService.list(current, size, name); 77 | } 78 | 79 | 80 | @ApiOperation("数据导出接口") 81 | @GetMapping("/export/{filename}") 82 | @PreAuthorize("hasAnyAuthority('money:city:export')") 83 | public void export(HttpServletResponse response, @PathVariable String filename) throws IOException { 84 | this.cityService.export(response, filename); 85 | } 86 | 87 | @ApiOperation("数据导入接口") 88 | @PostMapping("/import") 89 | @PreAuthorize("hasAnyAuthority('money:city:import')") 90 | public ResponseDTO imp(MultipartFile file) throws IOException { 91 | return this.cityService.imp(file); 92 | } 93 | 94 | 95 | } 96 | 97 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.qiujie.dto.Response; 5 | import com.qiujie.dto.ResponseDTO; 6 | import com.qiujie.entity.Staff; 7 | import com.qiujie.entity.StaffDetails; 8 | import com.qiujie.entity.ValidateCode; 9 | import com.qiujie.mapper.StaffMapper; 10 | import com.qiujie.util.JwtUtil; 11 | import com.qiujie.util.RedisUtil; 12 | import com.qiujie.util.ValidateCodeUtil; 13 | import com.qiujie.vo.StaffDeptVO; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.security.authentication.AuthenticationManager; 16 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 17 | import org.springframework.security.core.Authentication; 18 | import org.springframework.stereotype.Service; 19 | 20 | import javax.annotation.Resource; 21 | import javax.imageio.ImageIO; 22 | import javax.servlet.http.HttpServletResponse; 23 | import java.io.IOException; 24 | import java.time.LocalDateTime; 25 | 26 | /** 27 | * @Author : qiujie 28 | * @Date : 2022/1/30 29 | */ 30 | 31 | @Service 32 | public class LoginService extends ServiceImpl { 33 | 34 | @Autowired 35 | private StaffMapper staffMapper; 36 | 37 | @Autowired 38 | private AuthenticationManager authenticationManager; 39 | 40 | @Autowired 41 | private RedisUtil redisUtil; 42 | 43 | public ResponseDTO login(Staff staff,String validateCode) { 44 | // 校验验证码 45 | String codeInRedis = redisUtil.get("validate:code").toString(); 46 | if(codeInRedis == null){ 47 | return Response.error("验证码不存在!"); 48 | } 49 | LocalDateTime expireTime = LocalDateTime.parse(redisUtil.get("expire:time").toString()); 50 | if(ValidateCodeUtil.isExpire(expireTime)){ 51 | return Response.error("验证码过期!"); 52 | } 53 | if (!codeInRedis.equals(validateCode)) { 54 | return Response.error("验证码错误!"); 55 | } 56 | // AuthenticationManager authenticationManager进行用户认证 57 | UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = 58 | new UsernamePasswordAuthenticationToken(staff.getCode(), staff.getPassword()); 59 | Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken); 60 | // 认证失败框架会抛出异常 61 | // 认证通过 62 | StaffDetails staffDetails = (StaffDetails) authenticate.getPrincipal(); 63 | String token = JwtUtil.generateToken(staffDetails); 64 | StaffDeptVO staffDeptVO = this.staffMapper.queryByCode(staffDetails.getUsername()); 65 | return Response.success(staffDeptVO, token); 66 | } 67 | 68 | public void getValidateCode(HttpServletResponse response) throws IOException { 69 | ValidateCode validateCode = ValidateCodeUtil.generateValidateCode(); 70 | redisUtil.set("validate:code", validateCode.getCode()); 71 | redisUtil.set("expire:time",validateCode.getExpireTime().toString()); 72 | ImageIO.write(validateCode.getImage(), "jpeg", response.getOutputStream()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /vue-elementui-hrm/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' // 引入vue 2 | import VueRouter from 'vue-router' // 引入vue-router 3 | import store from '../store' 4 | import { queryByStaffId, queryPermission } from '@/api/menu' 5 | 6 | // 解决当重复跳转一个路由的报错问题 7 | // 获取原型对象上的push函数 8 | const originalPush = VueRouter.prototype.push 9 | // 修改原型对象中的push方法 10 | VueRouter.prototype.push = function push (location) { 11 | return originalPush.call(this, location).catch((err) => err) 12 | } 13 | 14 | Vue.use(VueRouter) // 全局引入路由 15 | 16 | // 静态路由 17 | const routes = [{ 18 | path: '/login', name: 'login', component: () => import('../views/login') 19 | }] 20 | 21 | // router实例 22 | const router = new VueRouter({ 23 | mode: 'history', // 此模式下,url不出现"#" 24 | routes // 记住前面的属性是routes(路线),而不是routers(路由器),不然的内容不会显示 25 | }) 26 | 27 | // 重置路由 28 | export const resetRouter = () => { 29 | router.matcher = new VueRouter({ 30 | mode: 'history', routes 31 | }) 32 | } 33 | 34 | // 设置动态路由,刷新页面,会重置路由 35 | export const setDynamicRoute = (menuList) => { 36 | const dynamicRoute = { 37 | path: '/', component: () => import('../views/Main'), children: [] 38 | } 39 | // 添加添加菜单到dynamicRoute的children中 40 | menuList.forEach((menu) => { 41 | const route = { 42 | name: menu.code, path: menu.code, component: () => import('../views/' + menu.code), children: [] 43 | } 44 | // 判断是否有子菜单 45 | if (menu.children.length > 0) { 46 | menu.children.forEach((subMenu) => { 47 | route.children.push({ 48 | name: subMenu.code, 49 | path: subMenu.code, 50 | component: () => import('../views/' + menu.code + '/' + subMenu.code), 51 | children: [] 52 | }) 53 | }) 54 | } 55 | dynamicRoute.children.push(route) 56 | }) 57 | dynamicRoute.children.push(// 映射到home页面 58 | { 59 | path: '/', component: () => import('../views/home') 60 | }, // 404页面 61 | { 62 | path: '*', component: () => import('../views/error') 63 | }) 64 | 65 | router.addRoute(dynamicRoute) // addRoute()只负责添加路由,但不去重 66 | } 67 | 68 | router.beforeEach((to, from, next) => { 69 | // 如果有匹配的路由,则直接跳转 70 | if (to.matched.length === 0) { 71 | // 如果token存在,则说明已经登录,否则回到登录页面 72 | if (store.getters.token) { 73 | // 请求菜单数据 74 | queryByStaffId(store.getters.staff.id).then(response => { 75 | if (response.code === 200) { 76 | const menuList = response.data 77 | // 任何人都可访问主页 78 | menuList.push({ 79 | id: 0, code: 'home', name: '首页', icon: 's-home', path: '/home', children: [] 80 | }) 81 | // 设置动态路由 82 | setDynamicRoute(menuList) 83 | // 设置菜单 84 | store.commit('menu/SET_MENU', menuList) 85 | } 86 | }) 87 | queryPermission(store.getters.staff.id).then(response => { 88 | if (response.code === 200) { 89 | // 设置权限 90 | store.commit('permission/SET_PERMISSION', response.data) 91 | } 92 | }) 93 | } else { 94 | next({ name: 'login' }) 95 | } 96 | } 97 | next() 98 | }) 99 | 100 | export default router // 对外暴露 101 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/util/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.util; 2 | 3 | import io.jsonwebtoken.Claims; 4 | import io.jsonwebtoken.Jwts; 5 | import io.jsonwebtoken.SignatureAlgorithm; 6 | import io.jsonwebtoken.io.Decoders; 7 | import io.jsonwebtoken.security.Keys; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.security.Key; 11 | import java.util.Date; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | import java.util.function.Function; 15 | 16 | public class JwtUtil { 17 | 18 | // 密钥 19 | private final static String secretKey = "404E635266556A586E3272357538782F413F4428472B4B6250645367566B5970"; 20 | private final static long jwtExpiration = 2 * 60 * 60 * 1000; // token过期时间设为2小时 21 | private final static long refreshExpiration = 7 * 24 * 60 * 60 * 1000; 22 | 23 | private static Key getSignInKey() { 24 | byte[] keyBytes = Decoders.BASE64.decode(secretKey); 25 | return Keys.hmacShaKeyFor(keyBytes); 26 | } 27 | 28 | private static Claims extractAllClaims(String token) { 29 | return Jwts 30 | .parserBuilder() 31 | .setSigningKey(getSignInKey()) 32 | .build() 33 | .parseClaimsJws(token) 34 | .getBody(); 35 | } 36 | 37 | public static String extractUsername(String token) { 38 | return extractClaim(token, Claims::getSubject); 39 | } 40 | 41 | public static T extractClaim(String token, Function claimsResolver) { 42 | final Claims claims = extractAllClaims(token); 43 | return claimsResolver.apply(claims); 44 | } 45 | 46 | private static Date extractExpiration(String token) { 47 | return extractClaim(token, Claims::getExpiration); 48 | } 49 | 50 | private static String buildToken(Map extraClaims, UserDetails userDetails, long expiration) { 51 | return Jwts 52 | .builder() 53 | .setClaims(extraClaims) 54 | .setSubject(userDetails.getUsername()) 55 | .setIssuedAt(new Date(System.currentTimeMillis())) 56 | .setExpiration(new Date(System.currentTimeMillis() + expiration)) 57 | .signWith(getSignInKey(), SignatureAlgorithm.HS256) 58 | .compact(); 59 | } 60 | 61 | public static String generateToken(UserDetails userDetails) { 62 | return generateToken(new HashMap<>(), userDetails); 63 | } 64 | 65 | public static String generateToken(Map extraClaims, UserDetails userDetails) { 66 | return buildToken(extraClaims, userDetails, jwtExpiration); 67 | } 68 | 69 | public String generateRefreshToken(UserDetails userDetails) { 70 | return buildToken(new HashMap<>(), userDetails, refreshExpiration); 71 | } 72 | 73 | public static boolean isTokenValid(String token, UserDetails userDetails) { 74 | final String username = extractUsername(token); 75 | return (username.equals(userDetails.getUsername())) && !isTokenExpired(token); 76 | } 77 | 78 | public static boolean isTokenExpired(String token) { 79 | return extractExpiration(token).before(new Date()); 80 | } 81 | 82 | 83 | } -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/DeptController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.Dept; 4 | import com.qiujie.dto.ResponseDTO; 5 | import com.qiujie.service.DeptService; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import javax.annotation.Resource; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | import java.util.List; 16 | 17 | 18 | /** 19 | *

20 | * 前端控制器 21 | *

22 | * 23 | * @author qiujie 24 | * @since 2022-03-07 25 | */ 26 | @RestController 27 | @RequestMapping("/dept") 28 | public class DeptController { 29 | @Autowired 30 | private DeptService deptService; 31 | 32 | @ApiOperation("新增") 33 | @PostMapping 34 | @PreAuthorize("hasAnyAuthority('system:department:add')") 35 | public ResponseDTO add(@RequestBody Dept dept) { 36 | return this.deptService.add(dept); 37 | } 38 | 39 | @ApiOperation("逻辑删除") 40 | @DeleteMapping("/{id}") 41 | @PreAuthorize("hasAnyAuthority('system:department:delete')") 42 | public ResponseDTO delete(@PathVariable Integer id) { 43 | return this.deptService.delete(id); 44 | } 45 | 46 | @ApiOperation("批量逻辑删除") 47 | @DeleteMapping("/batch/{ids}") 48 | @PreAuthorize("hasAnyAuthority('system:department:delete')") 49 | public ResponseDTO deleteBatch(@PathVariable List ids) { 50 | return this.deptService.deleteBatch(ids); 51 | } 52 | 53 | @ApiOperation("编辑更新") 54 | @PutMapping 55 | @PreAuthorize("hasAnyAuthority('system:department:edit')") 56 | public ResponseDTO edit(@RequestBody Dept dept) { 57 | return this.deptService.edit(dept); 58 | } 59 | 60 | @ApiOperation("查询") 61 | @GetMapping("/{id}") 62 | public ResponseDTO query(@PathVariable Integer id) { 63 | return this.deptService.query(id); 64 | } 65 | 66 | @ApiOperation("查询所有") 67 | @GetMapping("/all") 68 | public ResponseDTO queryAll(){ 69 | return this.deptService.queryAll(); 70 | } 71 | 72 | @ApiOperation("条件查询") 73 | @GetMapping 74 | @PreAuthorize("hasAnyAuthority('system:department:list','system:department:search')") 75 | public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, String name) { 76 | return this.deptService.list(current, size, name); 77 | } 78 | 79 | @ApiOperation("数据导出接口") 80 | @GetMapping("/export/{filename}") 81 | @PreAuthorize("hasAnyAuthority('system:department:export')") 82 | public void export(HttpServletResponse response,@PathVariable String filename) throws Exception { 83 | this.deptService.export(response,filename); 84 | } 85 | 86 | @ApiOperation("数据导入接口") 87 | @PostMapping("/import") 88 | @PreAuthorize("hasAnyAuthority('system:department:import')") 89 | public ResponseDTO imp(MultipartFile file) throws IOException { 90 | return this.deptService.imp(file); 91 | } 92 | 93 | } 94 | 95 | -------------------------------------------------------------------------------- /hrm/src/main/resources/templates/controller.java.vm: -------------------------------------------------------------------------------- 1 | package ${package.Controller}; 2 | 3 | import ${package.Service}.${table.serviceName}; 4 | import ${package.Entity}.${entity}; 5 | 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import javax.annotation.Resource; 10 | 11 | 12 | #if(${superControllerClassPackage}) 13 | import ${superControllerClassPackage}; 14 | #end 15 | 16 | /** 17 | *

18 | * $!{table.comment} 前端控制器 19 | *

20 | * 21 | * @author ${author} 22 | * @since ${date} 23 | */ 24 | #if(${restControllerStyle}) 25 | @RestController 26 | #else 27 | @Controller 28 | #end 29 | @RequestMapping("#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end") 30 | #if(${kotlin}) 31 | class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end 32 | 33 | #else 34 | #if(${superControllerClass}) 35 | public class ${table.controllerName} extends ${superControllerClass} { 36 | #else 37 | public class ${table.controllerName} { 38 | #end 39 | @Resource 40 | private ${table.serviceName} ${table.entityPath}Service; 41 | 42 | @ApiOperation("新增") 43 | @PostMapping 44 | public ResponseDTO add(@RequestBody ${entity} ${table.entityPath}){ 45 | return this.${table.entityPath}Service.add(${table.entityPath}); 46 | } 47 | 48 | @ApiOperation("逻辑删除") 49 | @DeleteMapping("/{id}") 50 | public ResponseDTO delete(@PathVariable Integer id){ 51 | return this.${table.entityPath}Service.delete(id); 52 | } 53 | 54 | @ApiOperation("批量逻辑删除") 55 | @DeleteMapping("/batch/{ids}") 56 | public ResponseDTO deleteBatch(@PathVariable List ids){ 57 | return this.${table.entityPath}Service.deleteBatch(ids); 58 | } 59 | 60 | @ApiOperation("编辑更新") 61 | @PutMapping 62 | public ResponseDTO edit(@RequestBody ${entity} ${table.entityPath}){ 63 | return this.${table.entityPath}Service.edit(${table.entityPath}); 64 | } 65 | 66 | @ApiOperation("查询") 67 | @GetMapping("/{id}") 68 | public ResponseDTO query(@PathVariable Integer id){ 69 | return this.${table.entityPath}Service.query(id); 70 | } 71 | 72 | @ApiOperation("查询所有") 73 | @GetMapping("/all") 74 | public ResponseDTO queryAll(){ 75 | return this.${table.entityPath}Service.queryAll(); 76 | } 77 | 78 | @ApiOperation("条件查询") 79 | @GetMapping 80 | public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current,@RequestParam(defaultValue = "10") Integer size,String name){ 81 | return this.${table.entityPath}Service.list(current,size,name); 82 | } 83 | 84 | 85 | @ApiOperation("数据导出接口") 86 | @GetMapping("/export/{filename}") 87 | public void export(HttpServletResponse response,@PathVariable String filename)throws IOException{ 88 | this.${table.entityPath}Service.export(response,filename); 89 | } 90 | 91 | @ApiOperation("数据导入接口") 92 | @PostMapping("/import") 93 | public ResponseDTO imp(MultipartFile file)throws IOException{ 94 | return this.${table.entityPath}Service.imp(file); 95 | } 96 | 97 | 98 | } 99 | 100 | #end -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/listener/ManagerApproveListener.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.listener; 2 | 3 | import cn.hutool.core.date.DateUtil; 4 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 | import com.qiujie.dto.Response; 6 | import com.qiujie.entity.Attendance; 7 | import com.qiujie.entity.StaffLeave; 8 | import com.qiujie.entity.StaffOvertime; 9 | import com.qiujie.enums.AttendanceStatusEnum; 10 | import com.qiujie.enums.BusinessStatusEnum; 11 | import com.qiujie.enums.LeaveEnum; 12 | import com.qiujie.enums.OvertimeStatusEnum; 13 | import com.qiujie.exception.ServiceException; 14 | import com.qiujie.mapper.StaffOvertimeMapper; 15 | import com.qiujie.service.AttendanceService; 16 | import com.qiujie.service.StaffLeaveService; 17 | import com.qiujie.util.DatetimeUtil; 18 | import org.activiti.engine.delegate.DelegateExecution; 19 | import org.activiti.engine.delegate.ExecutionListener; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.stereotype.Component; 22 | import org.springframework.transaction.annotation.Transactional; 23 | 24 | import java.sql.Date; 25 | 26 | @Component 27 | public class ManagerApproveListener implements ExecutionListener { 28 | 29 | @Autowired 30 | private StaffLeaveService staffLeaveService; 31 | 32 | @Autowired 33 | private StaffOvertimeMapper staffOvertimeMapper; 34 | 35 | @Autowired 36 | private AttendanceService attendanceService; 37 | 38 | @Autowired 39 | private DatetimeUtil datetimeUtil; 40 | 41 | @Override 42 | @Transactional 43 | public void notify(DelegateExecution execution) { 44 | StaffLeave staffLeave = this.staffLeaveService.getOne(new QueryWrapper().eq("id", Integer.valueOf(execution.getProcessInstanceBusinessKey()))); 45 | for (int i = 0; i < staffLeave.getDays(); i++) { 46 | Date attendanceDate = DateUtil.offsetDay(staffLeave.getStartDate(), i).toSqlDate(); 47 | // 因为周末本就要休息,所以只需记录在休假期间包括的工作日的考勤状态到数据库 48 | if (DateUtil.isWeekend(attendanceDate) || this.datetimeUtil.isHoliday(attendanceDate)) { 49 | continue; 50 | } 51 | Attendance attendance = new Attendance().setAttendanceDate(attendanceDate).setStaffId(staffLeave.getStaffId()); 52 | // 如果请假类型是调休,考勤状态设为调休;其他类型的假期都设为休假 53 | if (staffLeave.getTypeNum() == LeaveEnum.TIME_OFF) { 54 | attendance.setStatus(AttendanceStatusEnum.TIME_OFF); 55 | // 删除员工的一条调休记录 56 | this.staffOvertimeMapper.delete(new QueryWrapper() 57 | .eq("staff_id", staffLeave.getStaffId()) 58 | .eq("status", OvertimeStatusEnum.TIME_OFF).orderByAsc("overtime_date").last("limit 1")); 59 | } else { 60 | attendance.setStatus(AttendanceStatusEnum.LEAVE); 61 | } 62 | QueryWrapper queryWrapper = new QueryWrapper<>(); 63 | queryWrapper.eq("staff_id", attendance.getStaffId()).eq("attendance_date", attendance.getAttendanceDate()); 64 | if (!this.attendanceService.saveOrUpdate(attendance, queryWrapper)) { 65 | throw new ServiceException(BusinessStatusEnum.ERROR); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/util/CodeGenerateUtil.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.util; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.baomidou.mybatisplus.generator.AutoGenerator; 6 | import com.baomidou.mybatisplus.generator.config.*; 7 | import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert; 8 | import com.baomidou.mybatisplus.generator.config.rules.DateType; 9 | 10 | import java.util.Collections; 11 | 12 | public class CodeGenerateUtil { 13 | public static void main(String[] args) { 14 | DataSourceConfig dataSourceConfig = new DataSourceConfig 15 | .Builder("jdbc:mysql://localhost:3306/hrm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2b8", "root", "123456") 16 | .typeConvert(new MySqlTypeConvert()) // 数据库字段类型转换 17 | .build(); 18 | 19 | // 全局配置 20 | GlobalConfig globalConfig = new GlobalConfig.Builder() 21 | .fileOverride() // 覆盖已生成的文件 22 | .outputDir("C:\\Users\\qiujie\\Desktop\\code\\java") // 输出路径为当前项目的/src/main/java目录下 23 | .author("qiujie") 24 | .enableSwagger() // 便于生成Api文档 25 | .dateType(DateType.SQL_PACK) // 使用java.sql.Timestamp 26 | .commentDate("yyyy-MM-dd") 27 | .build(); 28 | 29 | // 配置包名 30 | PackageConfig packageConfig = new PackageConfig.Builder() 31 | .parent("com.qiujie") 32 | .entity("entity") 33 | .service("service") 34 | .serviceImpl("service.impl") 35 | .mapper("mapper") 36 | .controller("controller") 37 | .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "C:\\Users\\qiujie\\Desktop\\code\\mapper")) // 设置mapperXml生成路径 38 | .build(); 39 | 40 | StrategyConfig strategyConfig = new StrategyConfig.Builder() 41 | .addTablePrefix("sys_", "per_", "soc_", "sal_", "att_", "act_re_", "sal_") // 根据表名生成实体名,去除指定的表前缀 42 | .addInclude("per_permission") 43 | .entityBuilder() // 1. entity策略配置 44 | .enableLombok() 45 | .enableTableFieldAnnotation() // 生成字段注解 46 | // .logicDeleteColumnName("is_deleted") // 指明逻辑删除字段 47 | // .addTableFills(new Column("create_time", FieldFill.INSERT)) // 插入时自动填入时间 48 | // .addTableFills(new Property("updateTime", FieldFill.INSERT_UPDATE)) // 插入或更新时自动填入时间 49 | .idType(IdType.AUTO) // 主键自增 50 | .enableChainModel() // 链式 51 | .mapperBuilder() // 2. mapper策略配置 52 | .superClass(BaseMapper.class) // 设置父类 53 | .serviceBuilder() // 3. service策略配置 54 | .formatServiceFileName("%sService") // 如果不设置,则默认为I%sService 55 | .controllerBuilder() // 4. controller策略配置 56 | .enableRestStyle() // 开启@RestController 57 | .enableHyphenStyle() // 开启驼峰转连字符 58 | .build(); 59 | 60 | new AutoGenerator(dataSourceConfig) 61 | .global(globalConfig) 62 | .packageInfo(packageConfig) 63 | .strategy(strategyConfig) 64 | .execute(); // 执行 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/LeaveService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.qiujie.enums.LeaveEnum; 6 | import com.qiujie.entity.Leave; 7 | import com.qiujie.mapper.LeaveMapper; 8 | import com.qiujie.dto.Response; 9 | import com.qiujie.dto.ResponseDTO; 10 | import com.qiujie.util.EnumUtil; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import javax.annotation.Resource; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | *

21 | * 请假表 服务类 22 | *

23 | * 24 | * @author qiujie 25 | * @since 2022-03-27 26 | */ 27 | @Service 28 | public class LeaveService extends ServiceImpl { 29 | 30 | @Autowired 31 | private LeaveMapper leaveMapper; 32 | 33 | public ResponseDTO add(Leave leave) { 34 | if (save(leave)) { 35 | return Response.success(); 36 | } 37 | return Response.error(); 38 | } 39 | 40 | public ResponseDTO delete(Integer id) { 41 | if (removeById(id)) { 42 | return Response.success(); 43 | } 44 | return Response.error(); 45 | } 46 | 47 | @Transactional(rollbackFor = Exception.class) 48 | public ResponseDTO deleteBatch(List ids) { 49 | if (removeBatchByIds(ids)) { 50 | return Response.success(); 51 | } 52 | return Response.error(); 53 | } 54 | 55 | public ResponseDTO edit(Leave leave) { 56 | if (updateById(leave)) { 57 | return Response.success(); 58 | } 59 | return Response.error(); 60 | } 61 | 62 | public ResponseDTO query(Integer id) { 63 | Leave leave = getById(id); 64 | if (leave != null) { 65 | return Response.success(leave); 66 | } 67 | return Response.error(); 68 | } 69 | 70 | public ResponseDTO queryByDeptIdAndTypeNum(Integer deptId, Integer typeNum) { 71 | QueryWrapper queryWrapper = new QueryWrapper<>(); 72 | queryWrapper.eq("dept_id", deptId).eq("type_num", typeNum); 73 | Leave leave = getOne(queryWrapper); 74 | if (leave != null) { 75 | return Response.success(leave); 76 | } 77 | return Response.error(); 78 | } 79 | 80 | public ResponseDTO setLeave(Leave leave) { 81 | QueryWrapper queryWrapper = new QueryWrapper<>(); 82 | queryWrapper.eq("dept_id", leave.getDeptId()).eq("type_num", leave.getTypeNum()); 83 | if (saveOrUpdate(leave, queryWrapper)) { 84 | return Response.success(); 85 | } 86 | return Response.error(); 87 | } 88 | 89 | public ResponseDTO queryByDeptId(Integer id) { 90 | List list = this.leaveMapper.selectList(new QueryWrapper().eq("dept_id", id)); 91 | return Response.success(list); 92 | } 93 | 94 | /** 95 | * 获取所有请假类型 96 | * @return 97 | */ 98 | public ResponseDTO queryAll() { 99 | return Response.success(EnumUtil.getEnumList(LeaveEnum.class)); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /hrm/src/main/resources/templates/service.java.vm: -------------------------------------------------------------------------------- 1 | package ${package.Service}; 2 | 3 | import ${package.Mapper}.${table.mapperName}; 4 | import ${package.Entity}.${entity}; 5 | 6 | import org.springframework.stereotype.Service; 7 | 8 | /** 9 | *

10 | * $!{table.comment} 服务类 11 | *

12 | * 13 | * @author ${author} 14 | * @since ${date} 15 | */ 16 | #if(${kotlin}) 17 | interface ${table.serviceName} : ${superServiceClass}<${entity}> 18 | #else 19 | @Service 20 | public class ${table.serviceName} extends ServiceImpl<${entity}Mapper,${entity} >{ 21 | #end 22 | 23 | 24 | public ResponseDTO add(${entity} ${table.entityPath}){ 25 | if(save(${table.entityPath})){ 26 | return Response.success(); 27 | } 28 | return Response.error(); 29 | } 30 | 31 | public ResponseDTO delete(Integer id){ 32 | if(removeById(id)){ 33 | return Response.success(); 34 | } 35 | return Response.error(); 36 | } 37 | 38 | public ResponseDTO deleteBatch(List ids){ 39 | if(removeBatchByIds(ids)){ 40 | return Response.success(); 41 | } 42 | return Response.error(); 43 | } 44 | 45 | 46 | public ResponseDTO edit(${entity} ${table.entityPath}){ 47 | if(updateById(${table.entityPath})){ 48 | return Response.success(); 49 | } 50 | return Response.error(); 51 | } 52 | 53 | 54 | public ResponseDTO query(Integer id){ 55 | ${entity} ${table.entityPath} =getById(id); 56 | if(${table.entityPath} !=null){ 57 | return Response.success(${table.entityPath}); 58 | } 59 | return Response.error(); 60 | } 61 | 62 | public ResponseDTO queryAll(){ 63 | List<${entity}> list=list(); 64 | return Response.success(list); 65 | } 66 | 67 | 68 | public ResponseDTO list(Integer current,Integer size,String name){ 69 | IPage<${entity}> config=new Page<>(current,size); 70 | QueryWrapper<${entity}> wrapper=null; 71 | if(name!=""&&name!=null){ 72 | wrapper=new QueryWrapper<>(); 73 | wrapper.like("name",name); 74 | } 75 | IPage<${entity}> page=page(config,wrapper); 76 | // 将响应数据填充到map中 77 | Map map=new HashMap(); 78 | map.put("pages",page.getPages()); 79 | map.put("total",page.getTotal()); 80 | map.put("list",page.getRecords()); 81 | return Response.success(map); 82 | } 83 | 84 | 85 | /** 86 | * 数据导出 87 | * 88 | * @param response 89 | * @return 90 | */ 91 | public void export(HttpServletResponse response,String filename)throws IOException{ 92 | List<${entity}> list=list(); 93 | HutoolExcelUtil.writeExcel(response,list,filename, ${entity}.class); 94 | } 95 | 96 | /** 97 | * 数据导入 98 | * 99 | * @param file 100 | * @return 101 | */ 102 | public ResponseDTO imp(MultipartFile file)throws IOException{ 103 | InputStream inputStream=file.getInputStream(); 104 | ExcelReader reader=ExcelUtil.getReader(inputStream); 105 | List<${entity}> list=reader.readAll(${entity}.class); 106 | // IService接口中的方法.批量插入数据 107 | if(saveBatch(list)){ 108 | return Response.success(); 109 | } 110 | return Response.error(); 111 | } 112 | 113 | 114 | } 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/controller/InsuranceController.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.controller; 2 | 3 | import com.qiujie.entity.Staff; 4 | import com.qiujie.service.InsuranceService; 5 | import com.qiujie.entity.Insurance; 6 | 7 | import com.qiujie.dto.ResponseDTO; 8 | import io.swagger.annotations.ApiOperation; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | import org.springframework.web.multipart.MultipartFile; 13 | 14 | import javax.annotation.Resource; 15 | import javax.servlet.http.HttpServletResponse; 16 | import java.io.IOException; 17 | import java.util.List; 18 | 19 | 20 | /** 21 | *

22 | * 前端控制器 23 | *

24 | * 25 | * @author qiujie 26 | * @since 2022-03-23 27 | */ 28 | @RestController 29 | @RequestMapping("/insurance") 30 | public class InsuranceController { 31 | @Autowired 32 | private InsuranceService insuranceService; 33 | 34 | @ApiOperation("新增") 35 | @PostMapping 36 | public ResponseDTO add(@RequestBody Insurance insurance) { 37 | return this.insuranceService.add(insurance); 38 | } 39 | 40 | @ApiOperation("逻辑删除") 41 | @DeleteMapping("/{id}") 42 | public ResponseDTO delete(@PathVariable Integer id) { 43 | return this.insuranceService.delete(id); 44 | } 45 | 46 | @ApiOperation("批量逻辑删除") 47 | @DeleteMapping("/batch/{ids}") 48 | public ResponseDTO deleteBatch(@PathVariable List ids) { 49 | return this.insuranceService.deleteBatch(ids); 50 | } 51 | 52 | @ApiOperation("编辑更新") 53 | @PutMapping 54 | public ResponseDTO edit(@RequestBody Insurance insurance) { 55 | return this.insuranceService.edit(insurance); 56 | } 57 | 58 | @ApiOperation("查询") 59 | @GetMapping("/{id}") 60 | public ResponseDTO query(@PathVariable Integer id) { 61 | return this.insuranceService.query(id); 62 | } 63 | 64 | @ApiOperation("查询") 65 | @GetMapping("/staff/{id}") 66 | public ResponseDTO queryByStaffId(@PathVariable Integer id) { 67 | return this.insuranceService.queryByStaffId(id); 68 | } 69 | 70 | @ApiOperation("多条件分页查询") 71 | @GetMapping 72 | @PreAuthorize("hasAnyAuthority('money:insurance:list','money:insurance:search')") 73 | public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, String name, Integer deptId){ 74 | return this.insuranceService.list(current, size, name,deptId); 75 | } 76 | 77 | @ApiOperation("数据导出接口") 78 | @GetMapping("/export/{filename}") 79 | @PreAuthorize("hasAnyAuthority('money:insurance:export')") 80 | public void export(HttpServletResponse response,@PathVariable String filename) throws IOException { 81 | this.insuranceService.export(response,filename); 82 | } 83 | 84 | @ApiOperation("数据导入接口") 85 | @PostMapping("/import") 86 | @PreAuthorize("hasAnyAuthority('money:insurance:import')") 87 | public ResponseDTO imp(MultipartFile file) throws IOException { 88 | return this.insuranceService.imp(file); 89 | } 90 | 91 | @ApiOperation("为员工设置社保") 92 | @PostMapping("/set") 93 | @PreAuthorize("hasAnyAuthority('money:insurance:set')") 94 | public ResponseDTO setInsurance(@RequestBody Insurance insurance) { 95 | return this.insuranceService.setInsurance(insurance); 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /hrm/src/main/java/com/qiujie/service/OvertimeService.java: -------------------------------------------------------------------------------- 1 | package com.qiujie.service; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.qiujie.entity.Leave; 6 | import com.qiujie.entity.Overtime; 7 | import com.qiujie.enums.AttendanceStatusEnum; 8 | import com.qiujie.enums.LeaveEnum; 9 | import com.qiujie.enums.OvertimeEnum; 10 | import com.qiujie.mapper.OvertimeMapper; 11 | import com.qiujie.dto.Response; 12 | import com.qiujie.dto.ResponseDTO; 13 | import com.qiujie.util.EnumUtil; 14 | import org.springframework.stereotype.Service; 15 | 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | *

21 | * 加班表 服务类 22 | *

23 | * 24 | * @author qiujie 25 | * @since 2022-03-28 26 | */ 27 | @Service 28 | public class OvertimeService extends ServiceImpl { 29 | 30 | 31 | public ResponseDTO add(Overtime overtime) { 32 | if (save(overtime)) { 33 | return Response.success(); 34 | } 35 | return Response.error(); 36 | } 37 | 38 | public ResponseDTO delete(Integer id) { 39 | if (removeById(id)) { 40 | return Response.success(); 41 | } 42 | return Response.error(); 43 | } 44 | 45 | public ResponseDTO deleteBatch(List ids) { 46 | if (removeBatchByIds(ids)) { 47 | return Response.success(); 48 | } 49 | return Response.error(); 50 | } 51 | 52 | 53 | public ResponseDTO edit(Overtime overtime) { 54 | if (updateById(overtime)) { 55 | return Response.success(); 56 | } 57 | return Response.error(); 58 | } 59 | 60 | 61 | public ResponseDTO query(Integer id) { 62 | Overtime overtime = getById(id); 63 | if (overtime != null) { 64 | return Response.success(overtime); 65 | } 66 | return Response.error(); 67 | } 68 | 69 | public ResponseDTO queryByDeptIdAndTypeNum(Integer deptId,String typeNum) { 70 | QueryWrapper queryWrapper = new QueryWrapper<>(); 71 | queryWrapper.eq("dept_id", deptId).eq("type_num", EnumUtil.fromValue(OvertimeEnum.class,typeNum)); 72 | Overtime one = getOne(queryWrapper); 73 | if (one != null) { 74 | return Response.success(one); 75 | } 76 | return Response.error(); 77 | } 78 | 79 | 80 | public ResponseDTO setOvertime(Overtime overtime) { 81 | QueryWrapper queryWrapper = new QueryWrapper<>(); 82 | queryWrapper.eq("dept_id", overtime.getDeptId()).eq("type_num", overtime.getTypeNum()); 83 | if (saveOrUpdate(overtime, queryWrapper)) { 84 | return Response.success(); 85 | } 86 | return Response.error(); 87 | } 88 | 89 | 90 | /** 91 | * 获取所有加班类型 92 | * @return 93 | */ 94 | public ResponseDTO queryAll() { 95 | List> enumList = EnumUtil.getEnumList(OvertimeEnum.class); 96 | for (Map map : enumList) { 97 | for (OvertimeEnum overtimeEnum : OvertimeEnum.values()) { 98 | if (map.get("code") == overtimeEnum.getCode()) { 99 | map.put("lowerLimit", overtimeEnum.getLowerLimit()); 100 | } 101 | } 102 | } 103 | return Response.success(enumList); 104 | } 105 | 106 | 107 | } 108 | 109 | 110 | 111 | 112 | --------------------------------------------------------------------------------