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
Litemall
Commits
2786b410
Commit
2786b410
authored
Jun 13, 2020
by
Junling Bu
Browse files
feat[litemall-admin]: 更新vue-element-admin到4.3.0
parent
92cfea63
Changes
21
Hide whitespace changes
Inline
Side-by-side
litemall-admin/package.json
View file @
2786b410
{
"name"
:
"litemall-admin"
,
"version"
:
"1.0.0"
,
"description"
:
"litemall-admin basing on vue-element-admin 4.
2.1
"
,
"description"
:
"litemall-admin basing on vue-element-admin 4.
3.0
"
,
"author"
:
"linlinjava <linlinjava@163.com>"
,
"license"
:
"MIT"
,
"scripts"
:
{
...
...
@@ -50,13 +50,14 @@
"clipboard"
:
"2.0.4"
,
"connect"
:
"3.6.6"
,
"echarts"
:
"4.2.1"
,
"element-ui"
:
"2.1
2.0
"
,
"element-ui"
:
"2.1
3.2
"
,
"file-saver"
:
"1.3.8"
,
"js-cookie"
:
"2.2.0"
,
"normalize.css"
:
"7.0.0"
,
"nprogress"
:
"0.2.0"
,
"path-to-regexp"
:
"2.4.0"
,
"screenfull"
:
"4.2.0"
,
"script-loader"
:
"0.7.2"
,
"vue"
:
"2.6.10"
,
"vue-count-to"
:
"1.0.13"
,
"vue-router"
:
"3.0.2"
,
...
...
@@ -83,11 +84,10 @@
"html-webpack-plugin"
:
"3.2.0"
,
"husky"
:
"1.3.1"
,
"lint-staged"
:
"8.1.5"
,
"
node-
sass"
:
"^
4.9.0
"
,
"sass"
:
"^
1.26.2
"
,
"runjs"
:
"^4.3.2"
,
"sass-loader"
:
"^7.1.0"
,
"script-ext-html-webpack-plugin"
:
"2.1.3"
,
"script-loader"
:
"0.7.2"
,
"serve-static"
:
"^1.13.2"
,
"svg-sprite-loader"
:
"4.1.3"
,
"svgo"
:
"1.2.0"
,
...
...
litemall-admin/src/components/Notice/index.vue
View file @
2786b410
...
...
@@ -42,7 +42,7 @@ export default {
</
script
>
<
style
lang=
"scss"
scoped
>
/
deep
/
.el-badge__content.is-fixed.is-dot
{
::v-
deep
.el-badge__content.is-fixed.is-dot
{
right
:
5px
;
top
:
10px
;
}
...
...
litemall-admin/src/components/ScrollPane/index.vue
View file @
2786b410
<
template
>
<el-scrollbar
ref=
"scrollContainer"
:vertical=
"false"
class=
"scroll-container"
@
wheel.native.prevent=
"handleScroll"
>
<slot/>
<slot
/>
</el-scrollbar>
</
template
>
...
...
@@ -80,7 +80,7 @@ export default {
position
:
relative
;
overflow
:
hidden
;
width
:
100%
;
/
deep
/
{
::v-
deep
{
.el-scrollbar__bar
{
bottom
:
0px
;
}
...
...
litemall-admin/src/permission.js
View file @
2786b410
...
...
@@ -28,7 +28,7 @@ router.beforeEach((to, from, next) => {
store
.
dispatch
(
'
GetUserInfo
'
).
then
(
res
=>
{
// 拉取user_info
const
perms
=
res
.
data
.
data
.
perms
// note: perms must be a array! such as: ['GET /aaa','POST /bbb']
store
.
dispatch
(
'
GenerateRoutes
'
,
{
perms
}).
then
(()
=>
{
// 根据perms权限生成可访问的路由表
router
.
addRoutes
(
store
.
getters
.
addRoute
r
s
)
// 动态添加可访问路由表
router
.
addRoutes
(
store
.
getters
.
addRoutes
)
// 动态添加可访问路由表
next
({
...
to
,
replace
:
true
})
// hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
})
}).
catch
((
err
)
=>
{
...
...
litemall-admin/src/router/index.js
View file @
2786b410
...
...
@@ -24,14 +24,14 @@ import Layout from '@/views/layout/Layout'
noCache: true if true ,the page will no be cached(default is false)
}
**/
export
const
constantRoute
rMap
=
[
export
const
constantRoute
s
=
[
{
path
:
'
/redirect
'
,
component
:
Layout
,
hidden
:
true
,
children
:
[
{
path
:
'
/redirect/:path
*
'
,
path
:
'
/redirect/:path
(.*)
'
,
component
:
()
=>
import
(
'
@/views/redirect/index
'
)
}
]
...
...
@@ -71,13 +71,7 @@ export const constantRouterMap = [
}
]
export
default
new
Router
({
// mode: 'history', // require service support
scrollBehavior
:
()
=>
({
y
:
0
}),
routes
:
constantRouterMap
})
export
const
asyncRouterMap
=
[
export
const
asyncRoutes
=
[
{
path
:
'
/user
'
,
component
:
Layout
,
...
...
@@ -612,3 +606,19 @@ export const asyncRouterMap = [
{
path
:
'
*
'
,
redirect
:
'
/404
'
,
hidden
:
true
}
]
const
createRouter
=
()
=>
new
Router
({
// mode: 'history', // require service support
scrollBehavior
:
()
=>
({
y
:
0
}),
routes
:
constantRoutes
})
const
router
=
createRouter
()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export
function
resetRouter
()
{
const
newRouter
=
createRouter
()
router
.
matcher
=
newRouter
.
matcher
// reset router
}
export
default
router
litemall-admin/src/store/getters.js
View file @
2786b410
...
...
@@ -8,12 +8,9 @@ const getters = {
token
:
state
=>
state
.
user
.
token
,
avatar
:
state
=>
state
.
user
.
avatar
,
name
:
state
=>
state
.
user
.
name
,
introduction
:
state
=>
state
.
user
.
introduction
,
status
:
state
=>
state
.
user
.
status
,
roles
:
state
=>
state
.
user
.
roles
,
perms
:
state
=>
state
.
user
.
perms
,
setting
:
state
=>
state
.
user
.
setting
,
permission_routers
:
state
=>
state
.
permission
.
routers
,
addRouters
:
state
=>
state
.
permission
.
addRouters
permission_routes
:
state
=>
state
.
permission
.
routes
,
addRoutes
:
state
=>
state
.
permission
.
addRoutes
}
export
default
getters
litemall-admin/src/store/modules/permission.js
View file @
2786b410
import
{
asyncRoute
rMap
,
constantRoute
rMap
}
from
'
@/router
'
import
{
asyncRoute
s
,
constantRoute
s
}
from
'
@/router
'
/**
* 通过meta.perms判断是否与当前用户权限匹配
...
...
@@ -15,16 +15,16 @@ function hasPermission(perms, route) {
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param routes asyncRoute
rMap
* @param routes asyncRoute
s
* @param perms
*/
function
filterAsyncRoute
r
(
routes
,
perms
)
{
function
filterAsyncRoute
s
(
routes
,
perms
)
{
const
res
=
[]
routes
.
forEach
(
route
=>
{
const
tmp
=
{
...
route
}
if
(
tmp
.
children
)
{
tmp
.
children
=
filterAsyncRoute
r
(
tmp
.
children
,
perms
)
tmp
.
children
=
filterAsyncRoute
s
(
tmp
.
children
,
perms
)
if
(
tmp
.
children
&&
tmp
.
children
.
length
>
0
)
{
res
.
push
(
tmp
)
}
...
...
@@ -40,26 +40,26 @@ function filterAsyncRouter(routes, perms) {
const
permission
=
{
state
:
{
route
r
s
:
constantRoute
rMap
,
addRoute
r
s
:
[]
routes
:
constantRoute
s
,
addRoutes
:
[]
},
mutations
:
{
SET_ROUTE
R
S
:
(
state
,
route
r
s
)
=>
{
state
.
addRoute
r
s
=
route
r
s
state
.
route
r
s
=
constantRoute
rMap
.
concat
(
route
r
s
)
SET_ROUTES
:
(
state
,
routes
)
=>
{
state
.
addRoutes
=
routes
state
.
routes
=
constantRoute
s
.
concat
(
routes
)
}
},
actions
:
{
GenerateRoutes
({
commit
},
data
)
{
return
new
Promise
(
resolve
=>
{
const
{
perms
}
=
data
let
accessedRoute
r
s
let
accessedRoutes
if
(
perms
.
includes
(
'
*
'
))
{
accessedRoute
r
s
=
asyncRoute
rMap
accessedRoutes
=
asyncRoute
s
}
else
{
accessedRoute
r
s
=
filterAsyncRoute
r
(
asyncRoute
rMap
,
perms
)
accessedRoutes
=
filterAsyncRoute
s
(
asyncRoute
s
,
perms
)
}
commit
(
'
SET_ROUTE
R
S
'
,
accessedRoute
r
s
)
commit
(
'
SET_ROUTES
'
,
accessedRoutes
)
resolve
()
})
}
...
...
litemall-admin/src/store/modules/user.js
View file @
2786b410
import
{
loginByUsername
,
logout
,
getUserInfo
}
from
'
@/api/login
'
import
{
getToken
,
setToken
,
removeToken
}
from
'
@/utils/auth
'
import
router
,
{
resetRouter
}
from
'
@/router
'
const
user
=
{
state
:
{
user
:
''
,
status
:
''
,
code
:
''
,
token
:
getToken
(),
name
:
''
,
avatar
:
''
,
introduction
:
''
,
roles
:
[],
perms
:
[],
setting
:
{
articlePlatform
:
[]
}
perms
:
[]
},
mutations
:
{
SET_CODE
:
(
state
,
code
)
=>
{
state
.
code
=
code
},
SET_TOKEN
:
(
state
,
token
)
=>
{
state
.
token
=
token
},
SET_INTRODUCTION
:
(
state
,
introduction
)
=>
{
state
.
introduction
=
introduction
},
SET_SETTING
:
(
state
,
setting
)
=>
{
state
.
setting
=
setting
},
SET_STATUS
:
(
state
,
status
)
=>
{
state
.
status
=
status
},
SET_NAME
:
(
state
,
name
)
=>
{
state
.
name
=
name
},
...
...
@@ -78,7 +61,6 @@ const user = {
commit
(
'
SET_ROLES
'
,
data
.
roles
)
commit
(
'
SET_NAME
'
,
data
.
name
)
commit
(
'
SET_AVATAR
'
,
data
.
avatar
)
commit
(
'
SET_INTRODUCTION
'
,
data
.
introduction
)
resolve
(
response
)
}).
catch
(
error
=>
{
reject
(
error
)
...
...
@@ -86,28 +68,20 @@ const user = {
})
},
// 第三方验证登录
// LoginByThirdparty({ commit, state }, code) {
// return new Promise((resolve, reject) => {
// commit('SET_CODE', code)
// loginByThirdparty(state.status, state.email, state.code).then(response => {
// commit('SET_TOKEN', response.data.token)
// setToken(response.data.token)
// resolve()
// }).catch(error => {
// reject(error)
// })
// })
// },
// 登出
LogOut
({
commit
,
state
})
{
LogOut
({
commit
,
state
,
dispatch
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
logout
(
state
.
token
).
then
(()
=>
{
commit
(
'
SET_TOKEN
'
,
''
)
commit
(
'
SET_ROLES
'
,
[])
commit
(
'
SET_PERMS
'
,
[])
removeToken
()
resetRouter
()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch
(
'
tagsView/delAllViews
'
,
null
,
{
root
:
true
})
resolve
()
}).
catch
(
error
=>
{
reject
(
error
)
...
...
@@ -119,6 +93,7 @@ const user = {
FedLogOut
({
commit
})
{
return
new
Promise
(
resolve
=>
{
commit
(
'
SET_TOKEN
'
,
''
)
commit
(
'
SET_ROLES
'
,
[])
removeToken
()
resolve
()
})
...
...
@@ -126,19 +101,23 @@ const user = {
// 动态修改权限
ChangeRoles
({
commit
,
dispatch
},
role
)
{
return
new
Promise
(
resolve
=>
{
return
new
Promise
(
async
resolve
=>
{
commit
(
'
SET_TOKEN
'
,
role
)
setToken
(
role
)
getUserInfo
(
role
).
then
(
response
=>
{
const
data
=
response
.
data
commit
(
'
SET_ROLES
'
,
data
.
roles
)
commit
(
'
SET_PERMS
'
,
data
.
perms
)
commit
(
'
SET_NAME
'
,
data
.
name
)
commit
(
'
SET_AVATAR
'
,
data
.
avatar
)
commit
(
'
SET_INTRODUCTION
'
,
data
.
introduction
)
dispatch
(
'
GenerateRoutes
'
,
data
)
// 动态修改权限后 重绘侧边菜单
resolve
()
})
const
{
roles
}
=
await
dispatch
(
'
GetUserInfo
'
)
resetRouter
()
const
accessRoutes
=
await
dispatch
(
'
permission/generateRoutes
'
,
roles
,
{
root
:
true
})
// dynamically add accessible routes
router
.
addRoutes
(
accessRoutes
)
// reset visited views and cached views
dispatch
(
'
tagsView/delAllViews
'
,
null
,
{
root
:
true
})
resolve
()
})
}
}
...
...
litemall-admin/src/styles/element-ui.scss
View file @
2786b410
...
...
@@ -31,7 +31,7 @@
.fixed-width
{
.el-button--mini
{
padding
:
7px
10px
;
width
:
60px
;
min-
width
:
60px
;
}
}
...
...
litemall-admin/src/styles/element-variables.scss
View file @
2786b410
...
...
@@ -6,7 +6,7 @@
/* theme color */
$--color-primary
:
#1890ff
;
$--color-success
:
#13ce66
;
$--color-warning
:
#
FFBA
00
;
$--color-warning
:
#
ffba
00
;
$--color-danger
:
#ff4949
;
// $--color-info: #1E1E1E;
...
...
@@ -17,10 +17,10 @@ $--button-font-weight: 400;
$--border-color-light
:
#dfe4ed
;
$--border-color-lighter
:
#e6ebf5
;
$--table-border
:
1px
solid
#dfe6ec
;
$--table-border
:
1px
solid
#dfe6ec
;
/* icon font path, required */
$--font-path
:
'
~element-ui/lib/theme-chalk/fonts
'
;
$--font-path
:
"
~element-ui/lib/theme-chalk/fonts
"
;
@import
"~element-ui/packages/theme-chalk/src/index"
;
...
...
litemall-admin/src/styles/sidebar.scss
View file @
2786b410
...
...
@@ -57,6 +57,11 @@
margin-right
:
16px
;
}
.sub-el-icon
{
margin-right
:
12px
;
margin-left
:
-2px
;
}
.el-menu
{
border
:
none
;
height
:
100%
;
...
...
@@ -105,6 +110,11 @@
.svg-icon
{
margin-left
:
20px
;
}
.sub-el-icon
{
margin-right
:
12px
;
margin-left
:
-2px
;
}
}
}
...
...
@@ -118,6 +128,11 @@
margin-left
:
20px
;
}
.sub-el-icon
{
margin-right
:
12px
;
margin-left
:
-2px
;
}
.el-submenu__icon-arrow
{
display
:
none
;
}
...
...
@@ -178,6 +193,10 @@
.svg-icon
{
margin-right
:
16px
;
}
.sub-el-icon
{
margin-right
:
12px
;
margin-left
:
-2px
;
}
}
.nest-menu
.el-submenu
>
.el-submenu__title
,
...
...
litemall-admin/src/vendor/Export2Excel.js
View file @
2786b410
/* eslint-disable */
require
(
'
script-loader!
file-saver
'
);
import
{
saveAs
}
from
'
file-saver
'
import
XLSX
from
'
xlsx
'
function
generateArray
(
table
)
{
...
...
@@ -145,20 +145,34 @@ export function export_table_to_excel(id) {
}
export
function
export_json_to_excel
({
multiHeader
=
[],
header
,
data
,
filename
,
merges
=
[],
autoWidth
=
true
,
bookType
=
'
xlsx
'
bookType
=
'
xlsx
'
}
=
{})
{
/* original data */
filename
=
filename
||
'
excel-list
'
data
=
[...
data
]
data
.
unshift
(
header
);
for
(
let
i
=
multiHeader
.
length
-
1
;
i
>
-
1
;
i
--
)
{
data
.
unshift
(
multiHeader
[
i
])
}
var
ws_name
=
"
SheetJS
"
;
var
wb
=
new
Workbook
(),
ws
=
sheet_from_array_of_arrays
(
data
);
if
(
merges
.
length
>
0
)
{
if
(
!
ws
[
'
!merges
'
])
ws
[
'
!merges
'
]
=
[];
merges
.
forEach
(
item
=>
{
ws
[
'
!merges
'
].
push
(
XLSX
.
utils
.
decode_range
(
item
))
})
}
if
(
autoWidth
)
{
/*设置worksheet每列的最大宽度*/
const
colWidth
=
data
.
map
(
row
=>
row
.
map
(
val
=>
{
...
...
litemall-admin/src/views/goods/comment.vue
View file @
2786b410
...
...
@@ -3,8 +3,8 @@
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
v-model=
"listQuery.userId"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入用户ID"
/>
<el-input
v-model=
"listQuery.valueId"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品ID"
/>
<el-input
v-model=
"listQuery.userId"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入用户ID"
/>
<el-input
v-model=
"listQuery.valueId"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入商品ID"
/>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-search"
@
click=
"handleFilter"
>
查找
</el-button>
<el-button
:loading=
"downloadLoading"
class=
"filter-item"
type=
"primary"
icon=
"el-icon-download"
@
click=
"handleDownload"
>
导出
</el-button>
</div>
...
...
@@ -12,21 +12,21 @@
<!-- 查询结果 -->
<el-table
v-loading=
"listLoading"
:data=
"list"
element-loading-text=
"正在查询中。。。"
border
fit
highlight-current-row
>
<el-table-column
align=
"center"
label=
"用户ID"
prop=
"userId"
/>
<el-table-column
align=
"center"
label=
"用户ID"
prop=
"userId"
/>
<el-table-column
align=
"center"
label=
"商品ID"
prop=
"valueId"
/>
<el-table-column
align=
"center"
label=
"商品ID"
prop=
"valueId"
/>
<el-table-column
align=
"center"
label=
"打分"
prop=
"star"
/>
<el-table-column
align=
"center"
label=
"打分"
prop=
"star"
/>
<el-table-column
align=
"center"
label=
"评论内容"
prop=
"content"
/>
<el-table-column
align=
"center"
label=
"评论内容"
prop=
"content"
/>
<el-table-column
align=
"center"
label=
"评论图片"
prop=
"picUrls"
>
<template
slot-scope=
"scope"
>
<el-image
v-for=
"item in scope.row.picUrls"
:key=
"item"
:src=
"item"
:preview-src-list=
"scope.row.picUrls"
:lazy=
"true"
style=
"width: 40px; height: 40px; margin-right: 5px;"
/>
<el-image
v-for=
"item in scope.row.picUrls"
:key=
"item"
:src=
"item"
:preview-src-list=
"scope.row.picUrls"
:lazy=
"true"
style=
"width: 40px; height: 40px; margin-right: 5px;"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"时间"
prop=
"addTime"
/>
<el-table-column
align=
"center"
label=
"时间"
prop=
"addTime"
/>
<el-table-column
align=
"center"
label=
"操作"
width=
"200"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
...
...
@@ -42,7 +42,7 @@
<el-dialog
:visible.sync=
"replyFormVisible"
title=
"回复"
>
<el-form
ref=
"replyForm"
:model=
"replyForm"
status-icon
label-position=
"left"
label-width=
"100px"
style=
"width: 400px; margin-left:50px;"
>
<el-form-item
label=
"回复内容"
prop=
"content"
>
<el-input
:autosize=
"{ minRows: 4, maxRows: 8}"
v-model=
"replyForm.content"
type=
"textarea"
/>
<el-input
v-model=
"replyForm.content"
:autosize=
"{ minRows: 4, maxRows: 8}"
type=
"textarea"
/>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
...
...
@@ -129,8 +129,6 @@ export default {
type
:
'
success
'
,
duration
:
2000
})
const
index
=
this
.
list
.
indexOf
(
row
)
this
.
list
.
splice
(
index
,
1
)
})
},
handleDownload
()
{
...
...
litemall-admin/src/views/layout/components/Navbar.vue
View file @
2786b410
...
...
@@ -46,8 +46,8 @@
密码修改
</router-link>
</el-dropdown-item>
<el-dropdown-item
divided
>
<span
style=
"display:block;"
@
click=
"logout"
>
退出
</span>
<el-dropdown-item
divided
@
click.native=
"logout"
>
<span
style=
"display:block;"
>
退出
</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
...
...
litemall-admin/src/views/layout/components/Sidebar/Item.vue
View file @
2786b410
...
...
@@ -17,7 +17,11 @@ export default {
const
vnodes
=
[]
if
(
icon
)
{
vnodes
.
push
(
<
svg
-
icon
icon
-
class
=
{
icon
}
/>
)
if
(
icon
.
includes
(
'
el-icon
'
))
{
vnodes
.
push
(
<
i
class
=
{[
icon
,
'
sub-el-icon
'
]}
/>
)
}
else
{
vnodes
.
push
(
<
svg
-
icon
icon
-
class
=
{
icon
}
/>
)
}
}
if
(
title
)
{
...
...
@@ -27,3 +31,11 @@ export default {
}
}
</
script
>
<
style
scoped
>
.sub-el-icon
{
color
:
currentColor
;
width
:
1em
;
height
:
1em
;
}
</
style
>
litemall-admin/src/views/layout/components/Sidebar/Link.vue
View file @
2786b410
<
template
>
<!-- eslint-disable vue/require-component-is-->
<component
v-bind=
"linkProps(to)"
>
<slot/>
<component
:is=
"type"
v-bind=
"linkProps(to)"
>
<slot
/>
</component>
</
template
>
<
script
>
import
{
isExternal
}
from
'
@/utils
'
import
{
isExternal
}
from
'
@/utils/validate
'
export
default
{
props
:
{
to
:
{
...
...
@@ -16,22 +13,28 @@ export default {
required
:
true
}
},
methods
:
{
isExternal
Link
(
routePath
)
{
return
isExternal
(
routePath
)
computed
:
{
isExternal
(
)
{
return
isExternal
(
this
.
to
)
},
linkProps
(
url
)
{
if
(
this
.
isExternalLink
(
url
))
{
type
()
{
if
(
this
.
isExternal
)
{
return
'
a
'
}
return
'
router-link
'
}
},
methods
:
{
linkProps
(
to
)
{
if
(
this
.
isExternal
)
{
return
{
is
:
'
a
'
,
href
:
url
,
href
:
to
,
target
:
'
_blank
'
,
rel
:
'
noopener
'
}
}
return
{
is
:
'
router-link
'
,
to
:
url
to
:
to
}
}
}
...
...
litemall-admin/src/views/layout/components/Sidebar/index.vue
View file @
2786b410
...
...
@@ -9,7 +9,7 @@
text-color=
"#bfcbd9"
active-text-color=
"#409EFF"
>
<sidebar-item
v-for=
"route in permission_route
r
s"
:key=
"route.path"
:item=
"route"
:base-path=
"route.path"
/>
<sidebar-item
v-for=
"route in permission_routes"
:key=
"route.path"
:item=
"route"
:base-path=
"route.path"
/>
</el-menu>
</el-scrollbar>
</
template
>
...
...
@@ -22,7 +22,7 @@ export default {
components
:
{
SidebarItem
},
computed
:
{
...
mapGetters
([
'
permission_route
r
s
'
,
'
permission_routes
'
,
'
sidebar
'
]),
isCollapse
()
{
...
...
litemall-admin/src/views/layout/components/ScrollPane.vue
→
litemall-admin/src/views/layout/components/
TagsView/
ScrollPane.vue
View file @
2786b410
...
...
@@ -6,7 +6,6 @@
<
script
>
const
tagAndTagSpacing
=
4
// tagAndTagSpacing
export
default
{
name
:
'
ScrollPane
'
,
data
()
{
...
...
@@ -19,27 +18,33 @@ export default {
return
this
.
$refs
.
scrollContainer
.
$refs
.
wrap
}
},
mounted
()
{
this
.
scrollWrapper
.
addEventListener
(
'
scroll
'
,
this
.
emitScroll
,
true
)
},
beforeDestroy
()
{
this
.
scrollWrapper
.
removeEventListener
(
'
scroll
'
,
this
.
emitScroll
)
},
methods
:
{
handleScroll
(
e
)
{
const
eventDelta
=
e
.
wheelDelta
||
-
e
.
deltaY
*
40
const
$scrollWrapper
=
this
.
scrollWrapper
$scrollWrapper
.
scrollLeft
=
$scrollWrapper
.
scrollLeft
+
eventDelta
/
4
},
emitScroll
()
{
this
.
$emit
(
'
scroll
'
)
},
moveToTarget
(
currentTag
)
{
const
$container
=
this
.
$refs
.
scrollContainer
.
$el
const
$containerWidth
=
$container
.
offsetWidth
const
$scrollWrapper
=
this
.
scrollWrapper
const
tagList
=
this
.
$parent
.
$refs
.
tag
let
firstTag
=
null
let
lastTag
=
null
// find first tag and last tag
if
(
tagList
.
length
>
0
)
{
firstTag
=
tagList
[
0
]
lastTag
=
tagList
[
tagList
.
length
-
1
]
}
if
(
firstTag
===
currentTag
)
{
$scrollWrapper
.
scrollLeft
=
0
}
else
if
(
lastTag
===
currentTag
)
{
...
...
@@ -49,13 +54,10 @@ export default {
const
currentIndex
=
tagList
.
findIndex
(
item
=>
item
===
currentTag
)
const
prevTag
=
tagList
[
currentIndex
-
1
]
const
nextTag
=
tagList
[
currentIndex
+
1
]
// the tag's offsetLeft after of nextTag
const
afterNextTagOffsetLeft
=
nextTag
.
$el
.
offsetLeft
+
nextTag
.
$el
.
offsetWidth
+
tagAndTagSpacing
// the tag's offsetLeft before of prevTag
const
beforePrevTagOffsetLeft
=
prevTag
.
$el
.
offsetLeft
-
tagAndTagSpacing
if
(
afterNextTagOffsetLeft
>
$scrollWrapper
.
scrollLeft
+
$containerWidth
)
{
$scrollWrapper
.
scrollLeft
=
afterNextTagOffsetLeft
-
$containerWidth
}
else
if
(
beforePrevTagOffsetLeft
<
$scrollWrapper
.
scrollLeft
)
{
...
...
@@ -73,7 +75,7 @@ export default {
position
:
relative
;
overflow
:
hidden
;
width
:
100%
;
/
deep
/
{
::v-
deep
{
.el-scrollbar__bar
{
bottom
:
0px
;
}
...
...
litemall-admin/src/views/layout/components/TagsView.vue
→
litemall-admin/src/views/layout/components/TagsView
/index
.vue
View file @
2786b410
<
template
>
<div
id=
"tags-view-container"
class=
"tags-view-container"
>
<scroll-pane
ref=
"scrollPane"
class=
"tags-view-wrapper"
>
<scroll-pane
ref=
"scrollPane"
class=
"tags-view-wrapper"
@
scroll=
"handleScroll"
>
<router-link
v-for=
"tag in visitedViews"
ref=
"tag"
...
...
@@ -17,10 +17,10 @@
</router-link>
</scroll-pane>
<ul
v-show=
"visible"
:style=
"
{left:left+'px',top:top+'px'}" class="contextmenu">
<li
@
click=
"refreshSelectedTag(selectedTag)"
>
刷新
</li>
<li
v-if=
"!isAffix(selectedTag)"
@
click=
"closeSelectedTag(selectedTag)"
>
关闭
</li>
<li
@
click=
"closeOthersTags"
>
关闭其他
</li>
<li
@
click=
"closeAllTags(selectedTag)"
>
关闭所有
</li>
<li
@
click=
"refreshSelectedTag(selectedTag)"
>
Refresh
</li>
<li
v-if=
"!isAffix(selectedTag)"
@
click=
"closeSelectedTag(selectedTag)"
>
Close
</li>
<li
@
click=
"closeOthersTags"
>
Close Others
</li>
<li
@
click=
"closeAllTags(selectedTag)"
>
Close All
</li>
</ul>
</div>
</
template
>
...
...
@@ -28,7 +28,6 @@
<
script
>
import
ScrollPane
from
'
./ScrollPane
'
import
path
from
'
path
'
export
default
{
components
:
{
ScrollPane
},
data
()
{
...
...
@@ -45,7 +44,7 @@ export default {
return
this
.
$store
.
state
.
tagsView
.
visitedViews
},
routes
()
{
return
this
.
$store
.
state
.
permission
.
route
r
s
return
this
.
$store
.
state
.
permission
.
routes
}
},
watch
:
{
...
...
@@ -176,19 +175,20 @@ export default {
const
offsetWidth
=
this
.
$el
.
offsetWidth
// container width
const
maxLeft
=
offsetWidth
-
menuMinWidth
// left boundary
const
left
=
e
.
clientX
-
offsetLeft
+
15
// 15: margin right
if
(
left
>
maxLeft
)
{
this
.
left
=
maxLeft
}
else
{
this
.
left
=
left
}
this
.
top
=
e
.
clientY
this
.
visible
=
true
this
.
selectedTag
=
tag
},
closeMenu
()
{
this
.
visible
=
false
},
handleScroll
()
{
this
.
closeMenu
()
}
}
}
...
...
litemall-admin/src/views/layout/components/index.js
View file @
2786b410
export
{
default
as
AppMain
}
from
'
./AppMain
'
export
{
default
as
Navbar
}
from
'
./Navbar
'
export
{
default
as
Sidebar
}
from
'
./Sidebar/index.vue
'
export
{
default
as
TagsView
}
from
'
./TagsView
'
export
{
default
as
AppMain
}
from
'
./AppMain
'
export
{
default
as
TagsView
}
from
'
./TagsView/index.vue
'
Prev
1
2
Next
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