mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-11-04 12:18:43 +08:00 
			
		
		
		
	refactor: mp/wx-msg 拆分组件
This commit is contained in:
		
							
								
								
									
										51
									
								
								src/views/mp/components/wx-msg/components/MsgEvent.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/views/mp/components/wx-msg/components/MsgEvent.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div v-if="item.event === 'subscribe'">
 | 
			
		||||
      <el-tag type="success">关注</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'unsubscribe'">
 | 
			
		||||
      <el-tag type="danger">取消关注</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'CLICK'">
 | 
			
		||||
      <el-tag>点击菜单</el-tag>
 | 
			
		||||
      【{{ item.eventKey }}】
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'VIEW'">
 | 
			
		||||
      <el-tag>点击菜单链接</el-tag>
 | 
			
		||||
      【{{ item.eventKey }}】
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'scancode_waitmsg'">
 | 
			
		||||
      <el-tag>扫码结果</el-tag>
 | 
			
		||||
      【{{ item.eventKey }}】
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'scancode_push'">
 | 
			
		||||
      <el-tag>扫码结果</el-tag>
 | 
			
		||||
      【{{ item.eventKey }}】
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'pic_sysphoto'">
 | 
			
		||||
      <el-tag>系统拍照发图</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'pic_photo_or_album'">
 | 
			
		||||
      <el-tag>拍照或者相册</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'pic_weixin'">
 | 
			
		||||
      <el-tag>微信相册</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else-if="item.event === 'location_select'">
 | 
			
		||||
      <el-tag>选择地理位置</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-else>
 | 
			
		||||
      <el-tag type="danger">未知事件类型</el-tag>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  item: any
 | 
			
		||||
}>()
 | 
			
		||||
 | 
			
		||||
const item = ref(props.item)
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped></style>
 | 
			
		||||
							
								
								
									
										110
									
								
								src/views/mp/components/wx-msg/components/MsgList.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/views/mp/components/wx-msg/components/MsgList.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="execution" v-for="item in props.list" :key="item.id">
 | 
			
		||||
    <div
 | 
			
		||||
      class="avue-comment"
 | 
			
		||||
      :class="{ 'avue-comment--reverse': item.sendFrom === SendFrom.MpBot }"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="avatar-div">
 | 
			
		||||
        <img :src="getAvatar(item.sendFrom)" class="avue-comment__avatar" />
 | 
			
		||||
        <div class="avue-comment__author">
 | 
			
		||||
          {{ getNickname(item.sendFrom) }}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="avue-comment__main">
 | 
			
		||||
        <div class="avue-comment__header">
 | 
			
		||||
          <div class="avue-comment__create_time">{{ formatDate(item.createTime) }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div
 | 
			
		||||
          class="avue-comment__body"
 | 
			
		||||
          :style="item.sendFrom === SendFrom.MpBot ? 'background: #6BED72;' : ''"
 | 
			
		||||
        >
 | 
			
		||||
          <!-- 【事件】区域 -->
 | 
			
		||||
          <MsgEvent v-if="item.type === MsgType.Event" :item="item" />
 | 
			
		||||
          <!-- 【消息】区域 -->
 | 
			
		||||
          <div v-else-if="item.type === MsgType.Text">{{ item.content }}</div>
 | 
			
		||||
          <div v-else-if="item.type === MsgType.Voice">
 | 
			
		||||
            <WxVoicePlayer :url="item.mediaUrl" :content="item.recognition" />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div v-else-if="item.type === MsgType.Image">
 | 
			
		||||
            <a target="_blank" :href="item.mediaUrl">
 | 
			
		||||
              <img :src="item.mediaUrl" style="width: 100px" />
 | 
			
		||||
            </a>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div
 | 
			
		||||
            v-else-if="item.type === MsgType.Video || item.type === 'shortvideo'"
 | 
			
		||||
            style="text-align: center"
 | 
			
		||||
          >
 | 
			
		||||
            <WxVideoPlayer :url="item.mediaUrl" />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div v-else-if="item.type === MsgType.Link" class="avue-card__detail">
 | 
			
		||||
            <el-link type="success" :underline="false" target="_blank" :href="item.url">
 | 
			
		||||
              <div class="avue-card__title"><i class="el-icon-link"></i>{{ item.title }}</div>
 | 
			
		||||
            </el-link>
 | 
			
		||||
            <div class="avue-card__info" style="height: unset">{{ item.description }}</div>
 | 
			
		||||
          </div>
 | 
			
		||||
          <!-- TODO 芋艿:待完善 -->
 | 
			
		||||
          <div v-else-if="item.type === MsgType.Location">
 | 
			
		||||
            <WxLocation
 | 
			
		||||
              :label="item.label"
 | 
			
		||||
              :location-y="item.locationY"
 | 
			
		||||
              :location-x="item.locationX"
 | 
			
		||||
            />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div v-else-if="item.type === MsgType.News" style="width: 300px">
 | 
			
		||||
            <!-- TODO 芋艿:待测试;详情页也存在类似的情况 -->
 | 
			
		||||
            <WxNews :articles="item.articles" />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div v-else-if="item.type === MsgType.Music">
 | 
			
		||||
            <WxMusic
 | 
			
		||||
              :title="item.title"
 | 
			
		||||
              :description="item.description"
 | 
			
		||||
              :thumb-media-url="item.thumbMediaUrl"
 | 
			
		||||
              :music-url="item.musicUrl"
 | 
			
		||||
              :hq-music-url="item.hqMusicUrl"
 | 
			
		||||
            />
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts" name="MsgList">
 | 
			
		||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play'
 | 
			
		||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play'
 | 
			
		||||
import WxNews from '@/views/mp/components/wx-news'
 | 
			
		||||
import WxLocation from '@/views/mp/components/wx-location'
 | 
			
		||||
import WxMusic from '@/views/mp/components/wx-music'
 | 
			
		||||
import MsgEvent from './MsgEvent.vue'
 | 
			
		||||
import { formatDate } from '@/utils/formatTime'
 | 
			
		||||
import { MsgType, User } from '../types'
 | 
			
		||||
import avatarWechat from '@/assets/imgs/wechat.png'
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  list: any[]
 | 
			
		||||
  accountId: number
 | 
			
		||||
  user: User
 | 
			
		||||
}>()
 | 
			
		||||
 | 
			
		||||
enum SendFrom {
 | 
			
		||||
  User = 1,
 | 
			
		||||
  MpBot = 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getAvatar = (sendFrom: SendFrom) =>
 | 
			
		||||
  sendFrom === SendFrom.User ? props.user.avatar : avatarWechat
 | 
			
		||||
 | 
			
		||||
const getNickname = (sendFrom: SendFrom) =>
 | 
			
		||||
  sendFrom === SendFrom.User ? props.user.nickname : '公众号'
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc  */
 | 
			
		||||
@import '../comment.scss';
 | 
			
		||||
@import '../card.scss';
 | 
			
		||||
 | 
			
		||||
.avatar-div {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  width: 80px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -7,123 +7,22 @@
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <div class="msg-div" :id="'msg-div' + nowStr">
 | 
			
		||||
    <div class="msg-div" :id="msgDivId">
 | 
			
		||||
      <!-- 加载更多 -->
 | 
			
		||||
      <div v-loading="loading"></div>
 | 
			
		||||
      <div v-if="!loading">
 | 
			
		||||
        <div class="el-table__empty-block" v-if="loadMore" @click="loadingMore"
 | 
			
		||||
        <div class="el-table__empty-block" v-if="hasMore" @click="loadMore"
 | 
			
		||||
          ><span class="el-table__empty-text">点击加载更多</span></div
 | 
			
		||||
        >
 | 
			
		||||
        <div class="el-table__empty-block" v-if="!loadMore"
 | 
			
		||||
        <div class="el-table__empty-block" v-if="!hasMore"
 | 
			
		||||
          ><span class="el-table__empty-text">没有更多了</span></div
 | 
			
		||||
        >
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <!-- 消息列表 -->
 | 
			
		||||
      <div class="execution" v-for="item in list" :key="item.id">
 | 
			
		||||
        <div class="avue-comment" :class="item.sendFrom === 2 ? 'avue-comment--reverse' : ''">
 | 
			
		||||
          <div class="avatar-div">
 | 
			
		||||
            <img
 | 
			
		||||
              :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>
 | 
			
		||||
          <div class="avue-comment__main">
 | 
			
		||||
            <div class="avue-comment__header">
 | 
			
		||||
              <div class="avue-comment__create_time">{{ formatDate(item.createTime) }}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div
 | 
			
		||||
              class="avue-comment__body"
 | 
			
		||||
              :style="item.sendFrom === 2 ? 'background: #6BED72;' : ''"
 | 
			
		||||
            >
 | 
			
		||||
              <!-- 【事件】区域 -->
 | 
			
		||||
              <div v-if="item.type === MsgType.Event && item.event === 'subscribe'">
 | 
			
		||||
                <el-tag type="success">关注</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'unsubscribe'">
 | 
			
		||||
                <el-tag type="danger">取消关注</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'CLICK'">
 | 
			
		||||
                <el-tag>点击菜单</el-tag>
 | 
			
		||||
                【{{ item.eventKey }}】
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'VIEW'">
 | 
			
		||||
                <el-tag>点击菜单链接</el-tag>
 | 
			
		||||
                【{{ item.eventKey }}】
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'scancode_waitmsg'">
 | 
			
		||||
                <el-tag>扫码结果</el-tag>
 | 
			
		||||
                【{{ item.eventKey }}】
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'scancode_push'">
 | 
			
		||||
                <el-tag>扫码结果</el-tag>
 | 
			
		||||
                【{{ item.eventKey }}】
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'pic_sysphoto'">
 | 
			
		||||
                <el-tag>系统拍照发图</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'pic_photo_or_album'">
 | 
			
		||||
                <el-tag>拍照或者相册</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'pic_weixin'">
 | 
			
		||||
                <el-tag>微信相册</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event && item.event === 'location_select'">
 | 
			
		||||
                <el-tag>选择地理位置</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Event">
 | 
			
		||||
                <el-tag type="danger">未知事件类型</el-tag>
 | 
			
		||||
              </div>
 | 
			
		||||
              <!-- 【消息】区域 -->
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Text">{{ item.content }}</div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Voice">
 | 
			
		||||
                <WxVoicePlayer :url="item.mediaUrl" :content="item.recognition" />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Image">
 | 
			
		||||
                <a target="_blank" :href="item.mediaUrl">
 | 
			
		||||
                  <img :src="item.mediaUrl" style="width: 100px" />
 | 
			
		||||
                </a>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div
 | 
			
		||||
                v-else-if="item.type === MsgType.Video || item.type === 'shortvideo'"
 | 
			
		||||
                style="text-align: center"
 | 
			
		||||
              >
 | 
			
		||||
                <WxVideoPlayer :url="item.mediaUrl" />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Link" class="avue-card__detail">
 | 
			
		||||
                <el-link type="success" :underline="false" target="_blank" :href="item.url">
 | 
			
		||||
                  <div class="avue-card__title"><i class="el-icon-link"></i>{{ item.title }}</div>
 | 
			
		||||
                </el-link>
 | 
			
		||||
                <div class="avue-card__info" style="height: unset">{{ item.description }}</div>
 | 
			
		||||
              </div>
 | 
			
		||||
              <!-- TODO 芋艿:待完善 -->
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Location">
 | 
			
		||||
                <WxLocation
 | 
			
		||||
                  :label="item.label"
 | 
			
		||||
                  :location-y="item.locationY"
 | 
			
		||||
                  :location-x="item.locationX"
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.News" style="width: 300px">
 | 
			
		||||
                <!-- TODO 芋艿:待测试;详情页也存在类似的情况 -->
 | 
			
		||||
                <WxNews :articles="item.articles" />
 | 
			
		||||
              </div>
 | 
			
		||||
              <div v-else-if="item.type === MsgType.Music">
 | 
			
		||||
                <WxMusic
 | 
			
		||||
                  :title="item.title"
 | 
			
		||||
                  :description="item.description"
 | 
			
		||||
                  :thumb-media-url="item.thumbMediaUrl"
 | 
			
		||||
                  :music-url="item.musicUrl"
 | 
			
		||||
                  :hq-music-url="item.hqMusicUrl"
 | 
			
		||||
                />
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <MsgList :list="list" :account-id="accountId" :user="user" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="msg-send" v-loading="sendLoading">
 | 
			
		||||
      <WxReplySelect ref="replySelectRef" v-model="reply" />
 | 
			
		||||
      <el-button type="success" class="send-but" @click="sendMsg">发送(S)</el-button>
 | 
			
		||||
@@ -132,18 +31,12 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts" name="WxMsg">
 | 
			
		||||
import WxReplySelect from '@/views/mp/components/wx-reply'
 | 
			
		||||
import WxVideoPlayer from '@/views/mp/components/wx-video-play'
 | 
			
		||||
import WxVoicePlayer from '@/views/mp/components/wx-voice-play'
 | 
			
		||||
import WxNews from '@/views/mp/components/wx-news'
 | 
			
		||||
import WxLocation from '@/views/mp/components/wx-location'
 | 
			
		||||
import WxMusic from '@/views/mp/components/wx-music'
 | 
			
		||||
import WxReplySelect, { Reply, ReplyType } from '@/views/mp/components/wx-reply'
 | 
			
		||||
import MsgList from './components/MsgList.vue'
 | 
			
		||||
import { getMessagePage, sendMessage } from '@/api/mp/message'
 | 
			
		||||
import { getUser } from '@/api/mp/user'
 | 
			
		||||
import { formatDate } from '@/utils/formatTime'
 | 
			
		||||
import profile from '@/assets/imgs/profile.jpg'
 | 
			
		||||
import wechat from '@/assets/imgs/wechat.png'
 | 
			
		||||
import { MsgType } from './types'
 | 
			
		||||
import { User } from './types'
 | 
			
		||||
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
 | 
			
		||||
@@ -154,49 +47,30 @@ const props = defineProps({
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const nowStr = ref(new Date().getTime()) // 当前的时间戳,用于每次消息加载后,回到原位置;具体见 :id="'msg-div' + nowStr" 处
 | 
			
		||||
const accountId = ref<number>(-1) // 公众号ID,需要通过userId初始化
 | 
			
		||||
const msgDivId = `msg-div-{new Date().getTime()}` // 当前的时间戳,用于每次消息加载后,回到原位置;具体见 :id="'msg-div' + nowStr" 处
 | 
			
		||||
const loading = ref(false) // 消息列表是否正在加载中
 | 
			
		||||
const loadMore = ref(true) // 是否可以加载更多
 | 
			
		||||
const hasMore = ref(true) // 是否可以加载更多
 | 
			
		||||
const list = ref<any[]>([]) // 消息列表
 | 
			
		||||
const queryParams = reactive({
 | 
			
		||||
  pageNo: 1, // 当前页数
 | 
			
		||||
  pageSize: 14, // 每页显示多少条
 | 
			
		||||
  accountId: undefined
 | 
			
		||||
  accountId: accountId
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
interface User {
 | 
			
		||||
  nickname: string
 | 
			
		||||
  avatar: string
 | 
			
		||||
  accountId: number
 | 
			
		||||
}
 | 
			
		||||
// 由于微信不再提供昵称,直接使用“用户”展示
 | 
			
		||||
const user: User = reactive({
 | 
			
		||||
  nickname: '用户',
 | 
			
		||||
  avatar: profile,
 | 
			
		||||
  accountId: 0 // 公众号账号编号
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
interface Mp {
 | 
			
		||||
  nickname: string
 | 
			
		||||
  avatar: string
 | 
			
		||||
}
 | 
			
		||||
const mp: Mp = reactive({
 | 
			
		||||
  nickname: '公众号',
 | 
			
		||||
  avatar: wechat
 | 
			
		||||
  accountId: accountId // 公众号账号编号
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// ========= 消息发送 =========
 | 
			
		||||
const sendLoading = ref(false) // 发送消息是否加载中
 | 
			
		||||
interface Reply {
 | 
			
		||||
  type: MsgType
 | 
			
		||||
  accountId: number | null
 | 
			
		||||
  articles: any[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 微信发送消息
 | 
			
		||||
const reply = ref<Reply>({
 | 
			
		||||
  type: MsgType.Text,
 | 
			
		||||
  accountId: null,
 | 
			
		||||
  type: ReplyType.Text,
 | 
			
		||||
  accountId: -1,
 | 
			
		||||
  articles: []
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@@ -207,8 +81,7 @@ onMounted(async () => {
 | 
			
		||||
  const data = await getUser(props.userId)
 | 
			
		||||
  user.nickname = data.nickname?.length > 0 ? data.nickname : user.nickname
 | 
			
		||||
  user.avatar = user.avatar?.length > 0 ? data.avatar : user.avatar
 | 
			
		||||
  user.accountId = data.accountId
 | 
			
		||||
  queryParams.accountId = data.accountId
 | 
			
		||||
  accountId.value = data.accountId
 | 
			
		||||
  reply.value.accountId = data.accountId
 | 
			
		||||
 | 
			
		||||
  refreshChange()
 | 
			
		||||
@@ -220,7 +93,11 @@ const sendMsg = async () => {
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  // 公众号限制:客服消息,公众号只允许发送一条
 | 
			
		||||
  if (reply.value.type === MsgType.News && reply.value.articles.length > 1) {
 | 
			
		||||
  if (
 | 
			
		||||
    reply.value.type === ReplyType.News &&
 | 
			
		||||
    reply.value.articles &&
 | 
			
		||||
    reply.value.articles.length > 1
 | 
			
		||||
  ) {
 | 
			
		||||
    reply.value.articles = [reply.value.articles[0]]
 | 
			
		||||
    message.success('图文消息条数限制在 1 条以内,已默认发送第一条')
 | 
			
		||||
  }
 | 
			
		||||
@@ -229,18 +106,18 @@ const sendMsg = async () => {
 | 
			
		||||
  sendLoading.value = false
 | 
			
		||||
 | 
			
		||||
  list.value = [...list.value, ...[data]]
 | 
			
		||||
  scrollToBottom()
 | 
			
		||||
  await scrollToBottom()
 | 
			
		||||
 | 
			
		||||
  // 发送后清空数据
 | 
			
		||||
  replySelectRef.value?.clear()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const loadingMore = () => {
 | 
			
		||||
const loadMore = () => {
 | 
			
		||||
  queryParams.pageNo++
 | 
			
		||||
  getPage(queryParams, null)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getPage = async (page, params) => {
 | 
			
		||||
const getPage = async (page: any, params: any) => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  let dataTemp = await getMessagePage(
 | 
			
		||||
    Object.assign(
 | 
			
		||||
@@ -254,7 +131,7 @@ const getPage = async (page, params) => {
 | 
			
		||||
    )
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const msgDiv = document.getElementById('msg-div' + nowStr.value)
 | 
			
		||||
  const msgDiv = document.getElementById(msgDivId)
 | 
			
		||||
  let scrollHeight = 0
 | 
			
		||||
  if (msgDiv) {
 | 
			
		||||
    scrollHeight = msgDiv.scrollHeight
 | 
			
		||||
@@ -264,24 +141,23 @@ const getPage = async (page, params) => {
 | 
			
		||||
  list.value = [...data, ...list.value]
 | 
			
		||||
  loading.value = false
 | 
			
		||||
  if (data.length < queryParams.pageSize || data.length === 0) {
 | 
			
		||||
    loadMore.value = false
 | 
			
		||||
    hasMore.value = false
 | 
			
		||||
  }
 | 
			
		||||
  queryParams.pageNo = page.pageNo
 | 
			
		||||
  queryParams.pageSize = page.pageSize
 | 
			
		||||
  // 滚动到原来的位置
 | 
			
		||||
  if (queryParams.pageNo === 1) {
 | 
			
		||||
    // 定位到消息底部
 | 
			
		||||
    scrollToBottom()
 | 
			
		||||
    await 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
 | 
			
		||||
        }
 | 
			
		||||
    await nextTick()
 | 
			
		||||
    if (scrollHeight !== 0) {
 | 
			
		||||
      let div = document.getElementById(msgDivId)
 | 
			
		||||
      if (div && msgDiv) {
 | 
			
		||||
        msgDiv.scrollTop = div.scrollHeight - scrollHeight - 100
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -290,26 +166,16 @@ const refreshChange = () => {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 定位到消息底部 */
 | 
			
		||||
const scrollToBottom = () => {
 | 
			
		||||
  nextTick(() => {
 | 
			
		||||
    let div = document.getElementById('msg-div' + nowStr.value)
 | 
			
		||||
    if (div) {
 | 
			
		||||
      div.scrollTop = div.scrollHeight
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
const scrollToBottom = async () => {
 | 
			
		||||
  await nextTick()
 | 
			
		||||
  let div = document.getElementById(msgDivId)
 | 
			
		||||
  if (div) {
 | 
			
		||||
    div.scrollTop = div.scrollHeight
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
/* 因为 joolun 实现依赖 avue 组件,该页面使用了 comment.scss、card.scc  */
 | 
			
		||||
@import './comment.scss';
 | 
			
		||||
@import './card.scss';
 | 
			
		||||
 | 
			
		||||
.msg-main {
 | 
			
		||||
  margin-top: -30px;
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.msg-div {
 | 
			
		||||
  height: 50vh;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
@@ -322,11 +188,6 @@ const scrollToBottom = () => {
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.avatar-div {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  width: 80px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.send-but {
 | 
			
		||||
  float: right;
 | 
			
		||||
  margin-top: 8px;
 | 
			
		||||
 
 | 
			
		||||
@@ -9,3 +9,9 @@ export enum MsgType {
 | 
			
		||||
  Music = 'music',
 | 
			
		||||
  News = 'news'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface User {
 | 
			
		||||
  nickname: string
 | 
			
		||||
  avatar: string
 | 
			
		||||
  accountId: number
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user