feat(system): 实现基于Session的认证与菜单管理功能
- 菜单图标字段从icon改为vueIcon,适配前端图标组件 - 登录认证方式改为Session认证,使用FormData格式提交数据 - 验证码获取方式改为直接图片URL,防止缓存问题 - 权限验证改为基于Session的用户角色判断 - axios请求配置支持withCredentials,允许携带cookie - 部门管理新增树形结构构建方法 - 菜单管理新增路由地址、组件路径等字段 - 字典管理新增根据字典类型查询数据接口 - 系统配置新增根据配置键查询接口 - 首页控制器新增用户信息和路由信息获取接口- 菜单控制器新增菜单列表、详情、增删改查接口 - 数据库菜单表新增path、component、query、status、vue_icon、is_frame字段dev_1.0.0
parent
ffe6ce25df
commit
bbe760abf6
|
|
@ -1,21 +1,21 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 登录方法
|
||||
export function login(username, password, code, uuid) {
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
uuid
|
||||
}
|
||||
// 登录方法 - 基于 Session 认证,使用 FormData 格式
|
||||
export function login(username, password, code, rememberMe) {
|
||||
const formData = new FormData()
|
||||
formData.append('username', username)
|
||||
formData.append('password', password)
|
||||
formData.append('validateCode', code)
|
||||
formData.append('rememberMe', rememberMe || false)
|
||||
return request({
|
||||
url: '/login',
|
||||
headers: {
|
||||
isToken: false,
|
||||
'Content-Type': 'multipart/form-data',
|
||||
repeatSubmit: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -39,22 +39,10 @@ export function getInfo() {
|
|||
})
|
||||
}
|
||||
|
||||
// 退出方法
|
||||
// 退出方法 - 基于 Session 认证
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export function getCodeImg() {
|
||||
return request({
|
||||
url: '/captchaImage',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get',
|
||||
timeout: 20000
|
||||
})
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ import store from './store'
|
|||
import { Message } from 'element-ui'
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { isPathMatch } from '@/utils/validate'
|
||||
import { isRelogin } from '@/utils/request'
|
||||
|
||||
|
|
@ -17,43 +16,37 @@ const isWhiteList = (path) => {
|
|||
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start()
|
||||
if (getToken()) {
|
||||
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
|
||||
/* has token*/
|
||||
if (to.path === '/login') {
|
||||
next({ path: '/' })
|
||||
NProgress.done()
|
||||
} else if (isWhiteList(to.path)) {
|
||||
next()
|
||||
} else {
|
||||
if (store.getters.roles.length === 0) {
|
||||
isRelogin.show = true
|
||||
// 判断当前用户是否已拉取完user_info信息
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
isRelogin.show = false
|
||||
store.dispatch('GenerateRoutes').then(accessRoutes => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
})
|
||||
}).catch(err => {
|
||||
store.dispatch('LogOut').then(() => {
|
||||
Message.error(err)
|
||||
next({ path: '/' })
|
||||
})
|
||||
})
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
// 基于 Session 认证:通过是否有角色信息来判断登录状态
|
||||
const hasRoles = store.getters.roles && store.getters.roles.length > 0
|
||||
|
||||
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
|
||||
|
||||
if (isWhiteList(to.path)) {
|
||||
// 在免登录白名单,直接进入
|
||||
next()
|
||||
NProgress.done()
|
||||
} else {
|
||||
// 没有token
|
||||
if (isWhiteList(to.path)) {
|
||||
// 在免登录白名单,直接进入
|
||||
if (hasRoles) {
|
||||
// 已有用户信息,放行
|
||||
next()
|
||||
} else {
|
||||
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页
|
||||
NProgress.done()
|
||||
// 没有用户信息,尝试获取
|
||||
isRelogin.show = true
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
isRelogin.show = false
|
||||
store.dispatch('GenerateRoutes').then(accessRoutes => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
})
|
||||
}).catch(err => {
|
||||
// 获取用户信息失败,说明未登录或 Session 已过期
|
||||
store.dispatch('FedLogOut').then(() => {
|
||||
Message.error(err || '未登录或登录超时,请重新登录')
|
||||
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)
|
||||
NProgress.done()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import router from '@/router'
|
||||
import { MessageBox, } from 'element-ui'
|
||||
import { login, logout, getInfo } from '@/api/login'
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
import { isHttp, isEmpty } from "@/utils/validate"
|
||||
import defAva from '@/assets/images/profile.jpg'
|
||||
|
||||
const user = {
|
||||
state: {
|
||||
token: getToken(),
|
||||
id: '',
|
||||
name: '',
|
||||
nickName: '',
|
||||
|
|
@ -17,9 +15,6 @@ const user = {
|
|||
},
|
||||
|
||||
mutations: {
|
||||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
},
|
||||
SET_ID: (state, id) => {
|
||||
state.id = id
|
||||
},
|
||||
|
|
@ -41,16 +36,14 @@ const user = {
|
|||
},
|
||||
|
||||
actions: {
|
||||
// 登录
|
||||
// 登录 - 基于 Session 认证,不需要保存 token
|
||||
Login({ commit }, userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
const password = userInfo.password
|
||||
const code = userInfo.code
|
||||
const uuid = userInfo.uuid
|
||||
const rememberMe = userInfo.rememberMe
|
||||
return new Promise((resolve, reject) => {
|
||||
login(username, password, code, uuid).then(res => {
|
||||
setToken(res.token)
|
||||
commit('SET_TOKEN', res.token)
|
||||
login(username, password, code, rememberMe).then(res => {
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
|
|
@ -62,14 +55,16 @@ const user = {
|
|||
GetInfo({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getInfo().then(res => {
|
||||
const user = res.user
|
||||
// 后端返回的数据在 res.data 中
|
||||
const data = res.data || res
|
||||
const user = data.user
|
||||
let avatar = user.avatar || ""
|
||||
if (!isHttp(avatar)) {
|
||||
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
|
||||
}
|
||||
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
commit('SET_ROLES', res.roles)
|
||||
commit('SET_PERMISSIONS', res.permissions)
|
||||
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||
commit('SET_ROLES', data.roles)
|
||||
commit('SET_PERMISSIONS', data.permissions)
|
||||
} else {
|
||||
commit('SET_ROLES', ['ROLE_DEFAULT'])
|
||||
}
|
||||
|
|
@ -78,13 +73,13 @@ const user = {
|
|||
commit('SET_NICK_NAME', user.nickName)
|
||||
commit('SET_AVATAR', avatar)
|
||||
/* 初始密码提示 */
|
||||
if(res.isDefaultModifyPwd) {
|
||||
if(data.isDefaultModifyPwd) {
|
||||
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||
}).catch(() => {})
|
||||
}
|
||||
/* 过期密码提示 */
|
||||
if(!res.isDefaultModifyPwd && res.isPasswordExpired) {
|
||||
if(!data.isDefaultModifyPwd && data.isPasswordExpired) {
|
||||
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||
}).catch(() => {})
|
||||
|
|
@ -96,14 +91,12 @@ const user = {
|
|||
})
|
||||
},
|
||||
|
||||
// 退出系统
|
||||
// 退出系统 - 基于 Session 认证
|
||||
LogOut({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout(state.token).then(() => {
|
||||
commit('SET_TOKEN', '')
|
||||
logout().then(() => {
|
||||
commit('SET_ROLES', [])
|
||||
commit('SET_PERMISSIONS', [])
|
||||
removeToken()
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
|
|
@ -111,11 +104,11 @@ const user = {
|
|||
})
|
||||
},
|
||||
|
||||
// 前端 登出
|
||||
// 前端 登出 - 清除状态
|
||||
FedLogOut({ commit }) {
|
||||
return new Promise(resolve => {
|
||||
commit('SET_TOKEN', '')
|
||||
removeToken()
|
||||
commit('SET_ROLES', [])
|
||||
commit('SET_PERMISSIONS', [])
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import axios from 'axios'
|
||||
import { Notification, MessageBox, Message, Loading } from 'element-ui'
|
||||
import store from '@/store'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import errorCode from '@/utils/errorCode'
|
||||
import { tansParams, blobValidate } from "@/utils/ruoyi"
|
||||
import cache from '@/plugins/cache'
|
||||
|
|
@ -17,18 +16,17 @@ const service = axios.create({
|
|||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL: process.env.VUE_APP_BASE_API,
|
||||
// 超时
|
||||
timeout: 10000
|
||||
timeout: 10000,
|
||||
// 允许携带cookie(Session认证必需)
|
||||
withCredentials: true
|
||||
})
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(config => {
|
||||
// 是否需要设置 token
|
||||
const isToken = (config.headers || {}).isToken === false
|
||||
// 是否需要防止数据重复提交
|
||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
|
||||
if (getToken() && !isToken) {
|
||||
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
}
|
||||
config.headers['X-Requested-With'] = 'H5'
|
||||
// Session 认证依赖 Cookie,无需手动设置 token
|
||||
// get请求映射params参数
|
||||
if (config.method === 'get' && config.params) {
|
||||
let url = config.url + '?' + tansParams(config.params)
|
||||
|
|
@ -39,7 +37,7 @@ service.interceptors.request.use(config => {
|
|||
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
|
||||
const requestObj = {
|
||||
url: config.url,
|
||||
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
|
||||
data: (typeof config.data === 'object' && !(config.data instanceof FormData)) ? JSON.stringify(config.data) : config.data,
|
||||
time: new Date().getTime()
|
||||
}
|
||||
const requestSize = Object.keys(JSON.stringify(requestObj)).length // 请求数据大小
|
||||
|
|
@ -79,7 +77,7 @@ service.interceptors.response.use(res => {
|
|||
const msg = errorCode[code] || res.data.msg || errorCode['default']
|
||||
// 二进制数据则直接返回
|
||||
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
|
||||
return res.data
|
||||
return res
|
||||
}
|
||||
if (code === 401) {
|
||||
if (!isRelogin.show) {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getCodeImg } from "@/api/login"
|
||||
import Cookies from "js-cookie"
|
||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
||||
|
||||
|
|
@ -74,10 +73,9 @@ export default {
|
|||
codeUrl: "",
|
||||
loginForm: {
|
||||
username: "admin",
|
||||
password: "admin123",
|
||||
password: "admin@123",
|
||||
rememberMe: false,
|
||||
code: "",
|
||||
uuid: ""
|
||||
code: ""
|
||||
},
|
||||
loginRules: {
|
||||
username: [
|
||||
|
|
@ -110,13 +108,10 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
getCode() {
|
||||
getCodeImg().then(res => {
|
||||
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled
|
||||
if (this.captchaEnabled) {
|
||||
this.codeUrl = "data:image/gif;base64," + res.img
|
||||
this.loginForm.uuid = res.uuid
|
||||
}
|
||||
})
|
||||
// 基于 Session 认证,直接使用图片 URL,添加时间戳防止缓存
|
||||
const timestamp = new Date().getTime()
|
||||
this.codeUrl = `${process.env.VUE_APP_BASE_API}/captcha/captchaImage?type=math&s=${timestamp}`
|
||||
this.captchaEnabled = true
|
||||
},
|
||||
getCookie() {
|
||||
const username = Cookies.get("username")
|
||||
|
|
|
|||
|
|
@ -57,9 +57,9 @@
|
|||
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
|
||||
>
|
||||
<el-table-column prop="menuName" label="菜单名称" :show-overflow-tooltip="true" width="160"></el-table-column>
|
||||
<el-table-column prop="icon" label="图标" align="center" width="100">
|
||||
<el-table-column prop="vueIcon" label="图标" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<svg-icon :icon-class="scope.row.icon" />
|
||||
<svg-icon :icon-class="scope.row.vueIcon" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
|
||||
|
|
@ -131,19 +131,19 @@
|
|||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12" v-if="form.menuType != 'F'">
|
||||
<el-form-item label="菜单图标" prop="icon">
|
||||
<el-form-item label="菜单图标" prop="vueIcon">
|
||||
<el-popover
|
||||
placement="bottom-start"
|
||||
width="460"
|
||||
trigger="click"
|
||||
@show="$refs['iconSelect'].reset()"
|
||||
>
|
||||
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.icon" />
|
||||
<el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
|
||||
<IconSelect ref="iconSelect" @selected="selected" :active-icon="form.vueIcon" />
|
||||
<el-input slot="reference" v-model="form.vueIcon" placeholder="点击选择图标" readonly>
|
||||
<svg-icon
|
||||
v-if="form.icon"
|
||||
v-if="form.vueIcon"
|
||||
slot="prefix"
|
||||
:icon-class="form.icon"
|
||||
:icon-class="form.vueIcon"
|
||||
style="width: 25px;"
|
||||
/>
|
||||
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
|
||||
|
|
@ -353,7 +353,7 @@ export default {
|
|||
methods: {
|
||||
// 选择图标
|
||||
selected(name) {
|
||||
this.form.icon = name
|
||||
this.form.vueIcon = name
|
||||
},
|
||||
/** 查询菜单列表 */
|
||||
getList() {
|
||||
|
|
|
|||
|
|
@ -555,4 +555,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
|
|||
|
||||
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
|
||||
|
||||
const baseUrl = 'http://localhost:8080' // 后端接口
|
||||
const baseUrl = 'http://localhost:28080' // 后端接口
|
||||
|
||||
const port = process.env.port || process.env.npm_config_port || 80 // 端口
|
||||
|
||||
|
|
@ -38,6 +38,10 @@ module.exports = {
|
|||
[process.env.VUE_APP_BASE_API]: {
|
||||
target: baseUrl,
|
||||
changeOrigin: true,
|
||||
// Session 认证需要携带 Cookie
|
||||
cookieDomainRewrite: {
|
||||
'*': ''
|
||||
},
|
||||
pathRewrite: {
|
||||
['^' + process.env.VUE_APP_BASE_API]: ''
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import javax.servlet.ServletOutputStream;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
|
@ -48,6 +50,7 @@ public class SysCaptchaController extends BaseController
|
|||
response.setContentType("image/jpeg");
|
||||
|
||||
String type = request.getParameter("type");
|
||||
type = StringUtils.isEmpty(type) ? "math" : type;
|
||||
String capStr = null;
|
||||
String code = null;
|
||||
BufferedImage bi = null;
|
||||
|
|
|
|||
|
|
@ -155,4 +155,11 @@ public class SysConfigController extends BaseController
|
|||
{
|
||||
return configService.checkConfigKeyUnique(config);
|
||||
}
|
||||
@GetMapping("/configKey/{key}")
|
||||
@ResponseBody
|
||||
public AjaxResult queryKey(@PathVariable("key") String key)
|
||||
{
|
||||
return success(configService.selectConfigByKey(key));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
|
@ -33,7 +37,8 @@ public class SysDictDataController extends BaseController
|
|||
|
||||
@Autowired
|
||||
private ISysDictDataService dictDataService;
|
||||
|
||||
@Autowired
|
||||
private ISysDictTypeService dictTypeService;
|
||||
@RequiresPermissions("system:dict:view")
|
||||
@GetMapping()
|
||||
public String dictData()
|
||||
|
|
@ -72,6 +77,22 @@ public class SysDictDataController extends BaseController
|
|||
mmap.put("dictType", dictType);
|
||||
return prefix + "/add";
|
||||
}
|
||||
/**
|
||||
* 新增字典类型
|
||||
*/
|
||||
|
||||
@GetMapping("/type/{dictType}")
|
||||
@ResponseBody
|
||||
public AjaxResult add(@PathVariable("dictType") String dictType)
|
||||
{
|
||||
|
||||
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
|
||||
if (StringUtils.isNull(data))
|
||||
{
|
||||
data = new ArrayList<SysDictData>();
|
||||
}
|
||||
return success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增保存字典类型
|
||||
|
|
|
|||
|
|
@ -1,21 +1,11 @@
|
|||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.config.RuoYiConfig;
|
||||
import com.ruoyi.common.constant.ShiroConstants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.text.Convert;
|
||||
import com.ruoyi.common.utils.CookieUtils;
|
||||
|
|
@ -25,6 +15,18 @@ import com.ruoyi.common.utils.StringUtils;
|
|||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.system.service.ISysMenuService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 首页 业务处理
|
||||
|
|
@ -39,7 +41,6 @@ public class SysIndexController extends BaseController
|
|||
|
||||
@Autowired
|
||||
private ISysConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private SysPasswordService passwordService;
|
||||
@GetMapping("/test")
|
||||
|
|
@ -178,4 +179,164 @@ public class SysIndexController extends BaseController
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息(供前后端分离的前端调用)
|
||||
*
|
||||
* @return 用户信息、角色、权限
|
||||
*/
|
||||
@GetMapping("/getInfo")
|
||||
@ResponseBody
|
||||
public AjaxResult getInfo()
|
||||
{
|
||||
SysUser user = getSysUser();
|
||||
if (StringUtils.isNull(user))
|
||||
{
|
||||
return AjaxResult.error("未登录或登录超时");
|
||||
}
|
||||
// 角色集合
|
||||
Set<String> roles = user.getRoles().stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
|
||||
// 权限集合
|
||||
Set<String> permissions = menuService.selectPermsByUserId(user.getUserId());
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("user", user);
|
||||
data.put("roles", roles);
|
||||
data.put("permissions", permissions);
|
||||
data.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
|
||||
data.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
|
||||
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由信息(供前后端分离的前端调用)
|
||||
*
|
||||
* @return 路由信息
|
||||
*/
|
||||
@GetMapping("/getRouters")
|
||||
@ResponseBody
|
||||
public AjaxResult getRouters()
|
||||
{
|
||||
SysUser user = getSysUser();
|
||||
if (StringUtils.isNull(user))
|
||||
{
|
||||
return AjaxResult.error("未登录或登录超时");
|
||||
}
|
||||
|
||||
List<SysMenu> menus = menuService.selectMenusByUser(user);
|
||||
List<Map<String, Object>> routerList = buildRouters(menus);
|
||||
return AjaxResult.success(routerList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建前端路由所需格式(简化版,使用现有字段)
|
||||
*/
|
||||
private List<Map<String, Object>> buildRouters(List<SysMenu> menus)
|
||||
{
|
||||
List<Map<String, Object>> routers = new ArrayList<>();
|
||||
for (SysMenu menu : menus)
|
||||
{
|
||||
Map<String, Object> router = new HashMap<>();
|
||||
|
||||
// 基本属性
|
||||
router.put("name", getRouteName(menu));
|
||||
router.put("path", getRouterPath(menu));
|
||||
router.put("hidden", "1".equals(menu.getVisible()));
|
||||
router.put("component", getComponent(menu));
|
||||
|
||||
// 路由元信息
|
||||
router.put("meta", buildMeta(menu));
|
||||
|
||||
// 子路由
|
||||
List<SysMenu> cMenus = menu.getChildren();
|
||||
if (cMenus != null && !cMenus.isEmpty())
|
||||
{
|
||||
router.put("alwaysShow", true);
|
||||
router.put("redirect", "noRedirect");
|
||||
router.put("children", buildRouters(cMenus));
|
||||
}
|
||||
|
||||
routers.add(router);
|
||||
}
|
||||
return routers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建路由元信息
|
||||
*/
|
||||
private Map<String, Object> buildMeta(SysMenu menu)
|
||||
{
|
||||
Map<String, Object> meta = new HashMap<>();
|
||||
meta.put("title", menu.getMenuName());
|
||||
meta.put("icon", menu.getVueIcon());
|
||||
meta.put("noCache", "1".equals(menu.getIsRefresh()));
|
||||
return meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由名称
|
||||
*/
|
||||
private String getRouteName(SysMenu menu)
|
||||
{
|
||||
// 使用 path 字段作为路由名称,如果没有则使用 menuName
|
||||
String routerName = menu.getPath();
|
||||
if (StringUtils.isEmpty(routerName))
|
||||
{
|
||||
routerName = menu.getMenuName();
|
||||
}
|
||||
// 首字母大写
|
||||
return StringUtils.isNotEmpty(routerName) ? StringUtils.capitalize(routerName) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由地址
|
||||
*/
|
||||
private String getRouterPath(SysMenu menu)
|
||||
{
|
||||
// 优先使用 path 字段,如果没有则使用 url 字段
|
||||
String routerPath = menu.getPath();
|
||||
if (StringUtils.isEmpty(routerPath))
|
||||
{
|
||||
routerPath = menu.getUrl();
|
||||
}
|
||||
|
||||
// 一级目录需要加 /
|
||||
if (menu.getParentId() == 0 && "M".equals(menu.getMenuType()))
|
||||
{
|
||||
if (!routerPath.startsWith("/"))
|
||||
{
|
||||
routerPath = "/" + routerPath;
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.isNotEmpty(routerPath) ? routerPath : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件信息
|
||||
*/
|
||||
private String getComponent(SysMenu menu)
|
||||
{
|
||||
// 目录使用 Layout
|
||||
if ("M".equals(menu.getMenuType()))
|
||||
{
|
||||
if (menu.getParentId() == 0)
|
||||
{
|
||||
return "Layout";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "ParentView";
|
||||
}
|
||||
}
|
||||
// 菜单使用 url 字段作为组件路径
|
||||
else if ("C".equals(menu.getMenuType()))
|
||||
{
|
||||
String component = menu.getComponent();
|
||||
return StringUtils.isNotEmpty(component) ? component : menu.getPath();
|
||||
}
|
||||
|
||||
return "Layout";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
|
|
@ -52,6 +48,15 @@ public class SysMenuController extends BaseController
|
|||
List<SysMenu> menuList = menuService.selectMenuList(menu, userId);
|
||||
return menuList;
|
||||
}
|
||||
@RequiresPermissions("system:menu:list")
|
||||
@GetMapping("/list")
|
||||
@ResponseBody
|
||||
public AjaxResult listMenu(SysMenu menu)
|
||||
{
|
||||
Long userId = ShiroUtils.getUserId();
|
||||
List<SysMenu> menuList = menuService.selectMenuList(menu, userId);
|
||||
return AjaxResult.success(menuList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除菜单
|
||||
|
|
@ -73,6 +78,23 @@ public class SysMenuController extends BaseController
|
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||
return toAjax(menuService.deleteMenuById(menuId));
|
||||
}
|
||||
@Log(title = "菜单管理", businessType = BusinessType.DELETE)
|
||||
@RequiresPermissions("system:menu:remove")
|
||||
@DeleteMapping("/{menuId}")
|
||||
@ResponseBody
|
||||
public AjaxResult delete(@PathVariable("menuId") Long menuId)
|
||||
{
|
||||
if (menuService.selectCountMenuByParentId(menuId) > 0)
|
||||
{
|
||||
return AjaxResult.warn("存在子菜单,不允许删除");
|
||||
}
|
||||
if (menuService.selectCountRoleMenuByMenuId(menuId) > 0)
|
||||
{
|
||||
return AjaxResult.warn("菜单已分配,不允许删除");
|
||||
}
|
||||
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||
return toAjax(menuService.deleteMenuById(menuId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
|
|
@ -113,6 +135,20 @@ public class SysMenuController extends BaseController
|
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||
return toAjax(menuService.insertMenu(menu));
|
||||
}
|
||||
@Log(title = "菜单管理", businessType = BusinessType.INSERT)
|
||||
@RequiresPermissions("system:menu:add")
|
||||
@PostMapping()
|
||||
@ResponseBody
|
||||
public AjaxResult insert(@RequestBody @Validated SysMenu menu)
|
||||
{
|
||||
if (!menuService.checkMenuNameUnique(menu))
|
||||
{
|
||||
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
menu.setCreateBy(getLoginName());
|
||||
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||
return toAjax(menuService.insertMenu(menu));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改菜单
|
||||
|
|
@ -124,6 +160,30 @@ public class SysMenuController extends BaseController
|
|||
mmap.put("menu", menuService.selectMenuById(menuId));
|
||||
return prefix + "/edit";
|
||||
}
|
||||
@RequiresPermissions("system:menu:edit")
|
||||
@GetMapping("/{menuId}")
|
||||
@ResponseBody
|
||||
public AjaxResult query(@PathVariable("menuId") Long menuId)
|
||||
{
|
||||
|
||||
return AjaxResult.success(menuService.selectMenuById(menuId));
|
||||
}
|
||||
@Log(title = "菜单管理", businessType = BusinessType.UPDATE)
|
||||
@RequiresPermissions("system:menu:edit")
|
||||
@PutMapping()
|
||||
@ResponseBody
|
||||
public AjaxResult edit(@RequestBody @Validated SysMenu menu)
|
||||
{
|
||||
|
||||
if (!menuService.checkMenuNameUnique(menu))
|
||||
{
|
||||
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
|
||||
}
|
||||
menu.setUpdateBy(getLoginName());
|
||||
AuthorizationUtils.clearAllCachedAuthorizationInfo();
|
||||
return toAjax(menuService.updateMenu(menu));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改保存菜单
|
||||
|
|
@ -195,4 +255,17 @@ public class SysMenuController extends BaseController
|
|||
mmap.put("menu", menuService.selectMenuById(menuId));
|
||||
return prefix + "/tree";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取路由信息
|
||||
*
|
||||
* @return 路由信息
|
||||
*/
|
||||
@GetMapping("/getRouters")
|
||||
@ResponseBody
|
||||
public AjaxResult getRouters()
|
||||
{
|
||||
List<SysMenu> menus = menuService.selectMenusByUser(getSysUser());
|
||||
return AjaxResult.success(menus);
|
||||
}
|
||||
}
|
||||
|
|
@ -363,4 +363,31 @@ public class SysUserController extends BaseController
|
|||
mmap.put("dept", value==null?new SysDept():value);
|
||||
return prefix + "/deptTree";
|
||||
}
|
||||
|
||||
|
||||
// ----------------------VUE页面使用---------------------------
|
||||
@RequiresPermissions("system:user:list")
|
||||
@GetMapping("/list")
|
||||
@ResponseBody
|
||||
public TableDataInfo listPage(SysUser user) {
|
||||
startPage();
|
||||
List<SysUser> list = userService.selectUserList(user);
|
||||
return getDataTable(list);
|
||||
}
|
||||
@RequiresPermissions("system:user:list")
|
||||
@GetMapping("/{userId}")
|
||||
@ResponseBody
|
||||
public AjaxResult query(@PathVariable("userId") Long userId) {
|
||||
return success(userService.selectUserById(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门树列表
|
||||
*/
|
||||
@RequiresPermissions("system:user:list")
|
||||
@GetMapping("/deptTree")
|
||||
@ResponseBody
|
||||
public AjaxResult deptTree(SysDept dept) {
|
||||
return success(deptService.selectDeptTreeList(dept));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.ruoyi.common.core.domain;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.ruoyi.common.constant.UserConstants;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Treeselect树结构实体类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class TreeSelect implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 节点ID */
|
||||
private Long id;
|
||||
|
||||
/** 节点名称 */
|
||||
private String label;
|
||||
|
||||
/** 节点禁用 */
|
||||
private boolean disabled = false;
|
||||
|
||||
/** 子节点 */
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private List<TreeSelect> children;
|
||||
|
||||
public TreeSelect()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public TreeSelect(SysDept dept)
|
||||
{
|
||||
this.id = dept.getDeptId();
|
||||
this.label = dept.getDeptName();
|
||||
this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
|
||||
this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public TreeSelect(SysMenu menu)
|
||||
{
|
||||
this.id = menu.getMenuId();
|
||||
this.label = menu.getMenuName();
|
||||
this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label)
|
||||
{
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public boolean isDisabled()
|
||||
{
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled)
|
||||
{
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
public List<TreeSelect> getChildren()
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<TreeSelect> children)
|
||||
{
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,9 @@ import org.apache.commons.lang3.builder.ToStringStyle;
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门表 sys_dept
|
||||
*
|
||||
|
|
@ -53,7 +56,8 @@ public class SysDept extends BaseEntity
|
|||
|
||||
/** 排除编号 */
|
||||
private Long excludeId;
|
||||
|
||||
/** 子部门 */
|
||||
private List<SysDept> children = new ArrayList<SysDept>();
|
||||
public Long getDeptId()
|
||||
{
|
||||
return deptId;
|
||||
|
|
@ -181,6 +185,14 @@ public class SysDept extends BaseEntity
|
|||
this.excludeId = excludeId;
|
||||
}
|
||||
|
||||
public List<SysDept> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<SysDept> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package com.ruoyi.common.core.domain.entity;
|
|||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
|
@ -12,6 +15,7 @@ import com.ruoyi.common.core.domain.BaseEntity;
|
|||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@ToString
|
||||
public class SysMenu extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
@ -52,6 +56,23 @@ public class SysMenu extends BaseEntity
|
|||
/** 菜单图标 */
|
||||
private String icon;
|
||||
|
||||
/** 路由地址 */
|
||||
private String path;
|
||||
|
||||
|
||||
/** 组件路径 */
|
||||
private String component;
|
||||
|
||||
/** 路由参数 */
|
||||
private String query;
|
||||
|
||||
/** 是否为外链(0是 1否) */
|
||||
private String isFrame;
|
||||
|
||||
/** 菜单状态(0正常 1停用) */
|
||||
private String status;
|
||||
/** 菜单图标 */
|
||||
private String vueIcon;
|
||||
/** 子菜单 */
|
||||
private List<SysMenu> children = new ArrayList<SysMenu>();
|
||||
|
||||
|
|
@ -181,6 +202,59 @@ public class SysMenu extends BaseEntity
|
|||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
|
||||
public String getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(String component) {
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public String getIsFrame() {
|
||||
return isFrame;
|
||||
}
|
||||
|
||||
public void setIsFrame(String isFrame) {
|
||||
this.isFrame = isFrame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getVueIcon() {
|
||||
return vueIcon;
|
||||
}
|
||||
|
||||
public void setVueIcon(String vueIcon) {
|
||||
this.vueIcon = vueIcon;
|
||||
}
|
||||
|
||||
public List<SysMenu> getChildren()
|
||||
{
|
||||
return children;
|
||||
|
|
@ -191,24 +265,5 @@ public class SysMenu extends BaseEntity
|
|||
this.children = children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("menuId", getMenuId())
|
||||
.append("menuName", getMenuName())
|
||||
.append("parentId", getParentId())
|
||||
.append("orderNum", getOrderNum())
|
||||
.append("url", getUrl())
|
||||
.append("target", getTarget())
|
||||
.append("menuType", getMenuType())
|
||||
.append("visible", getVisible())
|
||||
.append("perms", getPerms())
|
||||
.append("icon", getIcon())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("remark", getRemark())
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.ruoyi.system.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.ruoyi.common.core.domain.TreeSelect;
|
||||
import com.ruoyi.common.core.domain.Ztree;
|
||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
|
|
@ -114,4 +116,19 @@ public interface ISysDeptService
|
|||
* @param deptId 部门id
|
||||
*/
|
||||
public void checkDeptDataScope(Long deptId);
|
||||
/**
|
||||
* 构建前端所需要树结构
|
||||
*
|
||||
* @param depts 部门列表
|
||||
* @return 树结构列表
|
||||
*/
|
||||
public List<SysDept> buildDeptTree(List<SysDept> depts);
|
||||
/**
|
||||
* 构建前端所需要下拉树结构
|
||||
*
|
||||
* @param depts 部门列表
|
||||
* @return 下拉树结构列表
|
||||
*/
|
||||
public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts);
|
||||
List<TreeSelect> selectDeptTreeList(SysDept dept);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
package com.ruoyi.system.service.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.ruoyi.common.core.domain.TreeSelect;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -325,4 +330,89 @@ public class SysDeptServiceImpl implements ISysDeptService
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TreeSelect> selectDeptTreeList(SysDept dept) {
|
||||
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
|
||||
return buildDeptTreeSelect(depts);
|
||||
}
|
||||
/**
|
||||
* 构建前端所需要下拉树结构
|
||||
*
|
||||
* @param depts 部门列表
|
||||
* @return 下拉树结构列表
|
||||
*/
|
||||
@Override
|
||||
public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts)
|
||||
{
|
||||
List<SysDept> deptTrees = buildDeptTree(depts);
|
||||
return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
|
||||
}
|
||||
/**
|
||||
* 构建前端所需要树结构
|
||||
*
|
||||
* @param depts 部门列表
|
||||
* @return 树结构列表
|
||||
*/
|
||||
@Override
|
||||
public List<SysDept> buildDeptTree(List<SysDept> depts)
|
||||
{
|
||||
List<SysDept> returnList = new ArrayList<SysDept>();
|
||||
List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
|
||||
for (SysDept dept : depts)
|
||||
{
|
||||
// 如果是顶级节点, 遍历该父节点的所有子节点
|
||||
if (!tempList.contains(dept.getParentId()))
|
||||
{
|
||||
recursionFn(depts, dept);
|
||||
returnList.add(dept);
|
||||
}
|
||||
}
|
||||
if (returnList.isEmpty())
|
||||
{
|
||||
returnList = depts;
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
/**
|
||||
* 递归列表
|
||||
*/
|
||||
private void recursionFn(List<SysDept> list, SysDept t)
|
||||
{
|
||||
// 得到子节点列表
|
||||
List<SysDept> childList = getChildList(list, t);
|
||||
t.setChildren(childList);
|
||||
for (SysDept tChild : childList)
|
||||
{
|
||||
if (hasChild(list, tChild))
|
||||
{
|
||||
recursionFn(list, tChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 得到子节点列表
|
||||
*/
|
||||
private List<SysDept> getChildList(List<SysDept> list, SysDept t)
|
||||
{
|
||||
List<SysDept> tlist = new ArrayList<SysDept>();
|
||||
Iterator<SysDept> it = list.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
SysDept n = (SysDept) it.next();
|
||||
if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
|
||||
{
|
||||
tlist.add(n);
|
||||
}
|
||||
}
|
||||
return tlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有子节点
|
||||
*/
|
||||
private boolean hasChild(List<SysDept> list, SysDept t)
|
||||
{
|
||||
return getChildList(list, t).size() > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ public class SysMenuServiceImpl implements ISysMenuService
|
|||
permsSet.addAll(Arrays.asList(perm.trim().split(",")));
|
||||
}
|
||||
}
|
||||
if (userId==1){
|
||||
permsSet.add("*:*:*");
|
||||
}
|
||||
return permsSet;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
</resultMap>
|
||||
|
||||
<sql id="selectMenuVo">
|
||||
select menu_id, menu_name, parent_id, order_num, url, target, menu_type, visible, is_refresh, ifnull(perms,'') as perms, icon, create_by, create_time
|
||||
select menu_id, menu_name, parent_id, order_num, url, target, menu_type, visible, is_refresh, ifnull(perms,'') as perms, icon, create_by, create_time ,path,component,query,status,vue_icon,is_frame
|
||||
from sys_menu
|
||||
</sql>
|
||||
|
||||
<select id="selectMenusByUserId" parameterType="Long" resultMap="SysMenuResult">
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name,m.path,m.component,m.query,m.status,m.vue_icon,m.is_frame, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
</select>
|
||||
|
||||
<select id="selectMenuNormalAll" resultMap="SysMenuResult">
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible,m.path,m.component,m.query,m.status,m.vue_icon,m.is_frame, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
from sys_menu m
|
||||
where m.menu_type in ('M', 'C') and m.visible = 0
|
||||
order by m.parent_id, m.order_num
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
</select>
|
||||
|
||||
<select id="selectMenuAllByUserId" parameterType="Long" resultMap="SysMenuResult">
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible,m.path,m.component,m.query,m.status,m.vue_icon,m.is_frame, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
</select>
|
||||
|
||||
<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
|
||||
select distinct m.menu_id, m.parent_id, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
select distinct m.menu_id, m.parent_id,m.path,m.component,m.query,m.status,m.vue_icon,m.is_frame, m.menu_name, m.url, m.visible, m.is_refresh, ifnull(m.perms,'') as perms, m.target, m.menu_type, m.icon, m.order_num, m.create_time
|
||||
from sys_menu m
|
||||
left join sys_role_menu rm on m.menu_id = rm.menu_id
|
||||
left join sys_user_role ur on rm.role_id = ur.role_id
|
||||
|
|
@ -119,7 +119,7 @@
|
|||
</delete>
|
||||
|
||||
<select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
|
||||
SELECT t.menu_id, t.parent_id, t.menu_name, t.order_num, t.url, t.target, t.menu_type, t.visible, t.is_refresh, t.perms, t.icon, t.remark,
|
||||
SELECT t.menu_id, t.parent_id, t.menu_name, t.order_num, t.url, t.target, t.menu_type, t.visible, t.is_refresh, t.perms, t.icon, t.remark,t.path,t.component,t.query,t.status,t.vue_icon,t.is_frame,
|
||||
(SELECT menu_name FROM sys_menu WHERE menu_id = t.parent_id) parent_name
|
||||
FROM sys_menu t
|
||||
where t.menu_id = #{menuId}
|
||||
|
|
@ -149,6 +149,12 @@
|
|||
<if test="icon !=null and icon != ''">icon = #{icon},</if>
|
||||
<if test="remark != null">remark = #{remark},</if>
|
||||
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
|
||||
<if test="path != null and path != ''">path = #{path},</if>
|
||||
<if test="component != null and component != ''">component = #{component},</if>
|
||||
<if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
|
||||
<if test="query != null and query != ''">query = #{query},</if>
|
||||
<if test="status != null and status != ''">status = #{status},</if>
|
||||
<if test="vueIcon != null and vueIcon != ''">vue_icon = #{vueIcon},</if>
|
||||
update_time = sysdate()
|
||||
</set>
|
||||
where menu_id = #{menuId}
|
||||
|
|
@ -169,6 +175,12 @@
|
|||
<if test="icon != null and icon != ''">icon,</if>
|
||||
<if test="remark != null and remark != ''">remark,</if>
|
||||
<if test="createBy != null and createBy != ''">create_by,</if>
|
||||
<if test="path != null and path != ''">path ,</if>
|
||||
<if test="component != null and component != ''">component ,</if>
|
||||
<if test="isFrame != null and isFrame != ''">is_frame,</if>
|
||||
<if test="query != null and query != ''">query ,</if>
|
||||
<if test="status != null and status != ''">status ,</if>
|
||||
<if test="vueIcon != null and vueIcon != ''">vue_icon,</if>
|
||||
create_time
|
||||
)values(
|
||||
<if test="menuId != null and menuId != 0">#{menuId},</if>
|
||||
|
|
@ -184,6 +196,12 @@
|
|||
<if test="icon != null and icon != ''">#{icon},</if>
|
||||
<if test="remark != null and remark != ''">#{remark},</if>
|
||||
<if test="createBy != null and createBy != ''">#{createBy},</if>
|
||||
<if test="path != null and path != ''"> #{path},</if>
|
||||
<if test="component != null and component != ''">#{component},</if>
|
||||
<if test="isFrame != null and isFrame != ''"> #{isFrame},</if>
|
||||
<if test="query != null and query != ''">#{query},</if>
|
||||
<if test="status != null and status != ''">#{status},</if>
|
||||
<if test="vueIcon != null and vueIcon != ''"> #{vueIcon},</if>
|
||||
sysdate()
|
||||
)
|
||||
</insert>
|
||||
|
|
|
|||
Loading…
Reference in New Issue