| | |
| | | <template> |
| | | <div class="service-box flex flex-col" :class="homesStore.kefu_url ? '' : 'pb-40'"> |
| | | <div> |
| | | <van-nav-bar ref="navEl" :title="$t('onLineService') + ' Jason David'" left-arrow @click-left="onClickLeft" |
| | | fixed /> |
| | | <van-nav-bar ref="navEl" :title="$t('onLineService')" left-arrow @click-left="onClickLeft" fixed /> |
| | | <div class="px-3.5 py-5" v-if="state == 0"> |
| | | <div class="white">{{ $t('OrdersWill') }} <span style="color: #1194F7">{{ dayjs.duration(remainingTime, |
| | | 'seconds').format('mm:ss') }}</span> {{ |
| | | $t('afterCancel') |
| | | }}</div> |
| | | $t('afterCancel') |
| | | }}</div> |
| | | <div class="mt-3"> |
| | | <span class="mr-1" style="color: #8A919E">{{ $t('lumpSum') }}</span> |
| | | <span class="white">{{ payInfo.currency }} {{ payInfo.amount }}</span> |
| | |
| | | {{ $t('historyMessage') }} |
| | | </div> |
| | | <ul class="flex flex-col pt-3"> |
| | | <li v-for="(item, index) in list" :key="index" class="flex flex-col my-3"> |
| | | <li v-for="(item, index) in list" :key="item.id" class="flex flex-col my-3"> |
| | | <!-- <p class="text-center py-2 text-grey text-30" v-if="showTime(index)">{{ |
| | | item.createtime && |
| | | item.createtime.split(' ')[0] |
| | |
| | | <template v-if="item.delete_status != -1"> |
| | | <p class="text-center pb-3 text-grey text-30">{{ |
| | | item.createtime |
| | | }}</p> |
| | | }}</p> |
| | | <div class="flex" :class="item.send_receive === 'send' ? 'justify-end' : ''"> |
| | | <template v-if="item.send_receive === 'receive'"> |
| | | <img src="@/assets/image/service/responser.png" class="w-20 h-20 mr-5" /> |
| | |
| | | import { Uploader, showImagePreview } from 'vant' |
| | | import { _getMsg, _getUnreadMsg, _sendMsg } from '@/service/im.api' |
| | | import { _uploadImage } from '@/service/upload.api' |
| | | import { ref, onMounted, onUnmounted, onBeforeMount, nextTick } from "vue"; |
| | | import { ref, onMounted, onUnmounted, onBeforeMount } from "vue"; |
| | | import { useI18n } from "vue-i18n"; |
| | | import { throttle } from '@/utils/index' |
| | | import { closeToast, showToast, showLoadingToast } from "vant"; |
| | |
| | | let orderNo = "" |
| | | let partyId = "" |
| | | // onMounted(() => { |
| | | // // 美洽客服 |
| | | // // const _ll="&id="+_id.value+"&name="+_name.value |
| | | // const _ll = "" |
| | | // // console.log(_ll) |
| | | // const _uull = 'https://cdn.chat20gm.cfd/chat_online/index?channelId=1958101585091772416' + _ll; |
| | | // // window.location.href=_uull |
| | | // // 美洽客服 |
| | | // // const _ll="&id="+_id.value+"&name="+_name.value |
| | | // // const _ll="" |
| | | |
| | | // // 绑定滚动事件监听器,使用 nextTick 确保 DOM 渲染完成 |
| | | // nextTick(() => { |
| | | // if (boxScrollEl.value) { |
| | | // boxScrollEl.value.addEventListener('scroll', handleScroll) |
| | | // // 初始化时检查是否在底部 |
| | | // setTimeout(() => { |
| | | // handleScroll() |
| | | // }, 100) |
| | | // } |
| | | // }) |
| | | // // const _uull='https://cdn.chat20gm.cfd/chat_online/index?channelId=1958101585091772416'+_ll; |
| | | // // window.location.href=_uull |
| | | // }) |
| | | |
| | | onMounted(() => { |
| | | orderNo = "" |
| | | partyId = "" |
| | |
| | | const fetchList = async (message_id = '') => { // 获取消息列表 |
| | | console.log("orderNo = " + orderNo); |
| | | console.log("partyId = " + partyId); |
| | | // 保存更新前的滚动位置和滚动高度 |
| | | let previousScrollTop = 0 |
| | | let previousScrollHeight = 0 |
| | | if (boxScrollEl.value && !message_id) { |
| | | previousScrollTop = boxScrollEl.value.scrollTop |
| | | previousScrollHeight = boxScrollEl.value.scrollHeight |
| | | } |
| | | |
| | | _getMsg({ message_id }, orderNo, partyId).then(data => { // |
| | | if (!lastMsgId.value) { |
| | | lastMsgId.value = data.length && data[data.length - 1]['id'] |
| | |
| | | |
| | | } |
| | | |
| | | // 使用 nextTick 确保 DOM 更新完成后再操作滚动 |
| | | setTimeout(() => { |
| | | if (boxScrollEl.value) { |
| | | if (message_id) { |
| | | // 加载更多时,保持滚动位置(通过计算新增内容的高度) |
| | | const newScrollHeight = boxScrollEl.value.scrollHeight |
| | | const heightDiff = newScrollHeight - previousScrollHeight |
| | | boxScrollEl.value.scrollTop = previousScrollTop + heightDiff |
| | | } else { |
| | | // 轮询新消息时,只有用户在底部才滚动到底部 |
| | | if (isScrollBottom.value) { |
| | | boxScrollEl.value.scrollTop = boxScrollEl.value.scrollHeight - boxScrollEl.value.offsetHeight |
| | | } else { |
| | | // 如果用户不在底部,保持当前滚动位置(通过计算新增内容的高度) |
| | | const newScrollHeight = boxScrollEl.value.scrollHeight |
| | | const heightDiff = newScrollHeight - previousScrollHeight |
| | | boxScrollEl.value.scrollTop = previousScrollTop + heightDiff |
| | | } |
| | | } |
| | | currentScrollTop.value = boxScrollEl.value.scrollTop |
| | | } |
| | | }, 0) |
| | | |
| | | if (isScrollBottom.value) { |
| | | boxScrollEl.value.scrollTop = boxScrollEl.value.scrollHeight - boxScrollEl.value.offsetHeight |
| | | } |
| | | currentScrollTop.value = boxScrollEl.value.scrollTop; |
| | | if (data.length < 10) { |
| | | finished.value = true |
| | | } |
| | |
| | | |
| | | const handleScroll = () => { |
| | | if (boxScrollEl.value) { |
| | | const { scrollTop, scrollHeight, offsetHeight } = boxScrollEl.value |
| | | // 判断是否在底部(允许5px的误差) |
| | | const isAtBottom = scrollHeight - scrollTop - offsetHeight <= 5 |
| | | isScrollBottom.value = isAtBottom |
| | | currentScrollTop.value = scrollTop |
| | | if (boxScrollEl.value.scrollTop === currentScrollTop.value) { |
| | | isScrollBottom.value = true |
| | | } else { |
| | | isScrollBottom.value = false |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | message.value = '' |
| | | isScrollBottom.value = true |
| | | // document.getElementById('bottom').click() |
| | | await fetchList() |
| | | // await fetchList() |
| | | }) |
| | | } |
| | | const getCountdown = () => { |
| | |
| | | |
| | | onUnmounted(() => { |
| | | clearIntervalTimer() |
| | | // 移除滚动事件监听器 |
| | | if (boxScrollEl.value) { |
| | | boxScrollEl.value.removeEventListener('scroll', handleScroll) |
| | | } |
| | | }) |
| | | |
| | | </script> |