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
0c4786dc
Commit
0c4786dc
authored
Feb 03, 2020
by
Junling Bu
Browse files
feat[litemall-admin]: 管理后台支持通知中心和通知管理
parent
366a2934
Changes
12
Hide whitespace changes
Inline
Side-by-side
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/util/AdminResponseCode.java
View file @
0c4786dc
...
...
@@ -23,5 +23,6 @@ public class AdminResponseCode {
public
static
final
Integer
GROUPON_GOODS_UNKNOWN
=
650
;
public
static
final
Integer
GROUPON_GOODS_EXISTED
=
651
;
public
static
final
Integer
GROUPON_GOODS_OFFLINE
=
652
;
public
static
final
Integer
NOTICE_UPDATE_NOT_ALLOWED
=
660
;
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminNoticeController.java
0 → 100644
View file @
0c4786dc
package
org.linlinjava.litemall.admin.web
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.apache.shiro.SecurityUtils
;
import
org.apache.shiro.authz.annotation.RequiresPermissions
;
import
org.apache.shiro.subject.Subject
;
import
org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc
;
import
org.linlinjava.litemall.core.util.JacksonUtil
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.core.validator.Order
;
import
org.linlinjava.litemall.core.validator.Sort
;
import
org.linlinjava.litemall.db.domain.*
;
import
org.linlinjava.litemall.db.service.LitemallAdminService
;
import
org.linlinjava.litemall.db.service.LitemallNoticeAdminService
;
import
org.linlinjava.litemall.db.service.LitemallNoticeService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.util.StringUtils
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.validation.constraints.NotNull
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.
NOTICE_UPDATE_NOT_ALLOWED
;
@RestController
@RequestMapping
(
"/admin/notice"
)
@Validated
public
class
AdminNoticeController
{
private
final
Log
logger
=
LogFactory
.
getLog
(
AdminNoticeController
.
class
);
@Autowired
private
LitemallNoticeService
noticeService
;
@Autowired
private
LitemallAdminService
adminService
;
@Autowired
private
LitemallNoticeAdminService
noticeAdminService
;
@RequiresPermissions
(
"admin:notice:list"
)
@RequiresPermissionsDesc
(
menu
=
{
"系统管理"
,
"通知管理"
},
button
=
"查询"
)
@GetMapping
(
"/list"
)
public
Object
list
(
String
title
,
String
content
,
@RequestParam
(
defaultValue
=
"1"
)
Integer
page
,
@RequestParam
(
defaultValue
=
"10"
)
Integer
limit
,
@Sort
@RequestParam
(
defaultValue
=
"add_time"
)
String
sort
,
@Order
@RequestParam
(
defaultValue
=
"desc"
)
String
order
)
{
List
<
LitemallNotice
>
noticeList
=
noticeService
.
querySelective
(
title
,
content
,
page
,
limit
,
sort
,
order
);
return
ResponseUtil
.
okList
(
noticeList
);
}
private
Object
validate
(
LitemallNotice
notice
)
{
String
title
=
notice
.
getTitle
();
if
(
StringUtils
.
isEmpty
(
title
))
{
return
ResponseUtil
.
badArgument
();
}
return
null
;
}
private
Integer
getAdminId
(){
Subject
currentUser
=
SecurityUtils
.
getSubject
();
LitemallAdmin
admin
=
(
LitemallAdmin
)
currentUser
.
getPrincipal
();
return
admin
.
getId
();
}
@RequiresPermissions
(
"admin:notice:create"
)
@RequiresPermissionsDesc
(
menu
=
{
"推广管理"
,
"通知管理"
},
button
=
"添加"
)
@PostMapping
(
"/create"
)
public
Object
create
(
@RequestBody
LitemallNotice
notice
)
{
Object
error
=
validate
(
notice
);
if
(
error
!=
null
)
{
return
error
;
}
// 1. 添加通知记录
notice
.
setAdminId
(
getAdminId
());
noticeService
.
add
(
notice
);
// 2. 添加管理员通知记录
List
<
LitemallAdmin
>
adminList
=
adminService
.
all
();
LitemallNoticeAdmin
noticeAdmin
=
new
LitemallNoticeAdmin
();
noticeAdmin
.
setNoticeId
(
notice
.
getId
());
noticeAdmin
.
setNoticeTitle
(
notice
.
getTitle
());
for
(
LitemallAdmin
admin
:
adminList
){
noticeAdmin
.
setAdminId
(
admin
.
getId
());
noticeAdminService
.
add
(
noticeAdmin
);
}
return
ResponseUtil
.
ok
(
notice
);
}
@RequiresPermissions
(
"admin:notice:read"
)
@RequiresPermissionsDesc
(
menu
=
{
"推广管理"
,
"通知管理"
},
button
=
"详情"
)
@GetMapping
(
"/read"
)
public
Object
read
(
@NotNull
Integer
id
)
{
LitemallNotice
notice
=
noticeService
.
findById
(
id
);
List
<
LitemallNoticeAdmin
>
noticeAdminList
=
noticeAdminService
.
queryByNoticeId
(
id
);
Map
<
String
,
Object
>
data
=
new
HashMap
<>(
2
);
data
.
put
(
"notice"
,
notice
);
data
.
put
(
"noticeAdminList"
,
noticeAdminList
);
return
ResponseUtil
.
ok
(
data
);
}
@RequiresPermissions
(
"admin:notice:update"
)
@RequiresPermissionsDesc
(
menu
=
{
"推广管理"
,
"通知管理"
},
button
=
"编辑"
)
@PostMapping
(
"/update"
)
public
Object
update
(
@RequestBody
LitemallNotice
notice
)
{
Object
error
=
validate
(
notice
);
if
(
error
!=
null
)
{
return
error
;
}
LitemallNotice
originalNotice
=
noticeService
.
findById
(
notice
.
getId
());
if
(
originalNotice
==
null
)
{
return
ResponseUtil
.
badArgument
();
}
// 如果通知已经有人阅读过,则不支持编辑
if
(
noticeAdminService
.
countReadByNoticeId
(
notice
.
getId
())
>
0
){
return
ResponseUtil
.
fail
(
NOTICE_UPDATE_NOT_ALLOWED
,
"通知已被阅读,不能重新编辑"
);
}
// 1. 更新通知记录
notice
.
setAdminId
(
getAdminId
());
noticeService
.
updateById
(
notice
);
// 2. 更新管理员通知记录
if
(!
originalNotice
.
getTitle
().
equals
(
notice
.
getTitle
())){
LitemallNoticeAdmin
noticeAdmin
=
new
LitemallNoticeAdmin
();
noticeAdmin
.
setNoticeTitle
(
notice
.
getTitle
());
noticeAdminService
.
updateByNoticeId
(
noticeAdmin
,
notice
.
getId
());
}
return
ResponseUtil
.
ok
(
notice
);
}
@RequiresPermissions
(
"admin:notice:delete"
)
@RequiresPermissionsDesc
(
menu
=
{
"推广管理"
,
"通知管理"
},
button
=
"删除"
)
@PostMapping
(
"/delete"
)
public
Object
delete
(
@RequestBody
LitemallNotice
notice
)
{
// 1. 删除通知管理员记录
noticeAdminService
.
deleteByNoticeId
(
notice
.
getId
());
// 2. 删除通知记录
noticeService
.
deleteById
(
notice
.
getId
());
return
ResponseUtil
.
ok
();
}
@RequiresPermissions
(
"admin:notice:batch-delete"
)
@RequiresPermissionsDesc
(
menu
=
{
"推广管理"
,
"通知管理"
},
button
=
"批量删除"
)
@PostMapping
(
"/batch-delete"
)
public
Object
batchDelete
(
@RequestBody
String
body
)
{
List
<
Integer
>
ids
=
JacksonUtil
.
parseIntegerList
(
body
,
"ids"
);
// 1. 删除通知管理员记录
noticeAdminService
.
deleteByNoticeIds
(
ids
);
// 2. 删除通知记录
noticeService
.
deleteByIds
(
ids
);
return
ResponseUtil
.
ok
();
}
}
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminProfileController.java
View file @
0c4786dc
package
org.linlinjava.litemall.admin.web
;
import
io.swagger.models.auth.In
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.apache.shiro.SecurityUtils
;
...
...
@@ -8,15 +9,25 @@ import org.apache.shiro.subject.Subject;
import
org.linlinjava.litemall.core.util.JacksonUtil
;
import
org.linlinjava.litemall.core.util.ResponseUtil
;
import
org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder
;
import
org.linlinjava.litemall.core.validator.Order
;
import
org.linlinjava.litemall.core.validator.Sort
;
import
org.linlinjava.litemall.db.domain.LitemallAdmin
;
import
org.linlinjava.litemall.db.domain.LitemallIssue
;
import
org.linlinjava.litemall.db.domain.LitemallNotice
;
import
org.linlinjava.litemall.db.domain.LitemallNoticeAdmin
;
import
org.linlinjava.litemall.db.service.LitemallAdminService
;
import
org.linlinjava.litemall.db.service.LitemallNoticeAdminService
;
import
org.linlinjava.litemall.db.service.LitemallNoticeService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.util.StringUtils
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.*
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
static
org
.
linlinjava
.
litemall
.
admin
.
util
.
AdminResponseCode
.
ADMIN_INVALID_ACCOUNT
;
...
...
@@ -28,6 +39,10 @@ public class AdminProfileController {
@Autowired
private
LitemallAdminService
adminService
;
@Autowired
private
LitemallNoticeService
noticeService
;
@Autowired
private
LitemallNoticeAdminService
noticeAdminService
;
@RequiresAuthentication
@PostMapping
(
"/password"
)
...
...
@@ -56,4 +71,89 @@ public class AdminProfileController {
return
ResponseUtil
.
ok
();
}
private
Integer
getAdminId
(){
Subject
currentUser
=
SecurityUtils
.
getSubject
();
LitemallAdmin
admin
=
(
LitemallAdmin
)
currentUser
.
getPrincipal
();
return
admin
.
getId
();
}
@RequiresAuthentication
@GetMapping
(
"/nnotice"
)
public
Object
nNotice
()
{
int
count
=
noticeAdminService
.
countUnread
(
getAdminId
());
return
ResponseUtil
.
ok
(
count
);
}
@RequiresAuthentication
@GetMapping
(
"/lsnotice"
)
public
Object
lsNotice
(
String
title
,
String
type
,
@RequestParam
(
defaultValue
=
"1"
)
Integer
page
,
@RequestParam
(
defaultValue
=
"10"
)
Integer
limit
,
@Sort
@RequestParam
(
defaultValue
=
"add_time"
)
String
sort
,
@Order
@RequestParam
(
defaultValue
=
"desc"
)
String
order
)
{
List
<
LitemallNoticeAdmin
>
noticeList
=
noticeAdminService
.
querySelective
(
title
,
type
,
getAdminId
(),
page
,
limit
,
sort
,
order
);
return
ResponseUtil
.
okList
(
noticeList
);
}
@RequiresAuthentication
@PostMapping
(
"/catnotice"
)
public
Object
catNotice
(
@RequestBody
String
body
)
{
Integer
noticeId
=
JacksonUtil
.
parseInteger
(
body
,
"noticeId"
);
if
(
noticeId
==
null
){
return
ResponseUtil
.
badArgument
();
}
LitemallNoticeAdmin
noticeAdmin
=
noticeAdminService
.
find
(
noticeId
,
getAdminId
());
if
(
noticeAdmin
==
null
){
return
ResponseUtil
.
badArgumentValue
();
}
// 更新通知记录中的时间
noticeAdmin
.
setReadTime
(
LocalDateTime
.
now
());
noticeAdminService
.
update
(
noticeAdmin
);
// 返回通知的相关信息
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
LitemallNotice
notice
=
noticeService
.
findById
(
noticeId
);
data
.
put
(
"title"
,
notice
.
getTitle
());
data
.
put
(
"content"
,
notice
.
getContent
());
data
.
put
(
"time"
,
notice
.
getUpdateTime
());
Integer
adminId
=
notice
.
getAdminId
();
if
(
adminId
.
equals
(
0
)){
data
.
put
(
"admin"
,
"系统"
);
}
else
{
LitemallAdmin
admin
=
adminService
.
findById
(
notice
.
getAdminId
());
data
.
put
(
"admin"
,
admin
.
getUsername
());
data
.
put
(
"avatar"
,
admin
.
getAvatar
());
}
return
ResponseUtil
.
ok
(
data
);
}
@RequiresAuthentication
@PostMapping
(
"/bcatnotice"
)
public
Object
bcatNotice
(
@RequestBody
String
body
)
{
List
<
Integer
>
ids
=
JacksonUtil
.
parseIntegerList
(
body
,
"ids"
);
noticeAdminService
.
markReadByIds
(
ids
,
getAdminId
());
return
ResponseUtil
.
ok
();
}
@RequiresAuthentication
@PostMapping
(
"/rmnotice"
)
public
Object
rmNotice
(
@RequestBody
String
body
)
{
Integer
id
=
JacksonUtil
.
parseInteger
(
body
,
"id"
);
if
(
id
==
null
){
return
ResponseUtil
.
badArgument
();
}
noticeAdminService
.
deleteById
(
id
,
getAdminId
());
return
ResponseUtil
.
ok
();
}
@RequiresAuthentication
@PostMapping
(
"/brmnotice"
)
public
Object
brmNotice
(
@RequestBody
String
body
)
{
List
<
Integer
>
ids
=
JacksonUtil
.
parseIntegerList
(
body
,
"ids"
);
noticeAdminService
.
deleteByIds
(
ids
,
getAdminId
());
return
ResponseUtil
.
ok
();
}
}
litemall-admin/src/api/notice.js
0 → 100644
View file @
0c4786dc
import
request
from
'
@/utils/request
'
export
function
listNotice
(
query
)
{
return
request
({
url
:
'
/notice/list
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
createNotice
(
data
)
{
return
request
({
url
:
'
/notice/create
'
,
method
:
'
post
'
,
data
})
}
export
function
readNotice
(
query
)
{
return
request
({
url
:
'
/notice/read
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
updateNotice
(
data
)
{
return
request
({
url
:
'
/notice/update
'
,
method
:
'
post
'
,
data
})
}
export
function
deleteNotice
(
data
)
{
return
request
({
url
:
'
/notice/delete
'
,
method
:
'
post
'
,
data
})
}
export
function
batchDeleteNotice
(
data
)
{
return
request
({
url
:
'
/notice/batch-delete
'
,
method
:
'
post
'
,
data
})
}
litemall-admin/src/api/profile.js
View file @
0c4786dc
...
...
@@ -7,3 +7,51 @@ export function changePassword(data) {
data
})
}
export
function
nNotice
()
{
return
request
({
url
:
'
/profile/nnotice
'
,
method
:
'
get
'
})
}
export
function
listNotice
(
query
)
{
return
request
({
url
:
'
/profile/lsnotice
'
,
method
:
'
get
'
,
params
:
query
})
}
export
function
catNotice
(
data
)
{
return
request
({
url
:
'
/profile/catnotice
'
,
method
:
'
post
'
,
data
})
}
export
function
bcatNotice
(
data
)
{
return
request
({
url
:
'
/profile/bcatnotice
'
,
method
:
'
post
'
,
data
})
}
export
function
rmotice
(
data
)
{
return
request
({
url
:
'
/profile/rmnotice
'
,
method
:
'
post
'
,
data
})
}
export
function
brmNotice
(
data
)
{
return
request
({
url
:
'
/profile/brmnotice
'
,
method
:
'
post
'
,
data
})
}
litemall-admin/src/components/Notice/index.vue
0 → 100644
View file @
0c4786dc
<
template
>
<div>
<el-badge
:is-dot=
"hasNotice"
>
<i
class=
"el-icon-bell"
@
click=
"click"
/>
</el-badge>
</div>
</
template
>
<
script
>
import
{
nNotice
}
from
'
@/api/profile
'
export
default
{
data
()
{
return
{
hasNotice
:
false
,
timer
:
''
}
},
mounted
()
{
this
.
timer
=
setInterval
(
this
.
checkNotice
,
10
*
1000
)
},
beforeDestroy
()
{
clearInterval
(
this
.
timer
)
},
created
()
{
this
.
checkNotice
()
},
methods
:
{
click
()
{
this
.
$router
.
push
({
path
:
'
/profile/notice
'
})
},
checkNotice
()
{
nNotice
().
then
(
response
=>
{
this
.
hasNotice
=
response
.
data
.
data
>
0
})
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
/
deep
/
.el-badge__content.is-fixed.is-dot
{
right
:
5px
;
top
:
10px
;
}
.el-icon-bell
{
font-size
:
20px
;
cursor
:
pointer
;
}
</
style
>
litemall-admin/src/components/Screenfull/index.vue
View file @
0c4786dc
<
template
>
<div>
<svg
t=
"1508738709248"
class=
"screenfull-svg"
viewBox=
"0 0 1024 1024"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
p-id=
"2069"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
width=
"32"
height=
"32"
@
click=
"click"
>
<path
d=
"M333.493443 428.647617 428.322206 333.832158 262.572184 168.045297 366.707916 64.444754 64.09683 64.444754 63.853283 366.570793 167.283957 262.460644Z"
p-id=
"2070"
/>
<path
d=
"M854.845439 760.133334 688.61037 593.95864 593.805144 688.764889 759.554142 854.56096 655.44604 958.161503 958.055079 958.161503 958.274066 656.035464Z"
p-id=
"2071"
/>
<path
d=
"M688.535669 428.550403 854.31025 262.801405 957.935352 366.921787 957.935352 64.34754 655.809313 64.081481 759.919463 167.535691 593.70793 333.731874Z"
p-id=
"2072"
/>
<path
d=
"M333.590658 594.033341 167.8171 759.804852 64.218604 655.67219 64.218604 958.270996 366.342596 958.502263 262.234493 855.071589 428.421466 688.86108Z"
p-id=
"2073"
/>
</svg>
<i
class=
"el-icon-full-screen"
@
click=
"click"
/>
</div>
</
template
>
...
...
@@ -67,12 +44,12 @@ export default {
</
script
>
<
style
scoped
>
.
screen
full-s
vg
{
.
el-icon-
full-s
creen
{
display
:
inline-block
;
cursor
:
pointer
;
fill
:
#5a5e66
;
;
width
:
20px
;
height
:
20px
;
vertical-align
:
1
0px
;
font-size
:
2
0px
;
}
</
style
>
litemall-admin/src/components/SizeSelect/index.vue
View file @
0c4786dc
<
template
>
<el-dropdown
trigger=
"click"
@
command=
"handleSetSize"
>
<div>
<
svg-icon
class-name=
"size-icon"
icon-class=
"size
"
/>
<
i
class=
"el-icon-rank
"
/>
</div>
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
:disabled=
"size==='medium'"
command=
"medium"
>
Medium
</el-dropdown-item>
...
...
@@ -46,10 +46,13 @@ export default {
</
script
>
<
style
scoped
>
.
siz
e-icon
{
font-size
:
20px
;
.e
l
-icon
-rank
{
display
:
inline-block
;
cursor
:
pointer
;
vertical-align
:
-4px
!important
;
fill
:
#5a5e66
;
;
width
:
20px
;
height
:
20px
;
font-size
:
20px
;
}
</
style
>
litemall-admin/src/router/index.js
View file @
0c4786dc
...
...
@@ -397,6 +397,16 @@ export const asyncRouterMap = [
noCache
:
true
}
},
{
path
:
'
notice
'
,
component
:
()
=>
import
(
'
@/views/sys/notice
'
),
name
:
'
notice
'
,
meta
:
{
perms
:
[
'
GET /admin/notice/list
'
,
'
POST /admin/notice/create
'
,
'
POST /admin/notice/update
'
,
'
POST /admin/notice/delete
'
],
title
:
'
通知管理
'
,
noCache
:
true
}
},
{
path
:
'
log
'
,
component
:
()
=>
import
(
'
@/views/sys/log
'
),
...
...
@@ -579,6 +589,12 @@ export const asyncRouterMap = [
component
:
()
=>
import
(
'
@/views/profile/password
'
),
name
:
'
password
'
,
meta
:
{
title
:
'
修改密码
'
,
noCache
:
true
}
},
{
path
:
'
notice
'
,
component
:
()
=>
import
(
'
@/views/profile/notice
'
),
name
:
'
notice
'
,
meta
:
{
title
:
'
通知中心
'
,
noCache
:
true
}
}
],
hidden
:
true
...
...
litemall-admin/src/views/layout/components/Navbar.vue
View file @
0c4786dc
<
template
>
<div
class=
"navbar"
>
<hamburger
:toggle-click=
"toggleSideBar"
:is-active=
"sidebar.opened"
class=
"hamburger-container"
/>
<hamburger
:toggle-click=
"toggleSideBar"
:is-active=
"sidebar.opened"
class=
"hamburger-container"
/>
<breadcrumb
class=
"breadcrumb-container"
/>
<breadcrumb
class=
"breadcrumb-container"
/>
<div
class=
"right-menu"
>
<template
v-if=
"device!=='mobile'"
>
<el-tooltip
content=
"全屏"
effect=
"dark"
placement=
"bottom"
>
<screenfull
class=
"
screenfull
right-menu-item"
/>
<screenfull
class=
"right-menu-item"
/>
</el-tooltip>
<el-tooltip
content=
"布局大小"
effect=
"dark"
placement=
"bottom"
>
<size-select
class=
"
international
right-menu-item"
/>
<size-select
class=
"right-menu-item"
/>
</el-tooltip>
<el-tooltip
content=
"通知中心"
effect=
"dark"
placement=
"bottom"
>
<notice
class=
"right-menu-item"
/>
</el-tooltip>
</
template
>
<el-dropdown
class=
"avatar-container right-menu-item"
trigger=
"click"
>
<div
class=
"avatar-wrapper"
>
<img
:src=
"avatar+'?imageView2/1/w/80/h/80'"
class=
"user-avatar"
>
<i
class=
"el-icon-caret-bottom"
/>
<i
class=
"el-icon-caret-bottom"
/>
</div>
<el-dropdown-menu
slot=
"dropdown"
>
<router-link
to=
"/"
>
...
...
@@ -58,13 +61,15 @@ import Breadcrumb from '@/components/Breadcrumb'
import
Hamburger
from
'
@/components/Hamburger
'
import
Screenfull
from
'
@/components/Screenfull
'
import
SizeSelect
from
'
@/components/SizeSelect
'
import
Notice
from
'
@/components/Notice
'
export
default
{
components
:
{
Breadcrumb
,
Hamburger
,
Screenfull
,
SizeSelect
SizeSelect
,
Notice
},
computed
:
{
...
mapGetters
([
...
...
@@ -114,11 +119,6 @@ export default {
.right-menu-item
{
display
:
inline-block
;
margin
:
0
8px
;
}
.screenfull
{
height
:
20px
;
}
.international
{
vertical-align
:
top
;
}
.avatar-container
{
...
...
litemall-admin/src/views/profile/notice.vue
0 → 100644
View file @
0c4786dc
<
template
>
<div
class=
"app-container"
>
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
v-model=
"listQuery.title"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入标题关键字"
/>
<el-select
v-model=
"listQuery.type"
class=
"filter-item"
placeholder=
"请选择通知类型"
>
<el-option
v-for=
"item in options"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-search"
@
click=
"handleFilter"
>
查找
</el-button>
</div>
<div
class=
"operator-container"
>
<el-button
class=
"filter-item"
type=
"primary"
icon=
"el-icon-edit"
@
click=
"handleBatchRead"
>
批量已读
</el-button>
<el-button
class=
"filter-item"
type=
"danger"
icon=
"el-icon-delete"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
<!-- 查询结果 -->
<el-table
v-loading=
"listLoading"
:data=
"list"
element-loading-text=
"正在查询中。。。"
border
fit
highlight-current-row
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
align=
"center"
label=
"通知标题"
prop=
"noticeTitle"
/>
<el-table-column
align=
"center"
label=
"通知时间"
prop=
"addTime"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"通知状态"
prop=
"readTime"
width=
"120"
>
<template
slot-scope=
"scope"
>
<el-tag
:type=
"scope.row.readTime ? 'success' : 'error' "
>
{{
scope
.
row
.
readTime
?
'
已读
'
:
'
未读
'
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"操作"
width=
"200"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"primary"
size=
"mini"
@
click=
"handleRead(scope.row)"
>
阅读
</el-button>
<el-button
type=
"danger"
size=
"mini"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<pagination
v-show=
"total>0"
:total=
"total"
:page.sync=
"listQuery.page"
:limit.sync=
"listQuery.limit"
@
pagination=
"getList"
/>
<el-dialog
:title=
"notice.title"
:visible.sync=
"noticeVisible"
center
>
<el-divider
content-position=
"left"
>
{{ notice.admin }} 于 {{ notice.time }} 通知如下内容:
</el-divider>
<div
v-html=
"notice.content"
/>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
type=
"primary"
@
click=
"afterRead"
>
确定
</el-button>
</div>
</el-dialog>
</div>
</template>
<
script
>
import
{
listNotice
,
catNotice
,
bcatNotice
,
rmNotice
,
brmNotice
}
from
'
@/api/profile
'
import
Pagination
from
'
@/components/Pagination
'
// Secondary package based on el-pagination
import
_
from
'
lodash
'
export
default
{
name
:
'
AdminNotice
'
,
components
:
{
Pagination
},
data
()
{
return
{
list
:
[],
total
:
0
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
20
,
title
:
''
,
type
:
'
unread
'
,
sort
:
'
add_time
'
,
order
:
'
desc
'
},
options
:
[{
value
:
'
all
'
,
label
:
'
所有
'
},
{
value
:
'
read
'
,
label
:
'
已读
'
},
{
value
:
'
unread
'
,
label
:
'
未读
'
}],
multipleSelection
:
[],
notice
:
{
title
:
''
,
source
:
''
,
content
:
''
,
addTime
:
''
},
noticeVisible
:
false
}
},
created
()
{
this
.
getList
()
},
methods
:
{
getList
()
{
this
.
listLoading
=
true
listNotice
(
this
.
listQuery
)
.
then
(
response
=>
{
this
.
list
=
response
.
data
.
data
.
list
this
.
total
=
response
.
data
.
data
.
total
this
.
listLoading
=
false
})
.
catch
(()
=>
{
this
.
list
=
[]
this
.
total
=
0
this
.
listLoading
=
false
})
},
handleFilter
()
{
this
.
listQuery
.
page
=
1
this
.
getList
()
},
handleDelete
(
row
)
{
rmNotice
(
row
)
.
then
(
response
=>
{
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
删除通知成功
'
})
const
index
=
this
.
list
.
indexOf
(
row
)
this
.
list
.
splice
(
index
,
1
)
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
},
handleSelectionChange
(
val
)
{
this
.
multipleSelection
=
val
},
handleBatchDelete
()
{
if
(
this
.
multipleSelection
.
length
===
0
)
{
this
.
$message
.
error
(
'
请选择至少一条记录
'
)
return
}
const
ids
=
[]
_
.
forEach
(
this
.
multipleSelection
,
function
(
item
)
{
ids
.
push
(
item
.
id
)
})
brmNotice
({
ids
:
ids
})
.
then
(
response
=>
{
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
批量删除通知成功
'
})
this
.
getList
()
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
},
handleRead
(
row
)
{
catNotice
(
row
)
.
then
(
response
=>
{
this
.
notice
=
response
.
data
.
data
this
.
noticeVisible
=
true
})
},
afterRead
()
{
this
.
noticeVisible
=
false
this
.
getList
()
},
handleBatchRead
()
{
if
(
this
.
multipleSelection
.
length
===
0
)
{
this
.
$message
.
error
(
'
请选择至少一条记录
'
)
return
}
const
ids
=
[]
_
.
forEach
(
this
.
multipleSelection
,
function
(
item
)
{
ids
.
push
(
item
.
id
)
})
bcatNotice
({
ids
:
ids
})
.
then
(
response
=>
{
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
批量设置通知已读成功
'
})
this
.
getList
()
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
}
}
}
</
script
>
litemall-admin/src/views/sys/notice.vue
0 → 100644
View file @
0c4786dc
<
template
>
<div
class=
"app-container"
>
<!-- 查询和其他操作 -->
<div
class=
"filter-container"
>
<el-input
v-model=
"listQuery.title"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入标题关键字"
/>
<el-input
v-model=
"listQuery.content"
clearable
class=
"filter-item"
style=
"width: 200px;"
placeholder=
"请输入内容关键字"
/>
<el-button
v-permission=
"['GET /admin/notice/list']"
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>
<div
class=
"operator-container"
>
<el-button
v-permission=
"['POST /admin/notice/create']"
class=
"filter-item"
type=
"primary"
icon=
"el-icon-edit"
@
click=
"handleCreate"
>
添加
</el-button>
<el-button
v-permission=
"['GET /admin/notice/batch-delete']"
class=
"filter-item"
type=
"danger"
icon=
"el-icon-delete"
@
click=
"handleBatchDelete"
>
批量删除
</el-button>
</div>
<!-- 查询结果 -->
<el-table
v-loading=
"listLoading"
:data=
"list"
element-loading-text=
"正在查询中。。。"
border
fit
highlight-current-row
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
align=
"center"
label=
"通知标题"
prop=
"title"
/>
<el-table-column
align=
"center"
label=
"通知详情"
prop=
"content"
>
<template
slot-scope=
"scope"
>
<el-dialog
:visible.sync=
"contentDialogVisible"
title=
"通知详情"
>
<div
v-html=
"contentDetail"
/>
</el-dialog>
<el-button
type=
"primary"
size=
"mini"
@
click=
"showContent(scope.row.content)"
>
查看
</el-button>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"添加时间"
prop=
"addTime"
/>
<el-table-column
align=
"center"
label=
"管理员ID"
prop=
"adminId"
/>
<el-table-column
align=
"center"
label=
"操作"
min-width=
"100"
class-name=
"small-padding fixed-width"
>
<
template
slot-scope=
"scope"
>
<el-button
v-permission=
"['POST /admin/notice/update']"
type=
"primary"
size=
"mini"
@
click=
"handleUpdate(scope.row)"
>
编辑
</el-button>
<el-button
v-permission=
"['POST /admin/notice/delete']"
type=
"danger"
size=
"mini"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<pagination
v-show=
"total>0"
:total=
"total"
:page.sync=
"listQuery.page"
:limit.sync=
"listQuery.limit"
@
pagination=
"getList"
/>
<!-- 添加或修改对话框 -->
<el-dialog
:title=
"textMap[dialogStatus]"
:visible.sync=
"dialogFormVisible"
>
<el-form
ref=
"dataForm"
:rules=
"rules"
:model=
"dataForm"
status-icon
label-position=
"left"
label-width=
"100px"
>
<el-form-item
label=
"通知标题"
prop=
"title"
>
<el-input
v-model=
"dataForm.title"
/>
</el-form-item>
<el-form-item
label=
"通知内容"
prop=
"content"
>
<editor
v-model=
"dataForm.content"
:init=
"editorInit"
/>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialogFormVisible = false"
>
取消
</el-button>
<el-button
v-if=
"dialogStatus=='create'"
type=
"primary"
@
click=
"createData"
>
确定
</el-button>
<el-button
v-else
type=
"primary"
@
click=
"updateData"
>
确定
</el-button>
</div>
</el-dialog>
<el-tooltip
placement=
"top"
content=
"返回顶部"
>
<back-to-top
:visibility-height=
"100"
/>
</el-tooltip>
</div>
</template>
<
script
>
import
{
listNotice
,
createNotice
,
updateNotice
,
deleteNotice
,
batchDeleteNotice
}
from
'
@/api/notice
'
import
BackToTop
from
'
@/components/BackToTop
'
import
Pagination
from
'
@/components/Pagination
'
// Secondary package based on el-pagination
import
_
from
'
lodash
'
import
Editor
from
'
@tinymce/tinymce-vue
'
import
{
createStorage
}
from
'
@/api/storage
'
import
{
getToken
}
from
'
@/utils/auth
'
export
default
{
name
:
'
Notice
'
,
components
:
{
BackToTop
,
Pagination
,
Editor
},
data
()
{
return
{
list
:
[],
total
:
0
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
20
,
title
:
undefined
,
content
:
undefined
,
sort
:
'
add_time
'
,
order
:
'
desc
'
},
multipleSelection
:
[],
contentDetail
:
''
,
contentDialogVisible
:
false
,
dataForm
:
{
id
:
undefined
,
title
:
undefined
,
content
:
undefined
},
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'
编辑
'
,
create
:
'
创建
'
},
rules
:
{
name
:
[
{
required
:
true
,
message
:
'
通知标题不能为空
'
,
trigger
:
'
blur
'
}
]
},
editorInit
:
{
language
:
'
zh_CN
'
,
height
:
200
,
convert_urls
:
false
,
plugins
:
[
'
advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount
'
],
toolbar
:
[
'
searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample
'
,
'
hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen
'
],
images_upload_handler
:
function
(
blobInfo
,
success
,
failure
)
{
const
formData
=
new
FormData
()
formData
.
append
(
'
file
'
,
blobInfo
.
blob
())
createStorage
(
formData
).
then
(
res
=>
{
success
(
res
.
data
.
data
.
url
)
}).
catch
(()
=>
{
failure
(
'
上传失败,请重新上传
'
)
})
}
},
downloadLoading
:
false
}
},
computed
:
{
headers
()
{
return
{
'
X-Litemall-Admin-Token
'
:
getToken
()
}
}
},
created
()
{
this
.
getList
()
},
methods
:
{
getList
()
{
this
.
listLoading
=
true
listNotice
(
this
.
listQuery
)
.
then
(
response
=>
{
this
.
list
=
response
.
data
.
data
.
list
this
.
total
=
response
.
data
.
data
.
total
this
.
listLoading
=
false
})
.
catch
(()
=>
{
this
.
list
=
[]
this
.
total
=
0
this
.
listLoading
=
false
})
},
handleFilter
()
{
this
.
listQuery
.
page
=
1
this
.
getList
()
},
resetForm
()
{
this
.
dataForm
=
{
id
:
undefined
,
title
:
undefined
,
content
:
undefined
}
},
handleCreate
()
{
this
.
resetForm
()
this
.
dialogStatus
=
'
create
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
createData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
(
valid
=>
{
if
(
valid
)
{
createNotice
(
this
.
dataForm
)
.
then
(
response
=>
{
this
.
list
.
unshift
(
response
.
data
.
data
)
this
.
dialogFormVisible
=
false
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
创建成功
'
})
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
}
})
},
handleUpdate
(
row
)
{
this
.
dataForm
=
Object
.
assign
({},
row
)
this
.
dialogStatus
=
'
update
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
})
},
updateData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
(
valid
=>
{
if
(
valid
)
{
updateNotice
(
this
.
dataForm
)
.
then
(()
=>
{
for
(
const
v
of
this
.
list
)
{
if
(
v
.
id
===
this
.
dataForm
.
id
)
{
const
index
=
this
.
list
.
indexOf
(
v
)
this
.
list
.
splice
(
index
,
1
,
this
.
dataForm
)
break
}
}
this
.
dialogFormVisible
=
false
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
更新广告成功
'
})
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
}
})
},
handleDelete
(
row
)
{
deleteNotice
(
row
)
.
then
(
response
=>
{
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
删除通知成功
'
})
const
index
=
this
.
list
.
indexOf
(
row
)
this
.
list
.
splice
(
index
,
1
)
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
},
handleSelectionChange
(
val
)
{
this
.
multipleSelection
=
val
},
showContent
(
content
)
{
this
.
contentDetail
=
content
this
.
contentDialogVisible
=
true
},
handleBatchDelete
()
{
if
(
this
.
multipleSelection
.
length
===
0
)
{
this
.
$message
.
error
(
'
请选择至少一条记录
'
)
return
}
const
ids
=
[]
_
.
forEach
(
this
.
multipleSelection
,
function
(
item
)
{
ids
.
push
(
item
.
id
)
})
batchDeleteNotice
({
ids
:
ids
})
.
then
(
response
=>
{
this
.
$notify
.
success
({
title
:
'
成功
'
,
message
:
'
批量删除通知成功
'
})
this
.
getList
()
})
.
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
})
})
},
handleDownload
()
{
this
.
downloadLoading
=
true
import
(
'
@/vendor/Export2Excel
'
).
then
(
excel
=>
{
const
tHeader
=
[
'
通知ID
'
,
'
通知标题
'
,
'
管理员ID
'
,
'
添加时间
'
,
'
更新时间
'
]
const
filterVal
=
[
'
id
'
,
'
title
'
,
'
content
'
,
'
adminId
'
,
'
addTime
'
,
'
updateTime
'
]
excel
.
export_json_to_excel2
(
tHeader
,
this
.
list
,
filterVal
,
'
通知
'
)
this
.
downloadLoading
=
false
})
}
}
}
</
script
>
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