Commit df5e6161aac60138b8696de546a77b19469d2565

Authored by YunaiV
1 parent 94178998

mp:重构 wx-msg 前的提交

yudao-ui-admin/src/views/mp/components/wx-msg/main.vue 0 → 100644
  1 +<!--
  2 + - Copyright (C) 2018-2019
  3 + - All rights reserved, Designed By www.joolun.com
  4 +-->
  5 +<template>
  6 + <div class="msg-main" v-loading="mainLoading">
  7 + <div class="msg-div" :id="'msg-div'+nowStr">
  8 + <div v-loading="tableLoading"></div>
  9 + <div v-if="!tableLoading">
  10 + <div class="el-table__empty-block" v-if="loadMore" @click="loadingMore"><span class="el-table__empty-text">点击加载更多</span></div>
  11 + <div class="el-table__empty-block" v-if="!loadMore"><span class="el-table__empty-text">没有更多了</span></div>
  12 + </div>
  13 + <div class="execution" v-for="item in tableData" :key='item.id'>
  14 + <div class="avue-comment" :class="item.type == '2' ? 'avue-comment--reverse' : ''">
  15 + <div class="avatar-div">
  16 + <img :src="item.type == '1' ? item.headimgUrl : item.appLogo" class="avue-comment__avatar">
  17 + <div class="avue-comment__author">{{item.type == '1' ? item.nickName : item.appName}}</div>
  18 + </div>
  19 + <div class="avue-comment__main">
  20 + <div class="avue-comment__header">
  21 + <div class="avue-comment__create_time">{{item.createTime}}</div>
  22 + </div>
  23 + <div class="avue-comment__body" :style="item.type == '2' ? 'background: #6BED72;' : ''">
  24 + <div v-if="item.repType == 'event' && item.repEvent == 'subscribe'"><el-tag type="success" size="mini">关注</el-tag></div>
  25 + <div v-if="item.repType == 'event' && item.repEvent == 'unsubscribe'"><el-tag type="danger" size="mini">取消关注</el-tag></div>
  26 + <div v-if="item.repType == 'event' && item.repEvent == 'CLICK'"><el-tag size="mini">点击菜单</el-tag>:【{{item.repName}}】</div>
  27 + <div v-if="item.repType == 'event' && item.repEvent == 'VIEW'"><el-tag size="mini">点击菜单链接</el-tag>:【{{item.repUrl}}】</div>
  28 + <div v-if="item.repType == 'event' && item.repEvent == 'scancode_waitmsg'"><el-tag size="mini">扫码结果:</el-tag>:【{{item.repContent}}】</div>
  29 + <div v-if="item.repType == 'text'">{{item.repContent}}</div>
  30 + <div v-if="item.repType == 'image'">
  31 + <a target="_blank" :href="item.repUrl"><img :src="item.repUrl" style="width: 100px"></a>
  32 + </div>
  33 + <div v-if="item.repType == 'voice'">
  34 + <WxVoicePlayer :objData="item"></WxVoicePlayer>
  35 + </div>
  36 + <div v-if="item.repType == 'video'" style="text-align: center">
  37 + <WxVideoPlayer :objData="item"></WxVideoPlayer>
  38 + </div>
  39 + <div v-if="item.repType == 'shortvideo'" style="text-align: center">
  40 + <WxVideoPlayer :objData="item"></WxVideoPlayer>
  41 + </div>
  42 + <div v-if="item.repType == 'location'">
  43 + <el-link type="primary" target="_blank" :href="'https://map.qq.com/?type=marker&isopeninfowin=1&markertype=1&pointx='+item.repLocationY+'&pointy='+item.repLocationX+'&name='+item.repContent+'&ref=joolun'">
  44 + <img :src="'https://apis.map.qq.com/ws/staticmap/v2/?zoom=10&markers=color:blue|label:A|'+item.repLocationX+','+item.repLocationY+'&key='+qqMapKey+'&size=250*180'">
  45 + <p/><i class="el-icon-map-location"></i>{{item.repContent}}
  46 + </el-link>
  47 + </div>
  48 + <div v-if="item.repType == 'link'" class="avue-card__detail">
  49 + <el-link type="success" :underline="false" target="_blank" :href="item.repUrl">
  50 + <div class="avue-card__title"><i class="el-icon-link"></i>{{item.repName}}</div>
  51 + </el-link>
  52 + <div class="avue-card__info" style="height: unset">{{item.repDesc}}</div>
  53 + </div>
  54 + <div v-if="item.repType == 'news'" style="width: 300px">
  55 + <WxNews :objData="item.content.articles"></WxNews>
  56 + </div>
  57 + <div v-if="item.repType == 'music'">
  58 + <el-link type="success" :underline="false" target="_blank" :href="item.repUrl">
  59 + <div class="avue-card__body" style="padding:10px;background-color: #fff;border-radius: 5px">
  60 + <div class="avue-card__avatar"><img :src="item.repThumbUrl" alt=""></div>
  61 + <div class="avue-card__detail">
  62 + <div class="avue-card__title" style="margin-bottom:unset">{{item.repName}}</div>
  63 + <div class="avue-card__info" style="height: unset">{{item.repDesc}}</div>
  64 + </div>
  65 + </div>
  66 + </el-link>
  67 + </div>
  68 + </div>
  69 + </div>
  70 + </div>
  71 + </div>
  72 + </div>
  73 +<!-- <div class="msg-send" v-loading="sendLoading">-->
  74 +<!-- <WxReplySelect :objData="objData"></WxReplySelect>-->
  75 +<!-- <el-button type="success" size="small" class="send-but" @click="sendMsg">发送(S)</el-button>-->
  76 +<!-- </div>-->
  77 + </div>
  78 +</template>
  79 +
  80 +<script>
  81 + import { getPage, addObj, putObj } from '@/api/wxmp/wxmsg'
  82 + import SockJS from 'sockjs-client';
  83 + import Stomp from 'stompjs';
  84 + import { getToken } from '@/utils/auth'
  85 + import WxReplySelect from '@/components/wx-reply/main.vue'
  86 + import WxNews from '@/components/wx-news/main.vue'
  87 + import WxVideoPlayer from '@/components/wx-video-play/main.vue'
  88 + import WxVoicePlayer from '@/components/wx-voice-play/main.vue'
  89 +
  90 + export default {
  91 + name: "wxMsg",
  92 + components: {
  93 + WxReplySelect,
  94 + WxNews,
  95 + WxVideoPlayer,
  96 + WxVoicePlayer
  97 + },
  98 + props: {
  99 + wxUserId:{
  100 + type:String
  101 + }
  102 + },
  103 + data() {
  104 + return {
  105 + nowStr: new Date().getTime(),
  106 + objData:{
  107 + repType: 'text'
  108 + },
  109 + mainLoading:false,
  110 + sendLoading:false,
  111 + tableLoading:false,
  112 + loadMore: true,
  113 + tableData: [],
  114 + page: {
  115 + total: 0, // 总页数
  116 + currentPage: 1, // 当前页数
  117 + pageSize: 14, // 每页显示多少条
  118 + ascs:[],//升序字段
  119 + descs:'create_time'//降序字段
  120 + },
  121 + option: {
  122 + props: {
  123 + avatar: 'avatar',
  124 + author: 'author',
  125 + body: 'body'
  126 + }
  127 + }
  128 + }
  129 + },
  130 + created() {
  131 + this.refreshChange()
  132 + },
  133 + destroyed: function() {
  134 + this.disconnect()
  135 + },
  136 + mounted(){
  137 + //开源版接口没有实现websocket,固隐藏
  138 + // this.initWebSocket()
  139 + },
  140 + beforeDestroy() {
  141 + // 页面离开时断开连接,清除定时器
  142 + this.disconnect();
  143 + clearInterval(this.timer);
  144 + },
  145 + computed: {
  146 +
  147 + },
  148 + methods:{
  149 + initWebSocket() {
  150 + this.connection();
  151 + let self = this;
  152 + //断开重连机制,尝试发送消息,捕获异常发生时重连
  153 + this.timer = setInterval(() => {
  154 + try {
  155 + self.stompClient.send("test");
  156 + } catch (err) {
  157 + console.log("断线了: " + err);
  158 + self.connection();
  159 + }
  160 + }, 5000);
  161 + },
  162 + connection() {
  163 + let token = getToken()
  164 + let headers = {
  165 + 'Authorization': 'Bearer ' + token
  166 + }
  167 + // 建立连接对象
  168 + this.socket = new SockJS('/weixin/ws');//连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
  169 + // 获取STOMP子协议的客户端对象
  170 + this.stompClient = Stomp.over(this.socket);
  171 +
  172 + // 向服务器发起websocket连接
  173 + this.stompClient.connect(headers, () => {
  174 + this.stompClient.subscribe('/weixin/wx_msg'+this.wxUserId, (msg) => { // 订阅服务端提供的某个topic;
  175 + let data = JSON.parse(msg.body)
  176 + this.tableData = [...this.tableData , ...[data]]//刷新消息
  177 + this.scrollToBottom()
  178 + //标记为已读
  179 + if(data.type == '1'){
  180 + putObj({
  181 + id: data.id,
  182 + readFlag: '0'
  183 + }).then(data => {})
  184 + }
  185 + });
  186 + }, (err) => {
  187 +
  188 + });
  189 + },
  190 + disconnect() {
  191 + if (this.stompClient != null) {
  192 + this.stompClient.disconnect();
  193 + console.log("Disconnected");
  194 + }
  195 + },
  196 + sendMsg(){
  197 + if(this.objData){
  198 + if(this.objData.repType == 'news'){
  199 + this.objData.content.articles = [this.objData.content.articles[0]]
  200 + this.$message({
  201 + showClose: true,
  202 + message: '图文消息条数限制在1条以内,已默认发送第一条',
  203 + type: 'success'
  204 + })
  205 + }
  206 + this.sendLoading = true
  207 + addObj(Object.assign({
  208 + wxUserId: this.wxUserId
  209 + },this.objData)).then(data => {
  210 + this.sendLoading = false
  211 + data = data.data
  212 + this.tableData = [...this.tableData , ...[data] ]
  213 + this.scrollToBottom()
  214 + this.objData = {
  215 + repType: 'text'
  216 + }
  217 + }).catch(() => {
  218 + this.sendLoading = false
  219 + })
  220 + }
  221 + },
  222 + scrollToBottom: function () {
  223 + this.$nextTick(() => {
  224 + let div = document.getElementById('msg-div'+this.nowStr)
  225 + div.scrollTop = div.scrollHeight
  226 + })
  227 + },
  228 + loadingMore(){
  229 + this.page.currentPage++
  230 + this.getPage(this.page)
  231 + },
  232 + getPage(page, params) {
  233 + this.tableLoading = true
  234 + getPage(Object.assign({
  235 + current: page.currentPage,
  236 + size: page.pageSize,
  237 + descs:page.descs,
  238 + ascs: page.ascs,
  239 + wxUserId: this.wxUserId
  240 + }, params)).then(response => {
  241 + let msgDiv = document.getElementById('msg-div'+this.nowStr)
  242 + let scrollHeight = 0
  243 + if(msgDiv){
  244 + scrollHeight = msgDiv.scrollHeight
  245 + }
  246 + let data = response.data.records.reverse()
  247 + this.tableData = [...data , ...this.tableData]
  248 + this.page.total = response.data.total
  249 + this.tableLoading = false
  250 + if(data.length < this.page.pageSize || data.length == 0){
  251 + this.loadMore = false
  252 + }
  253 + if(this.page.currentPage == 1){//定位到消息底部
  254 + this.scrollToBottom()
  255 + }else{
  256 + if(data.length != 0){
  257 + this.$nextTick(() => {//定位滚动条
  258 + if(scrollHeight != 0){
  259 + msgDiv.scrollTop = document.getElementById('msg-div'+this.nowStr).scrollHeight - scrollHeight - 100
  260 + }
  261 + })
  262 + }
  263 + }
  264 + this.page.currentPage = page.currentPage
  265 + this.page.pageSize = page.pageSize
  266 + })
  267 + },
  268 + /**
  269 + * 刷新回调
  270 + */
  271 + refreshChange() {
  272 + this.getPage(this.page)
  273 + }
  274 + }
  275 + };
  276 +</script>
  277 +
  278 +<style lang="scss" scoped>
  279 + .msg-main{
  280 + margin-top: -30px;
  281 + padding: 10px;
  282 + }
  283 + .msg-div{
  284 + height: 50vh;
  285 + overflow: auto;
  286 + background-color: #eaeaea;
  287 + }
  288 + .msg-send{
  289 + padding: 10px;
  290 + }
  291 + .avue-comment__main{
  292 + flex: unset!important;
  293 + border-radius: 5px!important;
  294 + margin: 0 8px!important;
  295 + }
  296 + .avue-comment__header{
  297 + border-top-left-radius: 5px;
  298 + border-top-right-radius: 5px;
  299 + }
  300 + .avue-comment__body {
  301 + border-bottom-right-radius: 5px;
  302 + border-bottom-left-radius: 5px;
  303 + }
  304 + .avatar-div{
  305 + text-align: center;
  306 + width: 80px;
  307 + }
  308 + .send-but{
  309 + float: right;
  310 + margin-top: 8px!important;
  311 + }
  312 +</style>
  313 +