123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- <template>
- <!-- #ifdef MP-WEIXIN -->
- <tuicallkit
- ref="TUICallKit"
- ></tuicallkit>
- <!-- #endif -->
- <view class="TUIChat" v-if="conversationType === 'chat'">
- <view
- class="more-btn"
- v-if="conversation?.type === 'GROUP'"
- @click="handleGetProfile"
- >
- 更多</view
- >
- <view class="TUIChat-container">
- <scroll-view
- class="TUIChat-main"
- scroll-y="true"
- :scroll-with-animation="true"
- :refresher-triggered="triggered"
- :refresher-enabled="true"
- @refresherrefresh="handleRefresher"
- :scroll-top="scrollTop"
- >
- <view
- class="TUI-message-list"
- @touchstart="handleTouchStart"
- @click="dialogID = ''"
- >
- <view class="loading-text" v-if="isCompleted">没有更多</view>
-
- <view
-
- v-for="(item, index) in messages"
- :key="item.ID"
- :id="'view' + item.ID"
- >
- <view class="time-container" v-if="item.showTime">{{
- caculateTimeago(item.time * 1000)
- }}</view>
- <MessageTip
- v-if="!item.isRevoked && item.type === types.MSG_GRP_TIP"
- :data="handleTipMessageShowContext(item)"
- />
- <!-- <MessageTip v-if="item.type === types.MSG_GRP_SYS_NOTICE" /> -->
- <MessageBubble
- v-if="!item.isRevoked && item.type !== types.MSG_GRP_TIP"
- :data="item"
- >
- <Message-Operate
- v-if="dialogID === item.ID"
- :data="item"
- class="dialog dialog-item"
- :style="{
- top: dialogPosition.top + 'px',
- right: dialogPosition.right + 'px',
- left: dialogPosition.left + 'px',
- }"
- >
- </Message-Operate>
- <MessageText
- :id="item.flow + '-' + item.ID"
- v-if="item.type === types.MSG_TEXT"
- :data="handleTextMessageShowContext(item)"
- :messageData="item"
- @longpress="handleItem($event, item)"
- ></MessageText>
- <MessageImage
- :id="item.flow + '-' + item.ID"
- v-if="item.type === types.MSG_IMAGE"
- :data="handleImageMessageShowContext(item)"
- :messageData="item"
- @longpress="handleItem($event, item)"
- ></MessageImage>
- <MessageVideo
- :id="item.flow + '-' + item.ID"
- v-if="item.type === types.MSG_VIDEO"
- :data="handleVideoMessageShowContext(item)"
- :messageData="item"
- @longpress="handleItem($event, item)"
- />
- <MessageAudio
- :id="item.flow + '-' + item.ID"
- v-if="item.type === types.MSG_AUDIO"
- :data="handleAudioMessageShowContext(item)"
- :messageData="item"
- @longpress="handleItem($event, item)"
- />
- <MessageFace
- :id="item.flow + '-' + item.ID"
- v-if="item.type === types.MSG_FACE"
- :data="handleFaceMessageShowContext(item)"
- :messageData="item"
- @longpress="handleItem($event, item)"
- />
- <MessageCustom
- :id="item.flow + '-' + item.ID"
- v-if="item.type === types.MSG_CUSTOM"
- :data="handleCustomMessageShowContext(item)"
- :messageData="item"
- @tap="handleCustomerItem($event, item)"
- @longpress="handleItem($event, item)"
- />
-
- </MessageBubble>
- <MessageRevoked
- v-if="item.isRevoked"
- :data="item"
- @edit="handleEdit(item)"
- />
- </view>
- </view>
- </scroll-view>
- </view>
- <TUIChatInput v-if="imType==1||imType==2" :text="text" :conversationData="conversation"></TUIChatInput>
- </view>
- <view class="TUIChat" v-if="conversationType === 'system'">
- <MessageSystem :data="messages" :types="types" />
- </view>
- </template>
- <script lang="ts">
-
- import {finishOrder} from '@/api/inquiryOrder.js'
- import {
- defineComponent,
- reactive,
- toRefs,
- computed,
- nextTick,
- watch,
- onMounted,
- shallowRef
- } from "vue";
- import {
- onReady,
- onLoad,
- onNavigationBarButtonTap,
- onUnload,
- } from "@dcloudio/uni-app";
- // 消息元素组件
- import MessageBubble from "./components/message-elements/message-bubble.vue";
- import MessageText from "./components/message-elements/message-text.vue";
- import MessageImage from "./components/message-elements/message-image.vue";
- import MessageOperate from "./components/message-elements/message-operate.vue";
- import MessageVideo from "./components/message-elements/message-video.vue";
- import MessageAudio from "./components/message-elements/message-audio.vue";
- import MessageFace from "./components/message-elements/message-face.vue";
- import MessageCustom from "./components/message-elements/message-custom.vue";
- import MessageTip from "./components/message-elements/message-tip.vue";
- import MessageRevoked from "./components/message-elements/message-revoked.vue";
- import MessageSystem from "./components/message-elements/message-system.vue";
- // 底部消息发送组件
- import TUIChatInput from "./components/message-input";
- import store from "@/store";
- import {
- handleAvatar,
- handleTextMessageShowContext,
- handleImageMessageShowContext,
- handleVideoMessageShowContext,
- handleAudioMessageShowContext,
- handleFileMessageShowContext,
- handleFaceMessageShowContext,
- handleLocationMessageShowContext,
- handleMergerMessageShowContext,
- handleTipMessageShowContext,
- handleCustomMessageShowContext,
- } from "../../utils/untis";
- import { caculateTimeago } from "../../utils/date";
- import Vuex from "vuex";
- import { TUIChatServer } from "../../TUICore/server";
- export default defineComponent({
- name: "TUIChat",
- components: {
- MessageText,
- MessageImage,
- MessageVideo,
- MessageAudio,
- MessageFace,
- MessageCustom,
- MessageBubble,
- MessageTip,
- MessageRevoked,
- MessageSystem,
- TUIChatInput,
- MessageOperate,
- },
- setup(props) {
- const timStore = store.state.timStore;
- uni.$TUIKit.TUIChatServer = new TUIChatServer();
- const TUICallKit = shallowRef(null);
- const TUIServer = uni.$TUIKit.TUIChatServer;
- const left: number | null = 0;
- const right: number | null = 0;
- const defaultDialogPosition = {
- top: -70,
- left,
- right,
- };
- const data = reactive({
- messageList: computed(() => timStore.messageList),
- conversation: computed(() => timStore.conversation),
- triggered: false,
- scrollTop: 999,
- text: "",
- types: uni.$TIM.TYPES,
- currentMessage: {},
- dialogID: "",
- forwardStatus: false,
- imageFlag: false,
- isCompleted: false,
- oldMessageTime: 0,
- dialogPosition: defaultDialogPosition,
- imType:computed(() => timStore.imType),
- orderId:computed(() => timStore.orderId)
- });
- // 判断当前会话类型:无/系统会话/正常C2C、群聊
- const conversationType = computed(() => {
- const conversation: any = data.conversation;
- if (!conversation?.conversationID) {
- return "";
- }
- if (conversation?.type === uni.$TIM.TYPES.CONV_SYSTEM) {
- return "system";
- }
- return "chat";
- });
- // 不展示已删除消息
- const messages = computed(() => {
- if (data.messageList.length > 0) {
- data.oldMessageTime = data.messageList[0].time;
-
- return data.messageList.filter((item: any) => {
- return !item.isDeleted;
- });
- }
- });
- // 获取页面参数
- onLoad((options) => {
- uni.setNavigationBarTitle({
- title: options && options.conversationName,
- });
- if(store.state.timStore.imType==1){
-
- }
- else if(store.state.timStore.imType==2){
-
- }
- });
- onUnload(() => {
- // #ifdef MP-WEIXIN
- //回收 TUICallKit
- uni.$TUICallKit.value !== null && uni.$TUICallKit.value.destroyed();
- // #endif
- TUIServer.destroyed();
- });
- // 监听数据渲染,展示最新一条消息
- watch(messages, (newVal: any, oldVal: any) => {
- // 下拉刷新不滑动 todo 优化
- nextTick(() => {
- const newLastMessage = newVal[newVal.length - 1];
- const oldLastMessage = oldVal ? oldVal[oldVal.length - 1] : {};
- data.oldMessageTime = messages.value[0].time;
- handleShowTime();
- if (oldVal && newLastMessage.ID !== oldLastMessage.ID) {
- handleScrollBottom(); // 非从conversationList 首次进入
- }
- });
- });
- // 监听数据初次渲染,展示最新一条消息
- // TODO app 中获取不到DOM 元素
- onReady(() => {
- const options = {
- sdkAppID: uni.$chat_SDKAppID, // 开通实时音视频服务创建应用后分配的 SDKAppID
- userID: uni.$chat_userID, // 用户 ID,可以由您的帐号系统指定
- userSig: uni.$chat_userSig, // 身份签名,相当于登录密码的作用
- tim: uni.$TUIKit, // tim 参数适用于业务中已存在 TIM 实例,为保证 TIM 实例唯一性
- }
- uni.$TUICallKit = TUICallKit;
- nextTick(() => {
- uni.$TUICallKit.value !== null && uni.$TUICallKit.value.init(options)
- });
- setTimeout(() => {
- handleScrollBottom();
- }, 500);
- });
- onMounted(() => {
- handleShowTime();
- setTimeout(function(){
- uni.$TUIKit.TUIConversationServer.setMessageRead(
- data.conversation.conversationID
- );
- uni.$emit('refreshMsgCount');
- },2000);
- // // 监听回退,已读上报
- // uni.addInterceptor("navigateBack", {
- // success() {
- // // 小程序无效 官网链接:https://uniapp.dcloud.io/api/interceptor.html
- // uni.$TUIKit.TUIConversationServer.setMessageRead(
- // data.conversation.conversationID
- // );
- // },
- // });
- });
- onNavigationBarButtonTap(() => {
- if (data.conversation?.type === uni.$TIM.TYPES.CONV_GROUP) {
- uni.navigateTo({
- url: "../TUIGroup/index",
- });
- } else {
- uni.showToast({
- title: "暂无信息",
- });
- }
- });
- const handleGetProfile = () => {
- uni.navigateTo({
- url: "../TUIGroup/index",
- });
- };
- const handleShowTime = () => {
- if (messages.value) {
- Array.from(messages.value).forEach((item) => {
- if (item.time - data.oldMessageTime > 5 * 60) {
- data.oldMessageTime = item.time;
- item.showTime = true;
- } else {
- item.showTime = false;
- }
- });
- }
- };
- const handleScrollBottom = () => {
-
- uni
- .createSelectorQuery()
- .select(".TUI-message-list")
- .boundingClientRect((res) => {
- const scrollH = res.height;
- data.scrollTop = scrollH;
-
- })
- .exec();
- };
- const handleCustomerItem = (event: any, item: any) => {
- if(item.payload.data=="order"){
- uni.navigateTo({
- url: '/pages_order/inquiryOrderDetails?orderId='+item.payload.description
- })
- }
- else if(item.payload.data=="prescribe"){
- var prescribe=JSON.parse(item.payload.extension);
- uni.navigateTo({
- url: '/pages_order/prescribeDetails?prescribeId='+prescribe.prescribeId
- })
- }
- else if(item.payload.data=="follow"){
- var follow=JSON.parse(item.payload.extension);
- console.log(follow)
- if(follow.writeStatus==0){
- uni.navigateTo({
- url: '/pages_user/doFollow?followId='+follow.followId
- })
- }
- else if(follow.writeStatus==1){
- uni.navigateTo({
- url: '/pages_user/followDetails?followId='+follow.followId
- })
- }
-
- }
- else if(item.payload.data=="report"){
- // var report=JSON.parse(item.payload.extension);
- uni.navigateTo({
- url: '/pages_order/inquiryOrderReport?orderId='+item.payload.description
- })
- }
- else if(item.payload.data=="drugReport"){
- // var report=JSON.parse(item.payload.extension);
- uni.navigateTo({
- url: '/pages_user/drugReportDetails?reportId='+item.payload.description
- })
- }
-
- };
- // 需要自实现下拉加载
- const handleScroll = (e: any) => {
- data.triggered = "restore"; // 需要重置
- };
- const handleRefresher = () => {
- data.triggered = true;
- if (!data.isCompleted) {
- TUIServer.getHistoryMessageList().then((res) => {
- data.triggered = false;
- data.isCompleted = res.isCompleted;
- });
- }
- setTimeout(() => {
- data.triggered = false;
- }, 500);
- };
- // 处理需要合并的数据
- const handleSend = (emo: any) => {
- data.text += emo.name;
- // inputEle.value.focus();
- };
-
- // 右键消息,展示处理功能
- const handleItem = (event: any, item: any) => {
- const { flow } = item;
- // const { height, top } = event.target.getBoundingClientRect();
- try {
- const query = uni.createSelectorQuery(); // .in(this)
- query
- .select(`#${item.flow + "-" + item.ID}`)
- .boundingClientRect((res: any) => {
- const { top } = res;
- // 弹框在下面显示,60--弹框高度;44--导航栏高度;20--弹框离信息间距
- if (top < 60 + 20) {
- data.dialogPosition = {
- ...data.dialogPosition,
- top: res.height?.res + 10, // 在下面展示弹框 + 10px 间隔
- };
- data.dialogPosition = {
- ...data.dialogPosition,
- right: flow === "out" ? 0 : null, // 发出去的消息(弹框 right 都是 0)
- left: flow === "in" ? 0 : null, // 接收的消息(弹框 left 都是 0)
- };
- } else {
- data.dialogPosition = {
- ...defaultDialogPosition,
- right: flow === "out" ? 0 : null, // 发出去的消息(弹框 right 都是 0)
- left: flow === "in" ? 0 : null, // 接收的消息(弹框 left 都是 0)
- };
- }
- })
- .exec((res: any) => {
- data.currentMessage = item;
- data.dialogID = item.ID;
- });
- } catch (error) {
- data.currentMessage = item;
- data.dialogID = item.ID;
- }
- };
- // 滑动触发时,失焦收起键盘
- const handleTouchStart = () => {
- uni.hideKeyboard();
- };
- // 重新编辑
- const handleEdit = (item: any) => {
- data.text = item.payload.text;
- };
- return {
- ...toRefs(data),
- TUICallKit,
- conversationType,
- messages,
- handleShowTime,
- handleTouchStart,
- handleRefresher,
- handleScroll,
- handleScrollBottom,
- handleCustomerItem,
- handleItem,
- handleEdit,
- handleTextMessageShowContext,
- handleImageMessageShowContext,
- handleVideoMessageShowContext,
- handleAudioMessageShowContext,
- handleFileMessageShowContext,
- handleFaceMessageShowContext,
- handleLocationMessageShowContext,
- handleMergerMessageShowContext,
- handleTipMessageShowContext,
- handleCustomMessageShowContext,
- handleSend,
- caculateTimeago,
- handleGetProfile,
- };
- },
- });
- </script>
- <style lang="scss" scoped>
- @import "../styles/TUIChat.scss";
- </style>
|