├── vue-manage-front
├── static
│ └── .gitkeep
├── config
│ ├── prod.env.js
│ ├── dev.env.js
│ └── index.js
├── build
│ ├── logo.png
│ ├── vue-loader.conf.js
│ ├── build.js
│ ├── check-versions.js
│ ├── webpack.base.conf.js
│ ├── utils.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── src
│ ├── assets
│ │ └── logo.png
│ ├── api
│ │ └── index.js
│ ├── App.vue
│ ├── lib
│ │ ├── utils.js
│ │ └── request.js
│ ├── main.js
│ ├── components
│ │ ├── system
│ │ │ └── FirstPage.vue
│ │ ├── layout
│ │ │ ├── MultiTree.vue
│ │ │ ├── LayoutMenu.vue
│ │ │ └── TreeSelect.vue
│ │ ├── Login.vue
│ │ └── Home.vue
│ ├── router
│ │ └── index.js
│ └── store
│ │ └── index.js
├── .gitignore
├── .babelrc
├── index.html
└── README.md
├── .gitignore
├── DockerFile
├── manage-web
├── src
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── dingjn
│ │ │ └── manage
│ │ │ └── web
│ │ │ ├── ManageWebApplicationTests.java
│ │ │ ├── BinarySearchTest.java
│ │ │ ├── SolveTest.java
│ │ │ ├── UserMapperTest.java
│ │ │ └── EntityGenerator.java
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── dingjn
│ │ │ └── manage
│ │ │ └── web
│ │ │ ├── ManageWebApplication.java
│ │ │ ├── config
│ │ │ ├── GlobalRequestAdvice.java
│ │ │ ├── MybatisPlusConfig.java
│ │ │ ├── GlobalExcepitonHandler.java
│ │ │ └── CorsConfig.java
│ │ │ └── controller
│ │ │ ├── SysRoleController.java
│ │ │ ├── SysUserController.java
│ │ │ ├── SysOrgController.java
│ │ │ ├── SysApiController.java
│ │ │ └── SysMenuController.java
│ │ └── resources
│ │ └── application.yml
├── .gitignore
└── pom.xml
├── manage-common
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── dingjn
│ │ └── manage
│ │ └── common
│ │ ├── response
│ │ ├── ResponseCode.java
│ │ └── ServerResponse.java
│ │ ├── util
│ │ ├── DataTree.java
│ │ └── DataTreeUtil.java
│ │ └── exception
│ │ ├── CustomExceptionType.java
│ │ └── CustomException.java
└── pom.xml
├── manage-model
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── dingjn
│ │ └── manage
│ │ └── model
│ │ ├── vo
│ │ ├── SysUserVO.java
│ │ ├── PermVO.java
│ │ └── SysRoleVO.java
│ │ ├── dto
│ │ ├── SysUserRoleDTO.java
│ │ └── SysUserDTO.java
│ │ └── node
│ │ ├── SysApiNode.java
│ │ ├── SysOrgNode.java
│ │ ├── SysMenuNode.java
│ │ ├── SysUser.java
│ │ ├── SysApi.java
│ │ ├── SysMenu.java
│ │ └── SysOrg.java
└── pom.xml
├── manage-persistence
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── dingjn
│ │ └── manage
│ │ └── persistence
│ │ ├── mapper
│ │ ├── SysDictMapper.java
│ │ ├── SysConfigMapper.java
│ │ ├── SysRoleMapper.java
│ │ ├── SysRoleApiMapper.java
│ │ ├── SysUserRoleMapper.java
│ │ ├── SysUserMapper.java
│ │ ├── SysRoleMenuMapper.java
│ │ ├── SysOrgMapper.java
│ │ ├── SysApiMapper.java
│ │ ├── xml
│ │ │ ├── SysRoleMapper.xml
│ │ │ ├── SysConfigMapper.xml
│ │ │ ├── SysUserRoleMapper.xml
│ │ │ ├── SysRoleApiMapper.xml
│ │ │ ├── SysDictMapper.xml
│ │ │ ├── SysRoleMenuMapper.xml
│ │ │ ├── SysApiMapper.xml
│ │ │ ├── SysOrgMapper.xml
│ │ │ ├── SysMenuMapper.xml
│ │ │ └── SysUserMapper.xml
│ │ └── SysMenuMapper.java
│ │ └── entity
│ │ ├── SysRoleApi.java
│ │ ├── SysRoleMenu.java
│ │ ├── SysUserRole.java
│ │ ├── SysRole.java
│ │ ├── SysConfig.java
│ │ ├── SysDict.java
│ │ ├── SysUser.java
│ │ ├── SysApi.java
│ │ ├── SysMenu.java
│ │ └── SysOrg.java
└── pom.xml
├── manage-service
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── dingjn
│ │ └── manage
│ │ └── service
│ │ ├── SysRoleService.java
│ │ ├── SysOrgService.java
│ │ ├── SysApiService.java
│ │ ├── SysUserService.java
│ │ ├── SysMenuService.java
│ │ └── impl
│ │ ├── SysRoleServiceImpl.java
│ │ ├── SysUserServiceImpl.java
│ │ ├── SysOrgServiceImpl.java
│ │ └── SysApiServiceImpl.java
└── pom.xml
├── README.md
├── manage-authentication
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── dingjn
│ │ └── manage
│ │ └── autentication
│ │ └── config
│ │ ├── model
│ │ ├── JwtProperties.java
│ │ └── MyUserDetails.java
│ │ ├── controller
│ │ └── JwtAuthController.java
│ │ ├── service
│ │ ├── MyRBACService.java
│ │ ├── MyUserDetailService.java
│ │ └── JwtAuthService.java
│ │ ├── mapper
│ │ └── MyUserDetailsServiceMapper.java
│ │ ├── config
│ │ ├── SecurityConfig.java
│ │ └── JwtAuthenticationTokenFilter.java
│ │ └── util
│ │ └── JwtTokenUtil.java
└── pom.xml
└── pom.xml
/vue-manage-front/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | target/
3 | *.iml
4 | .DS_Store
--------------------------------------------------------------------------------
/vue-manage-front/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/vue-manage-front/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oxonan9/vue-manage/HEAD/vue-manage-front/build/logo.png
--------------------------------------------------------------------------------
/vue-manage-front/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oxonan9/vue-manage/HEAD/vue-manage-front/src/assets/logo.png
--------------------------------------------------------------------------------
/vue-manage-front/src/api/index.js:
--------------------------------------------------------------------------------
1 | import HttpRequest from '@/lib/request.js'
2 |
3 | export const jwtServerInstance = new HttpRequest("http://localhost:8080")
4 |
--------------------------------------------------------------------------------
/DockerFile:
--------------------------------------------------------------------------------
1 | FROM java:8
2 |
3 | COPY *.jar /vuemanage.jar
4 |
5 | CMD ["--server.port=8080"]
6 |
7 | EXPOSE 8080
8 |
9 | ENTRYPOINT ["java","-jar","/vuemanage.jar"]
10 |
11 | CMD echo "---end---"
--------------------------------------------------------------------------------
/vue-manage-front/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/vue-manage-front/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/vue-manage-front/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/vue-manage-front/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
20 |
--------------------------------------------------------------------------------
/manage-web/src/test/java/com/dingjn/manage/web/ManageWebApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ManageWebApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/vue-manage-front/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | vue-manage-front
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/manage-common/src/main/java/com/dingjn/manage/common/response/ResponseCode.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.common.response;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 |
6 | /**
7 | * @Auther: dingjn
8 | * @Desc:
9 | */
10 | @Getter
11 | @AllArgsConstructor
12 | enum ResponseCode {
13 |
14 | SUCCESS(200, "success"),
15 | ERROR(0, "error");
16 |
17 | private int code;
18 | private String msg;
19 | }
20 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/vo/SysUserVO.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.vo;
2 |
3 | import com.dingjn.manage.model.node.SysUser;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc:
11 | */
12 | @Data
13 | @AllArgsConstructor
14 | @NoArgsConstructor
15 | public class SysUserVO extends SysUser {
16 | String orgName;
17 | }
18 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysDictMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysDict;
5 |
6 | /**
7 | *
8 | * 数据字典表 Mapper 接口
9 | *
10 | *
11 | * @author dingjn
12 | * @since 2020-06-13
13 | */
14 | public interface SysDictMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/vue-manage-front/src/lib/utils.js:
--------------------------------------------------------------------------------
1 | const LOCAL_JWT_KEY = "jskdfls";
2 | export const setJwtToken = (jwtToken) => {
3 | localStorage.setItem(LOCAL_JWT_KEY,jwtToken)
4 | }
5 | export const getJwtToken = () => {
6 | return localStorage.getItem(LOCAL_JWT_KEY)
7 | }
8 | export const getTokenUser = () => {
9 | let userString = decodeURIComponent(
10 | window.atob(getJwtToken().split('.')[1])
11 | )
12 | return JSON.parse(userString).sub
13 | }
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysConfigMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysConfig;
5 |
6 | /**
7 | *
8 | * 系统全局配置参数 Mapper 接口
9 | *
10 | *
11 | * @author dingjn
12 | * @since 2020-06-13
13 | */
14 | public interface SysConfigMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/manage-web/src/test/java/com/dingjn/manage/web/BinarySearchTest.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web;
2 |
3 | /**
4 | * @Auther: dingjn
5 | * @Desc:
6 | */
7 | public class BinarySearchTest {
8 |
9 |
10 | public static int binarySearch(int[] sortedArray, int targetValue) {
11 | //定义最小的下标
12 | int first = 0;
13 | //最大的下标
14 | int last = sortedArray.length - 1;
15 |
16 | //定义
17 |
18 | return -1;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/manage-web/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/dto/SysUserRoleDTO.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * @Auther: dingjn
11 | * @Desc: 为用户分配角色的传输类
12 | */
13 | @Data
14 | @AllArgsConstructor
15 | @NoArgsConstructor
16 | public class SysUserRoleDTO {
17 | private Integer userId;
18 | private List checkedroleIds;
19 | }
20 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/vo/PermVO.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * @Auther: dingjn
11 | * @Desc: 分配权限Vo类
12 | */
13 | @Data
14 | @AllArgsConstructor
15 | @NoArgsConstructor
16 | public class PermVO {
17 | //角色id
18 | private Integer roleId;
19 | //menu或api的ids
20 | private List checkKeys;
21 | }
22 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysRoleMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysRole;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 系统角色表 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysRoleMapper extends BaseMapper {
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/manage-common/src/main/java/com/dingjn/manage/common/util/DataTree.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.common.util;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @Auther: dingjn
7 | * @Desc: 树状数据接口,因为有很多需要返回树状
8 | */
9 | public interface DataTree {
10 | //元素的Id
11 | Integer getId();
12 |
13 | //元素的父Id
14 | //父id字段可能叫不同的名字,pid或parentId或org_pid等,
15 | //这里适配一下,统一为使用getParentId,获取父id数据
16 | Integer getParentId();
17 |
18 | //子节点集合
19 | void setChildren(List children);
20 |
21 | List getChildren();
22 | }
23 |
--------------------------------------------------------------------------------
/vue-manage-front/README.md:
--------------------------------------------------------------------------------
1 | # vue-manage-front
2 |
3 | > A Vue.js project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/dto/SysUserDTO.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.dto;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.util.Date;
8 |
9 | /**
10 | * @Auther: dingjn
11 | * @Desc: 查询用户的传输类
12 | */
13 | @Data
14 | @AllArgsConstructor
15 | @NoArgsConstructor
16 | public class SysUserDTO {
17 | Integer orgId;
18 | String username;
19 | String phone;
20 | String email;
21 | Boolean enabled;
22 | Date createStartTime;
23 | Date createEndTime;
24 | Integer pageNum;
25 | Integer pageSize;
26 | }
27 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysRoleApiMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysRoleApi;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 角色接口权限关系表 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysRoleApiMapper extends BaseMapper {
18 | int saveApiPerm(@Param("roleId") Integer roleId, @Param("apiIds") List apiIds);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/SysRoleService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service;
2 |
3 | import com.dingjn.manage.model.vo.SysRoleVO;
4 | import com.dingjn.manage.persistence.entity.SysRole;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc: 角色服务Service
11 | */
12 | public interface SysRoleService {
13 |
14 | /**
15 | * 获取角色信息.
16 | */
17 | List getRoles(String roleLike);
18 |
19 | /**
20 | * 删除角色.
21 | */
22 | void delRole(Integer roleId);
23 |
24 | /**
25 | * 保存角色.
26 | */
27 | void saveRole(SysRoleVO sysRoleVO);
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysUserRoleMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysUserRole;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 用户角色关系表 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysUserRoleMapper extends BaseMapper {
18 |
19 | void saveRoles(@Param("userId") Integer userId, @Param("roleIds") List roleIds);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/vue-manage-front/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/vue-manage-front/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 | import ElementUI from 'element-ui';
7 | import 'element-ui/lib/theme-chalk/index.css';
8 | import axios from 'axios'
9 | import store from './store/index.js'
10 |
11 | Vue.prototype.$http=axios
12 |
13 | Vue.config.productionTip = false
14 | Vue.use(ElementUI)
15 |
16 | /* eslint-disable no-new */
17 | new Vue({
18 | el: '#app',
19 | router,
20 | store,
21 | components: { App },
22 | template: ''
23 | })
24 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/vo/SysRoleVO.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import javax.validation.constraints.NotBlank;
8 |
9 | /**
10 | * @Auther: dingjn
11 | * @Desc:
12 | */
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | public class SysRoleVO {
17 | private Integer id;
18 | @NotBlank(message = "角色名称不能为空")
19 | private String roleName;
20 | @NotBlank(message = "角色描述不能为空")
21 | private String roleDesc;
22 | @NotBlank(message = "角色编码不能为空")
23 | private String roleCode;
24 | private Integer sort;
25 | }
26 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysUserMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.model.dto.SysUserDTO;
5 | import com.dingjn.manage.model.vo.SysUserVO;
6 | import com.dingjn.manage.persistence.entity.SysUser;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | *
12 | * 用户信息表 Mapper 接口
13 | *
14 | *
15 | * @author dingjn
16 | * @since 2020-06-13
17 | */
18 | public interface SysUserMapper extends BaseMapper {
19 |
20 | List getUsers(SysUserDTO sysUserBO);
21 |
22 | List getCheckedRoleIds(Integer userId);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysRoleMenuMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysRoleMenu;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 角色菜单权限关系表 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysRoleMenuMapper extends BaseMapper {
18 |
19 | List getCheckKeys(Integer roleId);
20 |
21 | int saveMenuPerm(@Param("roleId") Integer roleId, @Param("menuIds") List menuIds);
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/manage-common/src/main/java/com/dingjn/manage/common/exception/CustomExceptionType.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.common.exception;
2 |
3 | /**
4 | * @Auther: dingjn
5 | * @Desc: 自定义异常枚举类型
6 | */
7 | public enum CustomExceptionType {
8 | USER_INPUT_ERROR(400, "用户输入异常"),
9 | SYSTEM_ERROR(500, "系统服务异常"),
10 | OTHER_ERROR(999, "其他未知异常");
11 |
12 | CustomExceptionType(int code, String typeDesc) {
13 | this.code = code;
14 | this.typeDesc = typeDesc;
15 | }
16 |
17 | private String typeDesc;
18 |
19 | private int code;
20 |
21 | public String getTypeDesc() {
22 | return typeDesc;
23 | }
24 |
25 | public int getCode() {
26 | return code;
27 | }
28 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 项目介绍
2 |
3 | **一个基于SpringBoot + Vue + Element UI 开发的权限管理系统**
4 |
5 | - 角色权限精确到菜单、接口访问
6 | - 前后端通过jwt进行认证状态管理
7 | - 持续更新...
8 |
9 | ## 技术栈
10 |
11 | - 后端:SpringBoot、SpringSecurity+jwt、MyBatisPlus
12 | - 前端:Vue-cli、Vuex、ElementUI
13 |
14 | ## 项目截图
15 |
16 | 
17 |
18 | 
19 |
20 | 
21 |
22 | 
23 |
24 | 
25 |
26 | 
27 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysOrgMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysOrg;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 系统组织结构表 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysOrgMapper extends BaseMapper {
18 |
19 | List selectOrgTree(@Param("rootOrgId") Integer rootOrgId,
20 | @Param("orgNameLike") String orgNameLike,
21 | @Param("orgStatus") Boolean orgStatus);
22 | }
23 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/ManageWebApplication.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web;
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.context.annotation.ComponentScan;
7 |
8 | /**
9 | * 项目启动类.
10 | */
11 | @ComponentScan(basePackages = "com.dingjn") //扫描指定包,因为是多moudle开发,所以需要指定才能扫描其他moudle
12 | @MapperScan(basePackages = {"com.dingjn.**.mapper"}) //扫描Mapper **代表中间不管隔多少包
13 | @SpringBootApplication
14 | public class ManageWebApplication {
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(ManageWebApplication.class, args);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysApiMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysApi;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 系统Http接口表,配合sys_role_api控制接口访问权限 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysApiMapper extends BaseMapper {
18 | List selectApiTree(@Param("rootApiId") Integer rootApiId,
19 | @Param("apiNameLike") String apiNameLike,
20 | @Param("apiStatus") Boolean apiStatus);
21 | }
22 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/SysOrgService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service;
2 |
3 | import com.dingjn.manage.model.node.SysOrgNode;
4 | import com.dingjn.manage.persistence.entity.SysOrg;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc: 组织管理Service
11 | */
12 | public interface SysOrgService {
13 |
14 | /**
15 | * 获取组织信息 树状.
16 | */
17 | List getOrgTreeById(Integer rootOrgId,
18 | String orgNameLike,
19 | Boolean orgStatus);
20 |
21 | /**
22 | * 新增/修改组织.
23 | */
24 | void saveOrg(SysOrg sysOrg);
25 |
26 | /**
27 | * 删除组织.
28 | */
29 | void delOrg(Integer id, Integer orgPid);
30 | }
31 |
--------------------------------------------------------------------------------
/manage-common/src/main/java/com/dingjn/manage/common/exception/CustomException.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.common.exception;
2 |
3 |
4 | /**
5 | * @Auther: dingjn
6 | * @Desc: 自定义异常
7 | */
8 | public class CustomException extends RuntimeException {
9 | //异常错误编码
10 | private int code ;
11 | //异常信息
12 | private String message;
13 |
14 | private CustomException(){}
15 |
16 | public CustomException(CustomExceptionType exceptionTypeEnum,
17 | String message) {
18 | this.code = exceptionTypeEnum.getCode();
19 | this.message = message;
20 | }
21 |
22 | public int getCode() {
23 | return code;
24 | }
25 |
26 | @Override
27 | public String getMessage() {
28 | return message;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysApiNode.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 |
4 | import com.dingjn.manage.common.util.DataTree;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc:
11 | */
12 | public class SysApiNode extends SysApi implements DataTree {
13 | //为某对象加上children成员变量
14 | private List children;
15 |
16 | @Override
17 | public Integer getParentId() {
18 | return super.getApiPid();
19 | }
20 |
21 | //set和get方法,为children赋值取值
22 | @Override
23 | public void setChildren(List children) {
24 | this.children = children;
25 | }
26 |
27 | @Override
28 | public List getChildren() {
29 | return this.children;
30 | }
31 | }
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysRoleMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysConfigMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/SysMenuMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.dingjn.manage.persistence.entity.SysMenu;
5 | import org.apache.ibatis.annotations.Param;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 系统菜单表 Mapper 接口
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public interface SysMenuMapper extends BaseMapper {
18 |
19 | List selectMenuTree(@Param("rootMenuId") Integer rootMenuId ,
20 | @Param("menuNameLike") String menuNameLike,
21 | @Param("menuStatus") Boolean menuStatus);
22 |
23 | List selectMenuByUsername(@Param("username") String username );
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysUserRoleMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | INSERT INTO sys_user_role(user_id,role_id) VALUES
14 |
15 | (#{userId},#{item})
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysRoleApiMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | INSERT INTO sys_role_api(role_id,api_id) VALUES
15 |
16 | (#{roleId},#{item})
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysDictMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/config/GlobalRequestAdvice.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.config;
2 |
3 | import org.springframework.beans.propertyeditors.CustomDateEditor;
4 | import org.springframework.web.bind.WebDataBinder;
5 | import org.springframework.web.bind.annotation.ControllerAdvice;
6 | import org.springframework.web.bind.annotation.InitBinder;
7 |
8 | import java.text.SimpleDateFormat;
9 | import java.util.Date;
10 |
11 | /**
12 | * @Auther: dingjn
13 | * @Desc: 对日期空字符串全局处理
14 | */
15 | @ControllerAdvice
16 | public class GlobalRequestAdvice {
17 |
18 | @InitBinder
19 | protected void initBinder(WebDataBinder binder) {
20 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
21 | binder.registerCustomEditor(Date.class,
22 | //true表示转换为日期的字符串可以为空,不设置这个值接收空串会报错
23 | new CustomDateEditor(dateFormat, true)
24 | );
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/vue-manage-front/src/components/system/FirstPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
![]()
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
31 |
32 |
40 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysOrgNode.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 |
4 | import com.dingjn.manage.common.util.DataTree;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc:
11 | */
12 | public class SysOrgNode extends SysOrg implements DataTree {
13 | //为某对象加上children成员变量
14 | private List children;
15 |
16 | @Override
17 | public Integer getParentId() {
18 | //因为不同的人设计model或者数据库,
19 | //父id字段叫不同的名字,pid或parentId或org_pid等,
20 | //这里适配一下,统一为使用getParentId,获取父id数据
21 | return super.getOrgPid();
22 | }
23 | //set和get方法,为children赋值取值
24 | @Override
25 | public void setChildren(List children) {
26 | this.children = children;
27 | }
28 |
29 | @Override
30 | public List getChildren() {
31 | return this.children;
32 | }
33 | }
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/model/JwtProperties.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.model;
2 |
3 | import lombok.Data;
4 | import org.springframework.boot.context.properties.ConfigurationProperties;
5 | import org.springframework.stereotype.Component;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * @Auther: dingjn
11 | * @Desc: jwt的相关配置
12 | */
13 | @Data
14 | @Component
15 | @ConfigurationProperties(prefix = "manage.jwt")
16 | public class JwtProperties {
17 |
18 | //JWT密钥
19 | private String secret;
20 | //JWT有效时间
21 | private Long expiration;
22 | //前端向后端传递JWT时使用HTTP的header名称
23 | private String header;
24 | //允许哪些域对本服务的跨域请求
25 | private List corsAllowedOrigins;
26 | //允许哪些HTTP方法跨域
27 | private List corsAllowedMethods;
28 | //是否关闭csrf跨站攻击防御功能
29 | private Boolean csrfDisabled = true;
30 | //是否使用默认的JWTAuthController
31 | private Boolean useDefaultController = true;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysMenuNode.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 |
4 | import com.dingjn.manage.common.util.DataTree;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc:
11 | */
12 | public class SysMenuNode extends SysMenu implements DataTree {
13 |
14 | private List children;
15 |
16 | private String path; //新加入path
17 | private String name; //新加入name
18 |
19 | public String getPath() {
20 | return this.getUrl(); //path返回url
21 | }
22 | public String getName() {
23 | return this.getMenuName(); //name返回menuName
24 | }
25 |
26 | @Override
27 | public Integer getParentId() {
28 | return super.getMenuPid();
29 | }
30 | @Override
31 | public void setChildren(List children) {
32 | this.children = children;
33 | }
34 | @Override
35 | public List getChildren() {
36 | return this.children;
37 | }
38 | }
--------------------------------------------------------------------------------
/manage-model/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | vue-manage
7 | com.dingjn
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | manage-model
13 |
14 |
15 |
16 | com.dingjn
17 | manage-common
18 | 1.0-SNAPSHOT
19 |
20 |
21 |
22 | com.baomidou
23 | mybatis-plus-boot-starter
24 | 3.2.0
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysRoleMenuMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
26 |
27 |
--------------------------------------------------------------------------------
/manage-web/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080 #服务端口
3 |
4 | ####################
5 | # Spring 配置
6 | ####################
7 | spring:
8 | datasource:
9 | type: com.alibaba.druid.pool.DruidDataSource #数据源配置
10 | url: jdbc:mysql://localhost:3306/vuemanage?useUnicode=true&characterEncoding=utf-8&useSSL=false
11 | username: root
12 | password: 123456
13 | driver-class-name: com.mysql.cj.jdbc.Driver
14 |
15 |
16 | ####################
17 | # JWT 配置
18 | ####################
19 | manage:
20 | jwt:
21 | secret: fanffafw;asfkaweg # token密钥
22 | expiration: 3600 # token过期时间 秒
23 | header: JWTHeaderName # HearName用于接受前端传递的token
24 |
25 |
26 | ####################
27 | # Mybatis-plus 配置
28 | ####################
29 | mybatis-plus:
30 | configuration:
31 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql日志
32 | map-underscore-to-camel-case: true # 开启驼峰命名
33 | mapper-locations: classpath*:com/dingjn/manage/persistence/mapper/**/*.xml #Mapper映射文件地址,多moudle要用classpath*
34 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/SysApiService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service;
2 |
3 | import com.dingjn.manage.model.node.SysApiNode;
4 | import com.dingjn.manage.persistence.entity.SysApi;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc: 接口管理Service
11 | */
12 | public interface SysApiService {
13 |
14 | /**
15 | * 获取接口全部信息 树状.
16 | */
17 | List getApiTree(String apiNameLike,
18 | Boolean orgStatus);
19 |
20 | /**
21 | * 新增/修改菜单.
22 | */
23 | void saveApi(SysApi sysApi);
24 |
25 | /**
26 | * 删除菜单.
27 | */
28 | void delApi(Integer id, Integer apiPid);
29 |
30 |
31 | /**
32 | * 获取默认展开的数据 返回id集合.
33 | */
34 | List getDefauleExpandedKeys();
35 |
36 | /**
37 | * 获取当前角色默认具有的菜单 返回id集合.
38 | */
39 | List getDefaultCheckedKeys(Integer roleId);
40 |
41 |
42 | /**
43 | * 保存角色的接口权限.
44 | */
45 | void saveApiPerm(Integer roleId,List apiIds);
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/SysUserService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service;
2 |
3 | import com.dingjn.manage.model.dto.SysUserDTO;
4 | import com.dingjn.manage.model.dto.SysUserRoleDTO;
5 | import com.dingjn.manage.model.vo.SysUserVO;
6 | import com.dingjn.manage.persistence.entity.SysUser;
7 | import com.github.pagehelper.PageInfo;
8 |
9 | import java.util.Map;
10 |
11 | /**
12 | * @Auther: dingjn
13 | * @Desc: 用户管理Service
14 | */
15 | public interface SysUserService {
16 |
17 | /**
18 | * 根据用户名获取.
19 | */
20 | SysUser getUserByUserName(String userName);
21 |
22 | /**
23 | * 根据前端传过来的条件获取.
24 | */
25 | PageInfo getUsers(SysUserDTO sysUserBO);
26 |
27 | /**
28 | * 删除.
29 | */
30 | void deleteUser(Integer userId);
31 |
32 | /**
33 | * 保存.
34 | */
35 | void saveUser(SysUser sysuser);
36 |
37 | /**
38 | * 获取当前用户的权限.
39 | */
40 | Map getCheckedRoles(Integer userId);
41 |
42 | /**
43 | * 保存当前用户的权限.
44 | */
45 | void saveRoles(SysUserRoleDTO sysUserRoleDTO);
46 | }
47 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/config/MybatisPlusConfig.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.config;
2 |
3 |
4 | import com.alibaba.druid.pool.DruidDataSource;
5 | import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
6 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
7 | import org.mybatis.spring.annotation.MapperScan;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.transaction.annotation.EnableTransactionManagement;
11 |
12 | @Configuration //表示是一个配置组件
13 | @EnableTransactionManagement
14 | @MapperScan(basePackages = {"com.dingjn.manage.**.dao.mapper"}) //扫描该包下的Mapper类
15 | public class MybatisPlusConfig {
16 | /**
17 | * mybatis-plus分页插件
18 | */
19 | @Bean
20 | public PaginationInterceptor paginationInterceptor() {
21 | return new PaginationInterceptor();
22 | }
23 |
24 | /**
25 | * 乐观锁mybatis插件
26 | */
27 | @Bean
28 | public OptimisticLockerInterceptor optimisticLockerInterceptor() {
29 | return new OptimisticLockerInterceptor();
30 | }
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/SysMenuService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service;
2 |
3 | import com.dingjn.manage.model.node.SysMenuNode;
4 | import com.dingjn.manage.persistence.entity.SysMenu;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @Auther: dingjn
10 | * @Desc: 菜单管理Service
11 | */
12 | public interface SysMenuService {
13 |
14 | /**
15 | * 获取菜单全部信息 树状.
16 | */
17 | List getMenuTree(String orgNameLike,
18 | Boolean orgStatus);
19 |
20 |
21 | /**
22 | * 新增/修改菜单.
23 | */
24 | void saveMenu(SysMenu sysMenu);
25 |
26 | /**
27 | * 删除菜单.
28 | */
29 | void delMenu(Integer id, Integer menuPid);
30 |
31 | /**
32 | * 获取默认展开的数据 返回id集合,
33 | */
34 | List getDefauleExpandedKeys();
35 |
36 | /**
37 | * 获取当前角色默认具有的菜单 返回id集合.
38 | */
39 | List getDefaultCheckedKeys(Integer roleId);
40 |
41 | /**
42 | * 保存角色的菜单权限.
43 | */
44 | void saveMenuPerm(Integer roleId, List menuIds);
45 |
46 | /**
47 | * 根据用户名获取菜单信息 树状.
48 | */
49 | List getMenuTreeByUsername(String username);
50 | }
--------------------------------------------------------------------------------
/manage-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | vue-manage
7 | com.dingjn
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | manage-service
13 |
14 |
15 |
16 | com.dingjn
17 | manage-persistence
18 | 1.0-SNAPSHOT
19 |
20 |
21 |
22 | com.dingjn
23 | manage-authentication
24 | 1.0-SNAPSHOT
25 |
26 |
27 |
28 | com.github.pagehelper
29 | pagehelper-spring-boot-starter
30 | 1.2.10
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/vue-manage-front/src/components/layout/MultiTree.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{buttonName}}
6 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/manage-web/src/test/java/com/dingjn/manage/web/SolveTest.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | /**
6 | * @Auther: dingjn
7 | * @Desc:
8 | */
9 | public class SolveTest {
10 |
11 | /**
12 | * 给定一个有序数组和元素,找出下标.
13 | */
14 | @Test
15 | public void binarySearch() {
16 | int[] sortedArray = {2, 5, 7, 9, 15};
17 | int targetValue = 3;
18 | int index = binarySearch(sortedArray, targetValue);
19 | System.out.println(index);
20 | }
21 |
22 | // 二分搜索法:先和中间的比较,小就往前找,大就往后找
23 | public static int binarySearch(int[] sortedArray, int targetValue) {
24 | //最小坐标
25 | int first = 0;
26 | //最大坐标
27 | int last = sortedArray.length - 1;
28 | //当最小的坐标超过了最大的坐标说明已经找过一轮都没找到
29 | while (first <= last) {
30 | int mid = (first + last) / 2; // //计算中间的坐标
31 |
32 | if (targetValue < sortedArray[mid]) {
33 | last = mid - 1; //如果目标值小于中间的值,就从前半部分开始找,最大的坐标则为中间的坐标-1
34 | } else if (targetValue > sortedArray[mid]) {
35 | first = mid + 1; // //如果目标值小于中间的值,就从前后 部分开始找,最小的坐标则为中间的坐标+1
36 | } else {
37 | return mid; // 如果目标值等于中间的值,说明找到了,直接返回
38 | }
39 | }
40 |
41 | return -1; //如果没找到返回-1
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/config/GlobalExcepitonHandler.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.config;
2 |
3 | import com.dingjn.manage.common.exception.CustomException;
4 | import com.dingjn.manage.common.exception.CustomExceptionType;
5 | import com.dingjn.manage.common.response.ServerResponse;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.web.bind.MethodArgumentNotValidException;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | /**
11 | * @Auther: dingjn
12 | * @Desc: 全局异常处理
13 | */
14 | @Slf4j
15 | @RestControllerAdvice
16 | public class GlobalExcepitonHandler {
17 |
18 | /**
19 | * 自定义异常.
20 | */
21 | @ExceptionHandler(CustomException.class)
22 | public ServerResponse handle(CustomException e) {
23 | return ServerResponse.error(e.getCode(), e.getMessage());
24 | }
25 |
26 | /**
27 | * 参数校验异常 BindingResult.
28 | */
29 | @ExceptionHandler(MethodArgumentNotValidException.class)
30 | public ServerResponse methodArgumentNotValidException(MethodArgumentNotValidException e) {
31 | log.error("参数校验异常,提示信息:{},具体错误信息:{}", e.getBindingResult().getFieldErrors().get(0).getDefaultMessage(), e.getMessage());
32 | return ServerResponse.error(CustomExceptionType.USER_INPUT_ERROR.getCode(), e.getBindingResult().getFieldErrors().get(0).getDefaultMessage());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/vue-manage-front/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/controller/SysRoleController.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.controller;
2 |
3 | import com.dingjn.manage.common.response.ServerResponse;
4 | import com.dingjn.manage.model.vo.SysRoleVO;
5 | import com.dingjn.manage.persistence.entity.SysRole;
6 | import com.dingjn.manage.service.SysRoleService;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * @Auther: dingjn
14 | * @Desc: 角色管理Api
15 | */
16 | @RestController
17 | @RequestMapping("/sysrole")
18 | public class SysRoleController {
19 |
20 | @Autowired
21 | SysRoleService sysRoleService;
22 |
23 | @GetMapping("/query")
24 | public ServerResponse getRoles(@RequestParam("roleLike") String roleLike) {
25 | List sysRoleList = sysRoleService.getRoles(roleLike);
26 | return ServerResponse.success(sysRoleList);
27 | }
28 |
29 | @PostMapping("/add")
30 | public ServerResponse saveRole(@RequestBody SysRoleVO sysRoleVO) {
31 | sysRoleService.saveRole(sysRoleVO);
32 | return ServerResponse.success("保存角色成功!");
33 | }
34 |
35 | @PostMapping("/delete")
36 | public ServerResponse delRole(@RequestParam("id") Integer roleId) {
37 | sysRoleService.delRole(roleId);
38 | return ServerResponse.success("删除角色成功!");
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/config/CorsConfig.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.config;
2 |
3 | import org.springframework.boot.web.servlet.FilterRegistrationBean;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.web.cors.CorsConfiguration;
8 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
9 | import org.springframework.web.filter.CorsFilter;
10 |
11 | /**
12 | * @Auther: dingjn
13 | * @Desc: 跨域配置
14 | */
15 | @Configuration
16 | public class CorsConfig {
17 | @Bean
18 | public FilterRegistrationBean corsFilter() {
19 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
20 | CorsConfiguration corsConfiguration = new CorsConfiguration();
21 | corsConfiguration.addAllowedOrigin("*"); // 1允许任何域名使用
22 | corsConfiguration.addAllowedHeader("*"); // 2允许任何头
23 | corsConfiguration.addAllowedMethod("*"); // 3允许任何方法(post、get等)
24 | corsConfiguration.setAllowCredentials(true);// 4使用相同的sessionid
25 | source.registerCorsConfiguration("/**", corsConfiguration);
26 | FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new CorsFilter(source));
27 | // 代表这个过滤器在众多过滤器中级别最高,也就是过滤的时候最先执行!
28 | //这个很重要,否则对于鉴权问题也会抛出跨域问题
29 | filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
30 | return filterRegistrationBean;
31 | }
32 | }
--------------------------------------------------------------------------------
/vue-manage-front/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysRoleApi.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 角色接口权限关系表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysRoleApi extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 角色id
26 | */
27 | private Integer roleId;
28 |
29 | /**
30 | * 接口id
31 | */
32 | private Integer apiId;
33 |
34 | public Integer getId() {
35 | return id;
36 | }
37 |
38 | public void setId(Integer id) {
39 | this.id = id;
40 | }
41 |
42 | public Integer getRoleId() {
43 | return roleId;
44 | }
45 |
46 | public void setRoleId(Integer roleId) {
47 | this.roleId = roleId;
48 | }
49 |
50 | public Integer getApiId() {
51 | return apiId;
52 | }
53 |
54 | public void setApiId(Integer apiId) {
55 | this.apiId = apiId;
56 | }
57 |
58 | @Override
59 | protected Serializable pkVal() {
60 | return null;
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return "SysRoleApi{" +
66 | ", id=" + id +
67 | ", roleId=" + roleId +
68 | ", apiId=" + apiId +
69 | "}";
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysRoleMenu.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 角色菜单权限关系表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysRoleMenu extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 角色id
26 | */
27 | private Integer roleId;
28 |
29 | /**
30 | * 权限id
31 | */
32 | private Integer menuId;
33 |
34 | public Integer getId() {
35 | return id;
36 | }
37 |
38 | public void setId(Integer id) {
39 | this.id = id;
40 | }
41 |
42 | public Integer getRoleId() {
43 | return roleId;
44 | }
45 |
46 | public void setRoleId(Integer roleId) {
47 | this.roleId = roleId;
48 | }
49 |
50 | public Integer getMenuId() {
51 | return menuId;
52 | }
53 |
54 | public void setMenuId(Integer menuId) {
55 | this.menuId = menuId;
56 | }
57 |
58 | @Override
59 | protected Serializable pkVal() {
60 | return null;
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return "SysRoleMenu{" +
66 | ", id=" + id +
67 | ", roleId=" + roleId +
68 | ", menuId=" + menuId +
69 | "}";
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysUserRole.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 用户角色关系表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysUserRole extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 角色自增id
26 | */
27 | private Integer roleId;
28 |
29 | /**
30 | * 用户自增id
31 | */
32 | private Integer userId;
33 |
34 | public Integer getId() {
35 | return id;
36 | }
37 |
38 | public void setId(Integer id) {
39 | this.id = id;
40 | }
41 |
42 | public Integer getRoleId() {
43 | return roleId;
44 | }
45 |
46 | public void setRoleId(Integer roleId) {
47 | this.roleId = roleId;
48 | }
49 |
50 | public Integer getUserId() {
51 | return userId;
52 | }
53 |
54 | public void setUserId(Integer userId) {
55 | this.userId = userId;
56 | }
57 |
58 | @Override
59 | protected Serializable pkVal() {
60 | return null;
61 | }
62 |
63 | @Override
64 | public String toString() {
65 | return "SysUserRole{" +
66 | ", id=" + id +
67 | ", roleId=" + roleId +
68 | ", userId=" + userId +
69 | "}";
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysApiMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
34 |
35 |
--------------------------------------------------------------------------------
/vue-manage-front/src/components/layout/LayoutMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
30 |
41 |
42 |
60 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/impl/SysRoleServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 | import com.dingjn.manage.model.vo.SysRoleVO;
5 | import com.dingjn.manage.persistence.entity.SysRole;
6 | import com.dingjn.manage.persistence.mapper.SysRoleMapper;
7 | import com.dingjn.manage.service.SysRoleService;
8 | import org.springframework.beans.BeanUtils;
9 | import org.springframework.stereotype.Service;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.List;
13 |
14 | /**
15 | * @Auther: dingjn
16 | * @Desc: 权限管理Service实现类
17 | */
18 | @Service
19 | public class SysRoleServiceImpl implements SysRoleService {
20 |
21 | @Resource
22 | SysRoleMapper sysRoleMapper;
23 |
24 | @Override
25 | public List getRoles(String roleLike) {
26 | QueryWrapper queryWrapper = new QueryWrapper<>();
27 | queryWrapper.like("role_name", roleLike).
28 | or().like("role_code", roleLike).
29 | or().like("role_desc", roleLike);
30 | queryWrapper.orderByAsc("sort");
31 | return sysRoleMapper.selectList(queryWrapper);
32 | }
33 |
34 | public void saveRole(SysRoleVO sysRoleVO) {
35 | SysRole sysRole = new SysRole();
36 | BeanUtils.copyProperties(sysRoleVO, sysRole);
37 | if (sysRole.getId() == null) {
38 | sysRoleMapper.insert(sysRole);
39 | } else {
40 | sysRoleMapper.updateById(sysRole);
41 | }
42 | }
43 |
44 | @Override
45 | public void delRole(Integer roleId) {
46 | sysRoleMapper.deleteById(roleId);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/controller/JwtAuthController.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.controller;
2 |
3 | import com.dingjn.manage.autentication.config.service.JwtAuthService;
4 | import com.dingjn.manage.common.exception.CustomExceptionType;
5 | import com.dingjn.manage.common.response.ServerResponse;
6 | import org.apache.commons.lang3.StringUtils;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | import javax.annotation.Resource;
11 | import java.util.Map;
12 |
13 | /**
14 | * @Auther: dingjn
15 | * @Desc: 登录认证Controller
16 | */
17 | @CrossOrigin
18 | @RestController
19 | public class JwtAuthController {
20 |
21 | @Resource
22 | private JwtAuthService jwtAuthService;
23 |
24 | @PostMapping("/authentication")
25 | public ServerResponse authentication(@RequestBody Map map) {
26 | //获取用户名和密码
27 | String username = map.get("username");
28 | String password = map.get("password");
29 |
30 | //校验用户名和密码
31 | if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
32 | return ServerResponse.error(CustomExceptionType.USER_INPUT_ERROR,
33 | "用户名或密码不能为空");
34 | }
35 | //登录返回token
36 | return ServerResponse.success(jwtAuthService.login(username, password));
37 | }
38 |
39 |
40 | /**
41 | * 刷新JWT令牌
42 | */
43 | @RequestMapping(value = "/refreshtoken")
44 | public ServerResponse refresh(@RequestHeader("JWTHeaderName") String token) {
45 | return ServerResponse.success(jwtAuthService.refreshToken(token));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/service/MyRBACService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.service;
2 |
3 | import com.dingjn.manage.autentication.config.model.JwtProperties;
4 | import org.springframework.security.core.Authentication;
5 | import org.springframework.security.core.GrantedAuthority;
6 | import org.springframework.security.core.authority.AuthorityUtils;
7 | import org.springframework.security.core.userdetails.UserDetails;
8 | import org.springframework.stereotype.Component;
9 | import org.springframework.util.AntPathMatcher;
10 |
11 | import javax.annotation.Resource;
12 | import javax.servlet.http.HttpServletRequest;
13 | import java.util.List;
14 |
15 |
16 | /**
17 | * @Auther: dingjn
18 | * @Desc: 全局进行权限控制,判断用户访问某个url有没有权限
19 | */
20 | @Component("rabcService")
21 | public class MyRBACService {
22 |
23 | /**
24 | * 判断某用户是否具有该request资源的访问权限
25 | */
26 | public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
27 |
28 | //1。获取当前用户信息
29 | Object principal = authentication.getPrincipal();
30 |
31 | //2.判断当前用户属不属于UserDetails,也就是他有没有认证通过
32 | if (principal instanceof UserDetails) {
33 | //3.获取请求的Url
34 | List authorityList =
35 | AuthorityUtils.commaSeparatedStringToAuthorityList(request.getRequestURI());
36 | UserDetails userDetails = ((UserDetails) principal);
37 |
38 | //4.userDetails.getAuthorities()获取用户的权限列表,判断是否包含请求的url
39 | return userDetails.getAuthorities().contains(authorityList.get(0));
40 | }
41 |
42 | return false;
43 | }
44 |
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysOrgMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
35 |
36 |
--------------------------------------------------------------------------------
/manage-common/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | com.dingjn
7 | vue-manage
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | manage-common
13 |
14 |
15 |
16 | org.projectlombok
17 | lombok
18 |
19 |
20 |
21 |
22 | com.fasterxml.jackson.core
23 | jackson-core
24 | 2.10.4
25 |
26 |
27 |
28 | com.fasterxml.jackson.core
29 | jackson-databind
30 | 2.10.4
31 |
32 |
33 |
34 | com.fasterxml.jackson.core
35 | jackson-annotations
36 | 2.10.4
37 |
38 |
39 |
40 |
41 | org.apache.commons
42 | commons-lang3
43 | 3.10
44 |
45 |
46 |
47 |
48 | org.hibernate.validator
49 | hibernate-validator
50 | 6.0.20.Final
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/manage-persistence/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | vue-manage
7 | com.dingjn
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | manage-persistence
13 |
14 |
15 |
16 | com.dingjn
17 | manage-model
18 | 1.0-SNAPSHOT
19 |
20 |
21 |
22 | mysql
23 | mysql-connector-java
24 |
25 |
26 |
27 | com.ibeetl
28 | beetl
29 | 2.9.10
30 |
31 |
32 |
33 | com.baomidou
34 | mybatis-plus-generator
35 | 3.2.0
36 |
37 |
38 |
39 | com.alibaba
40 | druid
41 |
42 |
43 |
44 | org.projectlombok
45 | lombok
46 |
47 |
48 | junit
49 | junit
50 | 4.12
51 | test
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/controller/SysUserController.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.controller;
2 |
3 | import com.dingjn.manage.common.response.ServerResponse;
4 | import com.dingjn.manage.model.dto.SysUserDTO;
5 | import com.dingjn.manage.model.dto.SysUserRoleDTO;
6 | import com.dingjn.manage.model.vo.SysUserVO;
7 | import com.dingjn.manage.persistence.entity.SysUser;
8 | import com.dingjn.manage.service.SysUserService;
9 | import com.github.pagehelper.PageInfo;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.web.bind.annotation.*;
12 |
13 | /**
14 | * @Auther: dingjn
15 | * @Desc: 用户管理Controller
16 | */
17 | @RestController
18 | @RequestMapping("/sysuser")
19 | public class SysUserController {
20 |
21 | @Autowired
22 | SysUserService sysUserService;
23 |
24 | @GetMapping("/query")
25 | public ServerResponse> getUsers(SysUserDTO sysUserBO) {
26 | return ServerResponse.success(sysUserService.getUsers(sysUserBO));
27 | }
28 |
29 | @PostMapping(value = "/add")
30 | public ServerResponse saveUser(@RequestBody SysUser sysUser) {
31 | sysUserService.saveUser(sysUser);
32 | return ServerResponse.success("保存用户成功!");
33 | }
34 |
35 |
36 | @PostMapping(value = "/delete")
37 | public ServerResponse delUser(@RequestParam Integer userId) {
38 | sysUserService.deleteUser(userId);
39 | return ServerResponse.success("删除用户成功!");
40 | }
41 |
42 |
43 | @GetMapping("/checkedroles")
44 | public ServerResponse currentRole(@RequestParam("userId") Integer userId) {
45 | return ServerResponse.success(sysUserService.getCheckedRoles(userId));
46 | }
47 |
48 | @PostMapping("/saveroles")
49 | public ServerResponse saveRoles(@RequestBody SysUserRoleDTO sysUserRoleDTO) {
50 | sysUserService.saveRoles(sysUserRoleDTO);
51 | return ServerResponse.success("分配角色成功!");
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/manage-common/src/main/java/com/dingjn/manage/common/util/DataTreeUtil.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.common.util;
2 |
3 |
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | /**
8 | * @Auther: dingjn
9 | * @Desc:
10 | */
11 | public class DataTreeUtil {
12 |
13 | public static > List buildTree(
14 | List paramList, Integer rootNodeId) {
15 | List returnList = new ArrayList();
16 | for (T node : paramList) {//查找根节点
17 | if (node.getId().equals(rootNodeId)) {
18 | returnList.add(node);
19 | }
20 | }
21 | //递归为children赋值
22 | for (T entry : paramList) {
23 | toTreeChildren(returnList, entry);
24 | }
25 | return returnList;
26 | }
27 |
28 | public static > List buildTreeWithoutRoot(
29 | List paramList, Integer rootNodeId) {
30 | List returnList = new ArrayList();
31 | for (T node : paramList) {//查找根节点
32 | if (node.getParentId().equals(rootNodeId)) {
33 | returnList.add(node);
34 | }
35 | }
36 | //递归为children赋值
37 | for (T entry : paramList) {
38 | toTreeChildren(returnList, entry);
39 | }
40 | return returnList;
41 | }
42 |
43 | private static > void toTreeChildren(List returnList, T entry) {
44 | for (T node : returnList) { //根节点 1
45 | if (entry.getParentId().equals(node.getId())) { //如果parentId等于 1,那就添加到字节点中
46 | if (node.getChildren() == null) { //没有创建
47 | node.setChildren(new ArrayList());
48 | }
49 | node.getChildren().add(entry); //有就直接添加 childer = 2
50 | }
51 | if (node.getChildren() != null) { //如果不为 null再递归查找2的字节点,因为你都为null了,说明了
52 | toTreeChildren(node.getChildren(), entry);
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/controller/SysOrgController.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.controller;
2 |
3 | import com.dingjn.manage.common.exception.CustomException;
4 | import com.dingjn.manage.common.exception.CustomExceptionType;
5 | import com.dingjn.manage.common.response.ServerResponse;
6 | import com.dingjn.manage.persistence.entity.SysOrg;
7 | import com.dingjn.manage.persistence.entity.SysUser;
8 | import com.dingjn.manage.service.SysOrgService;
9 | import com.dingjn.manage.service.SysUserService;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import javax.annotation.Resource;
13 | import javax.validation.Valid;
14 |
15 | /**
16 | * @Auther: dingjn
17 | * @Desc: 组织管理Api
18 | */
19 | @RestController
20 | @RequestMapping("/sysorg")
21 | public class SysOrgController {
22 |
23 | @Resource
24 | private SysOrgService sysOrgService;
25 |
26 | @Resource
27 | private SysUserService sysUserService;
28 |
29 | @PostMapping(value = "/tree")
30 | public ServerResponse tree(@RequestParam("username") String username,
31 | @RequestParam("orgNameLike") String orgNameLike) {
32 | //当前只能查看自己的部门和子节点的部门
33 | SysUser sysUser = sysUserService.getUserByUserName(username);
34 | return ServerResponse.success(sysOrgService.getOrgTreeById(sysUser.getOrgId(), orgNameLike, null));
35 |
36 | }
37 |
38 | @PostMapping(value = "/add")
39 | public ServerResponse saveOrg(@Valid @RequestBody SysOrg sysOrg) {
40 | sysOrgService.saveOrg(sysOrg);
41 | return ServerResponse.success("保存组织机构成功!");
42 | }
43 |
44 |
45 | @PostMapping(value = "/delete")
46 | public ServerResponse delOrg(@RequestParam("id") Integer id,
47 | @RequestParam("orgPid") Integer orgPid) {
48 | if (id == null || orgPid == null) {
49 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "参数id和orgPid不能为空");
50 | }
51 | sysOrgService.delOrg(id, orgPid);
52 | return ServerResponse.success("删除组织机构成功!");
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/vue-manage-front/src/components/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 用户名:admin 密码:123456
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 登 录
18 |
19 |
20 |
21 |
22 |
23 |
24 |
56 |
57 |
74 |
--------------------------------------------------------------------------------
/vue-manage-front/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Login from '@/components/Login'
4 | import Home from '@/components/Home'
5 | import SysUser from '@/components/system/SysUser'
6 | import SysRole from '@/components/system/SysRole'
7 | import SysApi from '@/components/system/SysApi'
8 | import SysOrg from '@/components/system/SysOrg'
9 | import FirstPage from '@/components/system/FirstPage'
10 | import SysMenu from '@/components/system/SysMenu'
11 | import store from '@/store/index'
12 | import { refreshToken } from '@/api/system'
13 | import { setJwtToken } from "@/lib/utils";
14 |
15 |
16 | Vue.use(Router)
17 |
18 | const router = new Router({
19 | routes: [
20 | { path: '/', redirect: '/login' },
21 | { path: '/login', name: "login", component: Login },
22 | {
23 | path: '/home',
24 | name: "home",
25 | component: Home,
26 | children: [
27 | { path: '', redirect: 'firstPage' },
28 | { path: 'firstPage', component: FirstPage },
29 | { path: "sysuser", component: SysUser },
30 | { path: "sysapi", component: SysApi },
31 | { path: "sysorg", component: SysOrg },
32 | { path: "sysrole", component: SysRole },
33 | { path: "sysmenu", component: SysMenu },
34 | ]
35 | }
36 | ]
37 | })
38 |
39 | router.beforeEach((to, from, next) => {
40 | if (to.name !== 'login') {
41 | refreshToken().then(res => {
42 | //没有获得新的token==null,
43 | // 表示旧的token已经失效,需要重新登录
44 | if (res.data == null) {
45 | next({ name: 'login' }) //去登录界面
46 | setJwtToken('') //清空token
47 | } else {//否则去你想去的界面,并把新的token保存起来
48 | console.log("456" + res.data);
49 | // 把全局配置加载完成再去你想去的页面
50 | next()
51 | setJwtToken(res.data)
52 | }
53 | })
54 | } else {//每次去到登录页面都刷新一下,清除vuex状态
55 | next()
56 | setJwtToken('') //清空token
57 | }
58 |
59 | if (to.name === 'firstpage') {
60 | store.dispatch('addTab', to.path)
61 | }
62 | })
63 |
64 | router.afterEach((to, from) => {
65 | //store.commit('addTab',to.path)
66 | store.dispatch('addTab', to.path)
67 | })
68 | export default router
69 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysMenuMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
34 |
35 |
36 |
46 |
47 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/service/MyUserDetailService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.service;
2 |
3 | import com.dingjn.manage.autentication.config.mapper.MyUserDetailsServiceMapper;
4 | import com.dingjn.manage.autentication.config.model.MyUserDetails;
5 | import org.springframework.security.core.authority.AuthorityUtils;
6 | import org.springframework.security.core.userdetails.UserDetails;
7 | import org.springframework.security.core.userdetails.UserDetailsService;
8 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
9 | import org.springframework.stereotype.Component;
10 | import org.springframework.stereotype.Service;
11 |
12 | import javax.annotation.Resource;
13 | import java.util.List;
14 | import java.util.stream.Collectors;
15 |
16 | /**
17 | * @Auther: dingjn
18 | * @Desc: 动态加载用户信息,用户登录后会先访问这个接口拿到用户信息,然后再去认证
19 | */
20 | @Component
21 | public class MyUserDetailService implements UserDetailsService {
22 | @Resource
23 | private MyUserDetailsServiceMapper myUserDetailsServiceMapper;
24 |
25 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
26 |
27 | //1.加载基础用户信息
28 | MyUserDetails myUserDetails = myUserDetailsServiceMapper.findByUserName(username);
29 |
30 | //2.加载用户角色列表
31 | List roleCodes = myUserDetailsServiceMapper.findRoleByUserName(username);
32 |
33 | if (roleCodes!=null&&roleCodes.size() > 0) {
34 | //3.通过用户角色列表加载用户的资源权限列表
35 | List authorties = myUserDetailsServiceMapper.findApiByRoleCodes(roleCodes);
36 | //4.角色是一个特殊的权限,SpringSecurity规定对于角色需要加上ROLE_前缀
37 | roleCodes = roleCodes.stream()
38 | .map(rc -> "ROLE_" + rc)
39 | .collect(Collectors.toList());
40 |
41 | authorties.addAll(roleCodes);
42 |
43 | //5.将用户权限列表赋给用户信息
44 | myUserDetails.setAuthorities(
45 | AuthorityUtils.commaSeparatedStringToAuthorityList(
46 | String.join(",", authorties)
47 | )
48 | );
49 | }
50 | return myUserDetails;
51 |
52 | }
53 |
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/vue-manage-front/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 |
24 | /**
25 | * Source Maps
26 | */
27 |
28 | // https://webpack.js.org/configuration/devtool/#development
29 | devtool: 'cheap-module-eval-source-map',
30 |
31 | // If you have problems debugging vue-files in devtools,
32 | // set this to false - it *may* help
33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
34 | cacheBusting: true,
35 |
36 | cssSourceMap: true
37 | },
38 |
39 | build: {
40 | // Template for index.html
41 | index: path.resolve(__dirname, '../dist/index.html'),
42 |
43 | // Paths
44 | assetsRoot: path.resolve(__dirname, '../dist'),
45 | assetsSubDirectory: 'static',
46 | assetsPublicPath: '/',
47 |
48 | /**
49 | * Source Maps
50 | */
51 |
52 | productionSourceMap: true,
53 | // https://webpack.js.org/configuration/devtool/#production
54 | devtool: '#source-map',
55 |
56 | // Gzip off by default as many popular static hosts such as
57 | // Surge or Netlify already gzip all static assets for you.
58 | // Before setting to `true`, make sure to:
59 | // npm install --save-dev compression-webpack-plugin
60 | productionGzip: false,
61 | productionGzipExtensions: ['js', 'css'],
62 |
63 | // Run the build command with an extra argument to
64 | // View the bundle analyzer report after build finishes:
65 | // `npm run build --report`
66 | // Set to `true` or `false` to always turn it on or off
67 | bundleAnalyzerReport: process.env.npm_config_report
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/model/MyUserDetails.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.model;
2 |
3 | import org.springframework.security.core.GrantedAuthority;
4 | import org.springframework.security.core.userdetails.UserDetails;
5 |
6 | import java.util.Collection;
7 |
8 |
9 | /**
10 | * 用户信息
11 | * 这里的用户信息是包括权限集合等信息的,后面需要进行校验,和数据库的不是一个.
12 | */
13 | public class MyUserDetails implements UserDetails {
14 |
15 | String password; //密码
16 | String username; //用户名
17 | boolean accountNonExpired; //是否没过期
18 | boolean accountNonLocked; //是否没被锁定
19 | boolean credentialsNonExpired; //是否没过期
20 | boolean enabled; //账号是否可用
21 | Collection extends GrantedAuthority> authorities; //用户的权限集合
22 |
23 | public Collection extends GrantedAuthority> getAuthorities() {
24 | return authorities;
25 | }
26 |
27 | public String getPassword() {
28 | return password;
29 | }
30 |
31 | public String getUsername() {
32 | return username;
33 | }
34 |
35 | public boolean isAccountNonExpired() {
36 | return true;
37 | }
38 |
39 | public boolean isAccountNonLocked() {
40 | return true;
41 | }
42 |
43 | public boolean isCredentialsNonExpired() {
44 | return true;
45 | }
46 |
47 | public boolean isEnabled() {
48 | return enabled;
49 | }
50 |
51 | public void setPassword(String password) {
52 | this.password = password;
53 | }
54 |
55 | public void setUsername(String username) {
56 | this.username = username;
57 | }
58 |
59 | public void setAccountNonExpired(boolean accountNonExpired) {
60 | this.accountNonExpired = accountNonExpired;
61 | }
62 |
63 | public void setAccountNonLocked(boolean accountNonLocked) {
64 | this.accountNonLocked = accountNonLocked;
65 | }
66 |
67 | public void setCredentialsNonExpired(boolean credentialsNonExpired) {
68 | this.credentialsNonExpired = credentialsNonExpired;
69 | }
70 |
71 | public void setEnabled(boolean enabled) {
72 | this.enabled = enabled;
73 | }
74 |
75 | public void setAuthorities(Collection extends GrantedAuthority> authorities) {
76 | this.authorities = authorities;
77 | }
78 | }
--------------------------------------------------------------------------------
/manage-common/src/main/java/com/dingjn/manage/common/response/ServerResponse.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.common.response;
2 |
3 | import com.dingjn.manage.common.exception.CustomExceptionType;
4 | import com.fasterxml.jackson.annotation.JsonIgnore;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 | import lombok.Data;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * @Auther: dingjn
12 | * @Desc: 统一响应类
13 | */
14 | @Data
15 | @JsonInclude(JsonInclude.Include.NON_NULL)
16 | public class ServerResponse implements Serializable {
17 |
18 | /* 状态码 */
19 | private int status;
20 | /* 消息 */
21 | private String message;
22 | /* 实体 */
23 | private T data;
24 |
25 | public ServerResponse(int status, String message, T data) {
26 | this.status = status;
27 | this.message = message;
28 | this.data = data;
29 | }
30 |
31 | public ServerResponse(int status, String message) {
32 | this.status = status;
33 | this.message = message;
34 | }
35 |
36 | public ServerResponse(String message, T data) {
37 | this.message = message;
38 | this.data = data;
39 | }
40 |
41 | public ServerResponse(int status, T data) {
42 | this.status = status;
43 | this.data = data;
44 | }
45 |
46 |
47 | public static ServerResponse success(T data) {
48 | return new ServerResponse(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getMsg(), data);
49 | }
50 |
51 | public static ServerResponse success(String message, T data) {
52 | return new ServerResponse(ResponseCode.SUCCESS.getCode(), message, data);
53 | }
54 |
55 | public static ServerResponse error(int status, String message) {
56 | return new ServerResponse(status, message);
57 | }
58 |
59 | public static ServerResponse error(String message) {
60 | return new ServerResponse(ResponseCode.SUCCESS.getCode(), message);
61 | }
62 |
63 | public static ServerResponse error(CustomExceptionType type, String message) {
64 | return new ServerResponse(type.getCode(), message);
65 | }
66 |
67 | /**
68 | * 是否成功 不返回给前端.
69 | */
70 | @JsonIgnore
71 | public boolean isSuccess() {
72 | return status == 1;
73 | }
74 | }
75 |
76 |
--------------------------------------------------------------------------------
/vue-manage-front/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: './src/main.js'
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/mapper/MyUserDetailsServiceMapper.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.mapper;
2 |
3 | import com.dingjn.manage.autentication.config.model.MyUserDetails;
4 | import org.apache.ibatis.annotations.Param;
5 | import org.apache.ibatis.annotations.Select;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * @Auther: dingjn
11 | * @Desc: 用户信息Mapper
12 | */
13 | public interface MyUserDetailsServiceMapper {
14 |
15 | /**
16 | * 根据userID查询用户信息.
17 | */
18 | @Select("SELECT username,password,enabled\n" +
19 | "FROM sys_user u\n" +
20 | "WHERE u.username = #{userId} or u.phone = #{userId}")
21 | MyUserDetails findByUserName(@Param("userId") String userId);
22 |
23 | /**
24 | * 根据userID查询用户角色列表.
25 | */
26 | @Select("SELECT role_code\n" +
27 | "FROM sys_role r\n" +
28 | "LEFT JOIN sys_user_role ur ON r.id = ur.role_id\n" +
29 | "LEFT JOIN sys_user u ON u.id = ur.user_id\n" +
30 | "WHERE u.username = #{userId} or u.phone = #{userId}")
31 | List findRoleByUserName(@Param("userId") String userId);
32 |
33 |
34 | /**
35 | * 根据用户角色查询用户菜单权限.
36 | */
37 | @Select({
38 | ""
48 | })
49 | List findMenuByRoleCodes(@Param("roleCodes") List roleCodes);
50 |
51 |
52 | /**
53 | * 根据用户角色查询用户接口访问权限.
54 | */
55 | @Select({
56 | ""
66 | })
67 | List findApiByRoleCodes(@Param("roleCodes") List roleCodes);
68 |
69 | }
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/mapper/xml/SysUserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
47 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/service/JwtAuthService.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.service;
2 |
3 | import com.dingjn.manage.autentication.config.util.JwtTokenUtil;
4 | import com.dingjn.manage.common.exception.CustomException;
5 | import com.dingjn.manage.common.exception.CustomExceptionType;
6 | import org.springframework.security.authentication.AuthenticationManager;
7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8 | import org.springframework.security.core.Authentication;
9 | import org.springframework.security.core.AuthenticationException;
10 | import org.springframework.security.core.context.SecurityContextHolder;
11 | import org.springframework.security.core.userdetails.UserDetails;
12 | import org.springframework.stereotype.Service;
13 |
14 | import javax.annotation.Resource;
15 |
16 | /**
17 | * @Auther: dingjn
18 | * @Desc: jwt认证Service
19 | */
20 | @Service
21 | public class JwtAuthService {
22 | @Resource
23 | private AuthenticationManager authenticationManager;
24 |
25 | @Resource
26 | private MyUserDetailService myUserDetailService;
27 |
28 | @Resource
29 | private JwtTokenUtil jwtTokenUtil;
30 |
31 | /**
32 | * 登录
33 | * @return 返回token,以后请求携带token进行验证.
34 | */
35 | public String login(String username, String password) {
36 | try {
37 | //1.构建Token凭证
38 | UsernamePasswordAuthenticationToken token =
39 | new UsernamePasswordAuthenticationToken(username, password);
40 | //2.对Token进行认证,返回认证主体
41 | Authentication authentication = authenticationManager.authenticate(token);
42 | //3.将主体加载到上下文中,下次会从上下文获取认证状态,避免重复认证
43 | SecurityContextHolder.getContext().setAuthentication(authentication);
44 | } catch (AuthenticationException e) {
45 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "用户名或密码输入错误");
46 | }
47 | //4.返回用户信息
48 | UserDetails userDetails = myUserDetailService.loadUserByUsername(username);
49 | //5.生成token
50 | return jwtTokenUtil.generateToken(userDetails, null);
51 | }
52 |
53 |
54 | /**
55 | * 刷新token.
56 | * 成功返回新的token,失败返回null.
57 | * 如果返回的是null,说明前端传过来的token不存在了,前端可以根据这个接口进行做访问是跳转登录页面还是其他.
58 | */
59 | public String refreshToken(String oldToken){
60 | if(!jwtTokenUtil.isTokenExpired(oldToken)){
61 | return jwtTokenUtil.refreshToken(oldToken);
62 | }
63 | return null;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysRole.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 系统角色表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysRole extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 角色名称(汉字)
26 | */
27 | private String roleName;
28 |
29 | /**
30 | * 角色描述
31 | */
32 | private String roleDesc;
33 |
34 | /**
35 | * 角色的英文code.如:ADMIN
36 | */
37 | private String roleCode;
38 |
39 | /**
40 | * 角色顺序
41 | */
42 | private Integer sort;
43 |
44 | /**
45 | * 是否禁用,0:启用(否),1:禁用(是)
46 | */
47 | private Boolean status;
48 |
49 | public Integer getId() {
50 | return id;
51 | }
52 |
53 | public void setId(Integer id) {
54 | this.id = id;
55 | }
56 |
57 | public String getRoleName() {
58 | return roleName;
59 | }
60 |
61 | public void setRoleName(String roleName) {
62 | this.roleName = roleName;
63 | }
64 |
65 | public String getRoleDesc() {
66 | return roleDesc;
67 | }
68 |
69 | public void setRoleDesc(String roleDesc) {
70 | this.roleDesc = roleDesc;
71 | }
72 |
73 | public String getRoleCode() {
74 | return roleCode;
75 | }
76 |
77 | public void setRoleCode(String roleCode) {
78 | this.roleCode = roleCode;
79 | }
80 |
81 | public Integer getSort() {
82 | return sort;
83 | }
84 |
85 | public void setSort(Integer sort) {
86 | this.sort = sort;
87 | }
88 |
89 | public Boolean getStatus() {
90 | return status;
91 | }
92 |
93 | public void setStatus(Boolean status) {
94 | this.status = status;
95 | }
96 |
97 | @Override
98 | protected Serializable pkVal() {
99 | return null;
100 | }
101 |
102 | @Override
103 | public String toString() {
104 | return "SysRole{" +
105 | ", id=" + id +
106 | ", roleName=" + roleName +
107 | ", roleDesc=" + roleDesc +
108 | ", roleCode=" + roleCode +
109 | ", sort=" + sort +
110 | ", status=" + status +
111 | "}";
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/vue-manage-front/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vuex from 'vuex'
2 | import Vue from 'vue'
3 | import { getMenuTreeByUsername } from '@/api/system'
4 |
5 |
6 | Vue.use(Vuex)
7 |
8 | //创建store对象
9 | export default new Vuex.Store({
10 | //state 存储全局共享数据
11 | state: {
12 | //存放{ route: 路由路径, name: tab显示名称}对象数组
13 | //存放{ route: 路由路径, name: tab显示名称}对象数组
14 | maintabs: [{ route: "/home/firstpage", name: "系统首页", closable: false }],
15 | //当前被激活显示的那个Tab内容对应的route
16 | activeRoute: "/home/firstPage",
17 | menuList: [
18 | ],
19 | addTabName: ""
20 | },
21 | mutations: {
22 | setActiveRoute(state, route) {
23 | state.activeRoute = route;
24 | },
25 | addTabMutation(state, route) {
26 | let isAlreadyIn =
27 | state.maintabs.some(item => item.route === route)
28 | this.commit("findMenuNameByRoute", route);
29 | if (!isAlreadyIn && state.addTabName !== "") {
30 | state.maintabs.push({ route: route, name: state.addTabName });
31 | }
32 | },
33 | removeTab(state, route) {
34 | if (route !== "/home/firstpage") {
35 | state.maintabs = state.maintabs.filter(
36 | item => item.route !== route
37 | )
38 | state.activeRoute = state.maintabs[state.maintabs.length - 1].route
39 | }
40 | },
41 | findMenuNameByRoute(state, route) {
42 | let findOne;
43 | for (let i in state.menuList) {
44 | let tmpArr = state.menuList[i].children.filter(
45 | item => item.path === route
46 | )
47 | if (tmpArr.length > 0) {
48 | findOne = tmpArr[0]
49 | break;
50 | }
51 | }
52 | state.addTabName = findOne ? findOne.name : "";
53 | }
54 | },
55 | actions: {
56 | addTab({ state, commit }, route) {
57 | //因为menuList里面有一项非菜单路由
58 | //大于等于一表示菜单已经加载过了,并且页面没刷新,
59 | //只是切换路由组件,不重新加载菜单
60 | commit("setActiveRoute", route);
61 | if (state.menuList.length <= 1) {
62 | getMenuTreeByUsername()
63 | .then(res => {
64 | console.log(res.data)
65 | state.menuList = [...res.data]
66 | commit("addTabMutation", route); //菜单加载完成之后将Tab导航项添加
67 | })
68 | } else {
69 | commit("addTabMutation", route);//菜单加载完成之后将Tab导航项添加
70 | }
71 | }
72 | }
73 | })
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/controller/SysApiController.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.controller;
2 |
3 | import com.dingjn.manage.common.exception.CustomException;
4 | import com.dingjn.manage.common.exception.CustomExceptionType;
5 | import com.dingjn.manage.common.response.ServerResponse;
6 | import com.dingjn.manage.model.vo.PermVO;
7 | import com.dingjn.manage.persistence.entity.SysApi;
8 | import com.dingjn.manage.service.SysApiService;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import javax.annotation.Resource;
12 | import javax.validation.Valid;
13 | import java.util.HashMap;
14 | import java.util.Map;
15 |
16 | /**
17 | * @Auther: dingjn
18 | * @Desc: 接口管理Api
19 | */
20 | @RestController
21 | @RequestMapping("/sysapi")
22 | public class SysApiController {
23 |
24 | @Resource
25 | private SysApiService sysApiService;
26 |
27 | @PostMapping(value = "/tree")
28 | public ServerResponse tree(@RequestParam("apiNameLike") String apiNameLike) {
29 | return ServerResponse.success(sysApiService.getApiTree(apiNameLike, null));
30 | }
31 |
32 |
33 | @PostMapping(value = "/add")
34 | public ServerResponse saveOrg(@Valid @RequestBody SysApi sysApi) {
35 | sysApiService.saveApi(sysApi);
36 | return ServerResponse.success("保存接口信息成功!");
37 | }
38 |
39 |
40 | @PostMapping(value = "/delete")
41 | public ServerResponse delOrg(@RequestParam("id") Integer id,
42 | @RequestParam("apiPid") Integer apiPid) {
43 | if (id == null || apiPid == null) {
44 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "参数id和apiPid不能为空");
45 | }
46 | sysApiService.delApi(id, apiPid);
47 | return ServerResponse.success("删除接口信息成功!");
48 | }
49 |
50 | @PostMapping(value = "/checkedtree")
51 | public ServerResponse checkTree(@RequestParam("roleId") Integer roleId) {
52 | Map resultMap = new HashMap<>();
53 | // 1.获取全部的菜单树状数据
54 | resultMap.put("treeData", sysApiService.getApiTree(null, null));
55 | // 2.获取默认展开的数据 id
56 | resultMap.put("expandedKeys", sysApiService.getDefauleExpandedKeys());
57 | // 3.获取默认勾选的数据,也就是当前角色具有的菜单数据
58 | resultMap.put("checkedKeys", sysApiService.getDefaultCheckedKeys(roleId));
59 | return ServerResponse.success(resultMap);
60 | }
61 |
62 | /**
63 | * 保存菜单权限.
64 | */
65 | @PostMapping(value = "/savekeys")
66 | public ServerResponse saveMenuPerm(@RequestBody PermVO permVO) {
67 | sysApiService.saveApiPerm(permVO.getRoleId(), permVO.getCheckKeys());
68 | return ServerResponse.success("保存菜单权限成功!");
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/manage-web/src/test/java/com/dingjn/manage/web/UserMapperTest.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web;
2 |
3 | import java.time.LocalDateTime;
4 |
5 |
6 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
7 | import com.baomidou.mybatisplus.core.metadata.IPage;
8 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
9 | import com.dingjn.manage.model.node.SysApiNode;
10 | import com.dingjn.manage.persistence.entity.SysUser;
11 | import com.dingjn.manage.persistence.mapper.SysUserMapper;
12 | import com.dingjn.manage.service.SysApiService;
13 | import com.dingjn.manage.service.SysUserService;
14 | import com.dingjn.manage.service.impl.SysApiServiceImpl;
15 | import org.junit.jupiter.api.Test;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.boot.test.context.SpringBootTest;
18 | import org.springframework.security.crypto.password.PasswordEncoder;
19 |
20 | import javax.annotation.Resource;
21 | import java.util.List;
22 |
23 | /**
24 | * @Auther: dingjn
25 | * @Desc:
26 | */
27 |
28 | @SpringBootTest
29 | public class UserMapperTest {
30 |
31 | @Resource
32 | SysUserMapper sysUserMapper;
33 |
34 | @Autowired
35 | SysUserService sysUserService;
36 |
37 | @Autowired
38 | PasswordEncoder passwordEncoder;
39 |
40 | @Test
41 | public void test() {
42 | // List apiTree = sysApiService.getApiTree(null, null);
43 | // System.out.println(apiTree);
44 | }
45 |
46 |
47 | /**
48 | * 分页查询.
49 | */
50 | @Test
51 | public void fenye() {
52 | //参数1:当前页数 参数2:每页记录数
53 | IPage iPage = new Page<>(1, 10);
54 | IPage sysUserIPage = sysUserMapper.selectPage(iPage, null);
55 | System.out.println("总记录数:" + sysUserIPage.getTotal());
56 | System.out.println("总页数:" + sysUserIPage.getPages());
57 | System.out.println("当前页数:" + sysUserIPage.getCurrent());
58 | System.out.println("记录:" + sysUserIPage.getRecords());
59 | System.out.println("大小:" + sysUserIPage.getSize());
60 | }
61 |
62 |
63 | @Test
64 | public void save() {
65 | //参数1:当前页数 参数2:每页记录数
66 | for (int i = 0; i < 105; i++) {
67 | SysUser sysUser = new SysUser();
68 | sysUser.setUsername("匿名:"+i);
69 | sysUser.setPassword(passwordEncoder.encode("123456"));
70 | sysUser.setOrgId(3);
71 | sysUser.setEnabled(false);
72 | sysUser.setPhone("17376554257");
73 | sysUser.setEmail("code123@qq.com");
74 | sysUser.setCreateTime(LocalDateTime.now());
75 | sysUserService.saveUser(sysUser);
76 | }
77 |
78 |
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysConfig.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 | import java.time.LocalDateTime;
9 |
10 | /**
11 | *
12 | * 系统全局配置参数
13 | *
14 | *
15 | * @author dingjn
16 | * @since 2020-06-13
17 | */
18 | public class SysConfig extends Model {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Integer id;
24 |
25 | /**
26 | * 参数名称(中文)
27 | */
28 | private String paramName;
29 |
30 | /**
31 | * 参数编码唯一标识(英文及数字)
32 | */
33 | private String paramKey;
34 |
35 | /**
36 | * 参数值
37 | */
38 | private String paramValue;
39 |
40 | /**
41 | * 参数描述备注
42 | */
43 | private String paramDesc;
44 |
45 | /**
46 | * 创建时间
47 | */
48 | private LocalDateTime createTime;
49 |
50 | public Integer getId() {
51 | return id;
52 | }
53 |
54 | public void setId(Integer id) {
55 | this.id = id;
56 | }
57 |
58 | public String getParamName() {
59 | return paramName;
60 | }
61 |
62 | public void setParamName(String paramName) {
63 | this.paramName = paramName;
64 | }
65 |
66 | public String getParamKey() {
67 | return paramKey;
68 | }
69 |
70 | public void setParamKey(String paramKey) {
71 | this.paramKey = paramKey;
72 | }
73 |
74 | public String getParamValue() {
75 | return paramValue;
76 | }
77 |
78 | public void setParamValue(String paramValue) {
79 | this.paramValue = paramValue;
80 | }
81 |
82 | public String getParamDesc() {
83 | return paramDesc;
84 | }
85 |
86 | public void setParamDesc(String paramDesc) {
87 | this.paramDesc = paramDesc;
88 | }
89 |
90 | public LocalDateTime getCreateTime() {
91 | return createTime;
92 | }
93 |
94 | public void setCreateTime(LocalDateTime createTime) {
95 | this.createTime = createTime;
96 | }
97 |
98 | @Override
99 | protected Serializable pkVal() {
100 | return null;
101 | }
102 |
103 | @Override
104 | public String toString() {
105 | return "SysConfig{" +
106 | ", id=" + id +
107 | ", paramName=" + paramName +
108 | ", paramKey=" + paramKey +
109 | ", paramValue=" + paramValue +
110 | ", paramDesc=" + paramDesc +
111 | ", createTime=" + createTime +
112 | "}";
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.config;
2 |
3 | import com.dingjn.manage.autentication.config.service.MyUserDetailService;
4 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.security.authentication.AuthenticationManager;
9 | import org.springframework.security.config.BeanIds;
10 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
13 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
14 | import org.springframework.security.crypto.password.PasswordEncoder;
15 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
16 |
17 | import javax.annotation.Resource;
18 |
19 | /**
20 | * @Auther: dingjn
21 | * @Desc: SpringSecurity 配置
22 | */
23 | @Configuration //配置类,会被Spring扫描
24 | @Order(1) //越小越先执行
25 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
26 |
27 | @Resource
28 | private MyUserDetailService myUserDetailService;
29 |
30 | @Resource
31 | private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
32 |
33 | /**
34 | * 配置资源访问权限.
35 | */
36 | @Override
37 | protected void configure(HttpSecurity http) throws Exception {
38 | http.csrf().disable()
39 | .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
40 | .authorizeRequests()
41 | .antMatchers("/authentication", "/refreshtoken").permitAll(); //不需要认证就能访问的接口
42 |
43 | //全局控制接口Api的访问权限
44 | http.authorizeRequests().anyRequest()
45 | .access("@rabcService.hasPermission(request,authentication)");
46 | }
47 |
48 |
49 | @Bean
50 | public PasswordEncoder passwordEncoder() {
51 | return new BCryptPasswordEncoder();
52 | }
53 |
54 | /**
55 | * 配置用户信息数据源以及密码加密器.
56 | */
57 | @Override
58 | public void configure(AuthenticationManagerBuilder auth) throws Exception {
59 | auth.userDetailsService(myUserDetailService)
60 | .passwordEncoder(passwordEncoder());
61 | }
62 |
63 |
64 | /**
65 | * 注入AuthenticationManager.
66 | * 因为使用的jwt,所以需要手动调用AuthenticationManager去认证用户信息.
67 | */
68 | @Override
69 | @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
70 | @ConditionalOnMissingBean(AuthenticationManager.class)
71 | public AuthenticationManager authenticationManagerBean() throws Exception {
72 | return super.authenticationManagerBean();
73 | }
74 |
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/manage-web/src/main/java/com/dingjn/manage/web/controller/SysMenuController.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web.controller;
2 |
3 | import com.dingjn.manage.common.exception.CustomException;
4 | import com.dingjn.manage.common.exception.CustomExceptionType;
5 | import com.dingjn.manage.common.response.ServerResponse;
6 | import com.dingjn.manage.model.node.SysMenuNode;
7 | import com.dingjn.manage.model.vo.PermVO;
8 | import com.dingjn.manage.persistence.entity.SysMenu;
9 | import com.dingjn.manage.service.SysMenuService;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import javax.annotation.Resource;
13 | import javax.validation.Valid;
14 | import java.util.HashMap;
15 | import java.util.List;
16 | import java.util.Map;
17 |
18 | /**
19 | * @Auther: dingjn
20 | * @Desc:
21 | */
22 | @RestController
23 | @RequestMapping("/sysmenu")
24 | public class SysMenuController {
25 |
26 | @Resource
27 | private SysMenuService sysMenuService;
28 |
29 | @PostMapping(value = "/tree")
30 | public ServerResponse tree(@RequestParam("menuNameLike") String menuNameLike) {
31 | return ServerResponse.success(sysMenuService.getMenuTree(menuNameLike, null));
32 | }
33 |
34 |
35 | @PostMapping(value = "/add")
36 | public ServerResponse saveOrg(@Valid @RequestBody SysMenu sysMenu) {
37 | sysMenuService.saveMenu(sysMenu);
38 | return ServerResponse.success("保存菜单信息成功!");
39 | }
40 |
41 |
42 | @PostMapping(value = "/delete")
43 | public ServerResponse delOrg(@RequestParam("id") Integer id,
44 | @RequestParam("menuPid") Integer menuPid) {
45 | if (id == null || menuPid == null) {
46 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "参数id和menuPid不能为空");
47 | }
48 | sysMenuService.delMenu(id, menuPid);
49 | return ServerResponse.success("删除菜单信息成功!");
50 | }
51 |
52 | @PostMapping(value = "/checkedtree")
53 | public ServerResponse checkTree(@RequestParam("roleId") Integer roleId) {
54 | Map resultMap = new HashMap<>();
55 | // 1.获取全部的菜单树状数据
56 | resultMap.put("treeData", sysMenuService.getMenuTree(null, null));
57 | // 2.获取默认展开的数据 id
58 | resultMap.put("expandedKeys", sysMenuService.getDefauleExpandedKeys());
59 | // 3.获取默认勾选的数据,也就是当前角色具有的菜单数据
60 | resultMap.put("checkedKeys", sysMenuService.getDefaultCheckedKeys(roleId));
61 | return ServerResponse.success(resultMap);
62 | }
63 |
64 | /**
65 | * 保存菜单权限.
66 | */
67 | @PostMapping(value = "/savekeys")
68 | public ServerResponse saveMenuPerm(@RequestBody PermVO permMenuVO) {
69 | sysMenuService.saveMenuPerm(permMenuVO.getRoleId(), permMenuVO.getCheckKeys());
70 | return ServerResponse.success("保存菜单权限成功!");
71 | }
72 |
73 |
74 | @PostMapping(value = "/tree/user")
75 | public ServerResponse usertree(@RequestParam("username") String username) {
76 | return ServerResponse.success(sysMenuService.getMenuTreeByUsername(username));
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.dingjn
8 | vue-manage
9 | 1.0-SNAPSHOT
10 |
11 | pom
12 |
13 | org.springframework.boot
14 | spring-boot-starter-parent
15 | 2.3.0.RELEASE
16 |
17 |
18 |
19 | manage-web
20 | manage-common
21 | manage-authentication
22 | manage-persistence
23 | manage-service
24 | manage-model
25 |
26 |
27 |
28 | 2.2.4.RELEASE
29 | 1.18.12
30 | 0.9.0
31 | 1.1.21
32 |
33 |
34 |
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-parent
40 | ${springboot.version}
41 | pom
42 | import
43 |
44 |
45 |
46 | org.projectlombok
47 | lombok
48 | ${lombok.version}
49 |
50 |
51 |
52 | io.jsonwebtoken
53 | jjwt
54 | ${jjwt.version}
55 |
56 |
57 |
58 | com.alibaba
59 | druid
60 | ${druid.version}
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | src/main/java
69 |
70 | **/*.xml
71 | **/*.properties
72 |
73 |
74 |
75 |
76 | src/main/resources
77 | true
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/manage-authentication/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | com.dingjn
7 | vue-manage
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 | 认证鉴权模块
12 | manage-authentication
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter-security
18 |
19 |
20 |
21 | com.dingjn
22 | manage-persistence
23 | 1.0-SNAPSHOT
24 |
25 |
26 |
27 | io.jsonwebtoken
28 | jjwt
29 |
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-configuration-processor
34 | true
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-autoconfigure
39 |
40 |
41 |
42 | com.dingjn
43 | manage-common
44 | 1.0-SNAPSHOT
45 |
46 |
47 | org.springframework
48 | spring-web
49 |
50 |
51 | org.springframework
52 | spring-context
53 |
54 |
55 | org.springframework.security
56 | spring-security-core
57 |
58 |
59 | org.springframework.security
60 | spring-security-web
61 |
62 |
63 |
64 | javax.servlet
65 | javax.servlet-api
66 | provided
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | org.apache.maven.plugins
75 | maven-compiler-plugin
76 |
77 | 8
78 | 8
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysDict.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 | import java.time.LocalDateTime;
9 |
10 | /**
11 | *
12 | * 数据字典表
13 | *
14 | *
15 | * @author dingjn
16 | * @since 2020-06-13
17 | */
18 | public class SysDict extends Model {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Integer id;
24 |
25 | /**
26 | * 分组名称
27 | */
28 | private String groupName;
29 |
30 | /**
31 | * 分组编码
32 | */
33 | private String groupCode;
34 |
35 | /**
36 | * 字典项名称
37 | */
38 | private String itemName;
39 |
40 | /**
41 | * 字典项Value
42 | */
43 | private String itemValue;
44 |
45 | /**
46 | * 字典项描述
47 | */
48 | private String itemDesc;
49 |
50 | /**
51 | * 字典项创建时间
52 | */
53 | private LocalDateTime createTime;
54 |
55 | public Integer getId() {
56 | return id;
57 | }
58 |
59 | public void setId(Integer id) {
60 | this.id = id;
61 | }
62 |
63 | public String getGroupName() {
64 | return groupName;
65 | }
66 |
67 | public void setGroupName(String groupName) {
68 | this.groupName = groupName;
69 | }
70 |
71 | public String getGroupCode() {
72 | return groupCode;
73 | }
74 |
75 | public void setGroupCode(String groupCode) {
76 | this.groupCode = groupCode;
77 | }
78 |
79 | public String getItemName() {
80 | return itemName;
81 | }
82 |
83 | public void setItemName(String itemName) {
84 | this.itemName = itemName;
85 | }
86 |
87 | public String getItemValue() {
88 | return itemValue;
89 | }
90 |
91 | public void setItemValue(String itemValue) {
92 | this.itemValue = itemValue;
93 | }
94 |
95 | public String getItemDesc() {
96 | return itemDesc;
97 | }
98 |
99 | public void setItemDesc(String itemDesc) {
100 | this.itemDesc = itemDesc;
101 | }
102 |
103 | public LocalDateTime getCreateTime() {
104 | return createTime;
105 | }
106 |
107 | public void setCreateTime(LocalDateTime createTime) {
108 | this.createTime = createTime;
109 | }
110 |
111 | @Override
112 | protected Serializable pkVal() {
113 | return null;
114 | }
115 |
116 | @Override
117 | public String toString() {
118 | return "SysDict{" +
119 | ", id=" + id +
120 | ", groupName=" + groupName +
121 | ", groupCode=" + groupCode +
122 | ", itemName=" + itemName +
123 | ", itemValue=" + itemValue +
124 | ", itemDesc=" + itemDesc +
125 | ", createTime=" + createTime +
126 | "}";
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/vue-manage-front/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 |
8 | exports.assetsPath = function (_path) {
9 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
10 | ? config.build.assetsSubDirectory
11 | : config.dev.assetsSubDirectory
12 |
13 | return path.posix.join(assetsSubDirectory, _path)
14 | }
15 |
16 | exports.cssLoaders = function (options) {
17 | options = options || {}
18 |
19 | const cssLoader = {
20 | loader: 'css-loader',
21 | options: {
22 | sourceMap: options.sourceMap,
23 | minimize: true
24 | }
25 | }
26 |
27 | const postcssLoader = {
28 | loader: 'postcss-loader',
29 | options: {
30 | sourceMap: options.sourceMap
31 | }
32 | }
33 |
34 | // generate loader string to be used with extract text plugin
35 | function generateLoaders(loader, loaderOptions) {
36 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
37 |
38 | if (loader) {
39 | loaders.push({
40 | loader: loader + '-loader',
41 | options: Object.assign({}, loaderOptions, {
42 | sourceMap: options.sourceMap
43 | })
44 | })
45 | }
46 |
47 | // Extract CSS when that option is specified
48 | // (which is the case during production build)
49 | if (options.extract) {
50 | return ExtractTextPlugin.extract({
51 | use: loaders,
52 | fallback: 'vue-style-loader'
53 | })
54 | } else {
55 | return ['vue-style-loader'].concat(loaders)
56 | }
57 | }
58 |
59 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
60 | return {
61 | css: generateLoaders(),
62 | postcss: generateLoaders(),
63 | less: generateLoaders('less'),
64 | sass: generateLoaders('sass', { indentedSyntax: true }),
65 | scss: generateLoaders('sass'),
66 | stylus: generateLoaders('stylus'),
67 | styl: generateLoaders('stylus')
68 | }
69 | }
70 |
71 | // Generate loaders for standalone style files (outside of .vue)
72 | exports.styleLoaders = function (options) {
73 | const output = []
74 | const loaders = exports.cssLoaders(options)
75 |
76 | for (const extension in loaders) {
77 | const loader = loaders[extension]
78 | output.push({
79 | test: new RegExp('\\.' + extension + '$'),
80 | use: loader
81 | })
82 | }
83 |
84 | return output
85 | }
86 |
87 | exports.createNotifierCallback = () => {
88 | const notifier = require('node-notifier')
89 |
90 | return (severity, errors) => {
91 | if (severity !== 'error') return
92 |
93 | const error = errors[0]
94 | const filename = error.file && error.file.split('!').pop()
95 |
96 | notifier.notify({
97 | title: packageConfig.name,
98 | message: severity + ': ' + error.name,
99 | subtitle: filename || '',
100 | icon: path.join(__dirname, 'logo.png')
101 | })
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysUser.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 | import java.time.LocalDateTime;
9 |
10 | /**
11 | *
12 | * 用户信息表
13 | *
14 | *
15 | * @author dingjn
16 | * @since 2020-06-13
17 | */
18 | public class SysUser extends Model {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Integer id;
24 |
25 | /**
26 | * 用户名
27 | */
28 | private String username;
29 |
30 | /**
31 | * 密码
32 | */
33 | private String password;
34 |
35 | /**
36 | * 组织id
37 | */
38 | private Integer orgId;
39 |
40 | /**
41 | * 0无效用户,1是有效用户
42 | */
43 | private Boolean enabled;
44 |
45 | /**
46 | * 手机号
47 | */
48 | private String phone;
49 |
50 | /**
51 | * email
52 | */
53 | private String email;
54 |
55 | /**
56 | * 用户创建时间
57 | */
58 | private LocalDateTime createTime;
59 |
60 | public Integer getId() {
61 | return id;
62 | }
63 |
64 | public void setId(Integer id) {
65 | this.id = id;
66 | }
67 |
68 | public String getUsername() {
69 | return username;
70 | }
71 |
72 | public void setUsername(String username) {
73 | this.username = username;
74 | }
75 |
76 | public String getPassword() {
77 | return password;
78 | }
79 |
80 | public void setPassword(String password) {
81 | this.password = password;
82 | }
83 |
84 | public Integer getOrgId() {
85 | return orgId;
86 | }
87 |
88 | public void setOrgId(Integer orgId) {
89 | this.orgId = orgId;
90 | }
91 |
92 | public Boolean getEnabled() {
93 | return enabled;
94 | }
95 |
96 | public void setEnabled(Boolean enabled) {
97 | this.enabled = enabled;
98 | }
99 |
100 | public String getPhone() {
101 | return phone;
102 | }
103 |
104 | public void setPhone(String phone) {
105 | this.phone = phone;
106 | }
107 |
108 | public String getEmail() {
109 | return email;
110 | }
111 |
112 | public void setEmail(String email) {
113 | this.email = email;
114 | }
115 |
116 | public LocalDateTime getCreateTime() {
117 | return createTime;
118 | }
119 |
120 | public void setCreateTime(LocalDateTime createTime) {
121 | this.createTime = createTime;
122 | }
123 |
124 | @Override
125 | protected Serializable pkVal() {
126 | return null;
127 | }
128 |
129 | @Override
130 | public String toString() {
131 | return "SysUser{" +
132 | ", id=" + id +
133 | ", username=" + username +
134 | ", password=" + password +
135 | ", orgId=" + orgId +
136 | ", enabled=" + enabled +
137 | ", phone=" + phone +
138 | ", email=" + email +
139 | ", createTime=" + createTime +
140 | "}";
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysUser.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 | import java.time.LocalDateTime;
9 |
10 | /**
11 | *
12 | * 用户信息表
13 | *
14 | *
15 | * @author dingjn
16 | * @since 2020-06-13
17 | */
18 | public class SysUser extends Model {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Integer id;
24 |
25 | /**
26 | * 用户名
27 | */
28 | private String username;
29 |
30 | /**
31 | * 密码
32 | */
33 | private String password;
34 |
35 | /**
36 | * 组织id
37 | */
38 | private Integer orgId;
39 |
40 | /**
41 | * 0无效用户,1是有效用户
42 | */
43 | private Boolean enabled;
44 |
45 | /**
46 | * 手机号
47 | */
48 | private String phone;
49 |
50 | /**
51 | * email
52 | */
53 | private String email;
54 |
55 | /**
56 | * 用户创建时间
57 | */
58 | private LocalDateTime createTime;
59 |
60 | public Integer getId() {
61 | return id;
62 | }
63 |
64 | public void setId(Integer id) {
65 | this.id = id;
66 | }
67 |
68 | public String getUsername() {
69 | return username;
70 | }
71 |
72 | public void setUsername(String username) {
73 | this.username = username;
74 | }
75 |
76 | public String getPassword() {
77 | return password;
78 | }
79 |
80 | public void setPassword(String password) {
81 | this.password = password;
82 | }
83 |
84 | public Integer getOrgId() {
85 | return orgId;
86 | }
87 |
88 | public void setOrgId(Integer orgId) {
89 | this.orgId = orgId;
90 | }
91 |
92 | public Boolean getEnabled() {
93 | return enabled;
94 | }
95 |
96 | public void setEnabled(Boolean enabled) {
97 | this.enabled = enabled;
98 | }
99 |
100 | public String getPhone() {
101 | return phone;
102 | }
103 |
104 | public void setPhone(String phone) {
105 | this.phone = phone;
106 | }
107 |
108 | public String getEmail() {
109 | return email;
110 | }
111 |
112 | public void setEmail(String email) {
113 | this.email = email;
114 | }
115 |
116 | public LocalDateTime getCreateTime() {
117 | return createTime;
118 | }
119 |
120 | public void setCreateTime(LocalDateTime createTime) {
121 | this.createTime = createTime;
122 | }
123 |
124 | @Override
125 | protected Serializable pkVal() {
126 | return null;
127 | }
128 |
129 | @Override
130 | public String toString() {
131 | return "SysUser{" +
132 | ", id=" + id +
133 | ", username=" + username +
134 | ", password=" + password +
135 | ", orgId=" + orgId +
136 | ", enabled=" + enabled +
137 | ", phone=" + phone +
138 | ", email=" + email +
139 | ", createTime=" + createTime +
140 | "}";
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/config/JwtAuthenticationTokenFilter.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.config;
2 |
3 |
4 | import com.dingjn.manage.autentication.config.model.JwtProperties;
5 | import com.dingjn.manage.autentication.config.service.MyUserDetailService;
6 | import com.dingjn.manage.autentication.config.util.JwtTokenUtil;
7 | import org.apache.commons.lang3.StringUtils;
8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
9 | import org.springframework.security.core.context.SecurityContextHolder;
10 | import org.springframework.security.core.userdetails.UserDetails;
11 | import org.springframework.stereotype.Component;
12 | import org.springframework.web.filter.OncePerRequestFilter;
13 |
14 | import javax.annotation.Resource;
15 | import javax.servlet.FilterChain;
16 | import javax.servlet.ServletException;
17 | import javax.servlet.http.HttpServletRequest;
18 | import javax.servlet.http.HttpServletResponse;
19 | import java.io.IOException;
20 |
21 | /**
22 | * JWT令牌授权过滤器
23 | * 1.判断令牌的有效性
24 | * 2.根据令牌为该用户授权可以访问的资源
25 | */
26 | @Component
27 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
28 |
29 | @Resource
30 | private JwtProperties jwtProperties;
31 |
32 |
33 | @Resource
34 | private JwtTokenUtil jwtTokenUtil;
35 |
36 |
37 | @Resource
38 | private MyUserDetailService myUserDetailService;
39 |
40 | private JwtAuthenticationTokenFilter() {
41 | }
42 |
43 | public JwtAuthenticationTokenFilter(JwtProperties jwtProperties,
44 | JwtTokenUtil jwtTokenUtil,
45 | MyUserDetailService myUserDetailService) {
46 | this.jwtProperties = jwtProperties;
47 | this.jwtTokenUtil = jwtTokenUtil;
48 | this.myUserDetailService = myUserDetailService;
49 | }
50 |
51 | @Override
52 | protected void doFilterInternal(HttpServletRequest request,
53 | HttpServletResponse response,
54 | FilterChain filterChain)
55 | throws ServletException, IOException {
56 |
57 | //1.获取前端传递Tokean
58 | String jwtToken = request.getHeader(jwtProperties.getHeader());
59 | //2.判断Token是否为空
60 | if (!StringUtils.isEmpty(jwtToken)) {
61 | //3.解析token,获取到用户的username
62 | String username = jwtTokenUtil.getUsernameFromToken(jwtToken);
63 |
64 | if (username != null &&
65 | SecurityContextHolder.getContext().getAuthentication() == null) {
66 | //4.根据username查询用户的信息
67 | UserDetails userDetails = myUserDetailService.loadUserByUsername(username);
68 | //5.判断token是否有效
69 | if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
70 | //6.给使用该JWT令牌的用户进行授权
71 | UsernamePasswordAuthenticationToken authenticationToken
72 | = new UsernamePasswordAuthenticationToken(
73 | userDetails, null, userDetails.getAuthorities());
74 | SecurityContextHolder.getContext().setAuthentication(authenticationToken);
75 | }
76 | }
77 | }
78 | //如果token为空直接放行
79 | filterChain.doFilter(request, response);
80 | }
81 | }
--------------------------------------------------------------------------------
/vue-manage-front/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/manage-web/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.dingjn
7 | vue-manage
8 | 1.0-SNAPSHOT
9 |
10 |
11 | com.dingjn
12 | manage-web
13 | 0.0.1-SNAPSHOT
14 | web核心模块
15 | jar
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 | com.dingjn
24 | manage-service
25 | 1.0-SNAPSHOT
26 |
27 |
28 |
29 | org.mybatis.spring.boot
30 | mybatis-spring-boot-starter
31 | 2.1.2
32 |
33 |
34 |
35 | com.dingjn
36 | manage-common
37 | 1.0-SNAPSHOT
38 |
39 |
40 |
41 | com.dingjn
42 | manage-persistence
43 | 1.0-SNAPSHOT
44 |
45 |
46 |
47 | com.dingjn
48 | manage-authentication
49 | 1.0-SNAPSHOT
50 |
51 |
52 |
53 | mysql
54 | mysql-connector-java
55 |
56 |
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-web
61 |
62 |
63 |
64 |
65 | org.springframework.boot
66 | spring-boot-starter-security
67 |
68 |
69 |
70 |
71 |
72 | org.springframework.boot
73 | spring-boot-starter-test
74 | test
75 |
76 |
77 | org.junit.vintage
78 | junit-vintage-engine
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | org.springframework.boot
90 | spring-boot-maven-plugin
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysApi.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 系统Http接口表,配合sys_role_api控制接口访问权限
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysApi extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 接口父ID(即接口分组)
26 | */
27 | private Integer apiPid;
28 |
29 | /**
30 | * 当前接口的所有上级id(即所有上级分组)
31 | */
32 | private String apiPids;
33 |
34 | /**
35 | * 0:不是叶子节点,1:是叶子节点
36 | */
37 | private Boolean isLeaf;
38 |
39 | /**
40 | * 接口名称
41 | */
42 | private String apiName;
43 |
44 | /**
45 | * 跳转URL
46 | */
47 | private String url;
48 |
49 | /**
50 | * 排序
51 | */
52 | private Integer sort;
53 |
54 | /**
55 | * 层级,1:接口分组,2:接口
56 | */
57 | private Integer level;
58 |
59 | /**
60 | * 是否禁用,0:启用(否),1:禁用(是)
61 | */
62 | private Boolean status;
63 |
64 | public Integer getId() {
65 | return id;
66 | }
67 |
68 | public void setId(Integer id) {
69 | this.id = id;
70 | }
71 |
72 | public Integer getApiPid() {
73 | return apiPid;
74 | }
75 |
76 | public void setApiPid(Integer apiPid) {
77 | this.apiPid = apiPid;
78 | }
79 |
80 | public String getApiPids() {
81 | return apiPids;
82 | }
83 |
84 | public void setApiPids(String apiPids) {
85 | this.apiPids = apiPids;
86 | }
87 |
88 | public Boolean getLeaf() {
89 | return isLeaf;
90 | }
91 |
92 | public void setLeaf(Boolean isLeaf) {
93 | this.isLeaf = isLeaf;
94 | }
95 |
96 | public String getApiName() {
97 | return apiName;
98 | }
99 |
100 | public void setApiName(String apiName) {
101 | this.apiName = apiName;
102 | }
103 |
104 | public String getUrl() {
105 | return url;
106 | }
107 |
108 | public void setUrl(String url) {
109 | this.url = url;
110 | }
111 |
112 | public Integer getSort() {
113 | return sort;
114 | }
115 |
116 | public void setSort(Integer sort) {
117 | this.sort = sort;
118 | }
119 |
120 | public Integer getLevel() {
121 | return level;
122 | }
123 |
124 | public void setLevel(Integer level) {
125 | this.level = level;
126 | }
127 |
128 | public Boolean getStatus() {
129 | return status;
130 | }
131 |
132 | public void setStatus(Boolean status) {
133 | this.status = status;
134 | }
135 |
136 | @Override
137 | protected Serializable pkVal() {
138 | return null;
139 | }
140 |
141 | @Override
142 | public String toString() {
143 | return "SysApi{" +
144 | ", id=" + id +
145 | ", apiPid=" + apiPid +
146 | ", apiPids=" + apiPids +
147 | ", isLeaf=" + isLeaf +
148 | ", apiName=" + apiName +
149 | ", url=" + url +
150 | ", sort=" + sort +
151 | ", level=" + level +
152 | ", status=" + status +
153 | "}";
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysApi.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 系统Http接口表,配合sys_role_api控制接口访问权限
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysApi extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 接口父ID(即接口分组)
26 | */
27 | private Integer apiPid;
28 |
29 | /**
30 | * 当前接口的所有上级id(即所有上级分组)
31 | */
32 | private String apiPids;
33 |
34 | /**
35 | * 0:不是叶子节点,1:是叶子节点
36 | */
37 | private Boolean isLeaf;
38 |
39 | /**
40 | * 接口名称
41 | */
42 | private String apiName;
43 |
44 | /**
45 | * 跳转URL
46 | */
47 | private String url;
48 |
49 | /**
50 | * 排序
51 | */
52 | private Integer sort;
53 |
54 | /**
55 | * 层级,1:接口分组,2:接口
56 | */
57 | private Integer level;
58 |
59 | /**
60 | * 是否禁用,0:启用(否),1:禁用(是)
61 | */
62 | private Boolean status;
63 |
64 | public Integer getId() {
65 | return id;
66 | }
67 |
68 | public void setId(Integer id) {
69 | this.id = id;
70 | }
71 |
72 | public Integer getApiPid() {
73 | return apiPid;
74 | }
75 |
76 | public void setApiPid(Integer apiPid) {
77 | this.apiPid = apiPid;
78 | }
79 |
80 | public String getApiPids() {
81 | return apiPids;
82 | }
83 |
84 | public void setApiPids(String apiPids) {
85 | this.apiPids = apiPids;
86 | }
87 |
88 | public Boolean getLeaf() {
89 | return isLeaf;
90 | }
91 |
92 | public void setLeaf(Boolean isLeaf) {
93 | this.isLeaf = isLeaf;
94 | }
95 |
96 | public String getApiName() {
97 | return apiName;
98 | }
99 |
100 | public void setApiName(String apiName) {
101 | this.apiName = apiName;
102 | }
103 |
104 | public String getUrl() {
105 | return url;
106 | }
107 |
108 | public void setUrl(String url) {
109 | this.url = url;
110 | }
111 |
112 | public Integer getSort() {
113 | return sort;
114 | }
115 |
116 | public void setSort(Integer sort) {
117 | this.sort = sort;
118 | }
119 |
120 | public Integer getLevel() {
121 | return level;
122 | }
123 |
124 | public void setLevel(Integer level) {
125 | this.level = level;
126 | }
127 |
128 | public Boolean getStatus() {
129 | return status;
130 | }
131 |
132 | public void setStatus(Boolean status) {
133 | this.status = status;
134 | }
135 |
136 | @Override
137 | protected Serializable pkVal() {
138 | return null;
139 | }
140 |
141 | @Override
142 | public String toString() {
143 | return "SysApi{" +
144 | ", id=" + id +
145 | ", apiPid=" + apiPid +
146 | ", apiPids=" + apiPids +
147 | ", isLeaf=" + isLeaf +
148 | ", apiName=" + apiName +
149 | ", url=" + url +
150 | ", sort=" + sort +
151 | ", level=" + level +
152 | ", status=" + status +
153 | "}";
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/vue-manage-front/src/lib/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { getJwtToken } from "./utils";
3 |
4 | class HttpRequest {
5 | //构造函数
6 | constructor(baseUrl) {
7 | this.baseUrl = baseUrl
8 | }
9 |
10 | //针对当前axios实例的默认配置
11 | initConfig() {
12 | const config = {
13 | baseURL: this.baseUrl,
14 | headers: {
15 | //
16 | }
17 | }
18 | return config
19 | }
20 |
21 | //创建并返回axios实例,options参数为创建实例时传递的个性化参数
22 | request(options) {
23 | const instance = axios.create()
24 | instance.interceptors.response.use(
25 | response => {
26 | const res = response.data;
27 | if (res.status == 200) {
28 | return res;
29 | } else {
30 | console.log("resres")
31 | throw res;
32 | }
33 | },
34 | // 这里处理异常响应结果
35 | error => {
36 | if (error && error.response) {
37 | switch (error.response.status) {
38 | case 400:
39 | error.message = error.response.data.message;
40 | break;
41 | case 401:
42 | error.message = '未授权,请重新登录';
43 | break;
44 | case 403:
45 | error.message = '拒绝访问';
46 | break;
47 | case 404:
48 | error.message = '请求错误,未找到该资源';
49 | break;
50 | case 405:
51 | error.message = '请求方法未允许';
52 | break;
53 | case 408:
54 | error.message = '请求超时';
55 | break;
56 | case 500: //服务器错误,返回具体的信息
57 | error.message = error.response.data.message;
58 | break;
59 | case 501:
60 | error.message = '网络未实现';
61 | break;
62 | case 502:
63 | error.message = '网络错误';
64 | break;
65 | case 503:
66 | error.message = '服务不可用';
67 | break;
68 | case 504:
69 | error.message = '网络超时';
70 | break;
71 | case 505:
72 | error.message = 'http版本不支持该请求';
73 | break;
74 | default:
75 | error.message = `未知错误${error.response.status}`;
76 | }
77 | } else {
78 | error.message = "连接到服务器失败";
79 | }
80 | return Promise.reject(error);
81 | }
82 | )
83 | // request拦截器
84 | instance.interceptors.request.use(
85 | config => {
86 | //认证请求不需要携带令牌
87 | if (config.url !== "/authentication") {
88 | // 让每个请求携带token
89 | config.headers['JWTHeaderName'] = getJwtToken();
90 | }
91 | return config;
92 | }
93 | )
94 | options = Object.assign(this.initConfig(), options)
95 | return instance(options)
96 | }
97 | }
98 |
99 | export default HttpRequest
100 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysMenu.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 系统菜单表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysMenu extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 父菜单ID
26 | */
27 | private Integer menuPid;
28 |
29 | /**
30 | * 当前菜单所有父菜单
31 | */
32 | private String menuPids;
33 |
34 | /**
35 | * 0:不是叶子节点,1:是叶子节点
36 | */
37 | private Boolean isLeaf;
38 |
39 | /**
40 | * 菜单名称
41 | */
42 | private String menuName;
43 |
44 | /**
45 | * 跳转URL
46 | */
47 | private String url;
48 |
49 | private String icon;
50 |
51 | /**
52 | * 排序
53 | */
54 | private Integer sort;
55 |
56 | /**
57 | * 菜单层级
58 | */
59 | private Integer level;
60 |
61 | /**
62 | * 是否禁用,0:启用(否),1:禁用(是)
63 | */
64 | private Boolean status;
65 |
66 | public Integer getId() {
67 | return id;
68 | }
69 |
70 | public void setId(Integer id) {
71 | this.id = id;
72 | }
73 |
74 | public Integer getMenuPid() {
75 | return menuPid;
76 | }
77 |
78 | public void setMenuPid(Integer menuPid) {
79 | this.menuPid = menuPid;
80 | }
81 |
82 | public String getMenuPids() {
83 | return menuPids;
84 | }
85 |
86 | public void setMenuPids(String menuPids) {
87 | this.menuPids = menuPids;
88 | }
89 |
90 | public Boolean getLeaf() {
91 | return isLeaf;
92 | }
93 |
94 | public void setLeaf(Boolean isLeaf) {
95 | this.isLeaf = isLeaf;
96 | }
97 |
98 | public String getMenuName() {
99 | return menuName;
100 | }
101 |
102 | public void setMenuName(String menuName) {
103 | this.menuName = menuName;
104 | }
105 |
106 | public String getUrl() {
107 | return url;
108 | }
109 |
110 | public void setUrl(String url) {
111 | this.url = url;
112 | }
113 |
114 | public String getIcon() {
115 | return icon;
116 | }
117 |
118 | public void setIcon(String icon) {
119 | this.icon = icon;
120 | }
121 |
122 | public Integer getSort() {
123 | return sort;
124 | }
125 |
126 | public void setSort(Integer sort) {
127 | this.sort = sort;
128 | }
129 |
130 | public Integer getLevel() {
131 | return level;
132 | }
133 |
134 | public void setLevel(Integer level) {
135 | this.level = level;
136 | }
137 |
138 | public Boolean getStatus() {
139 | return status;
140 | }
141 |
142 | public void setStatus(Boolean status) {
143 | this.status = status;
144 | }
145 |
146 | @Override
147 | protected Serializable pkVal() {
148 | return null;
149 | }
150 |
151 | @Override
152 | public String toString() {
153 | return "SysMenu{" +
154 | ", id=" + id +
155 | ", menuPid=" + menuPid +
156 | ", menuPids=" + menuPids +
157 | ", isLeaf=" + isLeaf +
158 | ", menuName=" + menuName +
159 | ", url=" + url +
160 | ", icon=" + icon +
161 | ", sort=" + sort +
162 | ", level=" + level +
163 | ", status=" + status +
164 | "}";
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysMenu.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 系统菜单表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysMenu extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 父菜单ID
26 | */
27 | private Integer menuPid;
28 |
29 | /**
30 | * 当前菜单所有父菜单
31 | */
32 | private String menuPids;
33 |
34 | /**
35 | * 0:不是叶子节点,1:是叶子节点
36 | */
37 | private Boolean isLeaf;
38 |
39 | /**
40 | * 菜单名称
41 | */
42 | private String menuName;
43 |
44 | /**
45 | * 跳转URL
46 | */
47 | private String url;
48 |
49 | private String icon;
50 |
51 | /**
52 | * 排序
53 | */
54 | private Integer sort;
55 |
56 | /**
57 | * 菜单层级
58 | */
59 | private Integer level;
60 |
61 | /**
62 | * 是否禁用,0:启用(否),1:禁用(是)
63 | */
64 | private Boolean status;
65 |
66 | public Integer getId() {
67 | return id;
68 | }
69 |
70 | public void setId(Integer id) {
71 | this.id = id;
72 | }
73 |
74 | public Integer getMenuPid() {
75 | return menuPid;
76 | }
77 |
78 | public void setMenuPid(Integer menuPid) {
79 | this.menuPid = menuPid;
80 | }
81 |
82 | public String getMenuPids() {
83 | return menuPids;
84 | }
85 |
86 | public void setMenuPids(String menuPids) {
87 | this.menuPids = menuPids;
88 | }
89 |
90 | public Boolean getLeaf() {
91 | return isLeaf;
92 | }
93 |
94 | public void setLeaf(Boolean isLeaf) {
95 | this.isLeaf = isLeaf;
96 | }
97 |
98 | public String getMenuName() {
99 | return menuName;
100 | }
101 |
102 | public void setMenuName(String menuName) {
103 | this.menuName = menuName;
104 | }
105 |
106 | public String getUrl() {
107 | return url;
108 | }
109 |
110 | public void setUrl(String url) {
111 | this.url = url;
112 | }
113 |
114 | public String getIcon() {
115 | return icon;
116 | }
117 |
118 | public void setIcon(String icon) {
119 | this.icon = icon;
120 | }
121 |
122 | public Integer getSort() {
123 | return sort;
124 | }
125 |
126 | public void setSort(Integer sort) {
127 | this.sort = sort;
128 | }
129 |
130 | public Integer getLevel() {
131 | return level;
132 | }
133 |
134 | public void setLevel(Integer level) {
135 | this.level = level;
136 | }
137 |
138 | public Boolean getStatus() {
139 | return status;
140 | }
141 |
142 | public void setStatus(Boolean status) {
143 | this.status = status;
144 | }
145 |
146 | @Override
147 | protected Serializable pkVal() {
148 | return null;
149 | }
150 |
151 | @Override
152 | public String toString() {
153 | return "SysMenu{" +
154 | ", id=" + id +
155 | ", menuPid=" + menuPid +
156 | ", menuPids=" + menuPids +
157 | ", isLeaf=" + isLeaf +
158 | ", menuName=" + menuName +
159 | ", url=" + url +
160 | ", icon=" + icon +
161 | ", sort=" + sort +
162 | ", level=" + level +
163 | ", status=" + status +
164 | "}";
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/impl/SysUserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 |
5 | import com.dingjn.manage.model.dto.SysUserDTO;
6 | import com.dingjn.manage.model.dto.SysUserRoleDTO;
7 | import com.dingjn.manage.model.vo.SysUserVO;
8 | import com.dingjn.manage.persistence.entity.SysRole;
9 | import com.dingjn.manage.persistence.entity.SysUser;
10 | import com.dingjn.manage.persistence.entity.SysUserRole;
11 | import com.dingjn.manage.persistence.mapper.SysRoleMapper;
12 | import com.dingjn.manage.persistence.mapper.SysUserMapper;
13 | import com.dingjn.manage.persistence.mapper.SysUserRoleMapper;
14 | import com.dingjn.manage.service.SysUserService;
15 | import com.github.pagehelper.PageHelper;
16 | import com.github.pagehelper.PageInfo;
17 | import org.springframework.security.crypto.password.PasswordEncoder;
18 | import org.springframework.stereotype.Service;
19 | import org.springframework.transaction.annotation.Transactional;
20 |
21 | import javax.annotation.Resource;
22 | import java.time.LocalDateTime;
23 | import java.util.HashMap;
24 | import java.util.List;
25 | import java.util.Map;
26 |
27 | /**
28 | * @Auther: dingjn
29 | * @Desc: 用户管理Service实现类
30 | */
31 | @Service
32 | public class SysUserServiceImpl implements SysUserService {
33 |
34 | @Resource
35 | SysUserMapper sysUserMapper;
36 |
37 | @Resource
38 | SysRoleMapper sysRoleMapper;
39 |
40 | @Resource
41 | SysUserRoleMapper sysUserRoleMapper;
42 |
43 | /**
44 | * 密码加密处理.
45 | */
46 | @Resource
47 | private PasswordEncoder passwordEncoder;
48 |
49 |
50 |
51 | @Override
52 | public SysUser getUserByUserName(String userName) {
53 | QueryWrapper queryWrapper = new QueryWrapper<>();
54 | queryWrapper.eq("username", userName);
55 | return sysUserMapper.selectOne(queryWrapper);
56 | }
57 |
58 | @Override
59 | public PageInfo getUsers(SysUserDTO sysUserBO) {
60 | PageHelper.startPage(sysUserBO.getPageNum(), sysUserBO.getPageSize());
61 | List userVOList = sysUserMapper.getUsers(sysUserBO);
62 | return PageInfo.of(userVOList);
63 | }
64 |
65 | @Override
66 | public void saveUser(SysUser sysuser) {
67 | if (sysuser.getId() == null) {
68 | //TODO 初始密码优化为通用配置
69 | sysuser.setPassword(passwordEncoder.encode("123456"));
70 | sysuser.setCreateTime(LocalDateTime.now()); //创建时间
71 | sysuser.setEnabled(true); //新增用户激活
72 | sysUserMapper.insert(sysuser);
73 | } else {
74 | sysUserMapper.updateById(sysuser);
75 | }
76 |
77 | }
78 |
79 | @Override
80 | public Map getCheckedRoles(Integer userId) {
81 | HashMap resultMap = new HashMap<>();
82 | //1.全部的角色
83 | List roleDatas = sysRoleMapper.selectList(null);
84 | //2.当前用户具有的角色
85 | List checkedRoleIds = sysUserMapper.getCheckedRoleIds(userId);
86 | resultMap.put("roleDatas", roleDatas);
87 | resultMap.put("checkedRoleIds", checkedRoleIds);
88 | return resultMap;
89 | }
90 |
91 | @Override
92 | public void deleteUser(Integer userId) {
93 | sysUserMapper.deleteById(userId);
94 | }
95 |
96 | @Override
97 | @Transactional
98 | public void saveRoles(SysUserRoleDTO sysUserRoleDTO) {
99 | //保存角色信息之前先删除之前的信息
100 | QueryWrapper queryWrapper = new QueryWrapper<>();
101 | queryWrapper.eq("user_id", sysUserRoleDTO.getUserId());
102 | sysUserRoleMapper.delete(queryWrapper);
103 | sysUserRoleMapper.saveRoles(sysUserRoleDTO.getUserId(), sysUserRoleDTO.getCheckedroleIds());
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/manage-web/src/test/java/com/dingjn/manage/web/EntityGenerator.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.web;
2 |
3 | import com.baomidou.mybatisplus.generator.AutoGenerator;
4 | import com.baomidou.mybatisplus.generator.InjectionConfig;
5 | import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
6 | import com.baomidou.mybatisplus.generator.config.GlobalConfig;
7 | import com.baomidou.mybatisplus.generator.config.PackageConfig;
8 | import com.baomidou.mybatisplus.generator.config.StrategyConfig;
9 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
10 | import com.baomidou.mybatisplus.generator.engine.BeetlTemplateEngine;
11 | import org.junit.jupiter.api.Test;
12 |
13 | import java.util.HashMap;
14 | import java.util.Map;
15 |
16 | /*
17 | 数据层内容生成
18 | */
19 | public class EntityGenerator {
20 |
21 | // 生成输出目录,定位到工程的java目录下
22 | private String outputDir = "/Users/dingjn/Desktop/codes/vue-manage/manage-persistence/src/main/java";
23 | // 生成类的作者
24 | private String author = "dingjn";
25 | // 数据源相关配置
26 | private String url = "jdbc:mysql://localhost:3306/devicedb?useUnicode=true&characterEncoding=utf-8&useSSL=false";
27 | private String driverName = "com.mysql.cj.jdbc.Driver";
28 | private String userName = "root";
29 | private String userPwd = "mysql04141015";
30 | // DAO的包路径
31 | private String daoPackage = "com.dingjn.manage.persistence";
32 | // 待生成的表名,注意是覆盖更新
33 | private static String[] tableNames;
34 |
35 | static{
36 | tableNames = new String[]{
37 | "sys_api",
38 | "sys_config",
39 | "sys_dict",
40 | "sys_menu",
41 | "sys_org",
42 | "sys_role",
43 | "sys_role_api",
44 | "sys_role_menu",
45 | "sys_user",
46 | "sys_user_role",
47 | };
48 | }
49 |
50 | @Test
51 | public void entityGenerator() {
52 | AutoGenerator mpg = new AutoGenerator();
53 | mpg.setTemplateEngine(new BeetlTemplateEngine());
54 | // 全局配置
55 | GlobalConfig gc = new GlobalConfig();
56 | gc.setOutputDir(outputDir);
57 | gc.setFileOverride(true);
58 | gc.setActiveRecord(true);
59 | gc.setEnableCache(false);
60 | gc.setBaseResultMap(true);
61 | gc.setBaseColumnList(false);
62 | gc.setAuthor(author);
63 | mpg.setGlobalConfig(gc);
64 |
65 | // 数据源配置
66 | DataSourceConfig dsc = new DataSourceConfig();
67 | dsc.setUrl(url);
68 | // dsc.setSchemaName("public");
69 | dsc.setDriverName(driverName);
70 | dsc.setUsername(userName);
71 | dsc.setPassword(userPwd);
72 | mpg.setDataSource(dsc);
73 |
74 | // 策略配置
75 | StrategyConfig strategy = new StrategyConfig();
76 | //strategy.setTablePrefix(new String[]{"_"});// 此处可以修改为您的表前缀
77 | strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
78 | strategy.setInclude(tableNames);
79 | mpg.setStrategy(strategy);
80 |
81 | // 包配置
82 | PackageConfig pc = new PackageConfig();
83 | pc.setParent(null);
84 | pc.setEntity(daoPackage+".entity");
85 | pc.setMapper(daoPackage+".mapper");
86 | pc.setXml(daoPackage+".mapper.xml");
87 | mpg.setPackageInfo(pc);
88 |
89 | // 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值
90 | InjectionConfig cfg = new InjectionConfig() {
91 | @Override
92 | public void initMap() {
93 | Map map = new HashMap<>();
94 | map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
95 | this.setMap(map);
96 | }
97 | };
98 |
99 | mpg.setCfg(cfg);
100 |
101 | // 执行生成
102 | mpg.execute();
103 |
104 | // 打印注入设置
105 | System.err.println(mpg.getCfg().getMap().get("abc"));
106 |
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/manage-model/src/main/java/com/dingjn/manage/model/node/SysOrg.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.model.node;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import java.io.Serializable;
8 |
9 | /**
10 | *
11 | * 系统组织结构表
12 | *
13 | *
14 | * @author dingjn
15 | * @since 2020-06-13
16 | */
17 | public class SysOrg extends Model {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @TableId(value = "id", type = IdType.AUTO)
22 | private Integer id;
23 |
24 | /**
25 | * 上级组织编码
26 | */
27 | private Integer orgPid;
28 |
29 | /**
30 | * 所有的父节点id
31 | */
32 | private String orgPids;
33 |
34 | /**
35 | * 0:不是叶子节点,1:是叶子节点
36 | */
37 | private Boolean isLeaf;
38 |
39 | /**
40 | * 组织名
41 | */
42 | private String orgName;
43 |
44 | /**
45 | * 地址
46 | */
47 | private String address;
48 |
49 | /**
50 | * 电话
51 | */
52 | private String phone;
53 |
54 | /**
55 | * 邮件
56 | */
57 | private String email;
58 |
59 | /**
60 | * 排序
61 | */
62 | private Integer sort;
63 |
64 | /**
65 | * 组织层级
66 | */
67 | private Integer level;
68 |
69 | /**
70 | * 是否禁用,0:启用(否),1:禁用(是)
71 | */
72 | private Boolean status;
73 |
74 | public Integer getId() {
75 | return id;
76 | }
77 |
78 | public void setId(Integer id) {
79 | this.id = id;
80 | }
81 |
82 | public Integer getOrgPid() {
83 | return orgPid;
84 | }
85 |
86 | public void setOrgPid(Integer orgPid) {
87 | this.orgPid = orgPid;
88 | }
89 |
90 | public String getOrgPids() {
91 | return orgPids;
92 | }
93 |
94 | public void setOrgPids(String orgPids) {
95 | this.orgPids = orgPids;
96 | }
97 |
98 | public Boolean getLeaf() {
99 | return isLeaf;
100 | }
101 |
102 | public void setLeaf(Boolean isLeaf) {
103 | this.isLeaf = isLeaf;
104 | }
105 |
106 | public String getOrgName() {
107 | return orgName;
108 | }
109 |
110 | public void setOrgName(String orgName) {
111 | this.orgName = orgName;
112 | }
113 |
114 | public String getAddress() {
115 | return address;
116 | }
117 |
118 | public void setAddress(String address) {
119 | this.address = address;
120 | }
121 |
122 | public String getPhone() {
123 | return phone;
124 | }
125 |
126 | public void setPhone(String phone) {
127 | this.phone = phone;
128 | }
129 |
130 | public String getEmail() {
131 | return email;
132 | }
133 |
134 | public void setEmail(String email) {
135 | this.email = email;
136 | }
137 |
138 | public Integer getSort() {
139 | return sort;
140 | }
141 |
142 | public void setSort(Integer sort) {
143 | this.sort = sort;
144 | }
145 |
146 | public Integer getLevel() {
147 | return level;
148 | }
149 |
150 | public void setLevel(Integer level) {
151 | this.level = level;
152 | }
153 |
154 | public Boolean getStatus() {
155 | return status;
156 | }
157 |
158 | public void setStatus(Boolean status) {
159 | this.status = status;
160 | }
161 |
162 | @Override
163 | protected Serializable pkVal() {
164 | return null;
165 | }
166 |
167 | @Override
168 | public String toString() {
169 | return "SysOrg{" +
170 | ", id=" + id +
171 | ", orgPid=" + orgPid +
172 | ", orgPids=" + orgPids +
173 | ", isLeaf=" + isLeaf +
174 | ", orgName=" + orgName +
175 | ", address=" + address +
176 | ", phone=" + phone +
177 | ", email=" + email +
178 | ", sort=" + sort +
179 | ", level=" + level +
180 | ", status=" + status +
181 | "}";
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/manage-persistence/src/main/java/com/dingjn/manage/persistence/entity/SysOrg.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.persistence.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.extension.activerecord.Model;
6 |
7 | import javax.validation.constraints.NotBlank;
8 | import java.io.Serializable;
9 |
10 | /**
11 | *
12 | * 系统组织结构表
13 | *
14 | *
15 | * @author dingjn
16 | * @since 2020-06-13
17 | */
18 | public class SysOrg extends Model {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | @TableId(value = "id", type = IdType.AUTO)
23 | private Integer id;
24 |
25 | /**
26 | * 上级组织编码
27 | */
28 | private Integer orgPid;
29 |
30 | /**
31 | * 所有的父节点id
32 | */
33 | private String orgPids;
34 |
35 | /**
36 | * 0:不是叶子节点,1:是叶子节点
37 | */
38 | private Boolean isLeaf;
39 |
40 | /**
41 | * 组织名
42 | */
43 | @NotBlank(message = "组织名不能为空")
44 | private String orgName;
45 |
46 | /**
47 | * 地址
48 | */
49 | private String address;
50 |
51 | /**
52 | * 电话
53 | */
54 | private String phone;
55 |
56 | /**
57 | * 邮件
58 | */
59 | private String email;
60 |
61 | /**
62 | * 排序
63 | */
64 | private Integer sort;
65 |
66 | /**
67 | * 组织层级
68 | */
69 | private Integer level;
70 |
71 | /**
72 | * 是否禁用,0:启用(否),1:禁用(是)
73 | */
74 | private Boolean status;
75 |
76 | public Integer getId() {
77 | return id;
78 | }
79 |
80 | public void setId(Integer id) {
81 | this.id = id;
82 | }
83 |
84 | public Integer getOrgPid() {
85 | return orgPid;
86 | }
87 |
88 | public void setOrgPid(Integer orgPid) {
89 | this.orgPid = orgPid;
90 | }
91 |
92 | public String getOrgPids() {
93 | return orgPids;
94 | }
95 |
96 | public void setOrgPids(String orgPids) {
97 | this.orgPids = orgPids;
98 | }
99 |
100 | public Boolean getLeaf() {
101 | return isLeaf;
102 | }
103 |
104 | public void setLeaf(Boolean isLeaf) {
105 | this.isLeaf = isLeaf;
106 | }
107 |
108 | public String getOrgName() {
109 | return orgName;
110 | }
111 |
112 | public void setOrgName(String orgName) {
113 | this.orgName = orgName;
114 | }
115 |
116 | public String getAddress() {
117 | return address;
118 | }
119 |
120 | public void setAddress(String address) {
121 | this.address = address;
122 | }
123 |
124 | public String getPhone() {
125 | return phone;
126 | }
127 |
128 | public void setPhone(String phone) {
129 | this.phone = phone;
130 | }
131 |
132 | public String getEmail() {
133 | return email;
134 | }
135 |
136 | public void setEmail(String email) {
137 | this.email = email;
138 | }
139 |
140 | public Integer getSort() {
141 | return sort;
142 | }
143 |
144 | public void setSort(Integer sort) {
145 | this.sort = sort;
146 | }
147 |
148 | public Integer getLevel() {
149 | return level;
150 | }
151 |
152 | public void setLevel(Integer level) {
153 | this.level = level;
154 | }
155 |
156 | public Boolean getStatus() {
157 | return status;
158 | }
159 |
160 | public void setStatus(Boolean status) {
161 | this.status = status;
162 | }
163 |
164 | @Override
165 | protected Serializable pkVal() {
166 | return null;
167 | }
168 |
169 | @Override
170 | public String toString() {
171 | return "SysOrg{" +
172 | ", id=" + id +
173 | ", orgPid=" + orgPid +
174 | ", orgPids=" + orgPids +
175 | ", isLeaf=" + isLeaf +
176 | ", orgName=" + orgName +
177 | ", address=" + address +
178 | ", phone=" + phone +
179 | ", email=" + email +
180 | ", sort=" + sort +
181 | ", level=" + level +
182 | ", status=" + status +
183 | "}";
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/manage-authentication/src/main/java/com/dingjn/manage/autentication/config/util/JwtTokenUtil.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.autentication.config.util;
2 |
3 | import com.dingjn.manage.autentication.config.model.JwtProperties;
4 | import io.jsonwebtoken.Claims;
5 | import io.jsonwebtoken.Jwts;
6 | import io.jsonwebtoken.SignatureAlgorithm;
7 | import org.springframework.security.core.userdetails.UserDetails;
8 | import org.springframework.stereotype.Component;
9 |
10 | import java.util.Date;
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | /**
15 | * @Auther: dingjn
16 | * @Desc: jwt工具类
17 | */
18 | @Component
19 | public class JwtTokenUtil {
20 |
21 | private JwtProperties jwtProperties;
22 |
23 | public JwtTokenUtil(JwtProperties jwtProperties) {
24 | this.jwtProperties = jwtProperties;
25 | }
26 |
27 | public JwtProperties getJwtProperties() {
28 | return jwtProperties;
29 | }
30 |
31 | /**
32 | * 生成token令牌
33 | *
34 | * @param userDetails 用户
35 | * @param payloads 令牌中携带的附加信息
36 | * @return 令token牌
37 | */
38 | public String generateToken(UserDetails userDetails,
39 | Map payloads) {
40 | int payloadSizes = payloads == null ? 0 : payloads.size();
41 |
42 | Map claims = new HashMap<>(payloadSizes + 2);
43 | claims.put("sub", userDetails.getUsername());
44 | claims.put("created", new Date());
45 |
46 | if (payloadSizes > 0) {
47 | for (Map.Entry entry : payloads.entrySet()) {
48 | claims.put(entry.getKey(), entry.getValue());
49 | }
50 | }
51 |
52 | return generateToken(claims);
53 | }
54 |
55 | /**
56 | * 从令牌中获取用户名
57 | *
58 | * @param token 令牌
59 | * @return 用户名
60 | */
61 | public String getUsernameFromToken(String token) {
62 | String username;
63 | try {
64 | Claims claims = getClaimsFromToken(token);
65 | username = claims.getSubject();
66 | } catch (Exception e) {
67 | username = null;
68 | }
69 | return username;
70 | }
71 |
72 | /**
73 | * 判断令牌是否过期
74 | *
75 | * @param token 令牌
76 | * @return 是否过期
77 | */
78 | public Boolean isTokenExpired(String token) {
79 | try {
80 | Claims claims = getClaimsFromToken(token);
81 | Date expiration = claims.getExpiration();
82 | return expiration.before(new Date());
83 | } catch (Exception e) {
84 | return false;
85 | }
86 | }
87 |
88 | /**
89 | * 刷新令牌
90 | *
91 | * @param token 原令牌
92 | * @return 新令牌
93 | */
94 | public String refreshToken(String token) {
95 | String refreshedToken;
96 | try {
97 | Claims claims = getClaimsFromToken(token);
98 | claims.put("created", new Date());
99 | refreshedToken = generateToken(claims);
100 | } catch (Exception e) {
101 | refreshedToken = null;
102 | }
103 | return refreshedToken;
104 | }
105 |
106 | /**
107 | * 验证令牌
108 | *
109 | * @param token 令牌
110 | * @param userDetails 用户
111 | * @return 是否有效
112 | */
113 | public Boolean validateToken(String token, UserDetails userDetails) {
114 | String username = getUsernameFromToken(token);
115 | return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
116 | }
117 |
118 |
119 | /**
120 | * 从claims生成令牌,如果看不懂就看谁调用它
121 | *
122 | * @param claims 数据声明
123 | * @return 令牌
124 | */
125 | private String generateToken(Map claims) {
126 | Date expirationDate = new Date(System.currentTimeMillis() + jwtProperties.getExpiration() * 1000);
127 | return Jwts.builder().setClaims(claims)
128 | .setExpiration(expirationDate)
129 | .signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
130 | .compact();
131 | }
132 |
133 | /**
134 | * 从令牌中获取数据声明,如果看不懂就看谁调用它
135 | *
136 | * @param token 令牌
137 | * @return 数据声明
138 | */
139 | private Claims getClaimsFromToken(String token) {
140 | Claims claims;
141 | try {
142 | claims = Jwts.parser().setSigningKey(jwtProperties.getSecret()).parseClaimsJws(token).getBody();
143 | } catch (Exception e) {
144 | claims = null;
145 | }
146 | return claims;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/impl/SysOrgServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 | import com.dingjn.manage.common.exception.CustomException;
5 | import com.dingjn.manage.common.exception.CustomExceptionType;
6 | import com.dingjn.manage.common.util.DataTreeUtil;
7 | import com.dingjn.manage.model.node.SysOrgNode;
8 | import com.dingjn.manage.persistence.entity.SysOrg;
9 | import com.dingjn.manage.persistence.mapper.SysOrgMapper;
10 | import com.dingjn.manage.service.SysOrgService;
11 | import org.apache.commons.lang3.StringUtils;
12 | import org.springframework.beans.BeanUtils;
13 | import org.springframework.stereotype.Service;
14 | import org.springframework.transaction.annotation.Transactional;
15 |
16 | import javax.annotation.Resource;
17 | import java.util.List;
18 | import java.util.stream.Collectors;
19 |
20 | /**
21 | * @Auther: dingjn
22 | * @Desc: 组织管理Service实现类
23 | */
24 | @Service
25 | public class SysOrgServiceImpl implements SysOrgService {
26 | @Resource
27 | private SysOrgMapper sysOrgMapper;
28 |
29 | //查询组织信息 返回树状结构
30 | public List getOrgTreeById(Integer rootOrgId,
31 | String orgNameLike,
32 | Boolean orgStatus) {
33 | if (rootOrgId != null) {
34 | List sysOrgs
35 | = sysOrgMapper.selectOrgTree(rootOrgId, orgNameLike, orgStatus);
36 |
37 | List sysOrgNodes = sysOrgs.stream().map(item -> {
38 | SysOrgNode bean = new SysOrgNode();
39 | BeanUtils.copyProperties(item, bean);
40 | return bean;
41 | }).collect(Collectors.toList());
42 |
43 |
44 | if (StringUtils.isNotEmpty(orgNameLike) || orgStatus != null) {
45 | return sysOrgNodes;//根据条件查询,会破坏树形结构,所以返回平面列表
46 | } else {//否则返回树型结构列表
47 | return DataTreeUtil.buildTree(sysOrgNodes, rootOrgId);
48 | }
49 |
50 | } else {
51 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR,
52 | "查询参数用户名组织id不能为空");
53 | }
54 | }
55 |
56 | @Override
57 | @Transactional
58 | public void saveOrg(SysOrg sysOrg) {
59 | if (sysOrg.getId() == null) {
60 | //1.添加节点
61 | setOrgPidsAndLevel(sysOrg);
62 | sysOrg.setStatus(false);//默认不禁用
63 | sysOrg.setLeaf(true);//新增的节点都是叶子节点
64 | sysOrgMapper.insert(sysOrg);
65 | //2.更新父节点为非叶子节点
66 | SysOrg parent = new SysOrg();
67 | parent.setId(sysOrg.getOrgPid());
68 | parent.setLeaf(false);
69 | sysOrgMapper.updateById(parent);
70 | } else {
71 | //修改节点
72 | sysOrgMapper.updateById(sysOrg);
73 | }
74 |
75 | }
76 |
77 | //为新增的节点设置org_pids和level
78 | private void setOrgPidsAndLevel(SysOrg child) {
79 | //1.找出新增节点的直接父节点
80 | SysOrg sysOrg = sysOrgMapper.selectById(child.getOrgPid());
81 |
82 | //2.直接父节点的所有父节点id+直接父节点的id=新增节点的所有父id
83 | //因为数据库中的org_pids格式为 [1],[2],[3]
84 | child.setOrgPids(sysOrg.getOrgPids() + ",[" + child.getOrgPid() + "]");
85 | //4.设置新增节点的level 为父节点的level+1
86 | child.setLevel(sysOrg.getLevel() + 1);
87 | }
88 |
89 | @Override
90 | @Transactional
91 | public void delOrg(Integer id, Integer orgPid) {
92 | //查询当前节点下的子节点,如果有子节点不能删除,否则会破坏掉树形结构,导致它的子节点没有根源
93 | QueryWrapper queryWrapper = new QueryWrapper<>();
94 | queryWrapper.like("org_pids", "[" + id + "]");
95 | List childSysOrgList = sysOrgMapper.selectList(queryWrapper);
96 | if (childSysOrgList.size() > 0) {
97 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "不能删除有下级组织的组织机构");
98 | }
99 | setParentLeaf(orgPid);
100 | sysOrgMapper.deleteById(id);
101 |
102 | }
103 |
104 | //如果当前节点的上级组织只有它一个节点,那么当前节点被删除以后,上级组织应该变为叶子节点
105 | private void setParentLeaf(Integer orgPid) {
106 | //找出当前父节点有几个子节点
107 | QueryWrapper queryWrapper = new QueryWrapper<>();
108 | queryWrapper.like("org_pids", "[" + orgPid + "]");
109 | List childSysOrgList = sysOrgMapper.selectList(queryWrapper);
110 | if (childSysOrgList.size() == 1) {
111 | //设置Leaf为true
112 | SysOrg parent = new SysOrg();
113 | parent.setId(orgPid);
114 | parent.setLeaf(true);
115 | sysOrgMapper.updateById(parent);
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/vue-manage-front/src/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 后台管理系统
8 |
9 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
35 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
103 |
104 |
201 |
--------------------------------------------------------------------------------
/manage-service/src/main/java/com/dingjn/manage/service/impl/SysApiServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.dingjn.manage.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 | import com.dingjn.manage.common.exception.CustomException;
5 | import com.dingjn.manage.common.exception.CustomExceptionType;
6 | import com.dingjn.manage.common.util.DataTreeUtil;
7 | import com.dingjn.manage.model.node.SysApiNode;
8 | import com.dingjn.manage.persistence.entity.SysApi;
9 | import com.dingjn.manage.persistence.entity.SysMenu;
10 | import com.dingjn.manage.persistence.entity.SysRoleApi;
11 | import com.dingjn.manage.persistence.entity.SysRoleMenu;
12 | import com.dingjn.manage.persistence.mapper.SysApiMapper;
13 | import com.dingjn.manage.persistence.mapper.SysRoleApiMapper;
14 | import com.dingjn.manage.service.SysApiService;
15 | import org.apache.commons.lang3.StringUtils;
16 | import org.apache.ibatis.annotations.Mapper;
17 | import org.springframework.beans.BeanUtils;
18 | import org.springframework.stereotype.Service;
19 | import org.springframework.transaction.annotation.Transactional;
20 |
21 | import javax.annotation.Resource;
22 | import java.util.List;
23 | import java.util.stream.Collectors;
24 |
25 | /**
26 | * @Auther: dingjn
27 | * @Desc: 接口管理Service实现类
28 | */
29 | @Service
30 | public class SysApiServiceImpl implements SysApiService {
31 |
32 | @Resource
33 | SysApiMapper sysApiMapper;
34 |
35 | @Resource
36 | SysRoleApiMapper sysRoleApiMapper;
37 |
38 | @Override
39 | public List getApiTree(String apiNameLike, Boolean orgStatus) {
40 | //1.找出根节点
41 | QueryWrapper queryWrapper = new QueryWrapper<>();
42 | queryWrapper.eq("level", 1);
43 | SysApi sysMenu = sysApiMapper.selectOne(queryWrapper);
44 |
45 | List sysMenuList = sysApiMapper.selectApiTree(sysMenu.getApiPid(), apiNameLike, null);
46 | List sysMenuNodeList = sysMenuList.stream().map(menu -> {
47 | SysApiNode sysMenuNode = new SysApiNode();
48 | BeanUtils.copyProperties(menu, sysMenuNode);
49 | return sysMenuNode;
50 | }).collect(Collectors.toList());
51 |
52 | if (!StringUtils.isBlank(apiNameLike)) {
53 | return sysMenuNodeList;
54 | } else {
55 | return DataTreeUtil.buildTree(sysMenuNodeList, sysMenu.getId());
56 | }
57 | }
58 |
59 | @Transactional
60 | public void saveApi(SysApi sysApi) {
61 | //判断是添加还是修改
62 | if (sysApi.getId() == null) {
63 | sysApi.setStatus(false);//默认不禁用
64 | sysApi.setLeaf(true);//默认是叶子节点
65 | setMenuPidsAndLevel(sysApi);
66 | //添加当前节点
67 | sysApiMapper.insert(sysApi);
68 | setMenuPidsAndLevel(sysApi);
69 | } else {
70 | sysApiMapper.updateById(sysApi);
71 | }
72 | }
73 |
74 | private void setMenuPidsAndLevel(SysApi child) {
75 | SysApi sysApi = sysApiMapper.selectById(child.getApiPid());
76 | //设置menuPids
77 | child.setApiPids(sysApi.getApiPids() + ",[" + child.getApiPid() + "]");
78 | //设置Level
79 | child.setLevel(sysApi.getLevel() + 1);
80 | }
81 |
82 | @Override
83 | @Transactional
84 | public void delApi(Integer id, Integer apiPid) {
85 | //查询当前节点是否有子节点
86 | QueryWrapper queryWrapper = new QueryWrapper<>();
87 | queryWrapper.like("api_pids", "[" + id + "]");
88 | List sysMenuList = sysApiMapper.selectList(queryWrapper);
89 | if (sysMenuList.size() > 0) {
90 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "不能删除有下级菜单的菜单!");
91 | }
92 | setParentLeaf(apiPid);
93 | sysApiMapper.deleteById(id);
94 | }
95 |
96 | @Override
97 | public List getDefauleExpandedKeys() {
98 | //默认展开
99 | QueryWrapper queryWrapper = new QueryWrapper<>();
100 | queryWrapper.eq("level", 2);
101 | List sysMenuList = sysApiMapper.selectList(queryWrapper);
102 | return sysMenuList.stream().map(SysApi -> SysApi.getId()).collect(Collectors.toList());
103 | }
104 |
105 | @Override
106 | public List getDefaultCheckedKeys(Integer roleId) {
107 | QueryWrapper queryWrapper = new QueryWrapper<>();
108 | queryWrapper.eq("role_id", roleId);
109 | List sysRoleApiList = sysRoleApiMapper.selectList(queryWrapper);
110 | return sysRoleApiList.stream().map(SysRoleApi::getApiId).collect(Collectors.toList());
111 | }
112 |
113 | //设置它的父节点为叶子节点
114 | private void setParentLeaf(Integer menuPid) {
115 | //查询父节点有几个节点
116 | QueryWrapper queryWrapper = new QueryWrapper<>();
117 | queryWrapper.like("api_pids", "[" + menuPid + "]");
118 | List sysMenuList = sysApiMapper.selectList(queryWrapper);
119 | //如果只有它一下才设置
120 | if (sysMenuList.size() == 1) {
121 | SysApi parent = new SysApi();
122 | parent.setId(menuPid);
123 | parent.setLeaf(true);
124 | sysApiMapper.updateById(parent);
125 | }
126 | }
127 |
128 | @Override
129 | @Transactional
130 | public void saveApiPerm(Integer roleId, List menuIds) {
131 | //在添加之前需要先讲之前的权限删掉
132 | QueryWrapper queryWrapper = new QueryWrapper<>();
133 | queryWrapper.eq("role_id", roleId);
134 | sysRoleApiMapper.delete(queryWrapper);
135 | //添加
136 | sysRoleApiMapper.saveApiPerm(roleId, menuIds);
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/vue-manage-front/src/components/layout/TreeSelect.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
17 |
18 |
19 |
20 |
21 |
132 |
133 |
160 |
--------------------------------------------------------------------------------
/vue-manage-front/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | // new OptimizeCSSPlugin({
56 | // cssProcessorOptions: config.build.productionSourceMap
57 | // ? { safe: true, map: { inline: false } }
58 | // : { safe: true }
59 | // }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vendor modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------