Commit 556cb3d8 authored by trumansdo's avatar trumansdo
Browse files

vue最新版实现完全的异步加载组件

parent fb33a03c
# --------自定义应用属性
app:
name: SpringBoot-Plus
#打开审计功能,开发模式应该关闭
audit:
enable: false
# 1,1 是管理员密码,相当于启动后就登录,方便测试,系统需要取消这俩个配置
user:
id: 1
orgId: 1
# 文件操作的根目录配置 请根据各自计算机配置
localFile:
root: E:\code_workspace\temp_space\
# --------beetl配置
beetl:
suffix: html
# -------beetlsql配置
beetlsql:
ds:
baseDataSource:
basePackage: com.ibeetl.admin
daoSuffix: Dao
dbStyle: org.beetl.sql.core.db.MySqlStyle
mutiple:
datasource: baseDataSource
# -------- 文件预览配置
#文档预览服务的调用地址,参考https://gitee.com/kekingcn/file-online-preview 安装,没有如下配置无法使用预览功能
file:
previewURL: http://localhost:8012/onlinePreview
# ---------日志配置
logging:
level:
org:
springframework:
boot:
autoconfigure: ERROR
web:
servlet:
mvc:
method:
annotation: warn
root: info
pattern:
console: '%-4relative [%thread] %-5level %logger{256} %M %L - %msg%n'
# --------服务器undertow配置
server:
port: 8080
undertow:
accesslog:
enabled: true
buffer-size: 4096
direct-buffers: true
io-threads: 4
worker-threads: 20
spring:
cache:
type: caffeine
# 数据源配置
datasource:
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
username: root
session:
store-type: none
......@@ -5,11 +5,11 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import java.util.Comparator;
import lombok.Data;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.Data;
/**
* 对应前端页面的routes路由表。具体格式如下: { "path": "/profile", "name": "router-name", "meta": { "title":
......@@ -20,60 +20,77 @@ import lombok.Data;
@Data
public class CoreRoute extends BaseEntity implements Comparable<CoreRoute> {
private Long id;
private Long id;
private Long parentId;
private Long parentId;
/** 路由路径,完全参照vue router规范 */
private String path;
/**
* 路由路径,完全参照vue router规范
*/
private String path;
/** 路由名称,请确保唯一性 */
private String name;
/**
* 路由名称,请确保唯一性
*/
private String name;
/** 路由顺序 */
private Long seq = -999L;
/**
* 路由组件component
*/
private String component;
/** 路由元数据信息 */
private CoreRouteMeta meta;
/**
* 路由顺序
*/
private Long seq = -999L;
/** 子路由项 */
private List<CoreRoute> children = CollUtil.newArrayList();
/**
* 路由元数据信息
*/
private CoreRouteMeta meta;
public CoreRouteMeta getMeta() {
if (ObjectUtil.isNotEmpty(this.meta)) return this.meta;
Map<String, Object> metaMap = MapUtil.builder(getTails()).build();
this.meta = BeanUtil.mapToBean(metaMap, CoreRouteMeta.class, true);
return this.meta;
}
/**
* 子路由项
*/
private List<CoreRoute> children = CollUtil.newArrayList();
@Override
public boolean equals(Object o) {
if (o != null && o instanceof CoreRoute) {
CoreRoute othRoute = (CoreRoute) o;
if (this.getId().equals(othRoute.getId())) {
return true;
}
if (this.getParentId().equals(othRoute.getParentId())) {
return StrUtil.equals(this.getPath(), othRoute.getPath())
&& StrUtil.equals(this.getName(), othRoute.getName());
} else {
return false;
}
} else {
return false;
public CoreRouteMeta getMeta() {
if (ObjectUtil.isNotEmpty(this.meta)) {
return this.meta;
}
Map<String, Object> metaMap = MapUtil.builder(getTails()).build();
this.meta = BeanUtil.mapToBean(metaMap, CoreRouteMeta.class, true);
return this.meta;
}
}
@Override
public int hashCode() {
return Objects.hash(id, parentId, path, name);
}
@Override
public boolean equals(Object o) {
if (o != null && o instanceof CoreRoute) {
CoreRoute othRoute = (CoreRoute) o;
if (this.getId().equals(othRoute.getId())) {
return true;
}
if (this.getParentId().equals(othRoute.getParentId())) {
return StrUtil.equals(this.getPath(), othRoute.getPath())
&& StrUtil.equals(this.getName(), othRoute.getName());
} else {
return false;
}
} else {
return false;
}
}
@Override
public int compareTo(CoreRoute o) {
if (null == o) return -1;
Long seq1 = this.getSeq() == null ? -999L : this.getSeq();
Long seq2 = o.getSeq() == null ? -999L : o.getSeq();
return seq1.compareTo(seq2);
}
@Override
public int hashCode() {
return Objects.hash(id, parentId, path, name);
}
@Override
public int compareTo(CoreRoute o) {
if (null == o) return -1;
Long seq1 = this.getSeq() == null ? -999L : this.getSeq();
Long seq2 = o.getSeq() == null ? -999L : o.getSeq();
return seq1.compareTo(seq2);
}
}
package com.ibeetl.admin.core.entity;
import cn.hutool.core.collection.CollUtil;
import java.util.List;
import lombok.Data;
import java.util.List;
@Data
public class CoreRouteMeta {
/** 路由展示在菜单中显示的标题 */
private String title;
/**
* 路由展示在菜单中显示的标题
*/
private String title;
/** 在菜单中显示的图标 */
private String icon;
/**
* 在菜单中显示的图标
*/
private String icon;
/** 当前路由可以访问的角色 */
private List<Long> roles = CollUtil.<Long>newArrayList();
/**
* 当前路由可以访问的角色
*/
private List<Long> roles = CollUtil.<Long>newArrayList();
}
......@@ -66,7 +66,7 @@ public class RoleRoutesElService {
* */
public List<CoreRoute> getRoutes() {
List<CoreRoute> routesList = coreFunctionDao.getAllRoutes();
Map<Long, List<Long>> roleIdList =
/*Map<Long, List<Long>> roleIdList =
routesList.stream()
.collect(
Collectors.groupingBy(
......@@ -80,7 +80,7 @@ public class RoleRoutesElService {
.getMeta()
.getRoles()
.addAll(CollUtil.<Long>removeNull(roleIdList.get(coreRoute.getId())));
}
}*/
CoreRoute root = new CoreRoute();
root.setId(0L);
buildRoutesTree(root, routesList);
......@@ -95,7 +95,9 @@ public class RoleRoutesElService {
* @return
*/
private void buildRoutesTree(CoreRoute root, @NotNull List<CoreRoute> allRoutes) {
if (CollUtil.isEmpty(allRoutes)) return;
if (CollUtil.isEmpty(allRoutes)) {
return;
}
List<CoreRoute> childRoutes =
allRoutes.stream()
.filter(route -> route.getParentId().equals(root.getId()))
......
getAllRoutes
===
```sql
select menu.id,
menu.PARENT_MENU_ID PARENT_ID,
menu.PARENT_MENU_ID parent_id,
menu.NAME title,
menu.CODE name,
menu.ICON,
ifnull(menu.SEQ, 999999) seq,
func.ACCESS_URL path,
func.COMPONENT component,
role_menu.ROLE_ID
from core_menu menu
left join core_function func on func.ID = menu.FUNCTION_ID
......@@ -28,6 +28,7 @@ RouteMapping
"resultType": "com.ibeetl.admin.core.entity.CoreRoute",
"path": "path",
"name": "name",
"component": "component",
"id": "id",
"parentId": "parent_id",
"seq": "seq",
......
/*
* @Author: 一日看尽长安花
* @since: 2019-09-04 20:55:14
* @LastEditTime: 2019-10-29 23:17:53
* @LastEditTime: 2020-05-07 14:39:43
* @LastEditors: 一日看尽长安花
* @Description:
*/
......@@ -96,7 +96,18 @@ module.exports = {
// 关闭检测函数名称和调用它的左括号之间的空格
// 'func-call-spacing': 'off',
// 缩进为2个空格
indent: ['error', 2],
indent: [
'error',
2,
{
ignoredNodes: [
'TemplateLiteral'
]
}
],
'template-curly-spacing': [
'off'
],
// 关闭检测未使用的变量
'no-unused-vars': 'off',
// 对象展开时总是要添加逗号,一行时行末不需要逗号
......
......@@ -81,6 +81,8 @@
"devDependencies": {
"@babel/core": "7.0.0",
"@babel/register": "7.0.0",
"@babel/traverse": "^7.9.6",
"@babel/types": "^7.9.6",
"@vue/cli-plugin-babel": "4.2.3",
"@vue/cli-plugin-eslint": "^4.2.3",
"@vue/cli-plugin-unit-jest": "4.2.3",
......
/*
* @Author: 一日看尽长安花
* @since: 2019-12-01 11:03:53
* @LastEditTime: 2020-05-07 14:46:53
* @LastEditors: 一日看尽长安花
* @Description:
*/
/**
* 点击波纹效果
*
......@@ -6,34 +13,48 @@
* @return {[bollean]} [description]
*/
export default function(e, arg_opts) {
var opts = Object.assign({
ele: e.target, // 波纹作用元素
type: 'hit', // hit点击位置扩散center中心点扩展
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
}, arg_opts)
var target = opts.ele
var opts = Object.assign(
{
ele: e.target, // 波纹作用元素
type: 'hit', // hit点击位置扩散center中心点扩展
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
},
arg_opts
);
var target = opts.ele;
if (target) {
var rect = target.getBoundingClientRect()
var ripple = target.querySelector('.e-ripple')
var rect = target.getBoundingClientRect();
var ripple = target.querySelector('.e-ripple');
if (!ripple) {
ripple = document.createElement('span')
ripple.className = 'e-ripple'
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
target.appendChild(ripple)
ripple = document.createElement('span');
ripple.className = 'e-ripple';
ripple.style.height = ripple.style.width =
Math.max(rect.width, rect.height) + 'px';
target.appendChild(ripple);
} else {
ripple.className = 'e-ripple'
ripple.className = 'e-ripple';
}
switch (opts.type) {
case 'center':
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
break
default:
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
case 'center':
ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px';
ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px';
break;
default:
ripple.style.top =
e.pageY -
rect.top -
ripple.offsetHeight / 2 -
document.body.scrollTop +
'px';
ripple.style.left =
e.pageX -
rect.left -
ripple.offsetWidth / 2 -
document.body.scrollLeft +
'px';
}
ripple.style.backgroundColor = opts.bgc
ripple.className = 'e-ripple z-active'
return false
ripple.style.backgroundColor = opts.bgc;
ripple.className = 'e-ripple z-active';
return false;
}
}
......@@ -2,7 +2,7 @@
* @Description: In User Settings Edit
* @Author: your name
* @Date: 2019-09-09 12:16:28
* @LastEditTime: 2019-10-30 20:32:19
* @LastEditTime: 2020-05-07 15:03:38
* @LastEditors: 一日看尽长安花
*/
import { constantRoutes } from '@/router';
......@@ -11,6 +11,8 @@ import { default as asyncRoutesMap } from '@/router/maps/index';
import { deepClone, objectMerge } from '@/utils/index';
import { isExists, isNotExists } from '@/utils/object-util';
import Layout from '@/layout';
/**
* Use meta.role to determine if the current user has permission
* @param roles
......@@ -76,6 +78,29 @@ export function filterAsyncRoutes(routesMap, routes, roles) {
return resRoutes;
}
export function handleComponent(routes) {
for (let i in routes) {
let _route = routes[i];
if (_route.component && _route.component.trim().length > 0) {
if (_route.component === 'layout') {
_route.component = Layout;
} else {
/** 这里的异步不能直接在import里用template string写法,babel-eslint有bug*/
/** 两种异步写法:
* component = resolve => require([`@/views/modules/${URL}`], resolve);
* component = () => import(`@/${_route.component}`);这个也有问题
*/
//这一步多余的赋值遍历必须存在,import的bug
const name = _route.component;
_route.component = () => import(`@/${name}`);
}
}
if (_route.children && _route.children.length > 0) {
handleComponent(_route.children);
}
}
}
const state = {
routes: [],
addRoutes: []
......@@ -93,18 +118,11 @@ const actions = {
return new Promise((resolve, reject) => {
getRoutes()
.then(response => {
let accessedRoutes,
asyncRoutes = response.data;
accessedRoutes = filterAsyncRoutes(
deepClone(asyncRoutesMap),
asyncRoutes,
roles
);
accessedRoutes.push({ path: '*', redirect: '/404', hidden: true });
commit('SET_ROUTES', accessedRoutes);
resolve(accessedRoutes);
let asyncRoutes = response.data;
handleComponent(asyncRoutes);
asyncRoutes.push({ path: '*', redirect: '/404', hidden: true });
commit('SET_ROUTES', asyncRoutes);
resolve(asyncRoutes);
})
.catch(error => {
reject(error);
......
@import './variables.scss';
#app {
.main-container {
min-height: 100%;
transition: margin-left .28s;
transition: margin-left 0.28s;
margin-left: $sideBarWidth;
position: relative;
}
......@@ -22,7 +22,8 @@
// reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
transition: 0s width ease-in-out, 0s padding-left ease-in-out,
0s padding-right ease-in-out;
}
.scrollbar-wrapper {
......@@ -71,11 +72,11 @@
}
}
.is-active>.el-submenu__title {
.is-active > .el-submenu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-submenu>.el-submenu__title,
& .nest-menu .el-submenu > .el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
......@@ -111,7 +112,7 @@
.el-submenu {
overflow: hidden;
&>.el-submenu__title {
& > .el-submenu__title {
padding: 0 !important;
.svg-icon {
......@@ -126,8 +127,8 @@
.el-menu--collapse {
.el-submenu {
&>.el-submenu__title {
&>span {
& > .el-submenu__title {
& > span {
height: 0;
width: 0;
overflow: hidden;
......@@ -150,7 +151,7 @@
}
.sidebar-container {
transition: transform .28s;
transition: transform 0.28s;
width: $sideBarWidth !important;
}
......@@ -164,7 +165,6 @@
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
......@@ -174,13 +174,13 @@
// when menu collapsed
.el-menu--vertical {
&>.el-menu {
& > .el-menu {
.svg-icon {
margin-right: 16px;
}
}
.nest-menu .el-submenu>.el-submenu__title,
.nest-menu .el-submenu > .el-submenu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
......@@ -189,7 +189,7 @@
}
// the scroll bar appears when the subMenu is too long
>.el-menu--popup {
> .el-menu--popup {
max-height: 100vh;
overflow-y: auto;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment