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
16c5e3ea
authored
Mar 28, 2023
by
wuxiran
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1、微信组件更新第三波,消息页面能正常展示了。但是页面可能还要错乱
parent
ed5990f2
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
902 additions
and
505 deletions
+902
-505
src/assets/imgs/profile.jpg
+0
-0
src/assets/imgs/wechat.png
+0
-0
src/views/mp/components/wx-material-select/main.vue
+302
-0
src/views/mp/components/wx-msg/main.vue
+152
-155
src/views/mp/components/wx-reply/main.vue
+417
-334
src/views/mp/components/wx-video-play/main.vue
+1
-7
src/views/mp/message/index.vue
+30
-9
No files found.
src/assets/imgs/profile.jpg
0 → 100644
View file @
16c5e3ea
7.7 KB
src/assets/imgs/wechat.png
0 → 100644
View file @
16c5e3ea
1.84 KB
src/views/mp/components/wx-material-select/main.vue
0 → 100644
View file @
16c5e3ea
<!--
- Copyright (C) 2018-2019
- All rights reserved, Designed By www.joolun.com
芋道源码:
① 移除 avue 组件,使用 ElementUI 原生组件
-->
<
template
>
<!-- 类型:图片 -->
<div
v-if=
"objData.type === 'image'"
>
<div
class=
"waterfall"
v-loading=
"loading"
>
<div
class=
"waterfall-item"
v-for=
"item in list"
:key=
"item.mediaId"
>
<img
class=
"material-img"
:src=
"item.url"
/>
<p
class=
"item-name"
>
{{
item
.
name
}}
</p>
<el-row
class=
"ope-row"
>
<el-button
type=
"success"
@
click=
"selectMaterialFun(item)"
>
选择
<i
class=
"el-icon-circle-check el-icon--right"
></i>
</el-button>
</el-row>
</div>
</div>
<!-- 分页组件 -->
<pagination
v-show=
"total > 0"
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getMaterialPageFun"
/>
</div>
<!-- 类型:语音 -->
<div
v-else-if=
"objData.type === 'voice'"
>
<!-- 列表 -->
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"编号"
align=
"center"
prop=
"mediaId"
/>
<el-table-column
label=
"文件名"
align=
"center"
prop=
"name"
/>
<el-table-column
label=
"语音"
align=
"center"
>
<template
#
default=
"scope"
>
<wx-voice-player
:url=
"scope.row.url"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"上传时间"
align=
"center"
prop=
"createTime"
width=
"180"
>
<
template
#
default=
"scope"
>
<span>
{{
parseTime
(
scope
.
row
.
createTime
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
fixed=
"right"
class-name=
"small-padding fixed-width"
>
<
template
#
default=
"scope"
>
<el-button
type=
"text"
icon=
"el-icon-circle-plus"
@
click=
"selectMaterialFun(scope.row)"
>
选择
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
v-show=
"total > 0"
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getPage"
/>
</div>
<div
v-else-if=
"objData.type === 'video'"
>
<!-- 列表 -->
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"编号"
align=
"center"
prop=
"mediaId"
/>
<el-table-column
label=
"文件名"
align=
"center"
prop=
"name"
/>
<el-table-column
label=
"标题"
align=
"center"
prop=
"title"
/>
<el-table-column
label=
"介绍"
align=
"center"
prop=
"introduction"
/>
<el-table-column
label=
"视频"
align=
"center"
>
<
template
#
default=
"scope"
>
<wx-video-player
:url=
"scope.row.url"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"上传时间"
align=
"center"
prop=
"createTime"
width=
"180"
>
<
template
#
default=
"scope"
>
<span>
{{
parseTime
(
scope
.
row
.
createTime
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
fixed=
"right"
class-name=
"small-padding fixed-width"
>
<
template
#
default=
"scope"
>
<el-button
type=
"text"
icon=
"el-icon-circle-plus"
@
click=
"selectMaterialFun(scope.row)"
>
选择
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
v-show=
"total > 0"
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getMaterialPageFun"
/>
</div>
<div
v-else-if=
"objData.type === 'news'"
>
<div
class=
"waterfall"
v-loading=
"loading"
>
<div
class=
"waterfall-item"
v-for=
"item in list"
:key=
"item.mediaId"
>
<div
v-if=
"item.content && item.content.newsItem"
>
<wx-news
:articles=
"item.content.newsItem"
/>
<el-row
class=
"ope-row"
>
<el-button
type=
"success"
@
click=
"selectMaterialFun(item)"
>
选择
<i
class=
"el-icon-circle-check el-icon--right"
></i>
</el-button>
</el-row>
</div>
</div>
</div>
<!-- 分页组件 -->
<pagination
v-show=
"total > 0"
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getMaterialPageFun"
/>
</div>
</template>
<
script
lang=
"ts"
name=
"WxMaterialSelect"
>
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
WxVoicePlayer
from
'@/views/mp/components/wx-voice-play/main.vue'
import
WxVideoPlayer
from
'@/views/mp/components/wx-video-play/main.vue'
import
{
getMaterialPage
}
from
'@/api/mp/material'
import
{
getFreePublishPage
}
from
'@/api/mp/freePublish'
import
{
getDraftPage
}
from
'@/api/mp/draft'
import
{
dateFormatter
,
parseTime
}
from
'@/utils/formatTime'
import
{
defineComponent
,
PropType
}
from
'vue'
export
default
defineComponent
({
components
:
{
WxNews
,
WxVoicePlayer
,
WxVideoPlayer
},
props
:
{
objData
:
{
type
:
Object
,
// type - 类型;accountId - 公众号账号编号
required
:
true
},
newsType
:
{
// 图文类型:1、已发布图文;2、草稿箱图文
type
:
String
as
PropType
<
string
>
,
default
:
'1'
}
},
setup
(
props
,
ctx
)
{
// 遮罩层
const
loading
=
ref
(
false
)
// 总条数
const
total
=
ref
(
0
)
// 数据列表
const
list
=
ref
([])
// 查询参数
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
accountId
:
props
.
objData
.
accountId
})
const
objDataRef
=
reactive
(
props
.
objData
)
const
newsTypeRef
=
ref
(
props
.
newsType
)
const
selectMaterialFun
=
(
item
)
=>
{
ctx
.
emit
(
'selectMaterial'
,
item
)
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getPage
()
}
const
getPage
=
()
=>
{
loading
.
value
=
true
if
(
objDataRef
.
type
===
'news'
&&
newsTypeRef
.
value
===
'1'
)
{
// 【图文】+ 【已发布】
getFreePublishPageFun
()
}
else
if
(
objDataRef
.
type
===
'news'
&&
newsTypeRef
.
value
===
'2'
)
{
// 【图文】+ 【草稿】
getDraftPageFun
()
}
else
{
// 【素材】
getMaterialPageFun
()
}
}
const
getMaterialPageFun
=
async
()
=>
{
let
data
=
await
getMaterialPage
({
...
queryParams
,
type
:
objDataRef
.
type
})
list
.
value
=
data
.
list
total
.
value
=
data
.
total
loading
.
value
=
false
}
const
getFreePublishPageFun
=
async
()
=>
{
let
data
=
await
getFreePublishPage
(
queryParams
)
data
.
list
.
foreach
((
item
)
=>
{
const
newsItem
=
item
.
content
.
newsItem
newsItem
.
forEach
((
article
)
=>
{
article
.
picUrl
=
article
.
thumbUrl
})
})
list
.
value
=
data
.
list
total
.
value
=
data
.
total
loading
.
value
=
false
}
const
getDraftPageFun
=
async
()
=>
{
let
data
=
await
getDraftPage
(
queryParams
)
data
.
list
.
forEach
((
item
)
=>
{
const
newsItem
=
item
.
content
.
newsItem
newsItem
.
forEach
((
article
)
=>
{
article
.
picUrl
=
article
.
thumbUrl
})
})
list
.
value
=
data
.
list
total
.
value
=
data
.
total
loading
.
value
=
false
}
onMounted
(
async
()
=>
{
getPage
()
})
return
{
handleQuery
,
dateFormatter
,
selectMaterialFun
,
getMaterialPageFun
,
getPage
,
parseTime
,
newsTypeRef
,
queryParams
,
objDataRef
,
list
,
total
,
loading
}
}
})
</
script
>
<
style
lang=
"scss"
scoped
>
/*瀑布流样式*/
.waterfall
{
width
:
100%
;
column-gap
:
10px
;
column-count
:
5
;
margin
:
0
auto
;
}
.waterfall-item
{
padding
:
10px
;
margin-bottom
:
10px
;
break-inside
:
avoid
;
border
:
1px
solid
#eaeaea
;
}
.material-img
{
width
:
100%
;
}
p
{
line-height
:
30px
;
}
@media
(
min-width
:
992px
)
and
(
max-width
:
1300px
)
{
.waterfall
{
column-count
:
3
;
}
p
{
color
:
red
;
}
}
@media
(
min-width
:
768px
)
and
(
max-width
:
991px
)
{
.waterfall
{
column-count
:
2
;
}
p
{
color
:
orange
;
}
}
@media
(
max-width
:
767px
)
{
.waterfall
{
column-count
:
1
;
}
}
/*瀑布流样式*/
</
style
>
src/views/mp/components/wx-msg/main.vue
View file @
16c5e3ea
...
...
@@ -6,7 +6,7 @@
② 代码优化,补充注释,提升阅读性
-->
<
template
>
<
div
class=
"msg-main"
>
<
ContentWrap
>
<div
class=
"msg-div"
:id=
"'msg-div' + nowStr"
>
<!-- 加载更多 -->
<div
v-loading=
"loading"
></div>
...
...
@@ -26,9 +26,9 @@
:src=
"item.sendFrom === 1 ? user.avatar : mp.avatar"
class=
"avue-comment__avatar"
/>
<div
class=
"avue-comment__author"
>
{{
item
.
sendFrom
===
1
?
user
.
nickname
:
mp
.
nickname
}}
</div>
<div
class=
"avue-comment__author"
>
{{
item
.
sendFrom
===
1
?
user
.
nickname
:
mp
.
nickname
}}
</div>
</div>
<div
class=
"avue-comment__main"
>
<div
class=
"avue-comment__header"
>
...
...
@@ -40,37 +40,41 @@
>
<!-- 【事件】区域 -->
<div
v-if=
"item.type === 'event' && item.event === 'subscribe'"
>
<el-tag
type=
"success"
size=
"mini"
>
关注
</el-tag>
<el-tag
type=
"success"
>
关注
</el-tag>
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'unsubscribe'"
>
<el-tag
type=
"danger"
size=
"mini"
>
取消关注
</el-tag>
<el-tag
type=
"danger"
>
取消关注
</el-tag>
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'CLICK'"
>
<el-tag
size=
"mini"
>
点击菜单
</el-tag>
【
{{
item
.
eventKey
}}
】
<el-tag>
点击菜单
</el-tag>
【
{{
item
.
eventKey
}}
】
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'VIEW'"
>
<el-tag
size=
"mini"
>
点击菜单链接
</el-tag>
【
{{
item
.
eventKey
}}
】
<el-tag>
点击菜单链接
</el-tag>
【
{{
item
.
eventKey
}}
】
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'scancode_waitmsg'"
>
<el-tag
size=
"mini"
>
扫码结果
</el-tag>
【
{{
item
.
eventKey
}}
】
<el-tag>
扫码结果
</el-tag>
【
{{
item
.
eventKey
}}
】
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'scancode_push'"
>
<el-tag
size=
"mini"
>
扫码结果
</el-tag>
【
{{
item
.
eventKey
}}
】
<el-tag>
扫码结果
</el-tag>
【
{{
item
.
eventKey
}}
】
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'pic_sysphoto'"
>
<el-tag
size=
"mini"
>
系统拍照发图
</el-tag>
<el-tag>
系统拍照发图
</el-tag>
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'pic_photo_or_album'"
>
<el-tag
size=
"mini"
>
拍照或者相册
</el-tag>
<el-tag>
拍照或者相册
</el-tag>
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'pic_weixin'"
>
<el-tag
size=
"mini"
>
微信相册
</el-tag>
<el-tag>
微信相册
</el-tag>
</div>
<div
v-else-if=
"item.type === 'event' && item.event === 'location_select'"
>
<el-tag
size=
"mini"
>
选择地理位置
</el-tag>
<el-tag>
选择地理位置
</el-tag>
</div>
<div
v-else-if=
"item.type === 'event'"
>
<el-tag
type=
"danger"
size=
"mini"
>
未知事件类型
</el-tag>
<el-tag
type=
"danger"
>
未知事件类型
</el-tag>
</div>
<!-- 【消息】区域 -->
<div
v-else-if=
"item.type === 'text'"
>
{{
item
.
content
}}
</div>
...
...
@@ -124,10 +128,10 @@
<wx-reply-select
ref=
"replySelect"
:objData=
"objData"
/>
<el-button
type=
"success"
size=
"small"
class=
"send-but"
@
click=
"sendMsg"
>
发送(S)
</el-button>
</div>
</
div
>
</
ContentWrap
>
</
template
>
<
script
>
<
script
lang=
"ts"
name=
"WxMsg"
>
import
{
getMessagePage
,
sendMessage
}
from
'@/api/mp/message'
import
WxReplySelect
from
'@/views/mp/components/wx-reply/main.vue'
import
WxVideoPlayer
from
'@/views/mp/components/wx-video-play/main.vue'
...
...
@@ -136,9 +140,14 @@ import WxNews from '@/views/mp/components/wx-news/main.vue'
import
WxLocation
from
'@/views/mp/components/wx-location/main.vue'
import
WxMusic
from
'@/views/mp/components/wx-music/main.vue'
import
{
getUser
}
from
'@/api/mp/mpuser'
import
{
defineComponent
}
from
'vue'
const
message
=
useMessage
()
// 消息弹窗
import
profile
from
'@/assets/imgs/profile.jpg'
import
wechat
from
'@/assets/imgs/wechat.png'
import
{
parseTime
}
from
'@/utils/formatTime'
export
default
{
name
:
'WxMsg'
,
export
default
defineComponent
({
components
:
{
WxReplySelect
,
WxVideoPlayer
,
...
...
@@ -153,160 +162,144 @@ export default {
required
:
true
}
},
data
()
{
return
{
nowStr
:
new
Date
().
getTime
(),
// 当前的时间戳,用于每次消息加载后,回到原位置;具体见 :id="'msg-div' + nowStr" 处
loading
:
false
,
// 消息列表是否正在加载中
loadMore
:
true
,
// 是否可以加载更多
list
:
[],
// 消息列表
queryParams
:
{
pageNo
:
1
,
// 当前页数
pageSize
:
14
,
// 每页显示多少条
accountId
:
undefined
},
user
:
{
// 由于微信不再提供昵称,直接使用“用户”展示
nickname
:
'用户'
,
avatar
:
require
(
'@/assets/images/profile.jpg'
),
accountId
:
0
// 公众号账号编号
},
mp
:
{
nickname
:
'公众号'
,
avatar
:
require
(
'@/assets/images/wechat.png'
)
},
// ========= 消息发送 =========
sendLoading
:
false
,
// 发送消息是否加载中
objData
:
{
// 微信发送消息
type
:
'text'
}
}
},
created
()
{
// 获得用户信息
getUser
(
this
.
userId
).
then
((
response
)
=>
{
this
.
user
.
nickname
=
response
.
data
.
nickname
&&
response
.
data
.
nickname
.
length
>
0
?
response
.
data
.
nickname
:
this
.
user
.
nickname
this
.
user
.
avatar
=
response
.
data
.
avatar
&&
this
.
user
.
avatar
.
length
>
0
?
response
.
data
.
avatar
:
this
.
user
.
avatar
this
.
user
.
accountId
=
response
.
data
.
accountId
// 设置公众号账号编号
this
.
queryParams
.
accountId
=
response
.
data
.
accountId
this
.
objData
.
accountId
=
response
.
data
.
accountId
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
})
// 加载消息
console
.
log
(
this
.
queryParams
)
this
.
refreshChange
()
// ========= 消息发送 =========
const
sendLoading
=
ref
(
false
)
// 发送消息是否加载中
const
objData
=
reactive
({
// 微信发送消息
type
:
'text'
,
accountId
:
null
,
articles
:
[]
})
},
methods
:
{
sendMsg
()
{
if
(
!
this
.
objData
)
{
const
replySelect
=
ref
(
null
)
// 执行发送
const
sendMsg
=
async
()
=>
{
if
(
!
objData
)
{
return
}
// 公众号限制:客服消息,公众号只允许发送一条
if
(
this
.
objData
.
type
===
'news'
&&
this
.
objData
.
articles
.
length
>
1
)
{
this
.
objData
.
articles
=
[
this
.
objData
.
articles
[
0
]]
this
.
$message
({
showClose
:
true
,
message
:
'图文消息条数限制在 1 条以内,已默认发送第一条'
,
type
:
'success'
})
// // 公众号限制:客服消息,公众号只允许发送一条
if
(
objData
.
type
===
'news'
&&
objData
.
articles
.
length
>
1
)
{
objData
.
articles
=
[
objData
.
articles
[
0
]]
message
.
success
(
'图文消息条数限制在 1 条以内,已默认发送第一条'
)
}
// 执行发送
this
.
sendLoading
=
true
sendMessage
(
Object
.
assign
(
{
userId
:
this
.
userId
},
{
...
this
.
objData
}
)
)
.
then
((
response
)
=>
{
this
.
sendLoading
=
false
// 添加到消息列表,并滚动
this
.
list
=
[...
this
.
list
,
...[
response
.
data
]]
this
.
scrollToBottom
()
// 重置 objData 状态
this
.
$refs
[
'replySelect'
].
deleteObj
()
// 重置,避免 tab 的数据未清理
})
.
catch
(()
=>
{
this
.
sendLoading
=
false
})
},
loadingMore
()
{
this
.
queryParams
.
pageNo
++
this
.
getPage
(
this
.
queryParams
)
},
getPage
(
page
,
params
)
{
this
.
loading
=
true
getMessagePage
(
let
data
=
await
sendMessage
(
Object
.
assign
({
userId
:
props
.
userId
},
{
...
objData
}))
sendLoading
.
value
=
false
list
.
value
=
[...
list
.
value
,
...[
data
]]
scrollToBottom
()
//ts檢查的時候會判斷這個組件可能是空的,所以需要進行斷言。
//避免 tab 的数据未清理
const
deleteObj
=
(
replySelect
.
value
as
any
).
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
:
thi
s
.
userId
,
userId
:
prop
s
.
userId
,
accountId
:
page
.
accountId
},
params
)
).
then
((
response
)
=>
{
// 计算当前的滚动高度
const
msgDiv
=
document
.
getElementById
(
'msg-div'
+
this
.
nowStr
)
let
scrollHeight
=
0
if
(
msgDiv
)
{
scrollHeight
=
msgDiv
.
scrollHeight
}
// 处理数据
const
data
=
response
.
data
.
list
.
reverse
()
this
.
list
=
[...
data
,
...
this
.
list
]
this
.
loading
=
false
if
(
data
.
length
<
this
.
queryParams
.
pageSize
||
data
.
length
===
0
)
{
this
.
loadMore
=
false
}
this
.
queryParams
.
pageNo
=
page
.
pageNo
this
.
queryParams
.
pageSize
=
page
.
pageSize
// 滚动到原来的位置
if
(
this
.
queryParams
.
pageNo
===
1
)
{
// 定位到消息底部
this
.
scrollToBottom
()
}
else
if
(
data
.
length
!==
0
)
{
// 定位滚动条
this
.
$nextTick
(()
=>
{
if
(
scrollHeight
!==
0
)
{
msgDiv
.
scrollTop
=
document
.
getElementById
(
'msg-div'
+
this
.
nowStr
).
scrollHeight
-
scrollHeight
-
100
)
const
msgDiv
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
let
scrollHeight
=
0
if
(
msgDiv
)
{
scrollHeight
=
msgDiv
.
scrollHeight
}
// 处理数据
let
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
)
if
(
div
&&
msgDiv
)
{
msgDiv
.
scrollTop
=
div
.
scrollHeight
-
scrollHeight
-
100
}
})
}
})
},
/**
* 刷新回调
*/
refreshChange
()
{
this
.
getPage
(
this
.
queryParams
)
},
}
})
}
}
const
refreshChange
=
()
=>
{
getPage
(
queryParams
,
null
)
}
/** 定位到消息底部 */
scrollToBottom
:
function
()
{
this
.
$nextTick
(()
=>
{
let
div
=
document
.
getElementById
(
'msg-div'
+
this
.
nowStr
)
div
.
scrollTop
=
div
.
scrollHeight
const
scrollToBottom
=
()
=>
{
nextTick
(()
=>
{
let
div
=
document
.
getElementById
(
'msg-div'
+
nowStr
.
value
)
if
(
div
)
{
div
.
scrollTop
=
div
.
scrollHeight
}
})
}
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
,
parseTime
,
scrollToBottom
,
objData
,
mp
,
user
,
queryParams
,
list
,
loadMore
,
loading
,
nowStr
,
sendLoading
}
}
}
}
)
</
script
>
<
style
lang=
"scss"
scoped
>
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc */
...
...
@@ -317,6 +310,7 @@ export default {
margin-top
:
-30px
;
padding
:
10px
;
}
.msg-div
{
height
:
50vh
;
overflow
:
auto
;
...
...
@@ -324,13 +318,16 @@ export default {
margin-left
:
10px
;
margin-right
:
10px
;
}
.msg-send
{
padding
:
10px
;
}
.avatar-div
{
text-align
:
center
;
width
:
80px
;
}
.send-but
{
float
:
right
;
margin-top
:
8px
!important
;
...
...
src/views/mp/components/wx-reply/main.vue
View file @
16c5e3ea
...
...
@@ -8,100 +8,165 @@
④ 支持发送【视频】消息时,支持新建视频
-->
<
template
>
<el-tabs
type=
"border-card"
v-model=
"objData.type"
@
tab-click=
"handleClick"
>
<el-tabs
type=
"border-card"
v-model=
"objData
Ref
.type"
@
tab-click=
"handleClick"
>
<!-- 类型 1:文本 -->
<el-tab-pane
name=
"text"
>
<span
slot=
"label"
><i
class=
"el-icon-document"
></i>
文本
</span>
<template
#
label
>
<el-row
align=
"middle"
>
<icon
icon=
"ep:document"
/>
文本
</el-row>
</
template
>
<el-input
type=
"textarea"
:rows=
"5"
placeholder=
"请输入内容"
v-model=
"objData.content"
v-model=
"objData
Ref
.content"
@
input=
"inputContent"
/>
</el-tab-pane>
<!-- 类型 2:图片 -->
<el-tab-pane
name=
"image"
>
<span
slot=
"label"
><i
class=
"el-icon-picture"
></i>
图片
</span>
<el-row>
<!-- 情况一:已经选择好素材、或者上传好图片 -->
<div
class=
"select-item"
v-if=
"objData.url"
>
<img
class=
"material-img"
:src=
"objData.url"
/>
<p
class=
"item-name"
v-if=
"objData.name"
>
{{
objData
.
name
}}
</p>
<el-row
class=
"ope-row"
>
<el-button
type=
"danger"
icon=
"el-icon-delete"
circle
@
click=
"deleteObj"
/>
</el-row>
</div>
<!-- 情况二:未做完上述操作 -->
<div
v-else
>
<el-row
style=
"text-align: center"
>
<!-- 选择素材 -->
<el-col
:span=
"12"
class=
"col-select"
>
<el-button
type=
"success"
@
click=
"openMaterial"
>
素材库选择
<i
class=
"el-icon-circle-check el-icon--right"
></i>
</el-button>
<el-dialog
title=
"选择图片"
v-model:visible=
"dialogImageVisible"
width=
"90%"
append-to-body
>
<wx-material-select
:obj-data=
"objData"
@
selectMaterial=
"selectMaterial"
/>
</el-dialog>
</el-col>
<!-- 文件上传 -->
<el-col
:span=
"12"
class=
"col-add"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
multiple
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeImageUpload"
:on-success=
"handleUploadSuccess"
>
<el-button
type=
"primary"
>
上传图片
</el-button>
<div
slot=
"tip"
class=
"el-upload__tip"
<
template
#
label
>
<el-row
align=
"middle"
>
<icon
icon=
"ep:picture"
class=
"mr-5px"
/>
图片
</el-row>
</
template
>
<!-- 情况一:已经选择好素材、或者上传好图片 -->
<div
class=
"select-item"
v-if=
"objDataRef.url"
>
<img
class=
"material-img"
:src=
"objDataRef.url"
/>
<p
class=
"item-name"
v-if=
"objDataRef.name"
>
{{ objDataRef.name }}
</p>
<el-row
class=
"ope-row"
>
<el-button
type=
"danger"
circle
@
click=
"deleteObj"
>
<icon
icon=
"ep:delete"
/>
</el-button>
</el-row>
</div>
<!-- 情况二:未做完上述操作 -->
<el-row
v-else
style=
"text-align: center"
align=
"middle"
>
<!-- 选择素材 -->
<el-col
:span=
"12"
class=
"col-select"
>
<el-button
type=
"success"
@
click=
"openMaterial"
>
素材库选择
<icon
icon=
"ep:circle-check"
/>
</el-button>
<el-dialog
title=
"选择图片"
v-model=
"dialogImageVisible"
width=
"90%"
append-to-body
>
<wx-material-select
:obj-data=
"objDataRef"
@
selectMaterial=
"selectMaterial"
/>
</el-dialog>
</el-col>
<!-- 文件上传 -->
<el-col
:span=
"12"
class=
"col-add"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
multiple
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeImageUpload"
:on-success=
"handleUploadSuccess"
>
<el-button
type=
"primary"
>
上传图片
</el-button>
<
template
#
tip
>
<span>
<div
class=
"el-upload__tip"
>
支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M
</div
>
</el-upload
>
</
el-col
>
</el-
row
>
</
div
>
>
</span
>
</
template
>
</el-
upload
>
</
el-col
>
</el-row>
</el-tab-pane>
<!-- 类型 3:语音 -->
<el-tab-pane
name=
"voice"
>
<span
slot=
"label"
><i
class=
"el-icon-phone"
></i>
语音
</span>
<
template
#
label
>
<el-row
align=
"middle"
>
<icon
icon=
"ep:phone"
/>
语音
</el-row>
</
template
>
<div
class=
"select-item2"
v-if=
"objDataRef.url"
>
<p
class=
"item-name"
>
{{ objDataRef.name }}
</p>
<div
class=
"item-infos"
>
<wx-voice-player
:url=
"objDataRef.url"
/>
</div>
<el-row
class=
"ope-row"
>
<el-button
type=
"danger"
icon=
"el-icon-delete"
circle
@
click=
"deleteObj"
/>
</el-row>
</div>
<el-row
v-else
style=
"text-align: center"
>
<!-- 选择素材 -->
<el-col
:span=
"12"
class=
"col-select"
>
<el-button
type=
"success"
@
click=
"openMaterial"
>
素材库选择
<i
class=
"el-icon-circle-check el-icon--right"
></i>
</el-button>
<el-dialog
title=
"选择语音"
v-model=
"dialogVoiceVisible"
width=
"90%"
append-to-body
>
<WxMaterialSelect
:objData=
"objData"
@
selectMaterial=
"selectMaterial"
/>
</el-dialog>
</el-col>
<!-- 文件上传 -->
<el-col
:span=
"12"
class=
"col-add"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
multiple
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeVoiceUpload"
:on-success=
"handleUploadSuccess"
>
<el-button
type=
"primary"
>
点击上传
</el-button>
<
template
#
tip
>
<div
class=
"el-upload__tip"
>
格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s
</div>
</
template
>
</el-upload>
</el-col>
</el-row>
</el-tab-pane>
<!-- 类型 4:视频 -->
<el-tab-pane
name=
"video"
>
<
template
#
label
>
<el-row
align=
"middle"
>
<icon
icon=
"ep:share"
/>
视频
</el-row>
</
template
>
<el-row>
<div
class=
"select-item2"
v-if=
"objData.url"
>
<p
class=
"item-name"
>
{{
objData
.
name
}}
</p>
<div
class=
"item-infos"
>
<wx-voice-player
:url=
"objData.url"
/>
</div>
<el-row
class=
"ope-row"
>
<el-button
type=
"danger"
icon=
"el-icon-delete"
circle
@
click=
"deleteObj"
/>
</el-row>
<el-input
v-model=
"objDataRef.title"
class=
"input-margin-bottom"
placeholder=
"请输入标题"
@
input=
"inputContent"
/>
<el-input
class=
"input-margin-bottom"
v-model=
"objDataRef.description"
placeholder=
"请输入描述"
@
input=
"inputContent"
/>
<div
style=
"text-align: center"
>
<wx-video-player
v-if=
"objDataRef.url"
:url=
"objDataRef.url"
/>
</div>
<
div
v-else
>
<el-row
style=
"text-align: center"
>
<
el-col
>
<el-row
style=
"text-align: center"
align=
"middle"
>
<!-- 选择素材 -->
<el-col
:span=
"12"
class=
"col-select"
>
<el-col
:span=
"12"
>
<el-button
type=
"success"
@
click=
"openMaterial"
>
素材库选择
<i
class=
"el-icon-circle-check el-icon--right"
></i>
素材库选择
<icon
icon=
"ep:circle-check"
/>
</el-button>
<el-dialog
title=
"选择语音"
v-model:visible=
"dialogVoiceVisible"
width=
"90%"
append-to-body
>
<WxMaterialSelect
:objData=
"objData"
@
selectMaterial=
"selectMaterial"
/>
<el-dialog
title=
"选择视频"
v-model=
"dialogVideoVisible"
width=
"90%"
append-to-body
>
<wx-material-select
:objData=
"objDataRef"
@
selectMaterial=
"selectMaterial"
/>
</el-dialog>
</el-col>
<!-- 文件上传 -->
<el-col
:span=
"12"
class=
"col-add"
>
<el-col
:span=
"12"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
...
...
@@ -109,90 +174,50 @@
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeV
oice
Upload"
:before-upload=
"beforeV
ideo
Upload"
:on-success=
"handleUploadSuccess"
>
<el-button
type=
"primary"
>
点击上传
</el-button>
<div
slot=
"tip"
class=
"el-upload__tip"
>
格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s
</div
>
<el-button
type=
"primary"
>
新建视频
<icon
icon=
"ep:upload"
/>
</el-button
>
</el-upload>
</el-col>
</el-row>
</div>
</el-row>
</el-tab-pane>
<!-- 类型 4:视频 -->
<el-tab-pane
name=
"video"
>
<span
slot=
"label"
><i
class=
"el-icon-share"
></i>
视频
</span>
<el-row>
<el-input
v-model=
"objData.title"
placeholder=
"请输入标题"
@
input=
"inputContent"
/>
<div
style=
"margin: 20px 0"
></div>
<el-input
v-model=
"objData.description"
placeholder=
"请输入描述"
@
input=
"inputContent"
/>
<div
style=
"margin: 20px 0"
></div>
<div
style=
"text-align: center"
>
<wx-video-player
v-if=
"objData.url"
:url=
"objData.url"
/>
</div>
<div
style=
"margin: 20px 0"
></div>
<el-row
style=
"text-align: center"
>
<!-- 选择素材 -->
<el-col
:span=
"12"
>
<el-button
type=
"success"
@
click=
"openMaterial"
>
素材库选择
<i
class=
"el-icon-circle-check el-icon--right"
></i>
</el-button>
<el-dialog
title=
"选择视频"
v-model:visible=
"dialogVideoVisible"
width=
"90%"
append-to-body
>
<wx-material-select
:objData=
"objData"
@
selectMaterial=
"selectMaterial"
/>
</el-dialog>
</el-col>
<!-- 文件上传 -->
<el-col
:span=
"12"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
multiple
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeVideoUpload"
:on-success=
"handleUploadSuccess"
>
<el-button
type=
"primary"
>
新建视频
<i
class=
"el-icon-upload el-icon--right"
></i
></el-button>
</el-upload>
</el-col>
</el-row>
</el-col>
</el-row>
</el-tab-pane>
<!-- 类型 5:图文 -->
<el-tab-pane
name=
"news"
>
<span
slot=
"label"
><i
class=
"el-icon-news"
></i>
图文
</span>
<
template
#
label
>
<el-row
align=
"middle"
>
<icon
icon=
"ep:reading"
/>
图文
</el-row>
</
template
>
<el-row>
<div
class=
"select-item"
v-if=
"objData.articles"
>
<wx-news
:articles=
"objData.articles"
/>
<el-row
class=
"ope-row"
>
<el-button
type=
"danger"
icon=
"el-icon-delete"
circle
@
click=
"deleteObj"
/>
</el-row>
<div
class=
"select-item"
v-if=
"objDataRef.articles.size > 0"
>
<wx-news
:articles=
"objDataRef.articles"
/>
<el-col
class=
"ope-row"
>
<el-button
type=
"danger"
circle
@
click=
"deleteObj"
>
<icon
icon=
"ep:delete"
/>
</el-button>
</el-col>
</div>
<!-- 选择素材 -->
<
div
v-if=
"!objData
.content"
>
<el-row
style=
"text-align: center"
>
<
el-col
:span=
"24"
v-if=
"!objDataRef
.content"
>
<el-row
style=
"text-align: center"
align=
"middle"
>
<el-col
:span=
"24"
>
<el-button
type=
"success"
@
click=
"openMaterial"
>
{{
newsType
===
'1'
?
'选择已发布图文'
:
'选择草稿箱图文'
}}
<i
class=
"el-icon-circle-check el-icon--right"
></i
>
</el-button>
>
{{ newsType === '1' ? '选择已发布图文' : '选择草稿箱图文'
}}
<icon
icon=
"ep:circle-check"
/>
</el-button>
</el-col>
</el-row>
</
div
>
<el-dialog
title=
"选择图文"
v-model
:visible
=
"dialogNewsVisible"
width=
"90%"
append-to-body
>
</
el-col
>
<el-dialog
title=
"选择图文"
v-model=
"dialogNewsVisible"
width=
"90%"
append-to-body
>
<wx-material-select
:objData=
"objData"
:objData=
"objData
Ref
"
@
selectMaterial=
"selectMaterial"
:newsType=
"newsType"
/>
...
...
@@ -201,53 +226,69 @@
</el-tab-pane>
<!-- 类型 6:音乐 -->
<el-tab-pane
name=
"music"
>
<span
slot=
"label"
><i
class=
"el-icon-service"
></i>
音乐
</span>
<el-row>
<
template
#
label
>
<el-row
align=
"middle"
>
<icon
icon=
"ep:service"
/>
音乐
</el-row>
</
template
>
<el-row
align=
"middle"
justify=
"center"
>
<el-col
:span=
"6"
>
<div
class=
"thumb-div"
>
<img
style=
"width: 100px"
v-if=
"objData.thumbMediaUrl"
:src=
"objData.thumbMediaUrl"
/>
<i
v-else
class=
"el-icon-plus avatar-uploader-icon"
></i>
<div
class=
"thumb-but"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
multiple
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeThumbImageUpload"
:on-success=
"handleUploadSuccess"
>
<el-button
slot=
"trigger"
size=
"mini"
type=
"text"
>
本地上传
</el-button>
<el-button
size=
"mini"
type=
"text"
@
click=
"openMaterial"
style=
"margin-left: 5px"
>
素材库选择
</el-button
>
</el-upload>
</div>
</div>
<el-dialog
title=
"选择图片"
v-model:visible=
"dialogThumbVisible"
width=
"80%"
append-to-body
>
<el-row
align=
"middle"
justify=
"center"
class=
"thumb-div"
>
<el-col
:span=
"24"
>
<el-row
align=
"middle"
justify=
"center"
>
<img
style=
"width: 100px"
v-if=
"objDataRef.thumbMediaUrl"
:src=
"objDataRef.thumbMediaUrl"
/>
<icon
v-else
icon=
"ep:plus"
/>
</el-row>
<el-row
align=
"middle"
justify=
"center"
style=
"margin-top: 2%"
>
<div
class=
"thumb-but"
>
<el-upload
:action=
"actionUrl"
:headers=
"headers"
multiple
:limit=
"1"
:file-list=
"fileList"
:data=
"uploadData"
:before-upload=
"beforeThumbImageUpload"
:on-success=
"handleUploadSuccess"
>
<
template
#
trigger
>
<el-button
type=
"text"
>
本地上传
</el-button>
</
template
>
<el-button
type=
"text"
@
click=
"openMaterial"
style=
"margin-left: 5px"
>
素材库选择
</el-button>
</el-upload>
</div>
</el-row>
</el-col>
</el-row>
<el-dialog
title=
"选择图片"
v-model=
"dialogThumbVisible"
width=
"80%"
append-to-body
>
<wx-material-select
:objData=
"
{ type: 'image', accountId: objData.accountId }"
:objData=
"{ type: 'image', accountId: objData
Ref
.accountId }"
@
selectMaterial=
"selectMaterial"
/>
</el-dialog>
</el-col>
<el-col
:span=
"18"
>
<el-input
v-model=
"objData.title"
placeholder=
"请输入标题"
@
input=
"inputContent"
/>
<el-input
v-model=
"objData
Ref
.title"
placeholder=
"请输入标题"
@
input=
"inputContent"
/>
<div
style=
"margin: 20px 0"
></div>
<el-input
v-model=
"objData.description"
placeholder=
"请输入描述"
@
input=
"inputContent"
/>
<el-input
v-model=
"objDataRef.description"
placeholder=
"请输入描述"
@
input=
"inputContent"
/>
</el-col>
</el-row>
<div
style=
"margin: 20px 0"
></div>
<el-input
v-model=
"objData.musicUrl"
placeholder=
"请输入音乐链接"
@
input=
"inputContent"
/>
<el-input
v-model=
"objData
Ref
.musicUrl"
placeholder=
"请输入音乐链接"
@
input=
"inputContent"
/>
<div
style=
"margin: 20px 0"
></div>
<el-input
v-model=
"objData.hqMusicUrl"
v-model=
"objData
Ref
.hqMusicUrl"
placeholder=
"请输入高质量音乐链接"
@
input=
"inputContent"
/>
...
...
@@ -255,16 +296,16 @@
</el-tabs>
</template>
<
script
>
<
script
lang=
"ts"
name=
"WxReplySelect"
>
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
WxMaterialSelect
from
'@/views/mp/components/wx-material-select/main.vue'
import
WxVoicePlayer
from
'@/views/mp/components/wx-voice-play/main.vue'
import
WxVideoPlayer
from
'@/views/mp/components/wx-video-play/main.vue'
import
{
getAccessToken
}
from
'@/utils/auth'
import
{
defineComponent
}
from
'vue'
export
default
{
name
:
'WxReplySelect'
,
export
default
defineComponent
({
components
:
{
WxNews
,
WxMaterialSelect
,
...
...
@@ -283,39 +324,29 @@ export default {
default
:
'1'
}
},
data
()
{
return
{
tempPlayerObj
:
{
type
:
'2'
},
tempObj
:
new
Map
().
set
(
// 临时缓存,切换消息类型的 tab 的时候,可以保存对应的数据;
this
.
objData
.
type
,
// 消息类型
Object
.
assign
({},
this
.
objData
)
),
// 消息内容
// ========== 素材选择的弹窗,是否可见 ==========
dialogNewsVisible
:
false
,
// 图文
dialogImageVisible
:
false
,
// 图片
dialogVoiceVisible
:
false
,
// 语音
dialogVideoVisible
:
false
,
// 视频
dialogThumbVisible
:
false
,
// 缩略图
// ========== 文件上传(图片、语音、视频) ==========
fileList
:
[],
// 文件列表
uploadData
:
{
accountId
:
undefined
,
type
:
this
.
objData
.
type
,
title
:
''
,
introduction
:
''
},
actionUrl
:
process
.
env
.
VUE_APP_BASE_API
+
'/admin-api/mp/material/upload-temporary'
,
headers
:
{
Authorization
:
'Bearer '
+
getAccessToken
()
}
// 设置上传的请求头部
}
},
methods
:
{
beforeThumbImageUpload
(
file
)
{
setup
(
props
)
{
const
objDataRef
=
reactive
(
props
.
objData
)
const
message
=
useMessage
()
// 消息弹窗
const
tempObj
=
new
Map
().
set
(
objDataRef
.
type
,
Object
.
assign
({},
objDataRef
))
// ========== 素材选择的弹窗,是否可见 ==========
const
dialogNewsVisible
=
ref
(
false
)
// 图文
const
dialogImageVisible
=
ref
(
false
)
// 图片
const
dialogVoiceVisible
=
ref
(
false
)
// 语音
const
dialogVideoVisible
=
ref
(
false
)
// 视频
const
dialogThumbVisible
=
ref
(
false
)
// 缩略图
// ========== 文件上传(图片、语音、视频) ==========
const
fileList
=
ref
([])
const
uploadData
=
reactive
({
accountId
:
undefined
,
type
:
objDataRef
.
type
,
title
:
''
,
introduction
:
''
})
const
actionUrl
=
ref
(
import
.
meta
.
env
.
VITE_API_BASEPATH
+
'/admin-api/mp/material/upload-temporary'
)
const
headers
=
ref
({
Authorization
:
'Bearer '
+
getAccessToken
()
})
// 设置上传的请求头部
const
beforeThumbImageUpload
=
(
file
)
=>
{
const
isType
=
file
.
type
===
'image/jpeg'
||
file
.
type
===
'image/png'
||
...
...
@@ -323,18 +354,18 @@ export default {
file
.
type
===
'image/bmp'
||
file
.
type
===
'image/jpg'
if
(
!
isType
)
{
this
.
$
message
.
error
(
'上传图片格式不对!'
)
message
.
error
(
'上传图片格式不对!'
)
return
false
}
const
isLt
=
file
.
size
/
1024
/
1024
<
2
if
(
!
isLt
)
{
this
.
$
message
.
error
(
'上传图片大小不能超过 2M!'
)
message
.
error
(
'上传图片大小不能超过 2M!'
)
return
false
}
this
.
uploadData
.
accountId
=
this
.
objData
.
accountId
uploadData
.
accountId
=
objDataRef
.
accountId
return
true
}
,
beforeVoiceUpload
(
file
)
{
}
const
beforeVoiceUpload
=
(
file
)
=>
{
// 校验格式
const
isType
=
file
.
type
===
'audio/mp3'
||
...
...
@@ -343,19 +374,19 @@ export default {
file
.
type
===
'audio/wav'
||
file
.
type
===
'audio/amr'
if
(
!
isType
)
{
this
.
$
message
.
error
(
'上传语音格式不对!'
+
file
.
type
)
message
.
error
(
'上传语音格式不对!'
+
file
.
type
)
return
false
}
// 校验大小
const
isLt
=
file
.
size
/
1024
/
1024
<
2
if
(
!
isLt
)
{
this
.
$
message
.
error
(
'上传语音大小不能超过 2M!'
)
message
.
error
(
'上传语音大小不能超过 2M!'
)
return
false
}
this
.
uploadData
.
accountId
=
this
.
objData
.
accountId
uploadData
.
accountId
=
objDataRef
.
accountId
return
true
}
,
beforeImageUpload
(
file
)
{
}
const
beforeImageUpload
=
(
file
)
=>
{
// 校验格式
const
isType
=
file
.
type
===
'image/jpeg'
||
...
...
@@ -364,197 +395,232 @@ export default {
file
.
type
===
'image/bmp'
||
file
.
type
===
'image/jpg'
if
(
!
isType
)
{
this
.
$
message
.
error
(
'上传图片格式不对!'
)
message
.
error
(
'上传图片格式不对!'
)
return
false
}
// 校验大小
const
isLt
=
file
.
size
/
1024
/
1024
<
2
if
(
!
isLt
)
{
this
.
$
message
.
error
(
'上传图片大小不能超过 2M!'
)
message
.
error
(
'上传图片大小不能超过 2M!'
)
return
false
}
this
.
uploadData
.
accountId
=
this
.
objData
.
accountId
uploadData
.
accountId
=
objDataRef
.
accountId
return
true
}
,
beforeVideoUpload
(
file
)
{
}
const
beforeVideoUpload
=
(
file
)
=>
{
// 校验格式
const
isType
=
file
.
type
===
'video/mp4'
if
(
!
isType
)
{
this
.
$
message
.
error
(
'上传视频格式不对!'
)
message
.
error
(
'上传视频格式不对!'
)
return
false
}
// 校验大小
const
isLt
=
file
.
size
/
1024
/
1024
<
10
if
(
!
isLt
)
{
this
.
$
message
.
error
(
'上传视频大小不能超过 10M!'
)
message
.
error
(
'上传视频大小不能超过 10M!'
)
return
false
}
this
.
uploadData
.
accountId
=
this
.
objData
.
accountId
uploadData
.
accountId
=
objDataRef
.
accountId
return
true
}
,
handleUploadSuccess
(
response
,
file
,
fileList
)
{
}
const
handleUploadSuccess
=
(
response
)
=>
{
if
(
response
.
code
!==
0
)
{
this
.
$
message
.
error
(
'上传出错:'
+
response
.
msg
)
message
.
error
(
'上传出错:'
+
response
.
msg
)
return
false
}
// 清空上传时的各种数据
this
.
fileList
=
[]
this
.
uploadData
.
title
=
''
this
.
uploadData
.
introduction
=
''
fileList
.
value
=
[]
uploadData
.
title
=
''
uploadData
.
introduction
=
''
// 上传好的文件,本质是个素材,所以可以进行选中
let
item
=
response
.
data
this
.
selectMaterial
(
item
)
}
,
selectMaterial
(
item
)
}
/**
* 切换消息类型的 tab
*
* @param tab tab
* @param tab tab
没用 暂时删了tab
*/
handleClick
(
tab
)
{
const
handleClick
=
()
=>
{
// 设置后续文件上传的文件类型
this
.
uploadData
.
type
=
this
.
objData
.
type
if
(
this
.
uploadData
.
type
===
'music'
)
{
uploadData
.
type
=
objDataRef
.
type
if
(
uploadData
.
type
===
'music'
)
{
// 【音乐】上传的是缩略图
this
.
uploadData
.
type
=
'thumb'
uploadData
.
type
=
'thumb'
}
// 从 tempObj 临时缓存中,获取对应的数据,并设置回 objData
let
tempObjItem
=
t
his
.
tempObj
.
get
(
this
.
objData
.
type
)
// 从 tempObj 临时缓存中,获取对应的数据,并设置回 objData
Ref
let
tempObjItem
=
t
empObj
.
get
(
objDataRef
.
type
)
if
(
tempObjItem
)
{
this
.
objData
.
content
=
tempObjItem
.
content
?
tempObjItem
.
content
:
null
this
.
objData
.
mediaId
=
tempObjItem
.
mediaId
?
tempObjItem
.
mediaId
:
null
this
.
objData
.
url
=
tempObjItem
.
url
?
tempObjItem
.
url
:
null
this
.
objData
.
name
=
tempObjItem
.
url
?
tempObjItem
.
name
:
null
this
.
objData
.
title
=
tempObjItem
.
title
?
tempObjItem
.
title
:
null
this
.
objData
.
description
=
tempObjItem
.
description
?
tempObjItem
.
description
:
null
objDataRef
.
content
=
tempObjItem
.
content
?
tempObjItem
.
content
:
null
objDataRef
.
mediaId
=
tempObjItem
.
mediaId
?
tempObjItem
.
mediaId
:
null
objDataRef
.
url
=
tempObjItem
.
url
?
tempObjItem
.
url
:
null
objDataRef
.
name
=
tempObjItem
.
url
?
tempObjItem
.
name
:
null
objDataRef
.
title
=
tempObjItem
.
title
?
tempObjItem
.
title
:
null
objDataRef
.
description
=
tempObjItem
.
description
?
tempObjItem
.
description
:
null
return
}
// 如果获取不到,需要把 objData 复原
// 如果获取不到,需要把 objData
Ref
复原
// 必须使用 $set 赋值,不然 input 无法输入内容
this
.
$set
(
this
.
objData
,
'content'
,
''
)
this
.
$delete
(
this
.
objData
,
'mediaId'
)
this
.
$delete
(
this
.
objData
,
'url'
)
this
.
$set
(
this
.
objData
,
'title'
,
''
)
this
.
$set
(
this
.
objData
,
'description'
,
''
)
}
,
objDataRef
.
content
=
''
objDataRef
.
mediaId
=
''
objDataRef
.
url
=
''
objDataRef
.
title
=
''
objDataRef
.
description
=
''
}
/**
* 选择素材,将设置设置到 objData 变量
* 选择素材,将设置设置到 objData
Ref
变量
*
* @param item 素材
*/
selectMaterial
(
item
)
{
const
selectMaterial
=
(
item
)
=>
{
// 选择好素材,所以隐藏弹窗
this
.
closeMaterial
()
closeMaterial
()
// 创建 tempObjItem 对象,并设置对应的值
let
tempObjItem
=
{}
tempObjItem
.
type
=
this
.
objData
.
type
if
(
this
.
objData
.
type
===
'news'
)
{
let
tempObjItem
=
{
type
:
''
,
articles
:
''
,
thumbMediaId
:
''
,
thumbMediaUrl
:
''
,
introduction
:
''
,
title
:
''
,
musicUrl
:
''
,
hqMusicUrl
:
''
,
mediaId
:
''
,
url
:
''
,
name
:
''
,
description
:
''
}
tempObjItem
.
type
=
objDataRef
.
type
if
(
objDataRef
.
type
===
'news'
)
{
tempObjItem
.
articles
=
item
.
content
.
newsItem
this
.
objData
.
articles
=
item
.
content
.
newsItem
}
else
if
(
this
.
objData
.
type
===
'music'
)
{
objDataRef
.
articles
=
item
.
content
.
newsItem
}
else
if
(
objDataRef
.
type
===
'music'
)
{
// 音乐需要特殊处理,因为选择的是图片的缩略图
tempObjItem
.
thumbMediaId
=
item
.
mediaId
this
.
objData
.
thumbMediaId
=
item
.
mediaId
objDataRef
.
thumbMediaId
=
item
.
mediaId
tempObjItem
.
thumbMediaUrl
=
item
.
url
this
.
objData
.
thumbMediaUrl
=
item
.
url
// title、introduction、musicUrl、hqMusicUrl:从 objData 到 tempObjItem,避免上传素材后,被覆盖掉
tempObjItem
.
title
=
this
.
objData
.
title
||
''
tempObjItem
.
introduction
=
this
.
objData
.
introduction
||
''
tempObjItem
.
musicUrl
=
this
.
objData
.
musicUrl
||
''
tempObjItem
.
hqMusicUrl
=
this
.
objData
.
hqMusicUrl
||
''
}
else
if
(
this
.
objData
.
type
===
'image'
||
this
.
objData
.
type
===
'voice'
)
{
objDataRef
.
thumbMediaUrl
=
item
.
url
// title、introduction、musicUrl、hqMusicUrl:从 objData
Ref
到 tempObjItem,避免上传素材后,被覆盖掉
tempObjItem
.
title
=
objDataRef
.
title
||
''
tempObjItem
.
introduction
=
objDataRef
.
introduction
||
''
tempObjItem
.
musicUrl
=
objDataRef
.
musicUrl
||
''
tempObjItem
.
hqMusicUrl
=
objDataRef
.
hqMusicUrl
||
''
}
else
if
(
objDataRef
.
type
===
'image'
||
objDataRef
.
type
===
'voice'
)
{
tempObjItem
.
mediaId
=
item
.
mediaId
this
.
objData
.
mediaId
=
item
.
mediaId
objDataRef
.
mediaId
=
item
.
mediaId
tempObjItem
.
url
=
item
.
url
this
.
objData
.
url
=
item
.
url
objDataRef
.
url
=
item
.
url
tempObjItem
.
name
=
item
.
name
this
.
objData
.
name
=
item
.
name
}
else
if
(
this
.
objData
.
type
===
'video'
)
{
objDataRef
.
name
=
item
.
name
}
else
if
(
objDataRef
.
type
===
'video'
)
{
tempObjItem
.
mediaId
=
item
.
mediaId
this
.
objData
.
mediaId
=
item
.
mediaId
objDataRef
.
mediaId
=
item
.
mediaId
tempObjItem
.
url
=
item
.
url
this
.
objData
.
url
=
item
.
url
objDataRef
.
url
=
item
.
url
tempObjItem
.
name
=
item
.
name
this
.
objData
.
name
=
item
.
name
objDataRef
.
name
=
item
.
name
// title、introduction:从 item 到 tempObjItem,因为素材里有 title、introduction
if
(
item
.
title
)
{
this
.
objData
.
title
=
item
.
title
||
''
objDataRef
.
title
=
item
.
title
||
''
tempObjItem
.
title
=
item
.
title
||
''
}
if
(
item
.
introduction
)
{
this
.
objData
.
description
=
item
.
introduction
||
''
// 消息使用的是 description,素材使用的是 introduction,所以转换下
objDataRef
.
description
=
item
.
introduction
||
''
// 消息使用的是 description,素材使用的是 introduction,所以转换下
tempObjItem
.
description
=
item
.
introduction
||
''
}
}
else
if
(
this
.
objData
.
type
===
'text'
)
{
this
.
objData
.
content
=
item
.
content
||
''
}
else
if
(
objDataRef
.
type
===
'text'
)
{
objDataRef
.
content
=
item
.
content
||
''
}
// 最终设置到临时缓存
t
his
.
tempObj
.
set
(
this
.
objData
.
type
,
tempObjItem
)
}
,
openMaterial
()
{
if
(
this
.
objData
.
type
===
'news'
)
{
this
.
dialogNewsVisibl
e
=
true
}
else
if
(
this
.
objData
.
type
===
'image'
)
{
this
.
dialogImageVisibl
e
=
true
}
else
if
(
this
.
objData
.
type
===
'voice'
)
{
this
.
dialogVoiceVisibl
e
=
true
}
else
if
(
this
.
objData
.
type
===
'video'
)
{
this
.
dialogVideoVisibl
e
=
true
}
else
if
(
this
.
objData
.
type
===
'music'
)
{
this
.
dialogThumbVisibl
e
=
true
t
empObj
.
set
(
objDataRef
.
type
,
tempObjItem
)
}
const
openMaterial
=
()
=>
{
if
(
objDataRef
.
type
===
'news'
)
{
dialogNewsVisible
.
valu
e
=
true
}
else
if
(
objDataRef
.
type
===
'image'
)
{
dialogImageVisible
.
valu
e
=
true
}
else
if
(
objDataRef
.
type
===
'voice'
)
{
dialogVoiceVisible
.
valu
e
=
true
}
else
if
(
objDataRef
.
type
===
'video'
)
{
dialogVideoVisible
.
valu
e
=
true
}
else
if
(
objDataRef
.
type
===
'music'
)
{
dialogThumbVisible
.
valu
e
=
true
}
}
,
c
loseMaterial
()
{
this
.
dialogNewsVisibl
e
=
false
this
.
dialogImageVisibl
e
=
false
this
.
dialogVoiceVisibl
e
=
false
this
.
dialogVideoVisibl
e
=
false
this
.
dialogThumbVisibl
e
=
false
}
,
deleteObj
()
{
if
(
this
.
objData
.
type
===
'news'
)
{
this
.
$delete
(
this
.
objData
,
'articles'
)
}
else
if
(
this
.
objData
.
type
===
'image'
)
{
this
.
objData
.
mediaId
=
null
this
.
$delete
(
this
.
objData
,
'url'
)
this
.
objData
.
name
=
null
}
else
if
(
this
.
objData
.
type
===
'voice'
)
{
this
.
objData
.
mediaId
=
null
this
.
$delete
(
this
.
objData
,
'url'
)
this
.
objData
.
name
=
null
}
else
if
(
this
.
objData
.
type
===
'video'
)
{
this
.
objData
.
mediaId
=
null
this
.
$delete
(
this
.
objData
,
'url'
)
this
.
objData
.
name
=
null
this
.
objData
.
title
=
null
this
.
objData
.
description
=
null
}
else
if
(
this
.
objData
.
type
===
'music'
)
{
this
.
objData
.
thumbMediaId
=
null
this
.
objData
.
thumbMediaUrl
=
null
this
.
objData
.
title
=
null
this
.
objData
.
description
=
null
this
.
objData
.
musicUrl
=
null
this
.
objData
.
hqMusicUrl
=
null
}
else
if
(
this
.
objData
.
type
===
'text'
)
{
this
.
objData
.
content
=
null
}
c
onst
closeMaterial
=
()
=>
{
dialogNewsVisible
.
valu
e
=
false
dialogImageVisible
.
valu
e
=
false
dialogVoiceVisible
.
valu
e
=
false
dialogVideoVisible
.
valu
e
=
false
dialogThumbVisible
.
valu
e
=
false
}
const
deleteObj
=
()
=>
{
if
(
objDataRef
.
type
===
'news'
)
{
objDataRef
.
articles
=
''
}
else
if
(
objDataRef
.
type
===
'image'
)
{
objDataRef
.
mediaId
=
null
objDataRef
.
url
=
null
objDataRef
.
name
=
null
}
else
if
(
objDataRef
.
type
===
'voice'
)
{
objDataRef
.
mediaId
=
null
objDataRef
.
url
=
null
objDataRef
.
name
=
null
}
else
if
(
objDataRef
.
type
===
'video'
)
{
objDataRef
.
mediaId
=
null
objDataRef
.
url
=
null
objDataRef
.
name
=
null
objDataRef
.
title
=
null
objDataRef
.
description
=
null
}
else
if
(
objDataRef
.
type
===
'music'
)
{
objDataRef
.
thumbMediaId
=
null
objDataRef
.
thumbMediaUrl
=
null
objDataRef
.
title
=
null
objDataRef
.
description
=
null
objDataRef
.
musicUrl
=
null
objDataRef
.
hqMusicUrl
=
null
}
else
if
(
objDataRef
.
type
===
'text'
)
{
objDataRef
.
content
=
null
}
// 覆盖缓存
t
his
.
tempObj
.
set
(
this
.
objData
.
type
,
Object
.
assign
({},
this
.
objData
))
}
,
t
empObj
.
set
(
objDataRef
.
type
,
Object
.
assign
({},
objDataRef
))
}
/**
* 输入时,缓存每次 objData 到 tempObj 中
* 输入时,缓存每次 objData
Ref
到 tempObj 中
*
* why?不确定为什么 v-model="objData.content" 不能自动缓存,所以通过这样的方式
* why?不确定为什么 v-model="objData
Ref
.content" 不能自动缓存,所以通过这样的方式
*/
inputContent
(
str
)
{
const
inputContent
=
()
=>
{
// 覆盖缓存
this
.
tempObj
.
set
(
this
.
objData
.
type
,
Object
.
assign
({},
this
.
objData
))
tempObj
.
set
(
objDataRef
.
type
,
Object
.
assign
({},
objDataRef
))
}
return
{
inputContent
,
dialogNewsVisible
,
deleteObj
,
openMaterial
,
handleClick
,
beforeImageUpload
,
beforeVoiceUpload
,
handleUploadSuccess
,
beforeVideoUpload
,
selectMaterial
,
dialogImageVisible
,
dialogVoiceVisible
,
dialogThumbVisible
,
actionUrl
,
objDataRef
,
headers
,
fileList
,
beforeThumbImageUpload
,
uploadData
,
dialogVideoVisible
}
}
}
}
)
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
@@ -564,25 +630,34 @@ export default {
margin-right
:
2%
;
}
}
.pagination
{
text-align
:
right
;
margin-right
:
25px
;
}
.select-item
{
width
:
280px
;
padding
:
10px
;
margin
:
0
auto
10px
auto
;
border
:
1px
solid
#eaeaea
;
}
.select-item2
{
padding
:
10px
;
margin
:
0
auto
10px
auto
;
border
:
1px
solid
#eaeaea
;
}
.ope-row
{
padding-top
:
10px
;
text-align
:
center
;
}
.input-margin-bottom
{
margin-bottom
:
2%
;
}
.item-name
{
font-size
:
12px
;
overflow
:
hidden
;
...
...
@@ -590,20 +665,24 @@ export default {
white-space
:
nowrap
;
text-align
:
center
;
}
.el-form-item__content
{
line-height
:
unset
!important
;
}
.col-select
{
border
:
1px
solid
rgb
(
234
,
234
,
234
);
padding
:
50px
0px
;
height
:
160px
;
width
:
49.5%
;
}
.col-select2
{
border
:
1px
solid
rgb
(
234
,
234
,
234
);
padding
:
50px
0px
;
height
:
160px
;
}
.col-add
{
border
:
1px
solid
rgb
(
234
,
234
,
234
);
padding
:
50px
0px
;
...
...
@@ -611,6 +690,7 @@ export default {
width
:
49.5%
;
float
:
right
;
}
.avatar-uploader-icon
{
border
:
1px
solid
#d9d9d9
;
font-size
:
28px
;
...
...
@@ -620,13 +700,16 @@ export default {
line-height
:
100px
!important
;
text-align
:
center
;
}
.material-img
{
width
:
100%
;
}
.thumb-div
{
display
:
inline-block
;
text-align
:
center
;
}
.item-infos
{
width
:
30%
;
margin
:
auto
;
...
...
src/views/mp/components/wx-video-play/main.vue
View file @
16c5e3ea
...
...
@@ -19,13 +19,7 @@
</div>
<!-- 弹窗播放 -->
<el-dialog
v-model=
"dialogVideo"
title=
"视频播放"
width=
"40%"
append-to-body
@
close=
"closeDialog"
>
<el-dialog
v-model=
"dialogVideo"
title=
"视频播放"
width=
"40%"
append-to-body
>
<template
#
footer
>
<video-player
v-if=
"dialogVideo"
...
...
src/views/mp/message/index.vue
View file @
16c5e3ea
...
...
@@ -51,8 +51,14 @@
/>
</el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
@
click=
"handleQuery"
>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
...
...
@@ -85,16 +91,20 @@
<el-tag
type=
"danger"
>
取消关注
</el-tag>
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'CLICK'"
>
<el-tag>
点击菜单
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
<el-tag>
点击菜单
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'VIEW'"
>
<el-tag>
点击菜单链接
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
<el-tag>
点击菜单链接
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'scancode_waitmsg'"
>
<el-tag>
扫码结果
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
<el-tag>
扫码结果
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'scancode_push'"
>
<el-tag>
扫码结果
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
<el-tag>
扫码结果
</el-tag>
【
{{
scope
.
row
.
eventKey
}}
】
</div>
<div
v-else-if=
"scope.row.type === 'event' && scope.row.event === 'pic_sysphoto'"
>
<el-tag>
系统拍照发图
</el-tag>
...
...
@@ -125,7 +135,8 @@
<wx-video-player
:url=
"scope.row.mediaUrl"
style=
"margin-top: 10px"
/>
</div>
<div
v-else-if=
"scope.row.type === 'link'"
>
<el-tag>
链接
</el-tag>
:
<el-tag>
链接
</el-tag>
:
<a
:href=
"scope.row.url"
target=
"_blank"
>
{{
scope
.
row
.
title
}}
</a>
</div>
<div
v-else-if=
"scope.row.type === 'location'"
>
...
...
@@ -175,8 +186,10 @@
/>
<!-- 发送消息的弹窗 -->
<el-dialog
title=
"粉丝消息列表"
v-model:visible=
"open"
width=
"50%"
>
<wx-msg
:user-id=
"userId"
v-if=
"open"
/>
<el-dialog
title=
"粉丝消息列表"
v-model=
"open"
@
click=
"openDialog()"
width=
"50%"
>
<
template
#
footer
>
<wx-msg
:user-id=
"userId"
v-if=
"open"
/>
</
template
>
</el-dialog>
</ContentWrap>
</template>
...
...
@@ -189,6 +202,7 @@ import WxMusic from '@/views/mp/components/wx-music/main.vue'
import
WxNews
from
'@/views/mp/components/wx-news/main.vue'
import
*
as
MpAccountApi
from
'@/api/mp/account'
import
*
as
MpMessageApi
from
'@/api/mp/message'
const
message
=
useMessage
()
// 消息弹窗
import
{
DICT_TYPE
,
getStrDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
...
...
@@ -248,6 +262,13 @@ const handleSend = async (row) => {
open
.
value
=
true
}
const
openDialog
=
()
=>
{
open
.
value
=
true
}
// const closeDiaLog = () => {
// open.value = false
// }
/** 初始化 **/
onMounted
(
async
()
=>
{
accountList
.
value
=
await
MpAccountApi
.
getSimpleAccountList
()
...
...
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