Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
mall4cloud
Commits
a21f5a9a
Commit
a21f5a9a
authored
Dec 20, 2023
by
liang.tang
Browse files
mall4cloud
parents
Pipeline
#244
canceled with stages
Changes
355
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2064 additions
and
0 deletions
+2064
-0
front-end/mall4cloud-multishop-master/src/store/modules/app.js
...-end/mall4cloud-multishop-master/src/store/modules/app.js
+65
-0
front-end/mall4cloud-multishop-master/src/store/modules/permission.js
...ll4cloud-multishop-master/src/store/modules/permission.js
+72
-0
front-end/mall4cloud-multishop-master/src/store/modules/settings.js
...mall4cloud-multishop-master/src/store/modules/settings.js
+36
-0
front-end/mall4cloud-multishop-master/src/store/modules/tagsView.js
...mall4cloud-multishop-master/src/store/modules/tagsView.js
+160
-0
front-end/mall4cloud-multishop-master/src/store/modules/user.js
...end/mall4cloud-multishop-master/src/store/modules/user.js
+165
-0
front-end/mall4cloud-multishop-master/src/styles/btn.scss
front-end/mall4cloud-multishop-master/src/styles/btn.scss
+99
-0
front-end/mall4cloud-multishop-master/src/styles/element-ui.scss
...nd/mall4cloud-multishop-master/src/styles/element-ui.scss
+147
-0
front-end/mall4cloud-multishop-master/src/styles/element-variables.scss
...4cloud-multishop-master/src/styles/element-variables.scss
+31
-0
front-end/mall4cloud-multishop-master/src/styles/index.scss
front-end/mall4cloud-multishop-master/src/styles/index.scss
+191
-0
front-end/mall4cloud-multishop-master/src/styles/mixin.scss
front-end/mall4cloud-multishop-master/src/styles/mixin.scss
+66
-0
front-end/mall4cloud-multishop-master/src/styles/sidebar.scss
...t-end/mall4cloud-multishop-master/src/styles/sidebar.scss
+284
-0
front-end/mall4cloud-multishop-master/src/styles/transition.scss
...nd/mall4cloud-multishop-master/src/styles/transition.scss
+48
-0
front-end/mall4cloud-multishop-master/src/styles/variables.scss
...end/mall4cloud-multishop-master/src/styles/variables.scss
+35
-0
front-end/mall4cloud-multishop-master/src/utils/addr.js
front-end/mall4cloud-multishop-master/src/utils/addr.js
+75
-0
front-end/mall4cloud-multishop-master/src/utils/auth.js
front-end/mall4cloud-multishop-master/src/utils/auth.js
+15
-0
front-end/mall4cloud-multishop-master/src/utils/clipboard.js
front-end/mall4cloud-multishop-master/src/utils/clipboard.js
+32
-0
front-end/mall4cloud-multishop-master/src/utils/get-page-title.js
...d/mall4cloud-multishop-master/src/utils/get-page-title.js
+13
-0
front-end/mall4cloud-multishop-master/src/utils/i18n.js
front-end/mall4cloud-multishop-master/src/utils/i18n.js
+12
-0
front-end/mall4cloud-multishop-master/src/utils/index.js
front-end/mall4cloud-multishop-master/src/utils/index.js
+493
-0
front-end/mall4cloud-multishop-master/src/utils/permission.js
...t-end/mall4cloud-multishop-master/src/utils/permission.js
+25
-0
No files found.
Too many changes to show.
To preserve performance only
355 of 355+
files are displayed.
Plain diff
Email patch
front-end/mall4cloud-multishop-master/src/store/modules/app.js
0 → 100644
View file @
a21f5a9a
import
Cookies
from
'
js-cookie
'
import
{
getLanguage
}
from
'
@/lang/index
'
const
state
=
{
sidebar
:
{
opened
:
Cookies
.
get
(
'
sidebarStatus
'
)
?
!!+
Cookies
.
get
(
'
sidebarStatus
'
)
:
true
,
withoutAnimation
:
false
},
device
:
'
desktop
'
,
language
:
getLanguage
(),
size
:
Cookies
.
get
(
'
size
'
)
||
'
medium
'
}
const
mutations
=
{
TOGGLE_SIDEBAR
:
state
=>
{
state
.
sidebar
.
opened
=
!
state
.
sidebar
.
opened
state
.
sidebar
.
withoutAnimation
=
false
if
(
state
.
sidebar
.
opened
)
{
Cookies
.
set
(
'
sidebarStatus
'
,
1
)
}
else
{
Cookies
.
set
(
'
sidebarStatus
'
,
0
)
}
},
CLOSE_SIDEBAR
:
(
state
,
withoutAnimation
)
=>
{
Cookies
.
set
(
'
sidebarStatus
'
,
0
)
state
.
sidebar
.
opened
=
false
state
.
sidebar
.
withoutAnimation
=
withoutAnimation
},
TOGGLE_DEVICE
:
(
state
,
device
)
=>
{
state
.
device
=
device
},
SET_LANGUAGE
:
(
state
,
language
)
=>
{
state
.
language
=
language
Cookies
.
set
(
'
language
'
,
language
)
},
SET_SIZE
:
(
state
,
size
)
=>
{
state
.
size
=
size
Cookies
.
set
(
'
size
'
,
size
)
}
}
const
actions
=
{
toggleSideBar
({
commit
})
{
commit
(
'
TOGGLE_SIDEBAR
'
)
},
closeSideBar
({
commit
},
{
withoutAnimation
})
{
commit
(
'
CLOSE_SIDEBAR
'
,
withoutAnimation
)
},
toggleDevice
({
commit
},
device
)
{
commit
(
'
TOGGLE_DEVICE
'
,
device
)
},
setLanguage
({
commit
},
language
)
{
commit
(
'
SET_LANGUAGE
'
,
language
)
},
setSize
({
commit
},
size
)
{
commit
(
'
SET_SIZE
'
,
size
)
}
}
export
default
{
namespaced
:
true
,
state
,
mutations
,
actions
}
front-end/mall4cloud-multishop-master/src/store/modules/permission.js
0 → 100644
View file @
a21f5a9a
import
{
constantRoutes
}
from
'
@/router
'
import
{
menuList
}
from
'
@/api/rbac/menu
'
import
{
treeDataTranslate
}
from
'
@/utils
'
import
Layout
from
'
@/layout
'
import
store
from
'
@/store
'
/**
* Filter asynchronous routing tables by recursion
* @param routes asyncRoutes
* @param menuIds
*/
export
function
filterAsyncRoutes
(
routes
,
menuIds
)
{
const
res
=
[]
routes
.
forEach
(
route
=>
{
if
(
menuIds
.
indexOf
(
route
.
id
)
>
-
1
)
{
res
.
push
(
route
)
}
})
return
res
}
export
const
loadView
=
(
view
)
=>
{
// 路由懒加载
return
()
=>
Promise
.
resolve
(
require
(
`@/views/
${
view
}
`
).
default
)
}
const
state
=
{
routes
:
[],
addRoutes
:
[]
}
const
mutations
=
{
SET_ROUTES
:
(
state
,
routes
)
=>
{
state
.
addRoutes
=
routes
state
.
routes
=
constantRoutes
.
concat
(
routes
)
}
}
const
actions
=
{
generateRoutes
({
commit
},
menuIds
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
menuList
().
then
(
menuList
=>
{
for
(
const
menu
of
menuList
)
{
if
(
menu
.
component
===
'
Layout
'
)
{
menu
.
component
=
Layout
}
else
{
menu
.
component
=
loadView
(
menu
.
component
)
}
}
console
.
log
(
store
.
getters
)
const
isAdmin
=
store
.
getters
&&
store
.
getters
.
isAdmin
if
(
!
isAdmin
)
{
menuList
=
filterAsyncRoutes
(
menuList
,
menuIds
)
}
const
accessedRoutes
=
treeDataTranslate
(
menuList
)
commit
(
'
SET_ROUTES
'
,
accessedRoutes
)
resolve
(
accessedRoutes
)
}).
catch
(
error
=>
{
console
.
log
(
error
)
reject
(
error
)
})
})
}
}
export
default
{
namespaced
:
true
,
state
,
mutations
,
actions
}
front-end/mall4cloud-multishop-master/src/store/modules/settings.js
0 → 100644
View file @
a21f5a9a
import
variables
from
'
@/styles/element-variables.scss
'
import
defaultSettings
from
'
@/settings
'
const
{
showSettings
,
tagsView
,
fixedHeader
,
sidebarLogo
,
supportPinyinSearch
}
=
defaultSettings
const
state
=
{
theme
:
variables
.
theme
,
showSettings
,
tagsView
,
fixedHeader
,
sidebarLogo
,
supportPinyinSearch
}
const
mutations
=
{
CHANGE_SETTING
:
(
state
,
{
key
,
value
})
=>
{
// eslint-disable-next-line no-prototype-builtins
if
(
state
.
hasOwnProperty
(
key
))
{
state
[
key
]
=
value
}
}
}
const
actions
=
{
changeSetting
({
commit
},
data
)
{
commit
(
'
CHANGE_SETTING
'
,
data
)
}
}
export
default
{
namespaced
:
true
,
state
,
mutations
,
actions
}
front-end/mall4cloud-multishop-master/src/store/modules/tagsView.js
0 → 100644
View file @
a21f5a9a
const
state
=
{
visitedViews
:
[],
cachedViews
:
[]
}
const
mutations
=
{
ADD_VISITED_VIEW
:
(
state
,
view
)
=>
{
if
(
state
.
visitedViews
.
some
(
v
=>
v
.
path
===
view
.
path
))
return
state
.
visitedViews
.
push
(
Object
.
assign
({},
view
,
{
title
:
view
.
meta
.
title
||
'
no-name
'
})
)
},
ADD_CACHED_VIEW
:
(
state
,
view
)
=>
{
if
(
state
.
cachedViews
.
includes
(
view
.
name
))
return
if
(
!
view
.
meta
.
noCache
)
{
state
.
cachedViews
.
push
(
view
.
name
)
}
},
DEL_VISITED_VIEW
:
(
state
,
view
)
=>
{
for
(
const
[
i
,
v
]
of
state
.
visitedViews
.
entries
())
{
if
(
v
.
path
===
view
.
path
)
{
state
.
visitedViews
.
splice
(
i
,
1
)
break
}
}
},
DEL_CACHED_VIEW
:
(
state
,
view
)
=>
{
const
index
=
state
.
cachedViews
.
indexOf
(
view
.
name
)
index
>
-
1
&&
state
.
cachedViews
.
splice
(
index
,
1
)
},
DEL_OTHERS_VISITED_VIEWS
:
(
state
,
view
)
=>
{
state
.
visitedViews
=
state
.
visitedViews
.
filter
(
v
=>
{
return
v
.
meta
.
affix
||
v
.
path
===
view
.
path
})
},
DEL_OTHERS_CACHED_VIEWS
:
(
state
,
view
)
=>
{
const
index
=
state
.
cachedViews
.
indexOf
(
view
.
name
)
if
(
index
>
-
1
)
{
state
.
cachedViews
=
state
.
cachedViews
.
slice
(
index
,
index
+
1
)
}
else
{
// if index = -1, there is no cached tags
state
.
cachedViews
=
[]
}
},
DEL_ALL_VISITED_VIEWS
:
state
=>
{
// keep affix tags
const
affixTags
=
state
.
visitedViews
.
filter
(
tag
=>
tag
.
meta
.
affix
)
state
.
visitedViews
=
affixTags
},
DEL_ALL_CACHED_VIEWS
:
state
=>
{
state
.
cachedViews
=
[]
},
UPDATE_VISITED_VIEW
:
(
state
,
view
)
=>
{
for
(
let
v
of
state
.
visitedViews
)
{
if
(
v
.
path
===
view
.
path
)
{
v
=
Object
.
assign
(
v
,
view
)
break
}
}
}
}
const
actions
=
{
addView
({
dispatch
},
view
)
{
dispatch
(
'
addVisitedView
'
,
view
)
dispatch
(
'
addCachedView
'
,
view
)
},
addVisitedView
({
commit
},
view
)
{
commit
(
'
ADD_VISITED_VIEW
'
,
view
)
},
addCachedView
({
commit
},
view
)
{
commit
(
'
ADD_CACHED_VIEW
'
,
view
)
},
delView
({
dispatch
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
dispatch
(
'
delVisitedView
'
,
view
)
dispatch
(
'
delCachedView
'
,
view
)
resolve
({
visitedViews
:
[...
state
.
visitedViews
],
cachedViews
:
[...
state
.
cachedViews
]
})
})
},
delVisitedView
({
commit
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
commit
(
'
DEL_VISITED_VIEW
'
,
view
)
resolve
([...
state
.
visitedViews
])
})
},
delCachedView
({
commit
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
commit
(
'
DEL_CACHED_VIEW
'
,
view
)
resolve
([...
state
.
cachedViews
])
})
},
delOthersViews
({
dispatch
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
dispatch
(
'
delOthersVisitedViews
'
,
view
)
dispatch
(
'
delOthersCachedViews
'
,
view
)
resolve
({
visitedViews
:
[...
state
.
visitedViews
],
cachedViews
:
[...
state
.
cachedViews
]
})
})
},
delOthersVisitedViews
({
commit
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
commit
(
'
DEL_OTHERS_VISITED_VIEWS
'
,
view
)
resolve
([...
state
.
visitedViews
])
})
},
delOthersCachedViews
({
commit
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
commit
(
'
DEL_OTHERS_CACHED_VIEWS
'
,
view
)
resolve
([...
state
.
cachedViews
])
})
},
delAllViews
({
dispatch
,
state
},
view
)
{
return
new
Promise
(
resolve
=>
{
dispatch
(
'
delAllVisitedViews
'
,
view
)
dispatch
(
'
delAllCachedViews
'
,
view
)
resolve
({
visitedViews
:
[...
state
.
visitedViews
],
cachedViews
:
[...
state
.
cachedViews
]
})
})
},
delAllVisitedViews
({
commit
,
state
})
{
return
new
Promise
(
resolve
=>
{
commit
(
'
DEL_ALL_VISITED_VIEWS
'
)
resolve
([...
state
.
visitedViews
])
})
},
delAllCachedViews
({
commit
,
state
})
{
return
new
Promise
(
resolve
=>
{
commit
(
'
DEL_ALL_CACHED_VIEWS
'
)
resolve
([...
state
.
cachedViews
])
})
},
updateVisitedView
({
commit
},
view
)
{
commit
(
'
UPDATE_VISITED_VIEW
'
,
view
)
}
}
export
default
{
namespaced
:
true
,
state
,
mutations
,
actions
}
front-end/mall4cloud-multishop-master/src/store/modules/user.js
0 → 100644
View file @
a21f5a9a
import
{
login
,
logout
}
from
'
@/api/auth/auth
'
import
{
shopUserInfo
}
from
'
@/api/multishop/shop-user
'
import
{
menuPermissionsList
}
from
'
@/api/rbac/menu-permission
'
import
{
listMenuIds
}
from
'
@/api/rbac/menu
'
import
{
getToken
,
setToken
,
removeToken
}
from
'
@/utils/auth
'
import
router
,
{
resetRouter
}
from
'
@/router
'
const
state
=
{
token
:
getToken
(),
name
:
''
,
avatar
:
''
,
introduction
:
''
,
isAdmin
:
0
,
roles
:
[]
}
const
mutations
=
{
SET_TOKEN
:
(
state
,
token
)
=>
{
state
.
token
=
token
},
SET_INTRODUCTION
:
(
state
,
introduction
)
=>
{
state
.
introduction
=
introduction
},
SET_NAME
:
(
state
,
name
)
=>
{
state
.
name
=
name
},
SET_AVATAR
:
(
state
,
avatar
)
=>
{
state
.
avatar
=
avatar
},
SET_ISADMIN
:
(
state
,
isAdmin
)
=>
{
state
.
isAdmin
=
isAdmin
},
SET_ROLES
:
(
state
,
roles
)
=>
{
state
.
roles
=
roles
}
}
const
actions
=
{
// user login
login
({
commit
},
userInfo
)
{
const
{
username
,
password
,
captcha
}
=
userInfo
return
new
Promise
((
resolve
,
reject
)
=>
{
login
({
principal
:
username
.
trim
(),
credentials
:
password
,
captchaVerification
:
captcha
,
sysType
:
1
}).
then
(
response
=>
{
console
.
log
(
234234
)
commit
(
'
SET_TOKEN
'
,
response
.
accessToken
)
console
.
log
(
234234
)
setToken
(
response
.
accessToken
)
console
.
log
(
234234
)
console
.
log
(
getToken
())
resolve
()
}).
catch
(
error
=>
{
reject
(
error
)
})
})
},
// get permissions
listPermissions
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
state
.
isAdmin
)
{
commit
(
'
SET_ROLES
'
,
[
''
])
resolve
([
''
])
return
}
menuPermissionsList
().
then
(
permissions
=>
{
console
.
log
(
permissions
)
if
(
!
permissions
)
{
reject
(
'
Verification failed, please Login again.
'
)
}
// roles must be a non-empty array
if
(
!
permissions
||
permissions
.
length
<=
0
)
{
permissions
=
[
''
]
}
commit
(
'
SET_ROLES
'
,
permissions
)
resolve
(
permissions
)
}).
catch
(
error
=>
{
reject
(
error
)
})
})
},
// get userInfo
getUserInfo
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
shopUserInfo
().
then
(
shopUser
=>
{
commit
(
'
SET_NAME
'
,
shopUser
.
nickName
)
commit
(
'
SET_AVATAR
'
,
shopUser
.
avatar
)
commit
(
'
SET_ISADMIN
'
,
shopUser
.
isAdmin
)
resolve
(
shopUser
)
}).
catch
(
error
=>
{
reject
(
error
)
})
})
},
// get userInfo
listMenuIds
({
commit
,
state
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
listMenuIds
().
then
(
menuIds
=>
{
resolve
(
menuIds
)
}).
catch
(
error
=>
{
reject
(
error
)
})
})
},
// user logout
logout
({
commit
,
state
,
dispatch
})
{
return
new
Promise
((
resolve
,
reject
)
=>
{
logout
(
state
.
token
).
then
(()
=>
{
commit
(
'
SET_TOKEN
'
,
''
)
commit
(
'
SET_ROLES
'
,
[])
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
)
})
})
},
// remove token
resetToken
({
commit
})
{
return
new
Promise
(
resolve
=>
{
commit
(
'
SET_TOKEN
'
,
''
)
commit
(
'
SET_ROLES
'
,
[])
removeToken
()
resolve
()
})
},
// dynamically modify permissions
async
changeRoles
({
commit
,
dispatch
},
role
)
{
const
token
=
role
+
'
-token
'
commit
(
'
SET_TOKEN
'
,
token
)
setToken
(
token
)
const
{
roles
}
=
await
dispatch
(
'
getInfo
'
)
resetRouter
()
// generate accessible routes map based on roles
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
})
}
}
export
default
{
namespaced
:
true
,
state
,
mutations
,
actions
}
front-end/mall4cloud-multishop-master/src/styles/btn.scss
0 → 100644
View file @
a21f5a9a
@import
'./variables.scss'
;
@mixin
colorBtn
(
$color
)
{
background
:
$color
;
&
:hover
{
color
:
$color
;
&
:before
,
&
:after
{
background
:
$color
;
}
}
}
.blue-btn
{
@include
colorBtn
(
$blue
)
}
.light-blue-btn
{
@include
colorBtn
(
$light-blue
)
}
.red-btn
{
@include
colorBtn
(
$red
)
}
.pink-btn
{
@include
colorBtn
(
$pink
)
}
.green-btn
{
@include
colorBtn
(
$green
)
}
.tiffany-btn
{
@include
colorBtn
(
$tiffany
)
}
.yellow-btn
{
@include
colorBtn
(
$yellow
)
}
.pan-btn
{
font-size
:
14px
;
color
:
#fff
;
padding
:
14px
36px
;
border-radius
:
8px
;
border
:
none
;
outline
:
none
;
transition
:
600ms
ease
all
;
position
:
relative
;
display
:
inline-block
;
&
:hover
{
background
:
#fff
;
&
:before
,
&
:after
{
width
:
100%
;
transition
:
600ms
ease
all
;
}
}
&
:before
,
&
:after
{
content
:
''
;
position
:
absolute
;
top
:
0
;
right
:
0
;
height
:
2px
;
width
:
0
;
transition
:
400ms
ease
all
;
}
&
::after
{
right
:
inherit
;
top
:
inherit
;
left
:
0
;
bottom
:
0
;
}
}
.custom-button
{
display
:
inline-block
;
line-height
:
1
;
white-space
:
nowrap
;
cursor
:
pointer
;
background
:
#fff
;
color
:
#fff
;
-webkit-appearance
:
none
;
text-align
:
center
;
box-sizing
:
border-box
;
outline
:
0
;
margin
:
0
;
padding
:
10px
15px
;
font-size
:
14px
;
border-radius
:
4px
;
}
front-end/mall4cloud-multishop-master/src/styles/element-ui.scss
0 → 100644
View file @
a21f5a9a
// cover some element-ui styles
.el-breadcrumb__inner
,
.el-breadcrumb__inner
a
{
font-weight
:
400
!
important
;
}
.el-upload
{
input
[
type
=
"file"
]
{
display
:
none
!
important
;
}
}
.el-upload__input
{
display
:
none
;
}
.cell
{
.el-tag
{
margin-right
:
0px
;
}
}
.small-padding
{
.cell
{
padding-left
:
5px
;
padding-right
:
5px
;
}
}
.fixed-width
{
.el-button--mini
{
padding
:
7px
10px
;
min-width
:
60px
;
}
}
.status-col
{
.cell
{
padding
:
0
10px
;
text-align
:
center
;
.el-tag
{
margin-right
:
0px
;
}
}
}
// to fixed https://github.com/ElemeFE/element/issues/2461
.el-dialog
{
transform
:
none
;
left
:
0
;
position
:
relative
;
margin
:
0
auto
;
}
// refine element ui upload
.upload-container
{
.el-upload
{
width
:
100%
;
.el-upload-dragger
{
width
:
100%
;
height
:
200px
;
}
}
}
// dropdown
.el-dropdown-menu
{
a
{
display
:
block
}
}
// fix date-picker ui bug in filter-item
.el-range-editor.el-input__inner
{
display
:
inline-flex
!
important
;
}
// to fix el-date-picker css style
.el-range-separator
{
box-sizing
:
content-box
;
}
body
.el-table
th
.gutter
{
display
:
table-cell
!
important
;
}
// 页码样式
.el-pagination
span
:not
([
class
*=
suffix
]),
.el-pagination
button
{
height
:
30px
;
line-height
:
30px
;
}
.el-pagination.is-background
.btn-prev
,
.el-pagination.is-background
.btn-next
,
.el-pagination.is-background
.el-pager
li
{
background
:
#fff
;
border
:
1px
solid
#dcdfe6
;
line-height
:
30px
;
height
:
30px
;
}
.el-pagination.is-background
.el-pager
li
:not
(
.disabled
)
.active
{
border-color
:
#1890ff
;
}
.el-pagination__sizes
{
margin-right
:
5px
;
}
.el-pagination
.el-select
.el-input
.el-input__inner
{
border-radius
:
2px
;
}
.el-pagination__editor
{
line-height
:
18px
;
padding
:
0
3px
;
height
:
30px
;
}
.el-pagination__editor.el-input
{
width
:
48px
;
}
.el-pagination
span
:not
([
class
*=
suffix
]),
.el-pagination
button
{
font-size
:
12px
;
}
.el-input--mini
.el-input__inner
{
height
:
30px
!
important
;
line-height
:
30px
!
important
;
}
.el-pagination__jump
{
margin-left
:
10px
;
}
.el-pagination__editor.el-input
.el-input__inner
{
height
:
30px
;
line-height
:
30px
;
font-size
:
12px
;
border-radius
:
2px
;
}
\ No newline at end of file
front-end/mall4cloud-multishop-master/src/styles/element-variables.scss
0 → 100644
View file @
a21f5a9a
/**
* I think element-ui's default theme color is too light for long-term use.
* So I modified the default color and you can modify it to your liking.
**/
/* theme color */
$--color-primary
:
#1890ff
;
$--color-success
:
#13ce66
;
$--color-warning
:
#ffba00
;
$--color-danger
:
#ff4949
;
// $--color-info: #1E1E1E;
$--button-font-weight
:
400
;
// $--color-text-regular: #1f2d3d;
$--border-color-light
:
#dfe4ed
;
$--border-color-lighter
:
#e6ebf5
;
$--table-border
:
1px
solid
#dfe6ec
;
/* icon font path, required */
$--font-path
:
"~element-ui/lib/theme-chalk/fonts"
;
@import
"~element-ui/packages/theme-chalk/src/index"
;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export
{
theme
:
$--color-primary
;
}
front-end/mall4cloud-multishop-master/src/styles/index.scss
0 → 100644
View file @
a21f5a9a
@import
'./variables.scss'
;
@import
'./mixin.scss'
;
@import
'./transition.scss'
;
@import
'./element-ui.scss'
;
@import
'./sidebar.scss'
;
@import
'./btn.scss'
;
body
{
height
:
100%
;
-moz-osx-font-smoothing
:
grayscale
;
-webkit-font-smoothing
:
antialiased
;
text-rendering
:
optimizeLegibility
;
font-family
:
Helvetica
Neue
,
Helvetica
,
PingFang
SC
,
Hiragino
Sans
GB
,
Microsoft
YaHei
,
Arial
,
sans-serif
;
}
label
{
// font-weight: 600;
}
html
{
background
:
#f9f9f9
;
box-sizing
:
border-box
;
}
#app
{
height
:
100%
;
}
*,
*
:before
,
*
:after
{
box-sizing
:
inherit
;
}
.no-padding
{
padding
:
0px
!
important
;
}
.padding-content
{
padding
:
4px
0
;
}
a
:focus
,
a
:active
{
outline
:
none
;
}
a
,
a
:focus
,
a
:hover
{
cursor
:
pointer
;
color
:
inherit
;
text-decoration
:
none
;
}
div
:focus
{
outline
:
none
;
}
.fr
{
float
:
right
;
}
.fl
{
float
:
left
;
}
.pr-5
{
padding-right
:
5px
;
}
.pl-5
{
padding-left
:
5px
;
}
.block
{
display
:
block
;
}
.pointer
{
cursor
:
pointer
;
}
.inlineBlock
{
display
:
block
;
}
.clearfix
{
&
:after
{
visibility
:
hidden
;
display
:
block
;
font-size
:
0
;
content
:
" "
;
clear
:
both
;
height
:
0
;
}
}
aside
{
background
:
#eef1f6
;
padding
:
8px
24px
;
margin-bottom
:
20px
;
border-radius
:
2px
;
display
:
block
;
line-height
:
32px
;
font-size
:
16px
;
font-family
:
-
apple-system
,
BlinkMacSystemFont
,
"Segoe UI"
,
Roboto
,
Oxygen
,
Ubuntu
,
Cantarell
,
"Fira Sans"
,
"Droid Sans"
,
"Helvetica Neue"
,
sans-serif
;
color
:
#2c3e50
;
-webkit-font-smoothing
:
antialiased
;
-moz-osx-font-smoothing
:
grayscale
;
a
{
color
:
#337ab7
;
cursor
:
pointer
;
&
:hover
{
color
:
rgb
(
32
,
160
,
255
);
}
}
}
//main-container全局样式
.app-container
{
padding
:
20px
;
}
.components-container
{
margin
:
30px
50px
;
position
:
relative
;
}
.text-center
{
text-align
:
center
}
.sub-navbar
{
height
:
50px
;
line-height
:
50px
;
position
:
relative
;
width
:
100%
;
text-align
:
right
;
padding-right
:
20px
;
transition
:
600ms
ease
position
;
background
:
linear-gradient
(
90deg
,
rgba
(
32
,
182
,
249
,
1
)
0%
,
rgba
(
32
,
182
,
249
,
1
)
0%
,
rgba
(
33
,
120
,
241
,
1
)
100%
,
rgba
(
33
,
120
,
241
,
1
)
100%
);
.subtitle
{
font-size
:
20px
;
color
:
#fff
;
}
&
.draft
{
background
:
#d0d0d0
;
}
&
.deleted
{
background
:
#d0d0d0
;
}
}
.link-type
,
.link-type
:focus
{
color
:
#337ab7
;
cursor
:
pointer
;
&
:hover
{
color
:
rgb
(
32
,
160
,
255
);
}
}
.filter-container
{
padding-bottom
:
10px
;
.filter-item
{
display
:
inline-block
;
vertical-align
:
middle
;
margin-bottom
:
10px
;
margin-right
:
10px
;
}
.el-button
{
margin-right
:
0px
;
}
}
//refine vue-multiselect plugin
.multiselect
{
line-height
:
16px
;
}
.multiselect--active
{
z-index
:
1000
!
important
;
}
front-end/mall4cloud-multishop-master/src/styles/mixin.scss
0 → 100644
View file @
a21f5a9a
@mixin
clearfix
{
&
:after
{
content
:
""
;
display
:
table
;
clear
:
both
;
}
}
@mixin
scrollBar
{
&
::-webkit-scrollbar-track-piece
{
background
:
#d3dce6
;
}
&
::-webkit-scrollbar
{
width
:
6px
;
}
&
::-webkit-scrollbar-thumb
{
background
:
#99a9bf
;
border-radius
:
20px
;
}
}
@mixin
relative
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
}
@mixin
pct
(
$pct
)
{
width
:
#{
$pct
}
;
position
:
relative
;
margin
:
0
auto
;
}
@mixin
triangle
(
$width
,
$height
,
$color
,
$direction
)
{
$width
:
$width
/
2
;
$color-border-style
:
$height
solid
$color
;
$transparent-border-style
:
$width
solid
transparent
;
height
:
0
;
width
:
0
;
@if
$direction
==
up
{
border-bottom
:
$color-border-style
;
border-left
:
$transparent-border-style
;
border-right
:
$transparent-border-style
;
}
@else
if
$direction
==
right
{
border-left
:
$color-border-style
;
border-top
:
$transparent-border-style
;
border-bottom
:
$transparent-border-style
;
}
@else
if
$direction
==
down
{
border-top
:
$color-border-style
;
border-left
:
$transparent-border-style
;
border-right
:
$transparent-border-style
;
}
@else
if
$direction
==
left
{
border-right
:
$color-border-style
;
border-top
:
$transparent-border-style
;
border-bottom
:
$transparent-border-style
;
}
}
front-end/mall4cloud-multishop-master/src/styles/sidebar.scss
0 → 100644
View file @
a21f5a9a
#app
{
.main-container
{
display
:
flex
;
position
:
relative
;
width
:
1260px
;
min-height
:
100%
;
background
:
#f9f9f9
;
transition
:
margin-left
.28s
;
margin
:
0
auto
;
margin-top
:
20px
;
margin-bottom
:
20px
;
overflow
:
hidden
;
}
.sidebar-container
{
transition
:
width
0
.28s
;
width
:
$sideBarWidth
!
important
;
height
:
100vh
;
font-size
:
0
;
overflow
:
hidden
;
// 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
;
}
.scrollbar-wrapper
{
overflow-x
:
hidden
!
important
;
}
.el-scrollbar__bar.is-vertical
{
right
:
0px
;
}
.el-scrollbar
{
width
:
$sideBarWidth
;
height
:
100vh
;
background
:
#fff
;
}
&
.has-logo
{
.el-scrollbar
{
height
:
calc
(
100%
-
50px
);
}
}
.is-horizontal
{
display
:
none
;
}
a
{
display
:
inline-block
;
width
:
100%
;
overflow
:
hidden
;
}
.svg-icon
{
margin-right
:
10px
;
}
.sub-el-icon
{
margin-right
:
12px
;
margin-left
:
-2px
;
}
.el-menu
{
border
:
none
;
height
:
100%
;
width
:
100%
!
important
;
.el-menu-item
,
.el-submenu
.el-submenu__title
{
height
:
45px
;
line-height
:
45px
;
}
.el-submenu
,
.submenu-title-noDropdown
{
padding
:
0
!
important
;
border-bottom
:
1px
solid
#EEEEEE
;
margin
:
0
16px
;
}
div
{
&
:last-child
{
.el-submenu
,
.submenu-title-noDropdown
{
border
:
none
;
}
}
}
.nest-menu
{
&
:last-child
{
margin-bottom
:
11px
;
}
}
}
// menu hover
.submenu-title-noDropdown
,
.el-submenu__title
{
padding
:
0
!
important
;
&
:hover
{
background-color
:
#FFFFFF
!
important
;
}
.el-submenu__icon-arrow
{
right
:
0
;
transform
:rotate
(
-90deg
)
;
-ms-transform
:rotate
(
-90deg
)
;
-webkit-transform
:rotate
(
-90deg
)
;
margin-top
:
-6px
;
}
}
.is-opened
>
.el-submenu__title
.el-submenu__icon-arrow
{
transform
:rotate
(
0
)
;
-ms-transform
:rotate
(
0
)
;
-webkit-transform
:rotate
(
0
)
;
}
.is-active
{
background-color
:
#FFFFFF
!
important
;
}
.is-active
>
.el-submenu__title
{
color
:
$subMenuActiveText
!
important
;
}
&
.nest-menu
{
display
:
inline-block
;
width
:
50%
!
important
;
}
&
.nest-menu
.el-submenu
>
.el-submenu__title
,
&
.el-submenu
.el-menu-item
{
height
:
25px
!
important
;
line-height
:
25px
!
important
;
font-size
:
12px
!
important
;
color
:
#999999
!
important
;
padding
:
0
!
important
;
&
:hover
{
// background-color: $subMenuHover !important;
color
:
$menuActiveText
!
important
;
background-color
:
#FFFFFF
!
important
;
}
}
&
.el-submenu
.is-active
{
color
:
$menuActiveText
!
important
;
}
}
.fixed-sidebar
.el-scrollbar
{
position
:
fixed
;
top
:
0
;
}
.hideSidebar
{
.sidebar-container
{
width
:
54px
!
important
;
}
.main-container
{
margin-left
:
54px
;
}
.submenu-title-noDropdown
{
padding
:
0
!
important
;
position
:
relative
;
.el-tooltip
{
padding
:
0
!
important
;
.svg-icon
{
margin-left
:
20px
;
}
.sub-el-icon
{
margin-left
:
19px
;
}
}
}
.el-submenu
{
overflow
:
hidden
;
&
>
.el-submenu__title
{
padding
:
0
!
important
;
.svg-icon
{
margin-left
:
20px
;
}
.sub-el-icon
{
margin-left
:
19px
;
}
.el-submenu__icon-arrow
{
display
:
none
;
}
}
}
.el-menu--collapse
{
.el-submenu
{
&
>
.el-submenu__title
{
&
>
span
{
height
:
0
;
width
:
0
;
overflow
:
hidden
;
visibility
:
hidden
;
display
:
inline-block
;
}
}
}
}
}
.el-menu--collapse
.el-menu
.el-submenu
{
min-width
:
$sideBarWidth
!
important
;
}
// mobile responsive
.mobile
{
.main-container
{
margin-left
:
0px
;
}
.sidebar-container
{
transition
:
transform
.28s
;
width
:
$sideBarWidth
!
important
;
}
&
.hideSidebar
{
.sidebar-container
{
pointer-events
:
none
;
transition-duration
:
0
.3s
;
transform
:
translate3d
(
-
$sideBarWidth
,
0
,
0
);
}
}
}
.withoutAnimation
{
.main-container
,
.sidebar-container
{
transition
:
none
;
}
}
}
// when menu collapsed
.el-menu--vertical
{
&
>
.el-menu
{
.svg-icon
{
margin-right
:
16px
;
}
.sub-el-icon
{
margin-right
:
12px
;
margin-left
:
-2px
;
}
}
.nest-menu
.el-submenu
>
.el-submenu__title
,
.el-menu-item
{
&
:hover
{
// you can use $subMenuHover
// background-color: $menuHover !important;
background-color
:
#FFFFFF
!
important
;
}
}
// the scroll bar appears when the subMenu is too long
>
.el-menu--popup
{
max-height
:
100vh
;
overflow-y
:
auto
;
&
::-webkit-scrollbar-track-piece
{
background
:
#d3dce6
;
}
&
::-webkit-scrollbar
{
width
:
6px
;
}
&
::-webkit-scrollbar-thumb
{
background
:
#99a9bf
;
border-radius
:
20px
;
}
}
}
front-end/mall4cloud-multishop-master/src/styles/transition.scss
0 → 100644
View file @
a21f5a9a
// global transition css
/* fade */
.fade-enter-active
,
.fade-leave-active
{
transition
:
opacity
0
.28s
;
}
.fade-enter
,
.fade-leave-active
{
opacity
:
0
;
}
/* fade-transform */
.fade-transform-leave-active
,
.fade-transform-enter-active
{
transition
:
all
.5s
;
}
.fade-transform-enter
{
opacity
:
0
;
transform
:
translateX
(
-30px
);
}
.fade-transform-leave-to
{
opacity
:
0
;
transform
:
translateX
(
30px
);
}
/* breadcrumb transition */
.breadcrumb-enter-active
,
.breadcrumb-leave-active
{
transition
:
all
.5s
;
}
.breadcrumb-enter
,
.breadcrumb-leave-active
{
opacity
:
0
;
transform
:
translateX
(
20px
);
}
.breadcrumb-move
{
transition
:
all
.5s
;
}
.breadcrumb-leave-active
{
position
:
absolute
;
}
front-end/mall4cloud-multishop-master/src/styles/variables.scss
0 → 100644
View file @
a21f5a9a
// base color
$blue
:
#324157
;
$light-blue
:
#3A71A8
;
$red
:
#C03639
;
$pink
:
#E65D6E
;
$green
:
#30B08F
;
$tiffany
:
#4AB7BD
;
$yellow
:
#FEC171
;
$panGreen
:
#30B08F
;
// sidebar
$menuText
:
#333333
;
$menuActiveText
:
#007DE4
;
$subMenuActiveText
:
#333333
;
// https://github.com/ElemeFE/element/issues/12951
$menuBg
:
#ffffff
;
$menuHover
:
#f4f4f4
;
$subMenuBg
:
#ffffff
;
$subMenuHover
:
#f4f4f4
;
$sideBarWidth
:
206px
;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export
{
menuText
:
$menuText
;
menuActiveText
:
$menuActiveText
;
subMenuActiveText
:
$subMenuActiveText
;
menuBg
:
$menuBg
;
menuHover
:
$menuHover
;
subMenuBg
:
$subMenuBg
;
subMenuHover
:
$subMenuHover
;
sideBarWidth
:
$sideBarWidth
;
}
front-end/mall4cloud-multishop-master/src/utils/addr.js
0 → 100644
View file @
a21f5a9a
/**
* 通过地址id获取省市区的地址名
* @param {*} s
*/
export
function
areaNameList
(
areaData
,
cityList
)
{
// 插入数据
cityList
.
forEach
(
element
=>
{
var
city
=
element
// 省
for
(
var
i
=
0
;
i
<
areaData
.
length
;
i
++
)
{
// 市
const
cityIndex
=
areaData
[
i
].
areaIds
.
indexOf
(
city
.
parentId
)
if
(
cityIndex
>
-
1
)
{
// 区
const
areaIndex
=
areaData
[
i
].
areas
[
cityIndex
].
areaIds
.
indexOf
(
city
.
areaId
)
if
(
areaIndex
>
-
1
)
{
areaData
[
i
].
areas
[
cityIndex
].
areas
[
areaIndex
].
check
=
true
}
}
}
})
// 获取区域名
var
addrNameList
=
[]
// 城市名
var
cityNameList
=
[]
// 地区名
var
areaNameList
=
[]
areaData
.
forEach
(
province
=>
{
var
cityList
=
[]
var
cityAll
=
true
// 市
province
.
areas
.
forEach
(
city
=>
{
var
areaList
=
[]
var
areaAll
=
true
// 区
city
.
areas
.
forEach
(
area
=>
{
if
(
area
.
check
)
{
areaList
.
push
(
area
.
areaName
)
}
else
if
(
areaAll
)
{
areaAll
=
false
cityAll
=
false
}
})
// 区 END
if
(
areaAll
)
{
// 该市下的区已全部勾选,则添加城市名
cityList
.
push
(
city
.
areaName
)
city
.
check
=
true
}
else
if
(
areaList
.
length
>
0
)
{
// 仅勾选部分区,把勾选的区添加到地区名名的数组中
areaNameList
=
areaNameList
.
concat
(
areaList
)
}
if
(
!
city
.
check
)
{
cityAll
=
false
}
})
// 市 END
if
(
cityAll
)
{
// 所有的城市都已勾选,则添加省名
addrNameList
.
push
(
province
.
areaName
)
province
.
check
=
true
}
else
if
(
cityList
.
length
>
0
)
{
// 只勾选部分城市,把勾选的城市添加到城市名的数组中
cityNameList
=
cityNameList
.
concat
(
cityList
)
}
})
// 拼接省->市->区
if
(
cityNameList
.
length
>
0
)
{
addrNameList
=
addrNameList
.
concat
(
cityNameList
)
}
if
(
areaNameList
.
length
>
0
)
{
addrNameList
=
addrNameList
.
concat
(
areaNameList
)
}
return
addrNameList
}
front-end/mall4cloud-multishop-master/src/utils/auth.js
0 → 100644
View file @
a21f5a9a
import
Cookies
from
'
js-cookie
'
const
TokenKey
=
'
mall4cloud-Admin-Token
'
export
function
getToken
()
{
return
Cookies
.
get
(
TokenKey
)
}
export
function
setToken
(
token
)
{
return
Cookies
.
set
(
TokenKey
,
token
)
}
export
function
removeToken
()
{
return
Cookies
.
remove
(
TokenKey
)
}
front-end/mall4cloud-multishop-master/src/utils/clipboard.js
0 → 100644
View file @
a21f5a9a
import
Vue
from
'
vue
'
import
Clipboard
from
'
clipboard
'
function
clipboardSuccess
()
{
Vue
.
prototype
.
$message
({
message
:
'
Copy successfully
'
,
type
:
'
success
'
,
duration
:
1500
})
}
function
clipboardError
()
{
Vue
.
prototype
.
$message
({
message
:
'
Copy failed
'
,
type
:
'
error
'
})
}
export
default
function
handleClipboard
(
text
,
event
)
{
const
clipboard
=
new
Clipboard
(
event
.
target
,
{
text
:
()
=>
text
})
clipboard
.
on
(
'
success
'
,
()
=>
{
clipboardSuccess
()
clipboard
.
destroy
()
})
clipboard
.
on
(
'
error
'
,
()
=>
{
clipboardError
()
clipboard
.
destroy
()
})
clipboard
.
onClick
(
event
)
}
front-end/mall4cloud-multishop-master/src/utils/get-page-title.js
0 → 100644
View file @
a21f5a9a
import
defaultSettings
from
'
@/settings
'
import
i18n
from
'
@/lang
'
const
title
=
defaultSettings
.
title
||
'
Vue Element Admin
'
export
default
function
getPageTitle
(
key
)
{
const
hasKey
=
i18n
.
te
(
`route.
${
key
}
`
)
if
(
hasKey
)
{
const
pageName
=
i18n
.
t
(
`route.
${
key
}
`
)
return
`
${
pageName
}
-
${
title
}
`
}
return
`
${
title
}
`
}
front-end/mall4cloud-multishop-master/src/utils/i18n.js
0 → 100644
View file @
a21f5a9a
// translate router.meta.title, be used in breadcrumb sidebar tagsview
export
function
generateTitle
(
title
)
{
const
hasKey
=
this
.
$te
(
'
route.
'
+
title
)
if
(
hasKey
)
{
// $t :this method from vue-i18n, inject in @/lang/index.js
const
translatedTitle
=
this
.
$t
(
'
route.
'
+
title
)
return
translatedTitle
}
return
title
}
front-end/mall4cloud-multishop-master/src/utils/index.js
0 → 100644
View file @
a21f5a9a
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string | null}
*/
export
function
parseTime
(
time
,
cFormat
)
{
if
(
arguments
.
length
===
0
||
!
time
)
{
return
null
}
const
format
=
cFormat
||
'
{y}-{m}-{d} {h}:{i}:{s}
'
let
date
if
(
typeof
time
===
'
object
'
)
{
date
=
time
}
else
{
if
((
typeof
time
===
'
string
'
))
{
if
((
/^
[
0-9
]
+$/
.
test
(
time
)))
{
// support "1548221490638"
time
=
parseInt
(
time
)
}
else
{
// support safari
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
time
=
time
.
replace
(
new
RegExp
(
/-/gm
),
'
/
'
)
}
}
if
((
typeof
time
===
'
number
'
)
&&
(
time
.
toString
().
length
===
10
))
{
time
=
time
*
1000
}
date
=
new
Date
(
time
)
}
const
formatObj
=
{
y
:
date
.
getFullYear
(),
m
:
date
.
getMonth
()
+
1
,
d
:
date
.
getDate
(),
h
:
date
.
getHours
(),
i
:
date
.
getMinutes
(),
s
:
date
.
getSeconds
(),
a
:
date
.
getDay
()
}
const
time_str
=
format
.
replace
(
/{
([
ymdhisa
])
+}/g
,
(
result
,
key
)
=>
{
const
value
=
formatObj
[
key
]
// Note: getDay() returns 0 on Sunday
if
(
key
===
'
a
'
)
{
return
[
'
日
'
,
'
一
'
,
'
二
'
,
'
三
'
,
'
四
'
,
'
五
'
,
'
六
'
][
value
]
}
return
value
.
toString
().
padStart
(
2
,
'
0
'
)
})
return
time_str
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
export
function
formatTime
(
time
,
option
)
{
if
((
''
+
time
).
length
===
10
)
{
time
=
parseInt
(
time
)
*
1000
}
else
{
time
=
+
time
}
const
d
=
new
Date
(
time
)
const
now
=
Date
.
now
()
const
diff
=
(
now
-
d
)
/
1000
if
(
diff
<
30
)
{
return
'
刚刚
'
}
else
if
(
diff
<
3600
)
{
// less 1 hour
return
Math
.
ceil
(
diff
/
60
)
+
'
分钟前
'
}
else
if
(
diff
<
3600
*
24
)
{
return
Math
.
ceil
(
diff
/
3600
)
+
'
小时前
'
}
else
if
(
diff
<
3600
*
24
*
2
)
{
return
'
1天前
'
}
if
(
option
)
{
return
parseTime
(
time
,
option
)
}
else
{
return
(
d
.
getMonth
()
+
1
+
'
月
'
+
d
.
getDate
()
+
'
日
'
+
d
.
getHours
()
+
'
时
'
+
d
.
getMinutes
()
+
'
分
'
)
}
}
/**
* @param {string} url
* @returns {Object}
*/
export
function
getQueryObject
(
url
)
{
url
=
url
==
null
?
window
.
location
.
href
:
url
const
search
=
url
.
substring
(
url
.
lastIndexOf
(
'
?
'
)
+
1
)
const
obj
=
{}
const
reg
=
/
([^
?&=
]
+
)
=
([^
?&=
]
*
)
/g
search
.
replace
(
reg
,
(
rs
,
$1
,
$2
)
=>
{
const
name
=
decodeURIComponent
(
$1
)
let
val
=
decodeURIComponent
(
$2
)
val
=
String
(
val
)
obj
[
name
]
=
val
return
rs
})
return
obj
}
/**
* @param {string} input value
* @returns {number} output value
*/
export
function
byteLength
(
str
)
{
// returns the byte length of an utf8 string
let
s
=
str
.
length
for
(
var
i
=
str
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
code
=
str
.
charCodeAt
(
i
)
if
(
code
>
0x7f
&&
code
<=
0x7ff
)
s
++
else
if
(
code
>
0x7ff
&&
code
<=
0xffff
)
s
+=
2
if
(
code
>=
0xDC00
&&
code
<=
0xDFFF
)
i
--
}
return
s
}
/**
* @param {Array} actual
* @returns {Array}
*/
export
function
cleanArray
(
actual
)
{
const
newArray
=
[]
for
(
let
i
=
0
;
i
<
actual
.
length
;
i
++
)
{
if
(
actual
[
i
])
{
newArray
.
push
(
actual
[
i
])
}
}
return
newArray
}
/**
* @param {Object} json
* @returns {Array}
*/
export
function
param
(
json
)
{
if
(
!
json
)
return
''
return
cleanArray
(
Object
.
keys
(
json
).
map
(
key
=>
{
if
(
json
[
key
]
===
undefined
)
return
''
return
encodeURIComponent
(
key
)
+
'
=
'
+
encodeURIComponent
(
json
[
key
])
})
).
join
(
'
&
'
)
}
/**
* @param {string} url
* @returns {Object}
*/
export
function
param2Obj
(
url
)
{
const
search
=
decodeURIComponent
(
url
.
split
(
'
?
'
)[
1
]).
replace
(
/
\+
/g
,
'
'
)
if
(
!
search
)
{
return
{}
}
const
obj
=
{}
const
searchArr
=
search
.
split
(
'
&
'
)
searchArr
.
forEach
(
v
=>
{
const
index
=
v
.
indexOf
(
'
=
'
)
if
(
index
!==
-
1
)
{
const
name
=
v
.
substring
(
0
,
index
)
const
val
=
v
.
substring
(
index
+
1
,
v
.
length
)
obj
[
name
]
=
val
}
})
return
obj
}
/**
* @param {string} val
* @returns {string}
*/
export
function
html2Text
(
val
)
{
const
div
=
document
.
createElement
(
'
div
'
)
div
.
innerHTML
=
val
return
div
.
textContent
||
div
.
innerText
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
export
function
objectMerge
(
target
,
source
)
{
if
(
typeof
target
!==
'
object
'
)
{
target
=
{}
}
if
(
Array
.
isArray
(
source
))
{
return
source
.
slice
()
}
Object
.
keys
(
source
).
forEach
(
property
=>
{
const
sourceProperty
=
source
[
property
]
if
(
typeof
sourceProperty
===
'
object
'
)
{
target
[
property
]
=
objectMerge
(
target
[
property
],
sourceProperty
)
}
else
{
target
[
property
]
=
sourceProperty
}
})
return
target
}
/**
* @param {HTMLElement} element
* @param {string} className
*/
export
function
toggleClass
(
element
,
className
)
{
if
(
!
element
||
!
className
)
{
return
}
let
classString
=
element
.
className
const
nameIndex
=
classString
.
indexOf
(
className
)
if
(
nameIndex
===
-
1
)
{
classString
+=
''
+
className
}
else
{
classString
=
classString
.
substr
(
0
,
nameIndex
)
+
classString
.
substr
(
nameIndex
+
className
.
length
)
}
element
.
className
=
classString
}
/**
* @param {string} type
* @returns {Date}
*/
export
function
getTime
(
type
)
{
if
(
type
===
'
start
'
)
{
return
new
Date
().
getTime
()
-
3600
*
1000
*
24
*
90
}
else
{
return
new
Date
(
new
Date
().
toDateString
())
}
}
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export
function
debounce
(
func
,
wait
,
immediate
)
{
let
timeout
,
args
,
context
,
timestamp
,
result
const
later
=
function
()
{
// 据上一次触发时间间隔
const
last
=
+
new
Date
()
-
timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if
(
last
<
wait
&&
last
>
0
)
{
timeout
=
setTimeout
(
later
,
wait
-
last
)
}
else
{
timeout
=
null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if
(
!
immediate
)
{
result
=
func
.
apply
(
context
,
args
)
if
(
!
timeout
)
context
=
args
=
null
}
}
}
return
function
(...
args
)
{
context
=
this
timestamp
=
+
new
Date
()
const
callNow
=
immediate
&&
!
timeout
// 如果延时不存在,重新设定延时
if
(
!
timeout
)
timeout
=
setTimeout
(
later
,
wait
)
if
(
callNow
)
{
result
=
func
.
apply
(
context
,
args
)
context
=
args
=
null
}
return
result
}
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export
function
deepClone
(
source
)
{
if
(
!
source
&&
typeof
source
!==
'
object
'
)
{
throw
new
Error
(
'
error arguments
'
,
'
deepClone
'
)
}
const
targetObj
=
source
.
constructor
===
Array
?
[]
:
{}
Object
.
keys
(
source
).
forEach
(
keys
=>
{
if
(
source
[
keys
]
&&
typeof
source
[
keys
]
===
'
object
'
)
{
targetObj
[
keys
]
=
deepClone
(
source
[
keys
])
}
else
{
targetObj
[
keys
]
=
source
[
keys
]
}
})
return
targetObj
}
/**
* @param {Array} arr
* @returns {Array}
*/
export
function
uniqueArr
(
arr
)
{
return
Array
.
from
(
new
Set
(
arr
))
}
/**
* @returns {string}
*/
export
function
createUniqueString
()
{
const
timestamp
=
+
new
Date
()
+
''
const
randomNum
=
parseInt
((
1
+
Math
.
random
())
*
65536
)
+
''
return
(
+
(
randomNum
+
timestamp
)).
toString
(
32
)
}
/**
* Check if an element has a class
* @param {HTMLElement} elm
* @param {string} cls
* @returns {boolean}
*/
export
function
hasClass
(
ele
,
cls
)
{
return
!!
ele
.
className
.
match
(
new
RegExp
(
'
(
\\
s|^)
'
+
cls
+
'
(
\\
s|$)
'
))
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
*/
export
function
addClass
(
ele
,
cls
)
{
if
(
!
hasClass
(
ele
,
cls
))
ele
.
className
+=
'
'
+
cls
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
*/
export
function
removeClass
(
ele
,
cls
)
{
if
(
hasClass
(
ele
,
cls
))
{
const
reg
=
new
RegExp
(
'
(
\\
s|^)
'
+
cls
+
'
(
\\
s|$)
'
)
ele
.
className
=
ele
.
className
.
replace
(
reg
,
'
'
)
}
}
/**
* 树形数据转换
* @param {*} data
* @param {*} id
* @param {*} pid
*/
export
function
treeDataTranslate
(
data
,
id
=
'
id
'
,
pid
=
'
parentId
'
)
{
var
res
=
[]
var
temp
=
{}
for
(
var
i
=
0
;
i
<
data
.
length
;
i
++
)
{
temp
[
data
[
i
][
id
]]
=
data
[
i
]
}
for
(
var
k
=
0
;
k
<
data
.
length
;
k
++
)
{
if
(
temp
[
data
[
k
][
pid
]]
&&
data
[
k
][
id
]
!==
data
[
k
][
pid
])
{
if
(
!
temp
[
data
[
k
][
pid
]][
'
children
'
])
{
temp
[
data
[
k
][
pid
]][
'
children
'
]
=
[]
}
if
(
!
temp
[
data
[
k
][
pid
]][
'
_level
'
])
{
temp
[
data
[
k
][
pid
]][
'
_level
'
]
=
1
}
data
[
k
][
'
_level
'
]
=
temp
[
data
[
k
][
pid
]].
_level
+
1
temp
[
data
[
k
][
pid
]][
'
children
'
].
push
(
data
[
k
])
}
else
{
res
.
push
(
data
[
k
])
}
}
return
res
}
/**
* 获取uuid
*/
export
function
getUUID
()
{
return
'
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
'
.
replace
(
/
[
xy
]
/g
,
c
=>
{
return
(
c
===
'
x
'
?
(
Math
.
random
()
*
16
|
0
)
:
(
'
r&0x3
'
|
'
0x8
'
)).
toString
(
16
)
})
}
/**
* 将数组中的parentId列表取出,倒序排列
* @param {*} data
* @param {*} id
* @param {*} pid
*/
export
function
idList
(
data
,
val
,
id
=
'
id
'
,
children
=
'
children
'
)
{
const
res
=
[]
idListFromTree
(
data
,
val
,
res
,
id
)
return
res
}
/**
* @param {*} data
* @param {*} id
* @param {*} pid
*/
function
idListFromTree
(
data
,
val
,
res
=
[],
id
=
'
id
'
,
children
=
'
children
'
,
name
=
'
name
'
)
{
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
const
element
=
data
[
i
]
if
(
element
[
children
])
{
if
(
idListFromTree
(
element
[
children
],
val
,
res
,
id
,
children
))
{
res
.
push
({
id
:
element
[
id
],
name
:
element
[
name
]
})
return
true
}
}
if
(
element
[
id
]
===
val
)
{
res
.
push
({
id
:
element
[
id
],
name
:
element
[
name
]
})
return
true
}
}
}
// 计算每个sku后面有多少项
export
function
getLevels
(
tree
)
{
const
level
=
[]
for
(
let
i
=
tree
.
length
-
1
;
i
>=
0
;
i
--
)
{
if
(
tree
[
i
+
1
]
&&
tree
[
i
+
1
].
leaf
)
{
level
[
i
]
=
tree
[
i
+
1
].
leaf
.
length
*
level
[
i
+
1
]
||
1
}
else
{
level
[
i
]
=
1
}
}
return
level
}
/**
* 笛卡尔积运算
* @param {[type]} tree [description]
* @param {Array} stocks [description]
* @return {[type]} [description]
*/
export
function
flatten
(
tree
,
stocks
=
[],
options
)
{
const
{
optionValue
=
'
id
'
,
optionText
=
'
text
'
,
extraData
=
{}}
=
options
||
{}
const
result
=
[]
let
skuLen
=
0
const
stockMap
=
{}
// 记录已存在的stock的数据
const
level
=
getLevels
(
tree
)
if
(
tree
.
length
===
0
)
return
result
tree
.
forEach
(
sku
=>
{
const
{
leaf
}
=
sku
if
(
!
leaf
||
leaf
.
length
===
0
)
return
true
skuLen
=
(
skuLen
||
1
)
*
leaf
.
length
})
// 根据已有的stocks生成一个map
stocks
.
forEach
(
stock
=>
{
const
{
spuSkuAttrValues
,
...
attr
}
=
stock
stockMap
[
spuSkuAttrValues
.
map
(
item
=>
`
${
item
.
attrId
}
_
${
item
.
attrValueId
}
`
).
join
(
'
|
'
)]
=
attr
})
for
(
let
i
=
0
;
i
<
skuLen
;
i
++
)
{
const
spuSkuAttrValues
=
[]
const
mapKey
=
[]
tree
.
forEach
((
sku
,
column
)
=>
{
const
{
leaf
}
=
sku
let
item
=
{}
if
(
!
leaf
||
leaf
.
length
===
0
)
return
true
if
(
leaf
.
length
>
1
)
{
const
row
=
parseInt
(
i
/
level
[
column
],
10
)
%
leaf
.
length
item
=
tree
[
column
].
leaf
[
row
]
}
else
{
item
=
tree
[
column
].
leaf
[
0
]
}
if
(
!
sku
[
optionValue
]
||
!
item
[
optionValue
])
return
mapKey
.
push
(
`
${
sku
[
optionValue
]}
_
${
item
[
optionValue
]}
`
)
spuSkuAttrValues
.
push
({
attrId
:
sku
[
optionValue
],
// 属性ID
attrName
:
sku
[
optionText
],
// 属性名称
attrValueId
:
item
[
optionValue
],
// 属性值ID
attrValueName
:
item
[
optionText
]
// 属性值
})
})
const
{
...
data
}
=
stockMap
[
mapKey
.
join
(
'
|
'
)]
||
{}
// 从map中找出存在的sku并保留其值
result
.
push
({
...
extraData
,
...
data
,
spuSkuAttrValues
})
}
return
result
}
front-end/mall4cloud-multishop-master/src/utils/permission.js
0 → 100644
View file @
a21f5a9a
import
store
from
'
@/store
'
/**
* @param {Array} value
* @returns {Boolean}
* @example see @/views/permission/directive.vue
*/
export
default
function
checkPermission
(
value
)
{
if
(
value
&&
value
instanceof
Array
&&
value
.
length
>
0
)
{
const
roles
=
store
.
getters
&&
store
.
getters
.
roles
const
permissionRoles
=
value
const
hasPermission
=
roles
.
some
(
role
=>
{
return
permissionRoles
.
includes
(
role
)
})
if
(
!
hasPermission
)
{
return
false
}
return
true
}
else
{
console
.
error
(
`need roles! Like v-permission="['admin','editor']"`
)
return
false
}
}
Prev
1
…
13
14
15
16
17
18
Next
Write
Preview
Markdown
is supported
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