| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- <template>
- <Theme>
- <view class="user-chat__wrap">
- <!-- navbar -->
- <view class="user-chat__navbar">
- <Navbar fixed leftIconColor="var(--black)" id="chat_nav" leftShow>
- <template #center>
- <view class="nav_title">
- <trans _t="网购助手" />
- </view>
- </template>
- </Navbar>
- </view>
- <!-- list box -->
- <view class="message_body">
- <MessageList
- ref="messageListRef"
- :lower-threshold="lowerThreshold"
- :height="listHeight ? `${listHeight - tabbarHeight}px` : ''"
- :listHeight="listHeight ? listHeight : 0"
- :tabbarHeight="tabbarHeight"
- :data-list="dataList"
- :loading="isLoading"
- @on-scroll="handleScroll"
- @on-scroll-top="handleScrollTop"
- @on-scroll-bottom="handleScrollBottom"
- ></MessageList>
- </view>
- <view
- class="new_count"
- :style="{ bottom: footerHeightInfo.height + tabbarHeight + 5 + 'px' }"
- v-show="newMessageCount > 0"
- @click="messageListRef && messageListRef.computeScrollHeight()"
- >
- <text>{{ newMessageCount }} {{ $t("条新消息") }}</text>
- </view>
- <footer-input
- ref="footerInputRef"
- v-model="message"
- :bottomHeight="tabbarHeight"
- @heights="getFooterHeight"
- @submit="onMessageSend"
- @imageUp="imageUp"
- @linechange="inputHeightChange"
- />
- <Tabbar page="chat" @getTabbarHeight="getTabbarHeight" />
- </view>
- </Theme>
- </template>
- <script setup>
- import { onUnload, onLoad } from "@dcloudio/uni-app";
- import {
- ref,
- reactive,
- getCurrentInstance,
- nextTick,
- computed,
- provide,
- } from "vue";
- import { storeToRefs } from "pinia";
- import { t } from "@/locale";
- import { getUuid } from "@/utils";
- import Navbar from "@/components/navbar";
- import Tabbar from "@/components/tabbar";
- import MessageList from "./modules/messageList.vue";
- import footerInput from "@/components/footer_input";
- import { useSocketStore, useUserStore, useTabbarStore } from "@/store";
- import useListHeight from "./hooks/useListHeight";
- import useMessageData from "./hooks/useMessageData";
- const useScoket = useSocketStore();
- const useUser = useUserStore();
- const useTabbar = useTabbarStore();
- const { getuserInfo } = storeToRefs(useUser);
- const { navbarNodeInfo, footerHeightInfo, listHeight } = useListHeight();
- const {
- useMessage,
- channel,
- channelData,
- dataList,
- newMessageCount,
- lowerThreshold,
- distanceFromBottom,
- isLoading,
- isOpenning,
- fetchHistoryMessageList,
- openService,
- } = useMessageData();
- uni.$on("on-service-open", () => {
- messageListRef.value && messageListRef.value.updateInitState();
- openService();
- });
- uni.hideTabBar();
- provide("channel", channel);
- provide("channelData", channelData);
- const messageListRef = ref(null);
- const footerInputRef = ref(null);
- const footerInputLineCount = ref(1);
- const message = ref("");
- const tabbarHeight = ref(0);
- onLoad(() => {
- useMessage.updateUnreadCount(channel.value, -1);
- useMessage.updateGlobalMapUnreadCount("serviceChannel", -1);
- });
- onUnload(() => {
- useScoket.send({
- event: "pusher:unsubscribe",
- data: { channel: channel.value },
- });
- useMessage.updateUnreadCount(channel.value, -1);
- useMessage.updateGlobalMapUnreadCount("serviceChannel", -1);
- });
- function handleScroll(e) {
- const { detail } = e;
- const distanceForBottom =
- detail.scrollHeight - detail.scrollTop - listHeight.value;
- distanceFromBottom.value = distanceForBottom > 0 ? distanceForBottom : 0;
- if (distanceFromBottom.value <= lowerThreshold.value) {
- useMessage.updateUnreadCount(channel.value, -1);
- }
- }
- // 滚动顶部回调
- function handleScrollTop() {
- fetchHistoryMessageList();
- }
- function handleScrollBottom() {
- useMessage.updateUnreadCount(channel.value, -1);
- }
- // 图片
- const imageUp = (url) => {
- const msg = {
- type: "image",
- url: url,
- };
- sendMessage(msg, () => {
- nextTick(() => {
- messageListRef.value && messageListRef.value.computeScrollHeight();
- });
- });
- };
- // 消息发送:发送按钮回调(手机键盘右下角确认按钮回调&电脑键盘回车)
- function onMessageSend() {
- if (!message.value) return;
- const msg = {
- type: "text",
- text: message.value,
- };
- sendMessage(msg);
- }
- // 消息发送: 快捷问题
- function onQuestionSend(messageText) {
- if (!(channelData.value && channelData.value.openInfo.status == 1)) return;
- if (!messageText) return;
- const msg = {
- type: "text",
- text: messageText,
- };
- sendMessage(msg, () => {
- messageListRef.value && messageListRef.value.computeScrollHeight();
- });
- }
- provide("onQuestionSend", onQuestionSend);
- function sendMessage(msg, callback) {
- const messageData = reactive({
- loading: true,
- status: -1,
- send: 1,
- msg: msg,
- });
- useMessage.updateMessageList(channel.value, messageData, "push");
- useMessage
- .sendMessage(msg)
- .then((data) => {
- messageData.loading = false;
- messageData.status = 1;
- for (let key in data) {
- if (key != "msg") {
- messageData[key] = data[key];
- }
- }
- useMessage.updateGlobalMapLasttime(`serviceChannel`, data.indate);
- })
- .catch(() => {
- messageData.loading = false;
- messageData.status = 0;
- });
- callback && callback();
- /* if (footerInputLineCount.value == 1) {
- messageListRef.value && messageListRef.value.computeScrollHeight();
- } */
- footerInputRef.value && footerInputRef.value.clear();
- }
- // 底部高度
- const getFooterHeight = (res) => {
- footerHeightInfo.value = {
- ...res,
- };
- };
- const getTabbarHeight = (height) => {
- tabbarHeight.value = height;
- };
- // 输入框高度发送变化
- const inputHeightChange = (res) => {
- footerInputLineCount.value = res.detail.lineCount;
- };
- const leftClick = () => {
- uni.switchTab({ url: "/pages/index/index" });
- useTabbar.getPageCur("index");
- };
- </script>
- <style scoped lang="less">
- .user-chat__wrap {
- display: flex;
- flex-direction: column;
- height: 100vh;
- background-color: #fff;
- padding-bottom: constant(safe-area-inset-bottom);
- padding-bottom: env(safe-area-inset-bottom);
- }
- .nav_title {
- color: var(--black);
- font-size: 32rpx;
- font-weight: 500;
- }
- .bg_logo {
- position: absolute;
- // .size(128rpx);
- color: var(--inputBg);
- opacity: 0.06;
- top: 0;
- left: 50%;
- font-weight: bold;
- transform: translateX(-50%);
- line-height: 88rpx;
- text-transform: uppercase;
- font-family: "HarmonyOS_Sans";
- text-wrap: nowrap;
- }
- .message_body {
- width: 100%;
- height: auto;
- }
- .new_count {
- position: fixed;
- bottom: 0;
- right: 16rpx;
- z-index: 20;
- height: 52rpx;
- padding: 0 20rpx;
- border-radius: 26rpx;
- background-color: rgba(0, 0, 0, 1);
- color: #fff;
- font-size: 24rpx;
- line-height: 52rpx;
- }
- </style>
- <style lang="less">
- .message__input :deep(.uni-textarea-wrapper .uni-textarea-placeholder),
- .message__input :deep(.uni-textarea-wrapper .uni-textarea-line),
- .message__input :deep(.uni-textarea-wrapper .uni-textarea-compute),
- .message__input :deep(.uni-textarea-wrapper .uni-textarea-textarea) {
- top: 50%;
- transform: translateY(-50%);
- }
- </style>
|