Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
3536077a
authored
Apr 12, 2023
by
dhb52
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: MP消息管理 ts重构
parent
357a4789
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
259 additions
and
251 deletions
+259
-251
src/views/mp/components/wx-msg/main.vue
+181
-178
src/views/mp/components/wx-msg/types.ts
+11
-0
src/views/mp/message/index.vue
+67
-73
No files found.
src/views/mp/components/wx-msg/main.vue
View file @
3536077a
...
@@ -39,79 +39,79 @@
...
@@ -39,79 +39,79 @@
:style=
"item.sendFrom === 2 ? 'background: #6BED72;' : ''"
:style=
"item.sendFrom === 2 ? 'background: #6BED72;' : ''"
>
>
<!-- 【事件】区域 -->
<!-- 【事件】区域 -->
<div
v-if=
"item.type ===
'event'
&& item.event === 'subscribe'"
>
<div
v-if=
"item.type ===
MsgType.Event
&& item.event === 'subscribe'"
>
<el-tag
type=
"success"
>
关注
</el-tag>
<el-tag
type=
"success"
>
关注
</el-tag>
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'unsubscribe'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'unsubscribe'"
>
<el-tag
type=
"danger"
>
取消关注
</el-tag>
<el-tag
type=
"danger"
>
取消关注
</el-tag>
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'CLICK'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'CLICK'"
>
<el-tag>
点击菜单
</el-tag>
<el-tag>
点击菜单
</el-tag>
【
{{
item
.
eventKey
}}
】
【
{{
item
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'VIEW'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'VIEW'"
>
<el-tag>
点击菜单链接
</el-tag>
<el-tag>
点击菜单链接
</el-tag>
【
{{
item
.
eventKey
}}
】
【
{{
item
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'scancode_waitmsg'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'scancode_waitmsg'"
>
<el-tag>
扫码结果
</el-tag>
<el-tag>
扫码结果
</el-tag>
【
{{
item
.
eventKey
}}
】
【
{{
item
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'scancode_push'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'scancode_push'"
>
<el-tag>
扫码结果
</el-tag>
<el-tag>
扫码结果
</el-tag>
【
{{
item
.
eventKey
}}
】
【
{{
item
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'pic_sysphoto'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'pic_sysphoto'"
>
<el-tag>
系统拍照发图
</el-tag>
<el-tag>
系统拍照发图
</el-tag>
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'pic_photo_or_album'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'pic_photo_or_album'"
>
<el-tag>
拍照或者相册
</el-tag>
<el-tag>
拍照或者相册
</el-tag>
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'pic_weixin'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'pic_weixin'"
>
<el-tag>
微信相册
</el-tag>
<el-tag>
微信相册
</el-tag>
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
&& item.event === 'location_select'"
>
<div
v-else-if=
"item.type ===
MsgType.Event
&& item.event === 'location_select'"
>
<el-tag>
选择地理位置
</el-tag>
<el-tag>
选择地理位置
</el-tag>
</div>
</div>
<div
v-else-if=
"item.type ===
'event'
"
>
<div
v-else-if=
"item.type ===
MsgType.Event
"
>
<el-tag
type=
"danger"
>
未知事件类型
</el-tag>
<el-tag
type=
"danger"
>
未知事件类型
</el-tag>
</div>
</div>
<!-- 【消息】区域 -->
<!-- 【消息】区域 -->
<div
v-else-if=
"item.type ===
'text'
"
>
{{
item
.
content
}}
</div>
<div
v-else-if=
"item.type ===
MsgType.Text
"
>
{{
item
.
content
}}
</div>
<div
v-else-if=
"item.type ===
'voice'
"
>
<div
v-else-if=
"item.type ===
MsgType.Voice
"
>
<
wx-voice-p
layer
:url=
"item.mediaUrl"
:content=
"item.recognition"
/>
<
WxVoiceP
layer
:url=
"item.mediaUrl"
:content=
"item.recognition"
/>
</div>
</div>
<div
v-else-if=
"item.type ===
'image'
"
>
<div
v-else-if=
"item.type ===
MsgType.Image
"
>
<a
target=
"_blank"
:href=
"item.mediaUrl"
>
<a
target=
"_blank"
:href=
"item.mediaUrl"
>
<img
:src=
"item.mediaUrl"
style=
"width: 100px"
/>
<img
:src=
"item.mediaUrl"
style=
"width: 100px"
/>
</a>
</a>
</div>
</div>
<div
<div
v-else-if=
"item.type ===
'video'
|| item.type === 'shortvideo'"
v-else-if=
"item.type ===
MsgType.Video
|| item.type === 'shortvideo'"
style=
"text-align: center"
style=
"text-align: center"
>
>
<
wx-video-p
layer
:url=
"item.mediaUrl"
/>
<
WxVideoP
layer
:url=
"item.mediaUrl"
/>
</div>
</div>
<div
v-else-if=
"item.type ===
'link'
"
class=
"avue-card__detail"
>
<div
v-else-if=
"item.type ===
MsgType.Link
"
class=
"avue-card__detail"
>
<el-link
type=
"success"
:underline=
"false"
target=
"_blank"
:href=
"item.url"
>
<el-link
type=
"success"
:underline=
"false"
target=
"_blank"
:href=
"item.url"
>
<div
class=
"avue-card__title"
><i
class=
"el-icon-link"
></i>
{{
item
.
title
}}
</div>
<div
class=
"avue-card__title"
><i
class=
"el-icon-link"
></i>
{{
item
.
title
}}
</div>
</el-link>
</el-link>
<div
class=
"avue-card__info"
style=
"height: unset"
>
{{
item
.
description
}}
</div>
<div
class=
"avue-card__info"
style=
"height: unset"
>
{{
item
.
description
}}
</div>
</div>
</div>
<!-- TODO 芋艿:待完善 -->
<!-- TODO 芋艿:待完善 -->
<div
v-else-if=
"item.type ===
'location'
"
>
<div
v-else-if=
"item.type ===
MsgType.Location
"
>
<
wx-l
ocation
<
WxL
ocation
:label=
"item.label"
:label=
"item.label"
:location-y=
"item.locationY"
:location-y=
"item.locationY"
:location-x=
"item.locationX"
:location-x=
"item.locationX"
/>
/>
</div>
</div>
<div
v-else-if=
"item.type ===
'news'
"
style=
"width: 300px"
>
<div
v-else-if=
"item.type ===
MsgType.News
"
style=
"width: 300px"
>
<!-- TODO 芋艿:待测试;详情页也存在类似的情况 -->
<!-- TODO 芋艿:待测试;详情页也存在类似的情况 -->
<
wx-n
ews
:articles=
"item.articles"
/>
<
WxN
ews
:articles=
"item.articles"
/>
</div>
</div>
<div
v-else-if=
"item.type ===
'music'
"
>
<div
v-else-if=
"item.type ===
MsgType.Music
"
>
<
wx-m
usic
<
WxM
usic
:title=
"item.title"
:title=
"item.title"
:description=
"item.description"
:description=
"item.description"
:thumb-media-url=
"item.thumbMediaUrl"
:thumb-media-url=
"item.thumbMediaUrl"
...
@@ -125,182 +125,185 @@
...
@@ -125,182 +125,185 @@
</div>
</div>
</div>
</div>
<div
class=
"msg-send"
v-loading=
"sendLoading"
>
<div
class=
"msg-send"
v-loading=
"sendLoading"
>
<
wx-reply-select
ref=
"replySelect
"
:objData=
"objData"
/>
<
WxReplySelect
ref=
"replySelectRef
"
:objData=
"objData"
/>
<el-button
type=
"success"
size=
"small"
class=
"send-but"
@
click=
"sendMsg"
>
发送(S)
</el-button>
<el-button
type=
"success"
size=
"small"
class=
"send-but"
@
click=
"sendMsg"
>
发送(S)
</el-button>
</div>
</div>
</ContentWrap>
</ContentWrap>
</
template
>
</
template
>
<
script
lang=
"ts"
name=
"WxMsg"
>
<
script
setup
lang=
"ts"
name=
"WxMsg"
>
import
{
getMessagePage
,
sendMessage
}
from
'@/api/mp/message'
import
WxReplySelect
from
'@/views/mp/components/wx-reply/main.vue'
import
WxReplySelect
from
'@/views/mp/components/wx-reply/main.vue'
import
WxVideoPlayer
from
'@/views/mp/components/wx-video-play/main.vue'
import
WxVideoPlayer
from
'@/views/mp/components/wx-video-play/main.vue'
import
WxVoicePlayer
from
'@/views/mp/components/wx-voice-play/main.vue'
import
WxVoicePlayer
from
'@/views/mp/components/wx-voice-play/main.vue'
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
WxLocation
from
'@/views/mp/components/wx-location/main.vue'
import
WxLocation
from
'@/views/mp/components/wx-location/main.vue'
import
WxMusic
from
'@/views/mp/components/wx-music/main.vue'
import
WxMusic
from
'@/views/mp/components/wx-music/main.vue'
import
{
getMessagePage
,
sendMessage
}
from
'@/api/mp/message'
import
{
getUser
}
from
'@/api/mp/user'
import
{
getUser
}
from
'@/api/mp/user'
import
{
defineComponent
}
from
'vue'
import
{
formatDate
}
from
'@/utils/formatTime'
const
message
=
useMessage
()
// 消息弹窗
import
profile
from
'@/assets/imgs/profile.jpg'
import
profile
from
'@/assets/imgs/profile.jpg'
import
wechat
from
'@/assets/imgs/wechat.png'
import
wechat
from
'@/assets/imgs/wechat.png'
import
{
formatDate
}
from
'@/utils/formatTime
'
import
{
MsgType
}
from
'./types
'
export
default
defineComponent
({
const
message
=
useMessage
()
// 消息弹窗
components
:
{
WxReplySelect
,
WxVideoPlayer
,
WxVoicePlayer
,
WxNews
,
WxLocation
,
WxMusic
},
props
:
{
userId
:
{
type
:
Number
,
required
:
true
}
},
setup
(
props
)
{
const
nowStr
=
ref
(
new
Date
().
getTime
())
// 当前的时间戳,用于每次消息加载后,回到原位置;具体见 :id="'msg-div' + nowStr" 处
const
loading
=
ref
(
false
)
// 消息列表是否正在加载中
const
loadMore
=
ref
(
true
)
// 是否可以加载更多
const
list
=
ref
<
any
[]
>
([])
// 消息列表
const
queryParams
=
reactive
({
pageNo
:
1
,
// 当前页数
pageSize
:
14
,
// 每页显示多少条
accountId
:
undefined
})
const
user
=
reactive
({
// 由于微信不再提供昵称,直接使用“用户”展示
nickname
:
'用户'
,
avatar
:
profile
,
accountId
:
0
// 公众号账号编号
})
const
mp
=
reactive
({
nickname
:
'公众号'
,
avatar
:
wechat
})
// ========= 消息发送 =========
const
props
=
defineProps
({
const
sendLoading
=
ref
(
false
)
// 发送消息是否加载中
userId
:
{
const
objData
=
reactive
({
type
:
Number
,
// 微信发送消息
required
:
true
type
:
'text'
,
}
accountId
:
null
,
})
articles
:
[]
})
const
replySelect
=
ref
(
null
)
const
nowStr
=
ref
(
new
Date
().
getTime
())
// 当前的时间戳,用于每次消息加载后,回到原位置;具体见 :id="'msg-div' + nowStr" 处
// 执行发送
const
loading
=
ref
(
false
)
// 消息列表是否正在加载中
const
sendMsg
=
async
()
=>
{
const
loadMore
=
ref
(
true
)
// 是否可以加载更多
if
(
!
objData
)
{
const
list
=
ref
<
any
[]
>
([])
// 消息列表
return
const
queryParams
=
reactive
({
}
pageNo
:
1
,
// 当前页数
// // 公众号限制:客服消息,公众号只允许发送一条
pageSize
:
14
,
// 每页显示多少条
if
(
objData
.
type
===
'news'
&&
objData
.
articles
.
length
>
1
)
{
accountId
:
undefined
objData
.
articles
=
[
objData
.
articles
[
0
]]
})
message
.
success
(
'图文消息条数限制在 1 条以内,已默认发送第一条'
)
}
interface
User
{
let
data
=
await
sendMessage
(
Object
.
assign
({
userId
:
props
.
userId
},
{
...
objData
}))
nickname
:
string
sendLoading
.
value
=
false
avatar
:
string
list
.
value
=
[...
list
.
value
,
...[
data
]]
accountId
:
number
scrollToBottom
()
}
//ts檢查的時候會判斷這個組件可能是空的,所以需要進行斷言。
// 由于微信不再提供昵称,直接使用“用户”展示
//避免 tab 的数据未清理
const
user
:
User
=
reactive
({
const
deleteObj
=
(
replySelect
.
value
as
any
).
deleteObj
nickname
:
'用户'
,
if
(
deleteObj
)
{
avatar
:
profile
,
deleteObj
()
accountId
:
0
// 公众号账号编号
}
})
}
const
loadingMore
=
()
=>
{
interface
Mp
{
queryParams
.
pageNo
++
nickname
:
string
getPage
(
queryParams
,
null
)
avatar
:
string
}
}
const
getPage
=
async
(
page
,
params
)
=>
{
const
mp
:
Mp
=
reactive
({
loading
.
value
=
true
nickname
:
'公众号'
,
let
dataTemp
=
await
getMessagePage
(
avatar
:
wechat
Object
.
assign
(
})
{
pageNo
:
page
.
pageNo
,
// ========= 消息发送 =========
pageSize
:
page
.
pageSize
,
const
sendLoading
=
ref
(
false
)
// 发送消息是否加载中
userId
:
props
.
userId
,
interface
ObjData
{
accountId
:
page
.
accountId
type
:
MsgType
},
accountId
:
number
|
null
params
articles
:
any
[]
)
}
)
const
msgDiv
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
// 微信发送消息
let
scrollHeight
=
0
const
objData
:
ObjData
=
reactive
({
if
(
msgDiv
)
{
type
:
MsgType
.
Text
,
scrollHeight
=
msgDiv
.
scrollHeight
accountId
:
null
,
}
articles
:
[]
// 处理数据
})
let
data
=
dataTemp
.
list
.
reverse
()
list
.
value
=
[...
data
,
...
list
.
value
]
const
replySelectRef
=
ref
<
InstanceType
<
typeof
WxReplySelect
>
|
null
>
(
null
)
loading
.
value
=
false
if
(
data
.
length
<
queryParams
.
pageSize
||
data
.
length
===
0
)
{
/** 完成加载 */
loadMore
.
value
=
false
onMounted
(
async
()
=>
{
}
const
data
=
await
getUser
(
props
.
userId
)
queryParams
.
pageNo
=
page
.
pageNo
user
.
nickname
=
data
.
nickname
?.
length
>
0
?
data
.
nickname
:
user
.
nickname
queryParams
.
pageSize
=
page
.
pageSize
user
.
avatar
=
user
.
avatar
?.
length
>
0
?
data
.
avatar
:
user
.
avatar
// 滚动到原来的位置
user
.
accountId
=
data
.
accountId
if
(
queryParams
.
pageNo
===
1
)
{
queryParams
.
accountId
=
data
.
accountId
// 定位到消息底部
objData
.
accountId
=
data
.
accountId
scrollToBottom
()
}
else
if
(
data
.
length
!==
0
)
{
refreshChange
()
// 定位滚动条
})
await
nextTick
(()
=>
{
if
(
scrollHeight
!==
0
)
{
// 执行发送
let
div
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
const
sendMsg
=
async
()
=>
{
if
(
div
&&
msgDiv
)
{
if
(
!
objData
)
{
msgDiv
.
scrollTop
=
div
.
scrollHeight
-
scrollHeight
-
100
return
}
}
}
// 公众号限制:客服消息,公众号只允许发送一条
})
if
(
objData
.
type
===
MsgType
.
News
&&
objData
.
articles
.
length
>
1
)
{
}
objData
.
articles
=
[
objData
.
articles
[
0
]]
}
message
.
success
(
'图文消息条数限制在 1 条以内,已默认发送第一条'
)
const
refreshChange
=
()
=>
{
}
getPage
(
queryParams
,
null
)
}
const
data
=
await
sendMessage
(
Object
.
assign
({
userId
:
props
.
userId
},
{
...
objData
}))
/** 定位到消息底部 */
sendLoading
.
value
=
false
const
scrollToBottom
=
()
=>
{
nextTick
(()
=>
{
list
.
value
=
[...
list
.
value
,
...[
data
]]
scrollToBottom
()
//ts检查的時候会判断这个组件可能是空的,所以需要进行断言。
//避免 tab 的数据未清理
const
deleteObj
=
replySelectRef
.
value
?.
deleteObj
if
(
deleteObj
)
{
deleteObj
()
}
}
const
loadingMore
=
()
=>
{
queryParams
.
pageNo
++
getPage
(
queryParams
,
null
)
}
const
getPage
=
async
(
page
,
params
)
=>
{
loading
.
value
=
true
let
dataTemp
=
await
getMessagePage
(
Object
.
assign
(
{
pageNo
:
page
.
pageNo
,
pageSize
:
page
.
pageSize
,
userId
:
props
.
userId
,
accountId
:
page
.
accountId
},
params
)
)
const
msgDiv
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
let
scrollHeight
=
0
if
(
msgDiv
)
{
scrollHeight
=
msgDiv
.
scrollHeight
}
// 处理数据
const
data
=
dataTemp
.
list
.
reverse
()
list
.
value
=
[...
data
,
...
list
.
value
]
loading
.
value
=
false
if
(
data
.
length
<
queryParams
.
pageSize
||
data
.
length
===
0
)
{
loadMore
.
value
=
false
}
queryParams
.
pageNo
=
page
.
pageNo
queryParams
.
pageSize
=
page
.
pageSize
// 滚动到原来的位置
if
(
queryParams
.
pageNo
===
1
)
{
// 定位到消息底部
scrollToBottom
()
}
else
if
(
data
.
length
!==
0
)
{
// 定位滚动条
await
nextTick
(()
=>
{
if
(
scrollHeight
!==
0
)
{
let
div
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
let
div
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
if
(
div
)
{
if
(
div
&&
msgDiv
)
{
div
.
scrollTop
=
div
.
scrollHeight
msgDiv
.
scrollTop
=
div
.
scrollHeight
-
scrollHeight
-
100
}
}
})
}
}
onMounted
(
async
()
=>
{
let
data
=
await
getUser
(
props
.
userId
)
user
.
nickname
=
data
.
nickname
&&
data
.
nickname
.
length
>
0
?
data
.
nickname
:
user
.
nickname
user
.
avatar
=
data
.
avatar
&&
user
.
avatar
.
length
>
0
?
data
.
avatar
:
user
.
avatar
user
.
accountId
=
data
.
accountId
queryParams
.
accountId
=
data
.
accountId
objData
.
accountId
=
data
.
accountId
refreshChange
()
})
})
return
{
sendMsg
,
loadingMore
,
formatDate
,
scrollToBottom
,
objData
,
mp
,
user
,
queryParams
,
list
,
loadMore
,
loading
,
nowStr
,
sendLoading
}
}
}
})
}
const
refreshChange
=
()
=>
{
getPage
(
queryParams
,
null
)
}
/** 定位到消息底部 */
const
scrollToBottom
=
()
=>
{
nextTick
(()
=>
{
let
div
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
if
(
div
)
{
div
.
scrollTop
=
div
.
scrollHeight
}
})
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
@import
'./comment.scss'
;
@import
'./comment.scss'
;
...
...
src/views/mp/components/wx-msg/types.ts
0 → 100644
View file @
3536077a
export
enum
MsgType
{
Event
=
'event'
,
Text
=
'text'
,
Voice
=
'voice'
,
Image
=
'image'
,
Video
=
'video'
,
Link
=
'link'
,
Location
=
'location'
,
Music
=
'music'
,
News
=
'news'
}
src/views/mp/message/index.vue
View file @
3536077a
...
@@ -9,14 +9,7 @@
...
@@ -9,14 +9,7 @@
label-width=
"68px"
label-width=
"68px"
>
>
<el-form-item
label=
"公众号"
prop=
"accountId"
>
<el-form-item
label=
"公众号"
prop=
"accountId"
>
<el-select
v-model=
"queryParams.accountId"
placeholder=
"请选择公众号"
class=
"!w-240px"
>
<WxMpSelect
@
change=
"onAccountChanged"
/>
<el-option
v-for=
"item in accountList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"消息类型"
prop=
"type"
>
<el-form-item
label=
"消息类型"
prop=
"type"
>
<el-select
v-model=
"queryParams.type"
placeholder=
"请选择消息类型"
class=
"!w-240px"
>
<el-select
v-model=
"queryParams.type"
placeholder=
"请选择消息类型"
class=
"!w-240px"
>
...
@@ -84,70 +77,76 @@
...
@@ -84,70 +77,76 @@
<el-table-column
label=
"内容"
prop=
"content"
>
<el-table-column
label=
"内容"
prop=
"content"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<!-- 【事件】区域 -->
<!-- 【事件】区域 -->
<div
v-if=
"scope.row.type ===
'event'
&& scope.row.event === 'subscribe'"
>
<div
v-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'subscribe'"
>
<el-tag
type=
"success"
>
关注
</el-tag>
<el-tag
type=
"success"
>
关注
</el-tag>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
&& scope.row.event === 'unsubscribe'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'unsubscribe'"
>
<el-tag
type=
"danger"
>
取消关注
</el-tag>
<el-tag
type=
"danger"
>
取消关注
</el-tag>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
&& scope.row.event === 'CLICK'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'CLICK'"
>
<el-tag>
点击菜单
</el-tag>
<el-tag>
点击菜单
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
【
{{
scope
.
row
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
&& scope.row.event === 'VIEW'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'VIEW'"
>
<el-tag>
点击菜单链接
</el-tag>
<el-tag>
点击菜单链接
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
【
{{
scope
.
row
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'scancode_waitmsg'"
>
<div
v-else-if=
"scope.row.type === MsgType.Event && scope.row.event === 'scancode_waitmsg'"
>
<el-tag>
扫码结果
</el-tag>
<el-tag>
扫码结果
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
【
{{
scope
.
row
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
&& scope.row.event === 'scancode_push'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'scancode_push'"
>
<el-tag>
扫码结果
</el-tag>
<el-tag>
扫码结果
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
【
{{
scope
.
row
.
eventKey
}}
】
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
&& scope.row.event === 'pic_sysphoto'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'pic_sysphoto'"
>
<el-tag>
系统拍照发图
</el-tag>
<el-tag>
系统拍照发图
</el-tag>
</div>
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'pic_photo_or_album'"
>
<div
v-else-if=
"scope.row.type === MsgType.Event && scope.row.event === 'pic_photo_or_album'"
>
<el-tag>
拍照或者相册
</el-tag>
<el-tag>
拍照或者相册
</el-tag>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
&& scope.row.event === 'pic_weixin'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
&& scope.row.event === 'pic_weixin'"
>
<el-tag>
微信相册
</el-tag>
<el-tag>
微信相册
</el-tag>
</div>
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'location_select'"
>
<div
v-else-if=
"scope.row.type === MsgType.Event && scope.row.event === 'location_select'"
>
<el-tag>
选择地理位置
</el-tag>
<el-tag>
选择地理位置
</el-tag>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'event'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Event
"
>
<el-tag
type=
"danger"
>
未知事件类型
</el-tag>
<el-tag
type=
"danger"
>
未知事件类型
</el-tag>
</div>
</div>
<!-- 【消息】区域 -->
<!-- 【消息】区域 -->
<div
v-else-if=
"scope.row.type ===
'text'
"
>
{{
scope
.
row
.
content
}}
</div>
<div
v-else-if=
"scope.row.type ===
MsgType.Text
"
>
{{
scope
.
row
.
content
}}
</div>
<div
v-else-if=
"scope.row.type ===
'voice'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Voice
"
>
<wx-voice-player
:url=
"scope.row.mediaUrl"
:content=
"scope.row.recognition"
/>
<wx-voice-player
:url=
"scope.row.mediaUrl"
:content=
"scope.row.recognition"
/>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'image'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Image
"
>
<a
target=
"_blank"
:href=
"scope.row.mediaUrl"
>
<a
target=
"_blank"
:href=
"scope.row.mediaUrl"
>
<img
:src=
"scope.row.mediaUrl"
style=
"width: 100px"
/>
<img
:src=
"scope.row.mediaUrl"
style=
"width: 100px"
/>
</a>
</a>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'video'
|| scope.row.type === 'shortvideo'"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Video
|| scope.row.type === 'shortvideo'"
>
<wx-video-player
:url=
"scope.row.mediaUrl"
style=
"margin-top: 10px"
/>
<wx-video-player
:url=
"scope.row.mediaUrl"
style=
"margin-top: 10px"
/>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'link'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Link
"
>
<el-tag>
链接
</el-tag>
<el-tag>
链接
</el-tag>
:
:
<a
:href=
"scope.row.url"
target=
"_blank"
>
{{
scope
.
row
.
title
}}
</a>
<a
:href=
"scope.row.url"
target=
"_blank"
>
{{
scope
.
row
.
title
}}
</a>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'location'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Location
"
>
<
wx-l
ocation
<
WxL
ocation
:label=
"scope.row.label"
:label=
"scope.row.label"
:location-y=
"scope.row.locationY"
:location-y=
"scope.row.locationY"
:location-x=
"scope.row.locationX"
:location-x=
"scope.row.locationX"
/>
/>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'music'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.Music
"
>
<
wx-m
usic
<
WxM
usic
:title=
"scope.row.title"
:title=
"scope.row.title"
:description=
"scope.row.description"
:description=
"scope.row.description"
:thumb-media-url=
"scope.row.thumbMediaUrl"
:thumb-media-url=
"scope.row.thumbMediaUrl"
...
@@ -155,8 +154,8 @@
...
@@ -155,8 +154,8 @@
:hq-music-url=
"scope.row.hqMusicUrl"
:hq-music-url=
"scope.row.hqMusicUrl"
/>
/>
</div>
</div>
<div
v-else-if=
"scope.row.type ===
'news'
"
>
<div
v-else-if=
"scope.row.type ===
MsgType.News
"
>
<
wx-n
ews
:articles=
"scope.row.articles"
/>
<
WxN
ews
:articles=
"scope.row.articles"
/>
</div>
</div>
<div
v-else
>
<div
v-else
>
<el-tag
type=
"danger"
>
未知消息类型
</el-tag>
<el-tag
type=
"danger"
>
未知消息类型
</el-tag>
...
@@ -177,7 +176,7 @@
...
@@ -177,7 +176,7 @@
</el-table-column>
</el-table-column>
</el-table>
</el-table>
<!-- 分页组件 -->
<!-- 分页组件 -->
<
p
agination
<
P
agination
v-show=
"total > 0"
v-show=
"total > 0"
:total=
"total"
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:page=
"queryParams.pageNo"
...
@@ -186,9 +185,14 @@
...
@@ -186,9 +185,14 @@
/>
/>
<!-- 发送消息的弹窗 -->
<!-- 发送消息的弹窗 -->
<el-dialog
title=
"粉丝消息列表"
v-model=
"open"
@
click=
"openDialog()"
width=
"50%"
>
<el-dialog
title=
"粉丝消息列表"
v-model=
"showMessageBox"
@
click=
"showMessageBox = true"
width=
"50%"
>
<
template
#
footer
>
<
template
#
footer
>
<
wx-msg
:user-id=
"userId"
v-if=
"open
"
/>
<
WxMsg
:user-id=
"userId"
v-if=
"showMessageBox
"
/>
</
template
>
</
template
>
</el-dialog>
</el-dialog>
</ContentWrap>
</ContentWrap>
...
@@ -200,17 +204,27 @@ import WxMsg from '@/views/mp/components/wx-msg/main.vue'
...
@@ -200,17 +204,27 @@ import WxMsg from '@/views/mp/components/wx-msg/main.vue'
import
WxLocation
from
'@/views/mp/components/wx-location/main.vue'
import
WxLocation
from
'@/views/mp/components/wx-location/main.vue'
import
WxMusic
from
'@/views/mp/components/wx-music/main.vue'
import
WxMusic
from
'@/views/mp/components/wx-music/main.vue'
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
*
as
MpAccountApi
from
'@/api/mp/account
'
import
WxMpSelect
from
'@/views/mp/components/WxMpSelect.vue
'
import
*
as
MpMessageApi
from
'@/api/mp/message'
import
*
as
MpMessageApi
from
'@/api/mp/message'
const
message
=
useMessage
()
// 消息弹窗
import
{
DICT_TYPE
,
getStrDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getStrDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
MsgType
}
from
'@/views/mp/components/wx-msg/types'
import
type
{
FormInstance
}
from
'element-plus'
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
list
=
ref
<
any
[]
>
([])
// 列表的数据
const
queryParams
=
reactive
({
// 搜索参数
interface
QueryParams
{
pageNo
:
number
pageSize
:
number
openid
:
string
|
null
accountId
:
number
|
null
type
:
MsgType
|
null
createTime
:
string
[]
|
[]
}
const
queryParams
:
QueryParams
=
reactive
({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
openid
:
null
,
openid
:
null
,
...
@@ -218,19 +232,18 @@ const queryParams = reactive({
...
@@ -218,19 +232,18 @@ const queryParams = reactive({
type
:
null
,
type
:
null
,
createTime
:
[]
createTime
:
[]
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
<
FormInstance
|
null
>
(
null
)
// 搜索的表单
// TODO 芋艿:下面应该移除
const
showMessageBox
=
ref
(
false
)
// 是否显示弹出层
const
open
=
ref
(
false
)
// 是否显示弹出层
const
userId
=
ref
(
0
)
// 操作的用户编号
const
userId
=
ref
(
0
)
// 操作的用户编号
const
accountList
=
ref
<
MpAccountApi
.
AccountVO
[]
>
([])
// 公众号账号列表
/** 侦听accountId */
const
onAccountChanged
=
(
id
?:
number
)
=>
{
queryParams
.
accountId
=
id
as
number
handleQuery
()
}
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
// 如果没有选中公众号账号,则进行提示。
if
(
!
queryParams
.
accountId
)
{
await
message
.
error
(
'未选中公众号,无法查询消息'
)
return
}
try
{
try
{
loading
.
value
=
true
loading
.
value
=
true
const
data
=
await
MpMessageApi
.
getMessagePage
(
queryParams
)
const
data
=
await
MpMessageApi
.
getMessagePage
(
queryParams
)
...
@@ -249,34 +262,15 @@ const handleQuery = () => {
...
@@ -249,34 +262,15 @@ const handleQuery = () => {
/** 重置按钮操作 */
/** 重置按钮操作 */
const
resetQuery
=
async
()
=>
{
const
resetQuery
=
async
()
=>
{
queryFormRef
.
value
.
resetFields
()
const
accountId
=
queryParams
.
accountId
// 默认选中第一个
queryFormRef
.
value
?.
resetFields
()
if
(
accountList
.
value
.
length
>
0
)
{
queryParams
.
accountId
=
accountId
// @ts-ignore
queryParams
.
accountId
=
accountList
.
value
[
0
].
id
}
handleQuery
()
handleQuery
()
}
}
const
handleSend
=
async
(
row
)
=>
{
userId
.
value
=
row
.
userId
open
.
value
=
true
}
const
openDialog
=
()
=>
{
/** 打开消息发送窗口 */
open
.
value
=
true
const
handleSend
=
async
(
row
:
any
)
=>
{
userId
.
value
=
row
.
userId
showMessageBox
.
value
=
true
}
}
// const closeDiaLog = () => {
// open.value = false
// }
/** 初始化 **/
onMounted
(
async
()
=>
{
accountList
.
value
=
await
MpAccountApi
.
getSimpleAccountList
()
// 选中第一个
if
(
accountList
.
value
.
length
>
0
)
{
// @ts-ignore
queryParams
.
accountId
=
accountList
.
value
[
0
].
id
}
await
getList
()
})
</
script
>
</
script
>
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