| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- <template>
- <Theme>
- <view class="wrap">
- <Navbar title="系统" fixed border />
- <view
- class="content"
- :style="{
- '--height': bottomHeight + 'px',
- '--keyboardHeight': keyboardHeight + 'px',
- '--contHeight': contHeight + 'px',
- }"
- >
- <scroll-view
- class="chat_content"
- scroll-anchoring
- :scroll-y="true"
- :scroll-top="scrollTop"
- :lower-threshold="lowerThreshold"
- :refresher-triggered="refresherTriggered"
- :refresher-enabled="refresherEnabled"
- @refresherrefresh="refresherrefresh"
- refresher-default-style="none"
- refresher-background="var(--bg)"
- @scroll="onScroll"
- @scrolltolower="onScrollLower"
- >
- <view class="refresher" v-if="refresherTriggered">
- <up-loadmore :status="'loading'" :loadingText="$t('正在加载')" />
- </view>
- <view class="scroll" id="scroll_items">
- <Message :list="msgList" />
- </view>
- </scroll-view>
- </view>
- <view
- class="new_count"
- :style="{ bottom: bottomHeight + 5 + 'px' }"
- v-show="newMessageCount > 0"
- @click="getContHeight"
- >
- <text>{{ newMessageCount }} {{ $t("条新消息") }}</text>
- </view>
- <footer-input
- v-model="message"
- @heights="getFooterHeight"
- @submit="send"
- @linechange="inputHeightChange"
- @imageUp="imageUp"
- ref="footerInputRef"
- />
- </view>
- </Theme>
- </template>
- <script setup>
- import { onUnload, onLoad } from "@dcloudio/uni-app";
- import { ref, nextTick, onMounted, reactive, watch, provide } from "vue";
- import Navbar from "@/components/navbar";
- import footerInput from "@/components/footer_input";
- import Message from "@/components/message";
- import { query, systemInfo, useGlobal } from "@/utils";
- import { RONGIMCALL_HISTORY } from "@/api";
- import { useSocketStore, useMessageStore } from "@/store";
- import { storeToRefs } from "pinia";
- const useSocket = useSocketStore();
- const useMessage = useMessageStore();
- const { messageMap } = storeToRefs(useMessage);
- const bottomHeight = ref(0);
- const scrollTop = ref(0);
- const keyboardHeight = ref(0);
- const contHeight = ref(0);
- const newHeight = ref(0);
- const message = ref("");
- const footerInputRef = ref(null);
- const refresherTriggered = ref(false);
- const refresherEnabled = ref(true);
- const msgList = ref([]);
- const page = ref(1);
- const pagesize = ref(10);
- const total = ref(0);
- const channel = ref("");
- const firstMsg = ref({});
- const lowerThreshold = ref(0);
- const distanceFromBottom = ref(0);
- const newMessageCount = ref(0);
- const bottomSafeDistanceHeight = ref(0);
- watch(
- () => messageMap.value,
- (newVal, oldVal) => {
- const info = newVal[channel.value];
- if (channel.value && info) {
- msgList.value = info.messageList;
- newMessageCount.value =
- distanceFromBottom.value > lowerThreshold.value ? info.unreadCount : 0;
- }
- },
- { deep: true, immediate: true }
- );
- provide("onQuestionSend", send);
- function onScroll(e) {
- const { detail } = e;
- const distanceForBottom =
- detail.scrollHeight - detail.scrollTop - contHeight.value;
- distanceFromBottom.value = distanceForBottom > 0 ? distanceForBottom : 0;
- if (distanceFromBottom.value <= lowerThreshold.value) {
- useMessage.updateUnreadCount(channel.value, -1);
- }
- }
- function onScrollLower() {
- useMessage.updateUnreadCount(channel.value, -1);
- }
- const refresherrefresh = () => {
- refresherTriggered.value = true;
- if (total.value <= page.value * pagesize.value) {
- nextTick(() => {
- refresherTriggered.value = false;
- });
- return;
- }
- page.value += 1;
- nextTick(() => {
- getHistory(true);
- });
- };
- const getCont = () => {
- nextTick(() => {
- const { windowHeight, statusBarHeight } = systemInfo();
- contHeight.value = windowHeight - statusBarHeight - 44;
- });
- };
- const getContHeight = (isLoading) => {
- try {
- nextTick(async () => {
- const res = await query("#scroll_items");
- if (isLoading) {
- scrollTop.value = res.height - newHeight.value - 44;
- } else {
- scrollTop.value =
- res.height - bottomHeight.value - keyboardHeight.value - 44;
- const isIOS = uni.getSystemInfoSync().platform === "ios";
- if (isIOS) {
- scrollTop.value += bottomSafeDistanceHeight.value * 2;
- }
- }
- newHeight.value = res.height;
- });
- } catch (error) {}
- };
- const getFooterHeight = (res) => {
- nextTick(() => {
- bottomHeight.value = res.height || 0;
- keyboardHeight.value = res.keyboardHeight || 0;
- bottomSafeDistanceHeight.value = res.bottomSafeDistance || 0;
- getContHeight();
- });
- };
- function send(text) {
- sendMessage({ type: "text", text: text || message.value });
- }
- const imageUp = (url) => {
- sendMessage({ type: "image", url: url });
- };
- const sendMessage = (msgObject) => {
- let messageData = reactive({
- type: "notice",
- msg: JSON.stringify(msgObject),
- send: 1,
- loading: true,
- status: -1,
- });
- useMessage.updateMessageList(channel.value, messageData, "push");
- getContHeight();
- useMessage
- .sendMessage(msgObject, "notice")
- .then((data) => {
- messageData.loading = false;
- messageData.status = 1;
- for (let key in data) {
- if (key != "msg") {
- messageData[key] = data[key];
- }
- }
- useMessage.updateGlobalMapLasttime(`noticeChannel`, data.indate);
- })
- .catch(() => {
- messageData.loading = false;
- messageData.status = 0;
- });
- nextTick(() => {
- footerInputRef.value && footerInputRef.value.clear();
- });
- };
- const inputHeightChange = () => {
- // console.log("输入框高度发送变化");
- };
- const open = () => {
- useMessage
- .openChannel({
- type: "notice",
- socket_id: useSocket.socketId,
- })
- .then(async (res) => {
- firstMsg.value = res.data;
- channel.value = res.data.auth.channel;
- await getHistory();
- await clearCount();
- });
- };
- const getHistory = async (isLoading = false) => {
- try {
- let para = {
- page: page.value,
- pagesize: pagesize.value,
- type: "notice",
- };
- const res = await RONGIMCALL_HISTORY(para);
- const lists = res.data.lists;
- for (let i = 0; i < lists.length; i++) {
- const msgInfo = {
- ...lists[i],
- msg: JSON.parse(lists[i].msg),
- };
- useMessage.updateMessageList(channel.value, msgInfo, "unshift");
- }
- if (lists.length > 0 && page.value == 1) {
- let result = lists[0];
- let lastTime = result
- ? result.indate
- : (Date.now() / 1000).toFixed(0) - 0;
- useMessage.updateGlobalMapLasttime(`noticeChannel`, lastTime);
- }
- total.value = res.data.total;
- !total.value &&
- useMessage.updateMessageList(channel.value, firstMsg.value, "unshift");
- if (total.value <= page.value * pagesize.value) {
- nextTick(() => {
- refresherEnabled.value = false;
- });
- }
- nextTick(() => {
- getContHeight(isLoading);
- refresherTriggered.value = false;
- });
- } catch (error) {}
- };
- const clearCount = () => {
- useMessage.updateUnreadCount(channel.value, -1);
- useMessage.updateGlobalMapUnreadCount("noticeChannel", -1);
- };
- const openAndGetHistory = async () => {
- try {
- await open();
- await getCont();
- await getContHeight();
- } catch (error) {
- console.error(error);
- }
- };
- onMounted(() => {
- nextTick(() => {
- openAndGetHistory();
- });
- });
- onUnload(() => {
- useSocket.send({
- event: "pusher:unsubscribe",
- data: { channel: channel.value },
- });
- clearCount();
- });
- </script>
- <style lang="less" scoped>
- @import url("@/style.less");
- .wrap {
- background: var(--bg);
- height: 100vh;
- padding-bottom: constant(safe-area-inset-bottom);
- padding-bottom: env(safe-area-inset-bottom);
- .content {
- width: 100%;
- // padding: 0 30rpx;
- .chat_content {
- height: calc(var(--contHeight) - var(--keyboardHeight) - var(--height));
- .scroll {
- overflow: hidden;
- }
- }
- }
- .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>
|