Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
jinli gu
Springboot Plus
Commits
875339d5
"src/main/webapp/vscode:/vscode.git/clone" did not exist on "de1c2d2f39a07f97e923422365a772781ddd53d3"
Commit
875339d5
authored
Jun 14, 2020
by
trumansdo
Browse files
补完菜单项管理
parent
fbc2862e
Changes
20
Hide whitespace changes
Inline
Side-by-side
plus-admin/admin-console/pom.xml
View file @
875339d5
...
...
@@ -29,4 +29,15 @@
<artifactId>
spring-boot-starter-log4j2
</artifactId>
</dependency>
</dependencies>
</project>
<build>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<configuration>
<classifier>
exec
</classifier>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
plus-admin/admin-console/src/main/java/com/ibeetl/admin/console/dao/MenuConsoleDao.java
View file @
875339d5
package
com.ibeetl.admin.console.dao
;
import
java.util.List
;
import
org.beetl.sql.core.annotatoin.SqlResource
;
import
org.beetl.sql.core.engine.PageQuery
;
import
org.beetl.sql.core.mapper.BaseMapper
;
...
...
@@ -15,4 +16,6 @@ public interface MenuConsoleDao extends BaseMapper<CoreMenu> {
* @param query 查询条件
*/
void
queryByCondtion
(
PageQuery
query
);
List
<
CoreMenu
>
selectMenuAndRelationFunction
();
}
plus-admin/admin-console/src/main/java/com/ibeetl/admin/console/service/FunctionConsoleService.java
View file @
875339d5
package
com.ibeetl.admin.console.service
;
import
static
com
.
ibeetl
.
admin
.
core
.
service
.
CorePlatformService
.
FUNCTION_TREE_CACHE
;
import
cn.hutool.core.collection.CollUtil
;
import
com.ibeetl.admin.console.dao.FunctionConsoleDao
;
import
com.ibeetl.admin.console.dao.RoleFunctionConsoleDao
;
...
...
@@ -24,6 +26,7 @@ import java.util.stream.Collectors;
import
javax.validation.constraints.NotNull
;
import
org.beetl.sql.core.engine.PageQuery
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
...
...
@@ -52,13 +55,13 @@ public class FunctionConsoleService extends CoreBaseService<CoreFunction> {
/**
* @return 返回功能点构成的树结构
*/
@Cacheable
(
FUNCTION_TREE_CACHE
)
public
List
<
CoreFunction
>
getFuncTree
()
{
List
<
CoreFunction
>
coreFunctionList
=
functionConsoleDao
.
getSQLManager
()
.
lambdaQuery
(
CoreFunction
.
class
)
.
andEq
(
CoreFunction:
:
getDelFlag
,
DelFlagEnum
.
NORMAL
).
select
();
System
.
out
.
println
(
coreFunctionList
);
CoreFunction
root
=
new
CoreFunction
();
root
.
setId
(-
1L
);
...
...
plus-admin/admin-console/src/main/java/com/ibeetl/admin/console/service/MenuConsoleService.java
View file @
875339d5
package
com.ibeetl.admin.console.service
;
import
static
com
.
ibeetl
.
admin
.
core
.
service
.
CorePlatformService
.
MENU_FUNC_TREE_CACHE
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.ibeetl.admin.console.dao.MenuConsoleDao
;
import
com.ibeetl.admin.core.dao.CoreRoleMenuDao
;
import
com.ibeetl.admin.core.entity.CoreMenu
;
...
...
@@ -7,46 +11,59 @@ import com.ibeetl.admin.core.rbac.tree.MenuItem;
import
com.ibeetl.admin.core.service.CoreBaseService
;
import
com.ibeetl.admin.core.service.CorePlatformService
;
import
com.ibeetl.admin.core.util.PlatformException
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
javax.validation.constraints.NotNull
;
import
org.beetl.sql.core.engine.PageQuery
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.ArrayList
;
import
java.util.List
;
@Service
@Transactional
public
class
MenuConsoleService
extends
CoreBaseService
<
CoreMenu
>
{
@Autowired
MenuConsoleDao
menuDao
;
@Autowired
CoreRoleMenuDao
roleM
enuDao
;
@Autowired
MenuConsoleDao
m
enuDao
;
@Autowired
CorePlatformService
platformService
;
@Autowired
CoreRoleMenuDao
roleMenuDao
;
@Autowired
CorePlatformService
platformService
;
public
void
queryByCondtion
(
PageQuery
<
CoreMenu
>
query
)
{
menuDao
.
queryByCondtion
(
query
);
queryListAfter
(
query
.
getList
());
}
public
Long
saveMenu
(
CoreMenu
menu
)
{
CoreMenu
query
=
new
CoreMenu
();
query
.
setCode
(
menu
.
getCode
());
long
queryCount
=
menuDao
.
templateCount
(
query
);
if
(
queryCount
>
0
)
{
throw
new
PlatformException
(
"菜单编码已存在"
);
}
menu
.
setCreateTime
(
new
Date
());
menu
.
setParentMenuId
(
menu
.
getParent
().
getId
());
menu
.
setFunctionId
(
menu
.
getRelationFunction
().
getId
());
menuDao
.
insert
(
menu
,
true
);
platformService
.
clearMenuCache
();
return
menu
.
getId
();
}
public
void
deleteMenu
(
Long
menuId
)
{
deleteMenuId
(
menuId
);
}
public
void
batchDeleteMenuId
(
List
<
Long
>
menuIds
)
{
for
(
Long
id
:
menuIds
)
{
deleteMenuId
(
id
);
}
...
...
@@ -54,17 +71,22 @@ public class MenuConsoleService extends CoreBaseService<CoreMenu> {
}
public
void
updateMenu
(
CoreMenu
menu
)
{
menu
.
setParentMenuId
(
menu
.
getParent
().
getId
());
menu
.
setFunctionId
(
menu
.
getRelationFunction
().
getId
());
menuDao
.
updateById
(
menu
);
platformService
.
clearMenuCache
();
}
public
CoreMenu
getMenu
(
Long
menuId
)
{
CoreMenu
menu
=
menuDao
.
unique
(
menuId
);
platformService
.
clearMenuCache
();
return
menu
;
}
private
void
deleteMenuId
(
Long
menuId
)
{
MenuItem
root
=
platformService
.
buildMenu
();
MenuItem
fun
=
root
.
findChild
(
menuId
);
List
<
MenuItem
>
all
=
fun
.
findAllItem
();
...
...
@@ -74,6 +96,7 @@ public class MenuConsoleService extends CoreBaseService<CoreMenu> {
}
private
void
realDeleteMenu
(
List
<
MenuItem
>
all
)
{
List
<
Long
>
ids
=
new
ArrayList
<>(
all
.
size
());
for
(
MenuItem
item
:
all
)
{
ids
.
add
(
item
.
getId
());
...
...
@@ -82,4 +105,41 @@ public class MenuConsoleService extends CoreBaseService<CoreMenu> {
// 删除角色和菜单的关系
roleMenuDao
.
deleteRoleMenu
(
ids
);
}
/**
* @return 菜单树,排序
*/
@Cacheable
(
MENU_FUNC_TREE_CACHE
)
public
List
<
CoreMenu
>
getMenusTree
()
{
List
<
CoreMenu
>
coreMenuList
=
menuDao
.
selectMenuAndRelationFunction
();
System
.
out
.
println
(
coreMenuList
);
CoreMenu
root
=
new
CoreMenu
();
root
.
setId
(
0L
);
buildTree
(
root
,
coreMenuList
);
return
root
.
getChildren
();
}
/**
* 深度优先算法递归构建菜单树,根据seq排序
*/
private
void
buildTree
(
CoreMenu
root
,
@NotNull
List
<
CoreMenu
>
allNodes
)
{
if
(
CollUtil
.
isEmpty
(
allNodes
))
{
return
;
}
List
<
CoreMenu
>
childNodes
=
allNodes
.
stream
()
.
filter
(
route
->
ObjectUtil
.
equal
(
route
.
getParentMenuId
(),
root
.
getId
()))
.
sorted
()
.
collect
(
Collectors
.
toList
());
root
.
setChildren
(
childNodes
);
allNodes
.
removeAll
(
childNodes
);
List
<
CoreMenu
>
rootChildrenList
=
root
.
getChildren
();
for
(
CoreMenu
coreFunction
:
rootChildrenList
)
{
buildTree
(
coreFunction
,
allNodes
);
}
}
}
plus-admin/admin-console/src/main/java/com/ibeetl/admin/console/web/MenuElController.java
0 → 100644
View file @
875339d5
package
com.ibeetl.admin.console.web
;
import
com.ibeetl.admin.console.service.MenuConsoleService
;
import
com.ibeetl.admin.core.annotation.Function
;
import
com.ibeetl.admin.core.annotation.RequestBodyPlus
;
import
com.ibeetl.admin.core.entity.CoreFunction
;
import
com.ibeetl.admin.core.entity.CoreMenu
;
import
com.ibeetl.admin.core.rbac.tree.MenuItem
;
import
com.ibeetl.admin.core.service.CorePlatformService
;
import
com.ibeetl.admin.core.util.ConvertUtil
;
import
com.ibeetl.admin.core.web.JsonResult
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
org.beetl.sql.core.engine.PageQuery
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.DeleteMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.PutMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.bind.annotation.RestController
;
@RequestMapping
(
"menus"
)
@RestController
public
class
MenuElController
{
@Autowired
MenuConsoleService
menuConsoleService
;
@Autowired
CorePlatformService
platformService
;
@GetMapping
@Function
(
"menu.query"
)
public
JsonResult
<
List
<
CoreMenu
>>
menusTree
()
{
List
<
CoreMenu
>
menuTreeItems
=
menuConsoleService
.
getMenusTree
();
return
JsonResult
.
success
(
menuTreeItems
);
}
/**
* 添加
*
* @param menu
* @return
*/
@PostMapping
@Function
(
"menu.save"
)
@ResponseBody
public
JsonResult
save
(
@Validated
@RequestBody
CoreMenu
menu
)
{
Long
id
=
menuConsoleService
.
saveMenu
(
menu
);
return
JsonResult
.
success
(
id
);
}
/**
* 更新
*
* @param menu
* @return
*/
@PutMapping
@Function
(
"menu.update"
)
@ResponseBody
public
JsonResult
update
(
@RequestBody
CoreMenu
menu
)
{
menuConsoleService
.
updateMenu
(
menu
);
return
JsonResult
.
success
();
}
/**
* 批量删除
*
* @param ids 菜单id集合
* @return
*/
@DeleteMapping
@Function
(
"menu.delete"
)
@ResponseBody
public
JsonResult
delete
(
@RequestBodyPlus
(
"ids"
)
ArrayList
<
Long
>
ids
)
{
menuConsoleService
.
batchDeleteMenuId
(
ids
);
return
JsonResult
.
success
();
}
}
plus-admin/admin-console/src/main/resources/application.yml
View file @
875339d5
...
...
@@ -10,7 +10,7 @@ user:
orgId
:
1
# 文件操作的根目录配置 请根据各自计算机配置
localFile
:
root
:
E:\code_workspace\
temp_space
\
root
:
/home/pi/java_dir/
temp_space
/
# --------beetl配置
beetl
:
suffix
:
html
...
...
@@ -60,7 +60,7 @@ spring:
baseDataSource
:
driver-class-name
:
com.mysql.cj.jdbc.Driver
password
:
123456
url
:
jdbc:mysql://
127.0.0.1
:3306/starter_vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&useInformationSchema=true
url
:
jdbc:mysql://
localhost
:3306/starter_vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&useInformationSchema=true
username
:
root
session
:
store-type
:
none
plus-admin/admin-console/src/main/resources/log4j2.xml
View file @
875339d5
...
...
@@ -7,8 +7,8 @@
<!-- 日志文件目录、压缩文件目录、日志格式配置 -->
<properties>
<Property
name=
"fileName"
>
/
Users
/admin/Code/log
</Property>
<Property
name=
"fileGz"
>
/
Users
/admin/Code/log/7z
</Property>
<Property
name=
"fileName"
>
/
home/pi/java_dir
/admin/Code/log
</Property>
<Property
name=
"fileGz"
>
/
home/pi/java_dir
/admin/Code/log/7z
</Property>
<Property
name=
"PID"
>
????
</Property>
<Property
name=
"LOG_PATTERN"
>
%clr{%d{DEFAULT}}{blue} %clr{%5level} %clr{${sys:PID}}{magenta}
%clr{---}{faint} %clr{[%.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{信息:%m}{magenta} %clr{%l}{faint} %n%xwEx
...
...
plus-admin/admin-console/src/main/resources/sql/console/menu.md
View file @
875339d5
...
...
@@ -30,5 +30,47 @@ queryByCondtion
order by m.id
@}
selectMenuAndRelationFunction
=======
*
查询菜单和其关联的功能点
```
sql
select
cm
.
id
,
cm
.
name
,
cm
.
code
,
cm
.
function_id
,
cm
.
icon
,
cm
.
parent_menu_id
,
cm
.
seq
,
cm
.
type
,
cf
.
id
func_id
,
cf
.
access_url
func_access_url
,
cf
.
name
func_name
,
cf
.
type
func_type
from
core_menu
cm
join
core_function
cf
on
cf
.
id
=
cm
.
function_id
and
cm
.
del_flag
=
0
and
cf
.
del_flag
=
0
```
@ mapping("MenuFunctionMapping");
MenuFunctionMapping
===
*
菜单功能点结果集映射
```
javascript
var
menu_func_mapping
=
{
"
id
"
:
"
menu_func_map
"
,
"
mapping
"
:
{
"
resultType
"
:
"
com.ibeetl.admin.core.entity.CoreMenu
"
,
"
id
"
:
"
id
"
,
"
name
"
:
"
name
"
,
"
code
"
:
"
code
"
,
"
functionId
"
:
"
function_id
"
,
"
parentMenuId
"
:
"
parent_menu_id
"
,
"
icon
"
:
"
icon
"
,
"
seq
"
:
"
seq
"
,
"
type
"
:
"
type
"
,
"
relationFunction
"
:
{
"
resultType
"
:
"
com.ibeetl.admin.core.entity.CoreFunction
"
,
"
id
"
:
"
func_id
"
,
"
name
"
:
"
func_name
"
,
"
accessUrl
"
:
"
func_access_url
"
,
"
type
"
:
"
func_type
"
}
}
};
```
\ No newline at end of file
plus-admin/admin-core/src/main/java/com/ibeetl/admin/core/conf/CustomErrorController.java
View file @
875339d5
...
...
@@ -6,16 +6,17 @@ import cn.hutool.core.collection.CollUtil;
import
cn.hutool.core.convert.Convert
;
import
cn.hutool.core.util.CharsetUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.http.ContentType
;
import
cn.hutool.system.SystemUtil
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.ibeetl.admin.core.util.PlatformException
;
import
com.ibeetl.admin.core.web.JsonResult
;
import
java.io.IOException
;
import
java.io.UnsupportedEncodingException
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.validation.ConstraintViolation
;
...
...
@@ -25,11 +26,15 @@ import org.slf4j.LoggerFactory;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController
;
import
org.springframework.boot.web.servlet.error.DefaultErrorAttributes
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.util.MimeTypeUtils
;
import
org.springframework.validation.BindingResult
;
import
org.springframework.validation.FieldError
;
import
org.springframework.web.bind.MethodArgumentNotValidException
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.context.request.RequestAttributes
;
import
org.springframework.web.context.request.ServletWebRequest
;
import
org.springframework.web.context.request.WebRequest
;
import
org.springframework.web.servlet.ModelAndView
;
/**
...
...
@@ -46,15 +51,19 @@ public class CustomErrorController extends AbstractErrorController {
private
final
DefaultErrorAttributes
defaultErrorAttributes
;
@Autowired
ObjectMapper
objectMapper
;
@Autowired
ObjectMapper
objectMapper
;
public
CustomErrorController
(
DefaultErrorAttributes
defaultErrorAttributes
)
{
super
(
defaultErrorAttributes
);
this
.
defaultErrorAttributes
=
defaultErrorAttributes
;
}
@RequestMapping
(
ERROR_PATH
)
public
ModelAndView
getErrorPath
(
HttpServletRequest
request
,
HttpServletResponse
response
)
{
public
ModelAndView
getErrorPath
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
UnsupportedEncodingException
{
Throwable
cause
=
getRealException
(
request
);
Map
<
String
,
Object
>
errorInfo
=
wrapErrorInfo
(
request
);
// 后台打印日志信息方方便查错
...
...
@@ -64,13 +73,42 @@ public class CustomErrorController extends AbstractErrorController {
return
hanlderPlatformException
(
errorInfo
,
response
);
}
else
if
(
cause
instanceof
ConstraintViolationException
)
{
return
hanlderConstraintViolationException
(
errorInfo
,
request
,
response
);
}
else
if
(
cause
instanceof
MethodArgumentNotValidException
)
{
return
hanlderMethodArgumentNotValidException
(
errorInfo
,
request
,
response
);
}
else
{
return
hanlderGeneralException
(
errorInfo
,
response
);
}
}
private
ModelAndView
hanlderMethodArgumentNotValidException
(
Map
<
String
,
Object
>
errorInfo
,
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
UnsupportedEncodingException
{
ModelAndView
modelAndView
=
handlerHtml
(
errorInfo
);
if
(
modelAndView
!=
null
)
{
modelAndView
.
addObject
(
"errorMessage"
,
"服务器内部错误,请联系管理员"
);
logger
.
error
(
"方法参数校验失败,请查看上述详细信息"
);
}
else
{
if
(
Convert
.
toInt
(
errorInfo
.
get
(
"status"
)).
equals
(
HttpStatus
.
NOT_FOUND
.
value
()))
{
writeJson
(
response
,
JsonResult
.
http404
(
errorInfo
.
get
(
"path"
)));
}
else
{
MethodArgumentNotValidException
methodArgumentNotValidException
=
(
MethodArgumentNotValidException
)
getRealException
(
request
);
BindingResult
bindingResult
=
methodArgumentNotValidException
.
getBindingResult
();
List
<
String
>
messages
=
CollUtil
.<
String
>
newArrayList
();
List
<
FieldError
>
fieldErrors
=
bindingResult
.
getFieldErrors
();
for
(
FieldError
fieldError
:
fieldErrors
)
{
messages
.
add
(
fieldError
.
getDefaultMessage
());
}
writeJson
(
response
,
JsonResult
.
fail
(
messages
));
}
}
return
modelAndView
;
}
private
ModelAndView
hanlderGeneralException
(
Map
<
String
,
Object
>
errorInfo
,
HttpServletResponse
response
)
{
ModelAndView
modelAndView
=
handlerHtml
(
errorInfo
);
if
(
modelAndView
!=
null
)
{
modelAndView
.
addObject
(
"errorMessage"
,
"服务器内部错误,请联系管理员"
);
...
...
@@ -82,6 +120,7 @@ public class CustomErrorController extends AbstractErrorController {
private
ModelAndView
hanlderConstraintViolationException
(
Map
<
String
,
Object
>
errorInfo
,
HttpServletRequest
request
,
HttpServletResponse
response
)
{
ModelAndView
modelAndView
=
handlerHtml
(
errorInfo
);
if
(
modelAndView
!=
null
)
{
modelAndView
.
addObject
(
"errorMessage"
,
"服务器内部错误,请联系管理员"
);
...
...
@@ -107,6 +146,7 @@ public class CustomErrorController extends AbstractErrorController {
private
ModelAndView
hanlderPlatformException
(
Map
<
String
,
Object
>
errorInfo
,
HttpServletResponse
response
)
{
ModelAndView
modelAndView
=
handlerHtml
(
errorInfo
);
if
(
modelAndView
!=
null
)
{
modelAndView
.
addObject
(
"errorMessage"
,
errorInfo
.
get
(
"message"
));
...
...
@@ -118,11 +158,9 @@ public class CustomErrorController extends AbstractErrorController {
/**
* 通用处理页面请求方法
*
* @param errorInfo
* @return
*/
protected
ModelAndView
handlerHtml
(
Map
<
String
,
Object
>
errorInfo
)
{
ModelAndView
view
=
null
;
if
(!
Convert
.
toBool
(
errorInfo
.
get
(
"isAjax"
)))
{
view
=
new
ModelAndView
(
"/error.html"
);
...
...
@@ -135,6 +173,7 @@ public class CustomErrorController extends AbstractErrorController {
}
protected
void
handlerAjax
(
Map
<
String
,
Object
>
errorInfo
,
HttpServletResponse
response
)
{
if
(
Convert
.
toInt
(
errorInfo
.
get
(
"status"
)).
equals
(
HttpStatus
.
NOT_FOUND
.
value
()))
{
writeJson
(
response
,
JsonResult
.
http404
(
errorInfo
.
get
(
"path"
)));
}
else
{
...
...
@@ -144,26 +183,19 @@ public class CustomErrorController extends AbstractErrorController {
}
/**
* 提取errorAttributes 中的错误信息,包括:<br>
* timestamp:时间<br>
* status:http响应码<br>
* error:响应码的原因<br>
* exception:异常类名<br>
* errors:controller可能的校验错误对象集合<br>
* message:controller的错误信息<br>
* trace: 异常的堆栈信息<br>
* path:请求路径<br>
*
* @param request
* @return
* 提取errorAttributes 中的错误信息,包括:<br> timestamp:时间<br> status:http响应码<br> error:响应码的原因<br>
* exception:异常类名<br> errors:controller可能的校验错误对象集合<br> message:controller的错误信息<br> trace:
* 异常的堆栈信息<br> path:请求路径<br>
*/
protected
Map
<
String
,
Object
>
wrapErrorInfo
(
HttpServletRequest
request
)
{
Map
<
String
,
Object
>
errorAttributes
=
super
.
getErrorAttributes
(
request
,
true
);
errorAttributes
.
put
(
"isAjax"
,
isJsonRequest
(
request
));
return
Collections
.
unmodifiableMap
(
errorAttributes
);
}
protected
void
prettyLog
(
Map
errorInfo
)
{
Object
path
=
errorInfo
.
get
(
"path"
);
Object
status
=
errorInfo
.
get
(
"status"
);
Object
message
=
errorInfo
.
get
(
"message"
);
...
...
@@ -185,30 +217,25 @@ public class CustomErrorController extends AbstractErrorController {
/**
* json请求,要么是.json后缀的请求,要么是http请求报文中规定的json请求
*
* @param request
* @return
*/
protected
boolean
isJsonRequest
(
HttpServletRequest
request
)
{
String
requestUri
=
(
String
)
request
.
getAttribute
(
"javax.servlet.error.request_uri"
);
if
(
requestUri
!=
null
&&
requestUri
.
endsWith
(
".json"
))
{
return
true
;
}
else
{
return
(
request
.
getHeader
(
"Accept"
).
contains
(
"application/json"
)
||
(
request
.
getHeader
(
"X-Requested-With"
)
!=
null
&&
request
.
getHeader
(
"X-Requested-With"
).
contains
(
"XMLHttpRequest"
)));
&&
request
.
getHeader
(
"X-Requested-With"
).
contains
(
"XMLHttpRequest"
)));
}
}
/**
* json响应的输出流方式
*
* @param response
* @param error
*/
protected
void
writeJson
(
HttpServletResponse
response
,
JsonResult
error
)
{
response
.
addHeader
(
HttpHeaders
.
CONTENT_TYPE
,
MimeTypeUtils
.
APPLICATION_JSON_VALUE
);
response
.
addHeader
(
HttpHeaders
.
ACCEPT_CHARSET
,
CharsetUtil
.
UTF_8
);
response
.
setContentType
(
ContentType
.
JSON
.
toString
(
CharsetUtil
.
CHARSET_
UTF_8
)
)
;
try
{
response
.
getWriter
().
write
(
objectMapper
.
writeValueAsString
(
error
));
}
catch
(
IOException
e
)
{
...
...
@@ -218,22 +245,24 @@ public class CustomErrorController extends AbstractErrorController {
/**
* 获取真正的异常,而不是被tomcat等包装的异常
*
* @param request
* @return
*/
protected
Throwable
getRealException
(
HttpServletRequest
request
)
{
Throwable
error
=
(
Throwable
)
request
.
getAttribute
(
"javax.servlet.error.exception"
);
if
(
error
!=
null
)
{
while
(
error
instanceof
ServletException
&&
error
.
getCause
()
!=
null
)
{
error
=
error
.
getCause
();
}
WebRequest
webRequest
=
new
ServletWebRequest
(
request
);
Throwable
error
=
(
Throwable
)
webRequest
.
getAttribute
(
DefaultErrorAttributes
.
class
.
getName
()
+
".ERROR"
,
RequestAttributes
.
SCOPE_REQUEST
);
if
(
error
==
null
)
{
error
=
(
Throwable
)
webRequest
.
getAttribute
(
"javax.servlet.error.exception"
,
RequestAttributes
.
SCOPE_REQUEST
);
}
return
error
;
}
@Override
public
String
getErrorPath
()
{
return
ERROR_PATH
;
}
}
plus-admin/admin-core/src/main/java/com/ibeetl/admin/core/conf/SpringWebMvcConfigurer.java
View file @
875339d5
...
...
@@ -7,12 +7,15 @@ import static org.springframework.http.HttpMethod.POST;
import
static
org
.
springframework
.
http
.
HttpMethod
.
PUT
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.util.CharsetUtil
;
import
com.ibeetl.admin.core.conf.springmvc.convert.DateConditionalGenericConverter
;
import
com.ibeetl.admin.core.conf.springmvc.convert.StringToDictTypeEnumConverterFactory
;
import
com.ibeetl.admin.core.conf.springmvc.interceptor.HttpRequestInterceptor
;
import
com.ibeetl.admin.core.conf.springmvc.interceptor.SessionInterceptor
;
import
com.ibeetl.admin.core.conf.springmvc.resolve.RequestBodyPlusProcessor
;
import
com.ibeetl.admin.core.service.CoreUserService
;
import
java.nio.charset.Charset
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -24,41 +27,56 @@ import org.springframework.context.annotation.Configuration;
import
org.springframework.core.env.Environment
;
import
org.springframework.format.FormatterRegistry
;
import
org.springframework.format.datetime.DateFormatter
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.converter.HttpMessageConverter
;
import
org.springframework.http.converter.StringHttpMessageConverter
;
import
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
;
import
org.springframework.web.method.support.HandlerMethodArgumentResolver
;
import
org.springframework.web.servlet.config.annotation.CorsRegistry
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
import
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
;
/** 切勿在此配置类中向SpringMVC中添加bean。 也就是不要 @Bean这类方法。 会出现无法ServletContext注入null,因为父接口的原因 */
/**
* 切勿在此配置类中向SpringMVC中添加bean。 也就是不要 @Bean这类方法。 会出现无法ServletContext注入null,因为父接口的原因
*/
@Configuration
public
class
SpringWebMvcConfigurer
implements
WebMvcConfigurer
,
InitializingBean
{
public
static
final
String
DEFAULT_APP_NAME
=
"开发平台"
;
/** 系统名称,可以在application.properties中配置 app.name=xxx */
/**
* 系统名称,可以在application.properties中配置 app.name=xxx
*/
// @Value("${app.name}")
// String appName;
private
String
mvcTestPath
;
@Autowired
private
Environment
env
;
@Autowired
private
Environment
env
;
@Autowired
private
CoreUserService
userService
;
@Autowired
private
CoreUserService
userService
;
@Autowired
private
BeetlGroupUtilConfiguration
beetlGroupUtilConfiguration
;
@Autowired
private
BeetlGroupUtilConfiguration
beetlGroupUtilConfiguration
;
@Autowired
private
GroupTemplate
groupTemplate
;
@Autowired
private
GroupTemplate
groupTemplate
;
@Autowired
private
RequestMappingHandlerAdapter
adapter
;
@Autowired
private
RequestMappingHandlerAdapter
adapter
;
/**
* 添加拦截器
*
* @param registry 拦截器的注册器
* @param registry
* 拦截器的注册器
*/
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
registry
.
addInterceptor
(
new
HttpRequestInterceptor
()).
addPathPatterns
(
"/**"
);
registry
.
addInterceptor
(
new
SessionInterceptor
(
userService
))
...
...
@@ -66,13 +84,33 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea
.
addPathPatterns
(
"/**"
);
}
@Override
public
void
configureMessageConverters
(
List
<
HttpMessageConverter
<?>>
converters
)
{
for
(
HttpMessageConverter
<?>
converter
:
converters
)
{
if
(
converter
instanceof
MappingJackson2HttpMessageConverter
)
{
MappingJackson2HttpMessageConverter
mappingJackson2HttpMessageConverter
=
(
MappingJackson2HttpMessageConverter
)
converter
;
mappingJackson2HttpMessageConverter
.
setDefaultCharset
(
CharsetUtil
.
CHARSET_UTF_8
);
List
<
MediaType
>
supportedMediaTypes
=
mappingJackson2HttpMessageConverter
.
getSupportedMediaTypes
();
List
<
MediaType
>
customMediaTypes
=
CollUtil
.
newArrayList
(
supportedMediaTypes
);
customMediaTypes
.
add
(
MediaType
.
APPLICATION_JSON_UTF8
);
customMediaTypes
.
add
(
MediaType
.
parseMediaType
(
"text/html;charset=UTF-8"
));
customMediaTypes
.
add
(
MediaType
.
parseMediaType
(
"text/plain;charset=UTF-8"
));
customMediaTypes
.
add
(
MediaType
.
parseMediaType
(
"application/xml;charset=UTF-8"
));
mappingJackson2HttpMessageConverter
.
setSupportedMediaTypes
(
customMediaTypes
);
}
}
}
/**
* 增加跨域映射
*
* @param registry 跨域映射注册器
* @param registry
* 跨域映射注册器
*/
@Override
public
void
addCorsMappings
(
CorsRegistry
registry
)
{
registry
.
addMapping
(
"/**"
)
.
allowedOrigins
(
"*"
)
...
...
@@ -81,15 +119,16 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea
}
@Override
public
void
addArgumentResolvers
(
List
<
HandlerMethodArgumentResolver
>
resolvers
)
{}
public
void
addArgumentResolvers
(
List
<
HandlerMethodArgumentResolver
>
resolvers
)
{
}
/**
* SpringMVC的请求响应消息的转换格式器
*
* @param registry
*/
@Override
public
void
addFormatters
(
FormatterRegistry
registry
)
{
registry
.
addFormatter
(
new
DateFormatter
(
"yyyy-MM-dd HH:mm:ss"
));
registry
.
addFormatter
(
new
DateFormatter
(
"yyyy-MM-dd"
));
/*converter 在json传参时无效*/
...
...
@@ -99,6 +138,7 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea
@Override
public
void
afterPropertiesSet
()
{
this
.
mvcTestPath
=
env
.
getProperty
(
"mvc.test.path"
);
Map
<
String
,
Object
>
var
=
new
HashMap
<>(
5
);
String
appName
=
env
.
getProperty
(
"app.name"
);
...
...
@@ -113,4 +153,5 @@ public class SpringWebMvcConfigurer implements WebMvcConfigurer, InitializingBea
argumentResolvers
.
addAll
(
adapter
.
getArgumentResolvers
());
adapter
.
setArgumentResolvers
(
argumentResolvers
);
}
}
plus-admin/admin-core/src/main/java/com/ibeetl/admin/core/entity/CoreMenu.java
View file @
875339d5
package
com.ibeetl.admin.core.entity
;
import
com.ibeetl.admin.core.annotation.Dict
;
import
com.ibeetl.admin.core.util.ValidateConfig
;
import
com.ibeetl.admin.core.util.enums.CoreDictType
;
import
java.util.Date
;
import
java.util.List
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
org.beetl.sql.core.annotatoin.AutoID
;
import
org.beetl.sql.core.annotatoin.SeqID
;
import
org.beetl.sql.core.annotatoin.UpdateIgnore
;
import
com.ibeetl.admin.core.annotation.Dict
;
import
com.ibeetl.admin.core.util.ValidateConfig
;
import
com.ibeetl.admin.core.util.enums.CoreDictType
;
/** 系统菜单 */
public
class
CoreMenu
extends
BaseEntity
{
/**
* 系统菜单
*/
@NoArgsConstructor
@Data
public
class
CoreMenu
extends
BaseEntity
implements
Comparable
{
public
static
final
String
TYPE_SYSTEM
=
"MENU_S"
;
public
static
final
String
TYPE_NAV
=
"MENU_N"
;
public
static
final
String
TYPE_MENUITEM
=
"MENU_M"
;
@NotNull
(
message
=
"ID不能为空"
,
groups
=
ValidateConfig
.
UPDATE
.
class
)
...
...
@@ -26,7 +32,8 @@ public class CoreMenu extends BaseEntity {
protected
Long
id
;
// 创建时间
@UpdateIgnore
protected
Date
createTime
;
@UpdateIgnore
protected
Date
createTime
;
// 菜单代码
@NotBlank
(
message
=
"菜单代码不能为空"
,
groups
=
ValidateConfig
.
ADD
.
class
)
...
...
@@ -35,6 +42,8 @@ public class CoreMenu extends BaseEntity {
// 功能id
private
Long
functionId
;
private
CoreFunction
relationFunction
;
// 类型 /*1 系统 2 导航 3 菜单项(与功能点有关)*/
@NotNull
(
message
=
"菜单类型不能为空"
)
@Dict
(
type
=
CoreDictType
.
MENU_TYPE
)
...
...
@@ -49,83 +58,35 @@ public class CoreMenu extends BaseEntity {
private
Long
parentMenuId
;
// 排序
@NotNull
(
message
=
"排序不能为空"
)
private
Integer
seq
;
private
Integer
seq
=
Integer
.
MAX_VALUE
;
// 图标
private
String
icon
;
public
CoreMenu
()
{}
public
Long
getId
()
{
return
id
;
}
public
void
setId
(
Long
id
)
{
this
.
id
=
id
;
}
public
String
getCode
()
{
return
code
;
}
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
private
String
icon
=
"menu"
;
public
Long
getFunctionId
()
{
return
functionId
;
}
public
void
setFunctionId
(
Long
functionId
)
{
this
.
functionId
=
functionId
;
}
private
CoreMenu
parent
;
public
String
getType
()
{
return
type
;
}
private
List
<
CoreMenu
>
children
;
public
void
setType
(
String
type
)
{
this
.
type
=
type
;
}
private
short
delFlag
;
public
String
getName
()
{
return
name
;
}
@Override
public
int
compareTo
(
Object
o
)
{
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
if
(!(
o
instanceof
CoreMenu
))
{
throw
new
IllegalArgumentException
(
"给定的对象不是同一个类型"
);
}
if
(
o
==
null
)
{
throw
new
NullPointerException
(
"给定的对象为NULL"
);
}
CoreMenu
other
=
(
CoreMenu
)
o
;
// <0 =0 >0
if
(
this
.
seq
==
null
)
{
this
.
seq
=
Integer
.
MAX_VALUE
;
}
if
(
other
.
seq
==
null
)
{
other
.
seq
=
Integer
.
MAX_VALUE
;
}
return
this
.
seq
-
other
.
seq
;
}
public
Long
getParentMenuId
()
{
return
parentMenuId
;
}
public
void
setParentMenuId
(
Long
parentMenuId
)
{
this
.
parentMenuId
=
parentMenuId
;
}
public
Integer
getSeq
()
{
return
seq
;
}
public
void
setSeq
(
Integer
seq
)
{
this
.
seq
=
seq
;
}
public
String
getIcon
()
{
return
icon
;
}
public
void
setIcon
(
String
icon
)
{
this
.
icon
=
icon
;
}
public
Date
getCreateTime
()
{
return
createTime
;
}
public
void
setCreateTime
(
Date
createTime
)
{
this
.
createTime
=
createTime
;
}
}
plus-admin/admin-core/src/main/java/com/ibeetl/admin/core/service/CorePlatformService.java
View file @
875339d5
...
...
@@ -4,19 +4,6 @@ import static com.ibeetl.admin.core.util.HttpRequestLocal.ACCESS_CURRENT_ORG;
import
static
com
.
ibeetl
.
admin
.
core
.
util
.
HttpRequestLocal
.
ACCESS_CURRENT_USER
;
import
static
com
.
ibeetl
.
admin
.
core
.
util
.
HttpRequestLocal
.
ACCESS_USER_ORGS
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
javax.annotation.PostConstruct
;
import
org.beetl.sql.core.SQLManager
;
import
org.beetl.sql.core.engine.SQLPlaceholderST
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cache.annotation.CacheEvict
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
import
com.ibeetl.admin.core.dao.CoreFunctionDao
;
import
com.ibeetl.admin.core.dao.CoreMenuDao
;
import
com.ibeetl.admin.core.dao.CoreOrgDao
;
...
...
@@ -40,6 +27,17 @@ import com.ibeetl.admin.core.util.PlatformException;
import
com.ibeetl.admin.core.util.beetl.DataAccessFunction
;
import
com.ibeetl.admin.core.util.beetl.NextDayFunction
;
import
com.ibeetl.admin.core.util.enums.DelFlagEnum
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Set
;
import
javax.annotation.PostConstruct
;
import
org.beetl.sql.core.SQLManager
;
import
org.beetl.sql.core.engine.SQLPlaceholderST
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cache.annotation.CacheEvict
;
import
org.springframework.cache.annotation.Cacheable
;
import
org.springframework.stereotype.Service
;
/**
* 系统平台功能访问入口,所有方法应该支持缓存或者快速访问
...
...
@@ -51,53 +49,85 @@ public class CorePlatformService {
// 菜单树,组织机构树,功能树缓存标记
public
static
final
String
MENU_TREE_CACHE
=
"cache:core:menuTree"
;
/**
* 菜单与其关联功能点树
*/
public
static
final
String
MENU_FUNC_TREE_CACHE
=
"cache:core:menuFuncTree"
;
public
static
final
String
ORG_TREE_CACHE
=
"cache:core:orgTree"
;
public
static
final
String
ORG_CACHE_TREE_CHILDREN
=
"cache:core:orgTreeChildrens"
;
public
static
final
String
ORG_CACHE_TREE_LIST
=
"cache:core:orgTreeList"
;
public
static
final
String
FUNCTION_TREE_CACHE
=
"cache:core:functionTree"
;
// 字典列表
public
static
final
String
DICT_CACHE_TREE_CHILDREN
=
"cache:core:dictTreeChildrens"
;
public
static
final
String
DICT_CACHE_TREE_LIST
=
"cache:core:dictTreeList"
;
public
static
final
String
DICT_CACHE_TYPE
=
"cache:core:dictType"
;
public
static
final
String
DICT_CACHE_VALUE
=
"cache:core:dictValue"
;
public
static
final
String
DICT_CACHE_SAME_LEVEL
=
"cache:core:ditcSameLevel"
;
public
static
final
String
DICT_CACHE_CHILDREN
=
"cache:core:dictChildren"
;
public
static
final
String
USER_FUNCTION_ACCESS_CACHE
=
"cache:core:userFunctionAccess"
;
public
static
final
String
USER_FUNCTION_CHIDREN_CACHE
=
"ccache:core:functionChildren"
;
public
static
final
String
FUNCTION_CACHE
=
"cache:core:function"
;
public
static
final
String
USER_DATA_ACCESS_CACHE
=
"cache:core:userDataAccess"
;
public
static
final
String
USER_MENU_CACHE
=
"cache:core:userMenu"
;
public
static
final
String
ACCESS_SUPPER_ADMIN
=
"admin"
;
@Autowired
HttpRequestLocal
httpRequestLocal
;
@Autowired
HttpRequestLocal
httpRequestLocal
;
@Autowired
CoreRoleFunctionDao
roleFunctionDao
;
@Autowired
CoreRoleFunctionDao
roleFunctionDao
;
@Autowired
CoreRoleMenuDao
sysRoleMenuDao
;
@Autowired
CoreRoleMenuDao
sysRoleMenuDao
;
@Autowired
CoreOrgDao
sysOrgDao
;
@Autowired
CoreOrgDao
sysOrgDao
;
@Autowired
CoreRoleFunctionDao
sysRoleFunctionDao
;
@Autowired
CoreRoleFunctionDao
sysRoleFunctionDao
;
@Autowired
CoreMenuDao
sysMenuDao
;
@Autowired
CoreMenuDao
sysMenuDao
;
@Autowired
CoreUserDao
sysUserDao
;
@Autowired
CoreUserDao
sysUserDao
;
@Autowired
CoreFunctionDao
sysFunctionDao
;
@Autowired
CoreFunctionDao
sysFunctionDao
;
@Autowired
SQLManager
sqlManager
;
@Autowired
SQLManager
sqlManager
;
@Autowired
DataAccessFunction
dataAccessFunction
;
@Autowired
DataAccessFunction
dataAccessFunction
;
@Autowired
CorePlatformService
self
;
@Autowired
CorePlatformService
self
;
@Autowired
DataAccessFactory
dataAccessFactory
;
@Autowired
DataAccessFactory
dataAccessFactory
;
@PostConstruct
@SuppressWarnings
(
"unchecked"
)
public
void
init
()
{
SQLPlaceholderST
.
textFunList
.
add
(
"function"
);
// sql语句里带有此函数来判断数据权限
sqlManager
.
getBeetl
().
getGroupTemplate
().
registerFunction
(
"function"
,
dataAccessFunction
);
...
...
@@ -105,51 +135,59 @@ public class CorePlatformService {
}
public
CoreUser
getCurrentUser
()
{
checkSession
();
CoreUser
user
=
(
CoreUser
)
h
ttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_USER
);
CoreUser
user
=
(
CoreUser
)
H
ttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_USER
);
return
user
;
}
public
void
changeOrg
(
Long
orgId
)
{
List
<
CoreOrg
>
orgs
=
this
.
getCurrentOrgs
();
for
(
CoreOrg
org
:
orgs
)
{
if
(
org
.
getId
().
equals
(
orgId
))
{
h
ttpRequestLocal
.
setSessionValue
(
ACCESS_CURRENT_ORG
,
org
);
H
ttpRequestLocal
.
setSessionValue
(
ACCESS_CURRENT_ORG
,
org
);
}
}
}
public
Long
getCurrentOrgId
()
{
checkSession
();
CoreOrg
org
=
(
CoreOrg
)
h
ttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_ORG
);
CoreOrg
org
=
(
CoreOrg
)
H
ttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_ORG
);
return
org
.
getId
();
}
public
CoreOrg
getCurrentOrg
()
{
checkSession
();
CoreOrg
org
=
(
CoreOrg
)
h
ttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_ORG
);
CoreOrg
org
=
(
CoreOrg
)
H
ttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_ORG
);
return
org
;
}
public
List
<
CoreOrg
>
getCurrentOrgs
()
{
List
<
CoreOrg
>
orgs
=
(
List
<
CoreOrg
>)
httpRequestLocal
.
getSessionValue
(
ACCESS_USER_ORGS
);
List
<
CoreOrg
>
orgs
=
(
List
<
CoreOrg
>)
HttpRequestLocal
.
getSessionValue
(
ACCESS_USER_ORGS
);
return
orgs
;
}
protected
void
checkSession
()
{
CoreOrg
org
=
(
CoreOrg
)
httpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_ORG
);
CoreOrg
org
=
(
CoreOrg
)
HttpRequestLocal
.
getSessionValue
(
ACCESS_CURRENT_ORG
);
if
(
org
==
null
)
{
throw
new
PlatformException
(
"会话过期,重新登录"
);
}
}
public
void
setLoginUser
(
CoreUser
user
,
CoreOrg
currentOrg
,
List
<
CoreOrg
>
orgs
)
{
httpRequestLocal
.
setSessionValue
(
ACCESS_CURRENT_USER
,
user
);
httpRequestLocal
.
setSessionValue
(
ACCESS_CURRENT_ORG
,
currentOrg
);
httpRequestLocal
.
setSessionValue
(
ACCESS_USER_ORGS
,
orgs
);
HttpRequestLocal
.
setSessionValue
(
ACCESS_CURRENT_USER
,
user
);
HttpRequestLocal
.
setSessionValue
(
ACCESS_CURRENT_ORG
,
currentOrg
);
HttpRequestLocal
.
setSessionValue
(
ACCESS_USER_ORGS
,
orgs
);
}
public
MenuItem
getMenuItem
(
long
userId
,
long
orgId
)
{
CoreUser
user
=
this
.
sysUserDao
.
unique
(
userId
);
if
(
this
.
isSupperAdmin
(
user
))
{
return
self
.
buildMenu
();
...
...
@@ -160,7 +198,8 @@ public class CorePlatformService {
return
menu
;
}
public
OrgItem
getUserOrgTree
()
{
public
OrgItem
getUserOrgTree
()
{
if
(
this
.
isCurrentSupperAdmin
())
{
OrgItem
root
=
self
.
buildOrg
();
return
root
;
...
...
@@ -189,33 +228,29 @@ public class CorePlatformService {
/**
* 判断用户是否是超级管理员
*
* @param user
* @return
*/
public
boolean
isSupperAdmin
(
CoreUser
user
)
{
return
user
.
getCode
().
startsWith
(
ACCESS_SUPPER_ADMIN
);
}
public
boolean
isCurrentSupperAdmin
()
{
CoreUser
user
=
this
.
getCurrentUser
();
return
isSupperAdmin
(
user
);
}
public
boolean
isAllowUserName
(
String
name
)
{
return
!
name
.
startsWith
(
ACCESS_SUPPER_ADMIN
);
}
/**
* 获取用户在指定功能点的数据权限配置,如果没有,返回空集合
*
* @param userId
* @param orgId
* @param fucntionCode
* @return
*/
@Cacheable
(
USER_DATA_ACCESS_CACHE
)
public
List
<
CoreRoleFunction
>
getRoleFunction
(
Long
userId
,
Long
orgId
,
String
fucntionCode
)
{
List
<
CoreRoleFunction
>
list
=
sysRoleFunctionDao
.
getRoleFunction
(
userId
,
orgId
,
fucntionCode
);
return
list
;
}
...
...
@@ -223,14 +258,14 @@ public class CorePlatformService {
/**
* 当前用户是否能访问功能,用于后台功能验证,functionCode 目前只支持二级域名方式,不支持更多级别
*
* @param functionCode
"user.add","user"
*
@return
* @param functionCode
*
"user.add","user"
*/
@Cacheable
(
USER_FUNCTION_ACCESS_CACHE
)
public
boolean
canAcessFunction
(
Long
userId
,
Long
orgId
,
String
functionCode
)
{
CoreUser
user
=
getCurrentUser
();
if
(
user
.
getId
()
==
userId
&&
isSupperAdmin
(
user
))
{
if
(
Objects
.
equals
(
user
.
getId
()
,
userId
)
&&
isSupperAdmin
(
user
))
{
return
true
;
}
String
str
=
functionCode
;
...
...
@@ -246,13 +281,12 @@ public class CorePlatformService {
/**
* 当前功能的子功能,如果有,则页面需要做按钮级别的过滤
*
* @param userId
* @param orgId
* @param parentFunction 菜单对应的function
* @return
* @param parentFunction
* 菜单对应的function
*/
@Cacheable
(
USER_FUNCTION_CHIDREN_CACHE
)
public
List
<
String
>
getChildrenFunction
(
Long
userId
,
Long
orgId
,
String
parentFunction
)
{
CoreFunction
template
=
new
CoreFunction
();
template
.
setCode
(
parentFunction
);
List
<
CoreFunction
>
list
=
sysFunctionDao
.
template
(
template
);
...
...
@@ -266,23 +300,19 @@ public class CorePlatformService {
/**
* 查询当前用户有用的菜单项目,可以在随后验证是否能显示某项菜单
*
* @return
*/
@Cacheable
(
USER_MENU_CACHE
)
public
Set
<
Long
>
getCurrentMenuIds
(
Long
userId
,
Long
orgId
)
{
List
<
Long
>
list
=
sysRoleMenuDao
.
queryMenuByUser
(
userId
,
orgId
);
return
new
HashSet
<
Long
>(
list
);
}
/**
* 验证菜单是否能被显示
*
* @param item
* @param allows
* @return
*/
public
boolean
canShowMenu
(
CoreUser
user
,
MenuItem
item
,
Set
<
Long
>
allows
)
{
if
(
isSupperAdmin
(
user
))
{
return
true
;
}
...
...
@@ -291,6 +321,7 @@ public class CorePlatformService {
@Cacheable
(
MENU_TREE_CACHE
)
public
MenuItem
buildMenu
()
{
List
<
CoreMenu
>
list
=
sysMenuDao
.
allMenuWithURL
();
return
MenuBuildUtil
.
buildMenuTree
(
list
);
}
...
...
@@ -310,13 +341,13 @@ public class CorePlatformService {
@Cacheable
(
FUNCTION_TREE_CACHE
)
public
FunctionItem
buildFunction
()
{
List
<
CoreFunction
>
list
=
sysFunctionDao
.
all
();
return
FunctionBuildUtil
.
buildOrgTree
(
list
);
}
/**
* 用户信息被管理员修改,重置会话,让用户操作重新登录
*
* @param name
*/
public
void
restUserSession
(
String
name
)
{
// TODO
...
...
@@ -324,13 +355,14 @@ public class CorePlatformService {
@CacheEvict
(
cacheNames
=
{
FUNCTION_CACHE
,
FUNCTION_TREE_CACHE
,
/*功能点本身缓存*/
MENU_TREE_CACHE
,
USER_MENU_CACHE
,
/*功能点关联菜单缓存*/
USER_FUNCTION_ACCESS_CACHE
,
USER_FUNCTION_CHIDREN_CACHE
,
USER_DATA_ACCESS_CACHE
,
/*功能点相关权限缓存*/
FUNCTION_CACHE
,
FUNCTION_TREE_CACHE
,
/*功能点本身缓存*/
MENU_TREE_CACHE
,
MENU_FUNC_TREE_CACHE
,
USER_MENU_CACHE
,
/*功能点关联菜单缓存*/
USER_FUNCTION_ACCESS_CACHE
,
USER_FUNCTION_CHIDREN_CACHE
,
USER_DATA_ACCESS_CACHE
,
/*功能点相关权限缓存*/
},
allEntries
=
true
)
public
void
clearFunctionCache
()
{
...
...
@@ -338,7 +370,8 @@ public class CorePlatformService {
}
@CacheEvict
(
cacheNames
=
{
CorePlatformService
.
MENU_TREE_CACHE
,
CorePlatformService
.
USER_MENU_CACHE
},
cacheNames
=
{
MENU_TREE_CACHE
,
MENU_FUNC_TREE_CACHE
,
USER_MENU_CACHE
},
allEntries
=
true
)
public
void
clearMenuCache
()
{
// 没有做任何事情,交给spring cache来处理了
...
...
@@ -346,25 +379,28 @@ public class CorePlatformService {
@CacheEvict
(
cacheNames
=
{
CorePlatformService
.
DICT_CACHE_CHILDREN
,
CorePlatformService
.
DICT_CACHE_SAME_LEVEL
,
CorePlatformService
.
DICT_CACHE_TYPE
,
CorePlatformService
.
DICT_CACHE_VALUE
CorePlatformService
.
DICT_CACHE_CHILDREN
,
CorePlatformService
.
DICT_CACHE_SAME_LEVEL
,
CorePlatformService
.
DICT_CACHE_TYPE
,
CorePlatformService
.
DICT_CACHE_VALUE
},
allEntries
=
true
)
public
void
clearDictCache
()
{}
public
void
clearDictCache
()
{
}
@CacheEvict
(
cacheNames
=
{
CorePlatformService
.
ORG_TREE_CACHE
},
allEntries
=
true
)
public
void
clearOrgCache
()
{}
public
void
clearOrgCache
()
{
}
/**
* 得到类型为系统的菜单,通常就是根菜单下面
*
* @return
*/
public
List
<
MenuItem
>
getSysMenu
()
{
MenuItem
root
=
buildMenu
();
List
<
MenuItem
>
list
=
root
.
getChildren
();
for
(
MenuItem
item
:
list
)
{
...
...
@@ -377,13 +413,12 @@ public class CorePlatformService {
/**
* 得到菜单的子菜单
*
* @param menuId
* @return
*/
public
List
<
MenuItem
>
getChildMenu
(
Long
menuId
)
{
MenuItem
root
=
buildMenu
();
List
<
MenuItem
>
list
=
root
.
findChild
(
menuId
).
getChildren
();
return
list
;
}
}
ve-admin/admin-web/.env.development
View file @
875339d5
...
...
@@ -6,7 +6,8 @@ ENV = 'development'
# 仅限开发环境,生产环境要用NGINX仅限代理
VUE_APP_BASE_API = '/dev-api'
# VUE_APP_SERVER_HOST = 'http://127.0.0.1:9527/mock'
VUE_APP_SERVER_HOST = 'http://127.0.0.1:8080'
VUE_APP_SERVER_HOST = 'http://127.0.0.1:8080'
#VUE_APP_SERVER_HOST = 'http://192.168.1.177:8080'
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
...
...
ve-admin/admin-web/Description.md
View file @
875339d5
1、路由由登录后从后端动态生成发送给前端使用addRoutes添加到路由表中
\ No newline at end of file
1、路由由登录后从后端动态生成发送给前端使用addRoutes添加到路由表中
2、不能滥用key属性,更多是同一个父元素下的子元素每一个都要有独特的key,或者你需要一个完整的生命周期
key是vue区分新旧node时对比的关键
ve-admin/admin-web/src/api/menu.js
0 → 100644
View file @
875339d5
/*
* @Author: 一日看尽长安花
* @since: 2020-05-31 14:38:23
* @LastEditTime: 2020-06-13 12:42:08
* @LastEditors: 一日看尽长安花
* @Description:
*/
import
request
from
'
@/utils/request
'
;
/**
* 功能点管理的数据
* @param {*} params
*/
export
function
menus
(
params
)
{
return
request
({
url
:
'
/menus
'
,
method
:
'
get
'
,
params
});
}
/**
* 功能点管理的数据
* @param {*} params
*/
export
function
createMenuItem
(
params
)
{
return
request
({
url
:
'
/menus
'
,
method
:
'
post
'
,
params
});
}
/**
* 功能点管理的数据
* @param {*} params
*/
export
function
updateMenuItem
(
params
)
{
return
request
({
url
:
'
/menus
'
,
method
:
'
put
'
,
params
});
}
/**
* 功能点管理的数据
* @param {*} params
*/
export
function
delMenuItemsByParent
(
params
)
{
return
request
({
url
:
'
/menus
'
,
method
:
'
delete
'
,
params
});
}
ve-admin/admin-web/src/components/Refresh/index.vue
View file @
875339d5
<!--
* @Author: 一日看尽长安花
* @since: 2020-06-07 14:41:55
* @LastEditTime: 2020-06-
07 14:45:23
* @LastEditTime: 2020-06-
14 18:55:44
* @LastEditors: 一日看尽长安花
* @Description:
-->
<
template
><span></span></
template
>
<
script
>
export
default
{
name
:
'
Refresh
'
,
...
...
ve-admin/admin-web/src/icons/svg/menu.svg
0 → 100644
View file @
875339d5
<svg
t=
"1592122095549"
class=
"icon"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"1126"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"200"
height=
"200"
>
<path
d=
"M864 0h-152c-88.224 0-160 71.776-160 160v152c0 88.224 71.776 160 160 160h152c88.224 0 160-71.776 160-160V160c0-88.224-71.776-160-160-160z m80 312c0 44.112-35.888 80-80 80h-152c-44.112 0-80-35.888-80-80V160c0-44.112 35.888-80 80-80h152c44.112 0 80 35.888 80 80v152zM312 0H160C71.776 0 0 71.776 0 160v152c0 88.224 71.776 160 160 160h152c88.224 0 160-71.776 160-160V160c0-88.224-71.776-160-160-160z m80 312c0 44.112-35.888 80-80 80H160c-44.112 0-80-35.888-80-80V160c0-44.112 35.888-80 80-80h152c44.112 0 80 35.888 80 80v152zM312 552H160c-88.224 0-160 71.776-160 160v152c0 88.224 71.776 160 160 160h152c88.224 0 160-71.776 160-160v-152c0-88.224-71.776-160-160-160z m80 312c0 44.112-35.888 80-80 80H160c-44.112 0-80-35.888-80-80v-152c0-44.112 35.888-80 80-80h152c44.112 0 80 35.888 80 80v152zM984 824c-22.092 0-40 17.908-40 40 0 44.112-35.888 80-80 80h-152c-44.112 0-80-35.888-80-80v-152c0-44.112 35.888-80 80-80h152a80.06 80.06 0 0 1 73.35 47.992c8.85 20.242 32.436 29.472 52.676 20.624 20.242-8.852 29.474-32.436 20.624-52.676C985.164 589.658 927.6 552 864 552h-152c-88.224 0-160 71.776-160 160v152c0 88.224 71.776 160 160 160h152c88.224 0 160-71.776 160-160 0-22.092-17.908-40-40-40z"
p-id=
"1127"
></path>
</svg>
ve-admin/admin-web/src/views/functions/select_dialog.vue
View file @
875339d5
<!--
* @Author: 一日看尽长安花
* @since: 2020-05-30 12:53:38
* @LastEditTime: 2020-06-
06 18:44:44
* @LastEditTime: 2020-06-
14 15:23:59
* @LastEditors: 一日看尽长安花
* @Description:
-->
<
template
>
<el-dialog
id=
"sel-func-dialog"
:key=
"Math.random()"
title=
"功能点选择"
:visible=
"visible"
@
update:visible=
"$emit('update:visible', $event)"
>
<el-input
v-model=
"filterText"
placeholder=
"输入关键字进行过滤"
@
input=
"filterInput"
>
</el-input>
<el-input
v-model=
"filterText"
placeholder=
"输入关键字进行过滤"
>
</el-input>
<el-tree
:key=
"Math.random()"
ref=
"tree"
:data=
"treeData"
node-key=
"id"
...
...
@@ -82,10 +75,12 @@ export default {
filterText
:
''
};
},
watch
:
{
filterText
(
nv
,
ov
)
{
this
.
$refs
.
tree
.
filter
(
nv
);
}
},
methods
:
{
filterInput
(
value
)
{
this
.
$refs
.
tree
.
filter
(
value
);
},
filterNode
(
value
,
data
)
{
if
(
!
value
)
return
true
;
return
data
.
name
.
indexOf
(
value
)
!==
-
1
;
...
...
ve-admin/admin-web/src/views/menus/index.vue
0 → 100644
View file @
875339d5
<!--
* @Author: 一日看尽长安花
* @since: 2020-05-30 12:53:38
* @LastEditTime: 2020-06-14 18:58:00
* @LastEditors: 一日看尽长安花
* @Description:
-->
<
template
>
<!-- vue实例外创建 -->
<div
id=
"menu-manager"
class=
"sp-transfer_editor--two"
>
<div
class=
"sp-side_panel--left"
>
<el-input
v-model=
"filterText"
placeholder=
"输入关键字进行过滤"
>
</el-input>
<el-tree
key=
"treeKey"
ref=
"tree"
:data=
"treeData"
node-key=
"id"
default-expand-all
:expand-on-click-node=
"false"
:filter-node-method=
"filterNode"
>
<template
v-slot=
"
{ node: node, data: data }">
<div
:class=
"['sp-tree_node', 'sp-tree_node_type--' + data.type]"
>
<span>
{{
data
.
name
}}
</span>
<span>
<el-button
plain
type=
"primary"
size=
"mini"
@
click=
"appendNode(node, data)"
>
添加
</el-button>
<el-button
v-if=
"data.id !== 0"
plain
type=
"primary"
size=
"mini"
@
click=
"editNode(node, data)"
>
编辑
</el-button>
<el-button
v-if=
"data.id !== 0"
plain
type=
"primary"
size=
"mini"
@
click=
"removeNode(node, data)"
>
删除
</el-button>
</span>
</div>
</
template
>
</el-tree>
</div>
<div
class=
"sp-side_panel--right"
>
<el-form
key=
"formKey"
ref=
"nodeForm"
:rules=
"rules"
:model=
"formModel"
label-width=
"80px"
>
<el-form-item
label=
"功能名"
prop=
"name"
>
<el-input
v-model=
"formModel.name"
placeholder=
"请输入菜单名称"
></el-input>
</el-form-item>
<el-form-item
label=
"菜单代码"
prop=
"code"
>
<el-input
v-model=
"formModel.code"
placeholder=
"请输入系统唯一菜单代码"
></el-input>
</el-form-item>
<el-form-item
label=
"菜单地址"
prop=
"relation_function"
>
<el-input
v-model=
"formModel.relation_function.access_url"
placeholder=
"请选择关联功能点"
readonly
@
focus=
"openSelectRelationFunctionLayer"
></el-input>
</el-form-item>
<el-form-item
label=
"菜单图标"
>
<el-input
v-model=
"formModel.icon"
placeholder=
"请输入已有的svg图标,询问前端"
></el-input>
</el-form-item>
<el-form-item
label=
"菜单序号"
>
<el-input
v-model=
"formModel.seq"
placeholder=
"请输入本级中的菜单序号"
></el-input>
</el-form-item>
<el-form-item
label=
"父菜单"
prop=
"parent"
>
<el-input
v-model=
"formModel.parent.name"
placeholder=
"点击选择上一级菜单"
readonly
@
focus=
"openSelectParentNodeLayer"
></el-input>
</el-form-item>
<el-form-item
label=
"菜单类型"
prop=
"type"
>
<el-select
v-model=
"formModel.type"
placeholder=
"请选择菜单类型"
>
<el-option
label=
"系统"
value=
"MENU_S"
></el-option>
<el-option
label=
"导航"
value=
"MENU_N"
></el-option>
<el-option
label=
"菜单"
value=
"MENU_M"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"saveNode"
>
保存
</el-button>
<el-button>
取消
</el-button>
</el-form-item>
</el-form>
</div>
<sel-func-dialog
v-model=
"formModel"
:per-level-label=
"['relation_function']"
:visible.sync=
"selFuncDialogVisible"
:tree-data=
"funcTreeData"
>
</sel-func-dialog>
<sel-menu-dialog
v-model=
"formModel"
:per-level-label=
"['parent']"
:visible.sync=
"selParentDialogVisible"
:tree-data=
"treeData"
>
</sel-menu-dialog>
</div>
</template>
<
script
>
/** 菜单管理 */
import
{
menus
,
createMenuItem
,
updateMenuItem
,
delMenuItemsByParent
}
from
'
@/api/menu
'
;
import
{
funcs
}
from
'
@/api/func
'
;
import
SelFuncDialog
from
'
@/views/functions/select_dialog
'
;
import
SelMenuDialog
from
'
./select_dialog
'
;
export
default
{
name
:
'
MenuMange
'
,
components
:
{
SelFuncDialog
,
SelMenuDialog
},
props
:
{},
data
()
{
return
{
filterText
:
''
,
treeData
:
[],
funcTreeData
:
[],
formModel
:
{
parent
:
{
id
:
undefined
,
name
:
undefined
},
relation_function
:
{
id
:
undefined
,
name
:
undefined
}
},
actType
:
'
create
'
,
selFuncDialogVisible
:
false
,
selParentDialogVisible
:
false
,
rules
:
{
name
:
{
required
:
true
,
message
:
'
请输入名称
'
,
trigger
:
'
blur
'
},
code
:
{
required
:
true
,
message
:
'
请输入代码点
'
,
trigger
:
'
blur
'
},
relation_function
:
{
type
:
'
object
'
,
required
:
true
,
fields
:
{
access_url
:
{
type
:
'
string
'
,
message
:
'
请选择关联功能点
'
,
required
:
true
}
}
},
parent
:
{
type
:
'
object
'
,
required
:
true
,
fields
:
{
name
:
{
type
:
'
string
'
,
message
:
'
请选择父功能
'
,
required
:
true
}
}
},
type
:
{
type
:
'
string
'
,
required
:
true
,
message
:
'
请选择访问类型
'
,
trigger
:
'
change
'
}
}
};
},
watch
:
{
filterText
(
val
)
{
this
.
$refs
.
tree
.
filter
(
val
);
}
},
mounted
()
{
menus
().
then
(
res
=>
{
const
{
code
,
message
,
data
}
=
{
...
res
};
const
vmNode
=
[
{
id
:
0
,
name
:
'
平台
'
,
children
:
data
}
];
this
.
treeData
=
vmNode
;
});
funcs
().
then
(
res
=>
{
const
{
code
,
message
,
data
}
=
{
...
res
};
const
vmNode
=
[
{
id
:
-
1
,
name
:
'
平台
'
,
children
:
data
}
];
this
.
funcTreeData
=
vmNode
;
});
},
methods
:
{
filterNode
(
value
,
data
)
{
if
(
!
value
)
return
true
;
return
data
.
name
.
indexOf
(
value
)
!==
-
1
;
},
appendNode
(
node
,
data
)
{
this
.
formModel
=
{
parent
:
{
id
:
undefined
,
name
:
undefined
},
relation_function
:
{
id
:
undefined
,
name
:
undefined
}
};
this
.
formModel
.
parent
=
data
;
this
.
actType
=
'
create
'
;
},
editNode
(
node
,
data
)
{
this
.
formModel
=
data
;
this
.
formModel
.
parent
=
node
.
parent
.
data
;
this
.
actType
=
'
editor
'
;
},
removeNode
(
node
,
data
)
{
const
ids
=
this
.
getTreeBranchIds
(
node
);
this
.
$confirm
(
'
此操作将永久删除该菜单及其子菜单, 是否继续?
'
,
'
提示
'
,
{
confirmButtonText
:
'
确定
'
,
cancelButtonText
:
'
取消
'
,
type
:
'
warning
'
})
.
then
(()
=>
{
delMenuItemsByParent
({
ids
:
ids
}).
then
(
response
=>
{
const
{
code
,
message
,
data
}
=
{
...
response
};
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
'
Loading
'
,
spinner
:
'
el-icon-loading
'
,
background
:
'
rgba(0, 0, 0, 0.7)
'
});
const
_that
=
this
;
this
.
$message
({
message
:
'
删除成功
'
,
type
:
'
success
'
,
onClose
:
function
(
_instance
)
{
_that
.
$router
.
replace
(
'
/refresh
'
);
loading
.
close
();
}
});
});
})
.
catch
(()
=>
{});
},
getTreeBranchIds
(
node
)
{
let
ids
=
[];
ids
.
push
(
node
.
data
.
id
);
const
_children
=
node
.
childNodes
;
for
(
let
i
=
0
;
i
<
_children
.
length
;
i
++
)
{
const
child
=
_children
[
i
];
let
_child_ids
=
this
.
getTreeBranchIds
(
child
);
ids
=
ids
.
concat
(
_child_ids
);
}
return
ids
;
},
saveNode
()
{
const
_that
=
this
;
_that
.
$refs
.
nodeForm
.
validate
(
valid
=>
{
if
(
!
valid
)
{
_that
.
$message
.
error
(
'
数据请填写完成
'
);
return
false
;
}
// 解除循环引用
delete
_that
.
formModel
.
parent
.
children
;
if
(
_that
.
actType
===
'
create
'
)
{
_that
.
formModel
.
parent_menu_id
=
_that
.
formModel
.
parent
.
id
;
createMenuItem
(
_that
.
formModel
).
then
(
response
=>
{
const
{
code
,
message
,
data
}
=
{
...
response
};
const
_that
=
this
;
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
'
Loading
'
,
spinner
:
'
el-icon-loading
'
,
background
:
'
rgba(0, 0, 0, 0.7)
'
});
this
.
$message
({
message
:
'
创建菜单成功
'
,
type
:
'
success
'
,
onClose
:
function
(
_instance
)
{
// todo 可以用组件Mixin改写,或者直接挂载到Router原型上
_that
.
$router
.
replace
(
'
/refresh
'
);
loading
.
close
();
}
});
});
}
else
{
updateMenuItem
(
_that
.
formModel
).
then
(
response
=>
{
const
{
code
,
message
,
data
}
=
{
...
response
};
const
_that
=
this
;
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
'
Loading
'
,
spinner
:
'
el-icon-loading
'
,
background
:
'
rgba(0, 0, 0, 0.7)
'
});
this
.
$message
({
message
:
'
更新菜单成功
'
,
type
:
'
success
'
,
onClose
:
function
(
_instance
)
{
// todo 可以用组件Mixin改写,或者直接挂载到Router原型上
_that
.
$router
.
replace
(
'
/refresh
'
);
loading
.
close
();
}
});
});
}
});
},
openSelectParentNodeLayer
()
{
this
.
selParentDialogVisible
=
true
;
},
openSelectRelationFunctionLayer
()
{
this
.
selFuncDialogVisible
=
true
;
}
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.sp-transfer_editor--two
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
stretch
;
margin
:
10px
;
min-height
:
84vh
;
max-height
:
84vh
;
}
%sp-side_panel--common
{
flex-grow
:
1
;
flex-shrink
:
1
;
flex-basis
:
0%
;
box-shadow
:
2px
2px
6px
1px
#aaa
;
padding
:
10px
;
margin
:
0
10px
;
}
.sp-side_panel--left
{
@extend
%sp-side_panel--common
;
overflow-y
:
scroll
;
}
.sp-side_panel--right
{
@extend
%sp-side_panel--common
;
}
.sp-tree_node
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
width
:
100%
;
padding-left
:
6px
;
border-radius
:
5px
;
}
%sp-tree_node_type
{
box-shadow
:
1px
1px
1px
1px
#e8f4ff
;
}
.sp-tree_node_type--MENU_S
{
@extend
%sp-tree_node_type
;
background
:
linear-gradient
(
to
right
,
#ff0303
5e
,
transparent
);
}
.sp-tree_node_type--MENU_N
{
@extend
%sp-tree_node_type
;
background
:
linear-gradient
(
to
right
,
#fff503
5e
,
transparent
);
}
.sp-tree_node_type--MENU_M
{
@extend
%sp-tree_node_type
;
background
:
linear-gradient
(
to
right
,
#033cff
5e
,
transparent
);
}
</
style
>
<
style
lang=
"scss"
>
.el-tree-node
{
margin-top
:
5px
;
}
</
style
>
ve-admin/admin-web/src/views/menus/select_dialog.vue
0 → 100644
View file @
875339d5
<!--
* @Author: 一日看尽长安花
* @since: 2020-05-30 12:53:38
* @LastEditTime: 2020-06-14 15:24:13
* @LastEditors: 一日看尽长安花
* @Description:
-->
<
template
>
<el-dialog
id=
"sel-menu-dialog"
title=
"菜单选择"
:visible=
"visible"
@
update:visible=
"$emit('update:visible', $event)"
>
<el-input
v-model=
"filterText"
placeholder=
"输入关键字进行过滤"
>
</el-input>
<el-tree
ref=
"tree"
:data=
"treeData"
node-key=
"id"
:label=
"label"
:show-checkbox=
"true"
default-expand-all
:check-strictly=
"true"
:expand-on-click-node=
"false"
:filter-node-method=
"filterNode"
>
<template
v-slot=
"
{ node: node, data: data }">
<div
:class=
"['sp-tree_node', 'sp-tree_node_type--' + data.type]"
>
<span>
{{
data
.
name
}}
</span>
</div>
</
template
>
</el-tree>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
type=
"primary"
@
click=
"saveSelect"
>
确 定
</el-button>
</div>
</el-dialog>
</template>
<
script
>
export
default
{
name
:
'
SelMenuDialog
'
,
components
:
{},
model
:
{
prop
:
'
value
'
,
event
:
'
updateValue
'
},
props
:
{
visible
:
{
type
:
Boolean
,
default
:
false
},
treeData
:
{
type
:
Array
,
default
:
function
()
{
return
[];
}
},
label
:
{
type
:
String
,
default
:
'
name
'
},
perLevelLabel
:
{
type
:
Array
,
required
:
true
},
value
:
{
type
:
Object
,
required
:
true
}
},
data
()
{
return
{
filterText
:
''
};
},
watch
:
{
filterText
(
nv
)
{
this
.
$refs
.
tree
.
filter
(
nv
);
}
},
methods
:
{
filterNode
(
value
,
data
)
{
if
(
!
value
)
return
true
;
return
data
.
name
.
indexOf
(
value
)
!==
-
1
;
},
saveSelect
()
{
// 包括半选节点
const
selNodes
=
this
.
$refs
.
tree
.
getCheckedNodes
(
false
,
true
);
if
(
selNodes
&&
selNodes
.
length
===
0
)
{
this
.
$emit
(
'
update:visible
'
,
false
);
}
if
(
selNodes
&&
selNodes
.
length
!==
1
)
{
this
.
$message
({
message
:
'
只能选择一个节点
'
,
type
:
'
warning
'
});
return
;
}
let
_node
=
this
.
$refs
.
tree
.
getNode
(
selNodes
[
0
]);
let
resObj
=
{};
for
(
let
i
=
this
.
perLevelLabel
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
_label
=
this
.
perLevelLabel
[
i
];
this
.
$lodash
.
set
(
resObj
,
_label
,
_node
.
data
);
_node
=
_node
.
parent
;
}
const
updateValue
=
this
.
$lodash
.
assignIn
({},
this
.
value
,
resObj
);
this
.
$emit
(
'
updateValue
'
,
updateValue
);
this
.
$emit
(
'
update:visible
'
,
false
);
}
}
};
</
script
>
<
style
lang=
"scss"
scoped
>
.sp-tree_node
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
width
:
100%
;
padding-left
:
6px
;
border-radius
:
5px
;
}
%sp-tree_node_type
{
box-shadow
:
1px
1px
1px
1px
#e8f4ff
;
}
.sp-tree_node_type--MENU_S
{
@extend
%sp-tree_node_type
;
background
:
linear-gradient
(
to
right
,
#ff0303
5e
,
transparent
);
}
.sp-tree_node_type--MENU_N
{
@extend
%sp-tree_node_type
;
background
:
linear-gradient
(
to
right
,
#fff503
5e
,
transparent
);
}
.sp-tree_node_type--MENU_M
{
@extend
%sp-tree_node_type
;
background
:
linear-gradient
(
to
right
,
#033cff
5e
,
transparent
);
}
</
style
>
<
style
lang=
"scss"
>
.el-dialog
{
height
:
90%
;
overflow-y
:
scroll
;
top
:
-10vh
;
margin-bottom
:
-5vh
;
}
.el-tree-node
{
margin-top
:
5px
;
}
</
style
>
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment