mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-10-31 18:28:44 +08:00 
			
		
		
		
	1、微信组件更新第三波,消息页面能正常展示了。但是页面可能还要错乱
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								src/assets/imgs/profile.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/imgs/profile.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/imgs/wechat.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/assets/imgs/wechat.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										302
									
								
								src/views/mp/components/wx-material-select/main.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								src/views/mp/components/wx-material-select/main.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,302 @@ | ||||
| <!-- | ||||
|   - 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> | ||||
| @@ -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' | ||||
|  | ||||
| export default { | ||||
|   name: 'WxMsg', | ||||
| const message = useMessage() // 消息弹窗 | ||||
| import profile from '@/assets/imgs/profile.jpg' | ||||
| import wechat from '@/assets/imgs/wechat.png' | ||||
| import { parseTime } from '@/utils/formatTime' | ||||
|  | ||||
| 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 | ||||
|  | ||||
|       // 加载消息 | ||||
|       console.log(this.queryParams) | ||||
|       this.refreshChange() | ||||
|   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 | ||||
|     }) | ||||
|   }, | ||||
|   methods: { | ||||
|     sendMsg() { | ||||
|       if (!this.objData) { | ||||
|     const user = reactive({ | ||||
|       // 由于微信不再提供昵称,直接使用“用户”展示 | ||||
|       nickname: '用户', | ||||
|       avatar: profile, | ||||
|       accountId: 0 // 公众号账号编号 | ||||
|     }) | ||||
|     const mp = reactive({ | ||||
|       nickname: '公众号', | ||||
|       avatar: wechat | ||||
|     }) | ||||
|  | ||||
|     // ========= 消息发送 ========= | ||||
|     const sendLoading = ref(false) // 发送消息是否加载中 | ||||
|     const objData = reactive({ | ||||
|       // 微信发送消息 | ||||
|       type: 'text', | ||||
|       accountId: null, | ||||
|       articles: [] | ||||
|     }) | ||||
|  | ||||
|     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: this.userId, | ||||
|             userId: props.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; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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" | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 wuxiran
					wuxiran