微信客服

<template>
  <view class="container" @tap="togglePicker(0)">
    <!--内容-->
    <view class="scroll" :style="{ height: startData.scrollHeight }">
      <scroll-view :scroll-into-view="startData.scrollViewId" scroll-y style="height: 100%">
        <view class="item-space"></view>
        <!-- <view class="time">晚上 10:04</view> -->
        <view v-for="(item, index) in todoStore.msgList" :key="index">
          <!--撤销-->
          <view v-if="item?.data?.messageType == 10" class="cancel">
            <text v-if="item?.data?.sendUserId == startData.fromUserId" class="text">你撤回了一条消息</text>
            <text v-else class="text">成员 {{ item?.data?.sendUserId }} 撤回了一条消息</text>
          </view>
          <view v-else class="item flex-row"
            :class="[item?.data?.sendUserId == startData.fromUserId ? 'right' : 'left']">
            <!--处理头像-->
            <view v-if="item?.data?.sendUserId == startData.fromUserId">
              <image v-if="startData.fromUserFace" :src="startData.fromUserFace" class="face"></image>
              <image v-else src="../../../../static/message/face.png" class="face"></image>
            </view>
            <view v-else>
              <image v-if="item.toUserFace || item.userFace" :src="item.toUserFace || item.userFace" class="face">
              </image>
              <image v-else src="../../../../static/message/face.png" class="face"></image>
            </view>
            <!--文本-->
            <view style="position: relative;" v-if="item?.data?.messageType == 0" @longpress="longPress(item)"
              class="content flex-row">{{
                item?.data.sendContent }}<view class="chehui" v-show="item?.data?.messageId === startData.showch"
                @click="cheFn(item)">
                <image style="width: 50rpx; height: 40rpx;" src="../../../../static/img/my/chehui.png"></image>
                <view>撤 回</view>
              </view>
            </view>
            <!--视频-->
            <view @longpress="longPress(item)" style="position: relative;" v-if="item?.data?.messageType == 4">
              <video :src="JSON.parse(item?.data?.sendContent).tempFilePath" mode="widthFix" style="width: 320rpx">
              </video>
              <view class="chehui" v-show="item?.data?.messageId === startData.showch" @click="cheFn(item)">
                <image style="width: 50rpx; height: 40rpx;" src="../../../../static/img/my/chehui.png"></image>
                <view>撤 回</view>
              </view>
            </view>
            <!--图片-->
            <view v-if="item?.data?.messageType == 1" @longpress="longPress(item)"
              style="width: 320rpx;position: relative;">
              <image @click="previewImage(item?.data?.sendContent)" :src="item?.data?.sendContent" mode="widthFix"
                style=" width: 320rpx;">
              </image>
              <view class="chehui" v-show="item?.data?.messageId === startData.showch" @click="cheFn(item)">
                <image style="width: 50rpx; height: 40rpx;" src="../../../../static/img/my/chehui.png"></image>
                <view>撤 回</view>
              </view>
            </view>
            <!--订单-->
            <view style="position:relative;" @longpress="longPress(item)" v-if="item?.data?.messageType == 5"
              class="content order" @tap="openLocation(item?.data?.sendContent)">
              <view class="chehui" v-show="item?.data?.messageId === startData.showch" @click="cheFn(item)">
                <image style="width: 50rpx; height: 40rpx;" src="../../../../static/img/my/chehui.png"></image>
                <view>撤 回</view>
              </view>
              <view class="title"><text>订单号</text>:<text>{{
                item?.data?.messageType == 5 ? JSON.parse(item?.data?.sendContent)?.num : ""
              }}</text></view>
              <view class="title"><text>订单状态</text>:<text>{{
                item?.data?.messageType == 5 ? JSON.parse(item?.data?.sendContent)?.status : ""
              }}</text></view>
              <view class="title"><text>订单类型</text>:<text>{{
                item?.data?.messageType == 5 ? JSON.parse(item?.data?.sendContent)?.type : ""
              }}</text></view>
              <view class="title"><text>提交时间</text>:<text>{{
                item?.data?.messageType == 5 ? JSON.parse(item?.data?.sendContent)?.subtime : ""
              }}</text></view>
            </view>
            <!--文件-->
            <view style="position: relative;" @longpress="longPress(item)" v-if="item?.data?.messageType == 2"
              class="content order">
              <view class="chehui" v-show="item?.data?.messageId === startData.showch" @click="cheFn(item)">
                <image style="width: 50rpx; height: 40rpx;" src="../../../../static/img/my/chehui.png"></image>
                <view>撤 回</view>
              </view>
              <view @click="uniPdf(JSON.parse(item?.data?.sendContent)?.name)"
                v-if="item?.data?.sendUserId != startData.fromUserId">
                <image src="../../../../static/message/wjj.png" class="file-imagel"></image>
                <view style="padding: 80rpx">
                  <view class="file-textl">
                    <view style="width: 300rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; ">{{
                      JSON.parse(item?.data?.sendContent)?.fileName }}</view>
                    <view>{{ JSON.parse(item?.data?.sendContent)?.size }}</view>
                  </view>
                </view>
              </view>

              <view @click="uniPdf(JSON.parse(item?.data?.sendContent)?.name)"
                v-if="item?.data?.sendUserId == startData.fromUserId">
                <view style="padding: 80rpx">
                  <view class="file-textr">
                    <view style=" width: 300rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; ">{{
                      JSON.parse(item?.data?.sendContent)?.fileName }}</view>
                    <view>{{ JSON.parse(item?.data?.sendContent)?.size }}</view>
                  </view>
                </view>

                <image src="../../../../static/message/wjj.png" class="file-imager"></image>
              </view>
            </view>
            <!--语音-->
            <view @longpress="longPress(item)" style="position: relative;" v-if="item?.data?.messageType == 3"
              @tap="playVoice(item)" class="content flex-row">
              <view class="chehui" v-show="item?.data?.messageId === startData.showch" @click="cheFn(item)">
                <image style="width: 50rpx; height: 40rpx;" src="../../../../static/img/my/chehui.png"></image>
                <view>撤 回</view>
              </view>
              <view v-if="item?.data?.sendUserId == startData.fromUserId">
                <text> {{ ((JSON.parse(item?.data?.sendContent)?.duration) / 1000).toFixed(2) }} `</text>
                <image v-show="startData.voicePlayingId != item?.data?.messageId"
                  src="../../../../static/message/audio.png" class="voice-icon"></image>
                <image v-show="startData.voicePlayingId == item?.data?.messageId"
                  src="../../../../static/message/audio-play.gif" class="voice-icon"></image>
              </view>
              <view v-if="item?.data?.sendUserId != startData.fromUserId">
                <text> {{ ((JSON.parse(item?.data?.sendContent)?.duration) / 1000).toFixed(2) }} `</text>
                <image v-show="startData.voicePlayingId != item.id" src="../../../../static/message/audio.png"
                  class="voice-icon"></image>
                <image v-show="startData.voicePlayingId == item.id" src="../../../../static/message/audio-play.gif"
                  class="voice-icon"></image>
              </view>
            </view>
          </view>
        </view>
        <view id="bottom"></view>
      </scroll-view>
    </view>
    <!--输入-->
    <view class="oper flex-row" @tap.prevent.stop="">
      <!--语音切换-->
      <image v-if="startData.isEdit" @tap="toggleEdit(false)" src="../../../../static/message/voice-circle.png"
        class="icon">
      </image>
      <image v-else @tap="toggleEdit(true)" src="../../../../static/message/keyboard.png" class="icon"></image>
      <!--语音切换-->
      <input v-if="startData.isEdit" @focus="startData.inputFocus" :focus="startData.isFocus" :cursor-spacing="8"
        :adjust-position="false" type="text" v-model="startData.sendContent" class="input" />
      <view v-else @touchstart="startVoice" @touchend="endVoice" class="input" style="text-align: center;">按住 说话
      </view>
      <!--表情-->
      <image @tap="togglePicker(200, 'emoji')" src="../../../../static/message/emoji.png" class="icon"></image>
      <!--发送-->
      <view @touchend.prevent="send" v-show="startData.sendContent" class="btn">发送</view>
      <!--附件-->
      <image @tap="togglePicker(86, 'file')" v-show="!startData.sendContent" src="../../../../static/message/add.png"
        class="icon">
      </image>
    </view>
    <!--表情-->
    <view v-show="startData.showEmoji" class="emoji" @tap.prevent.stop="">
      <view class="list">
        <view class="item" @tap="startData.sendContent += item" v-for="(item, index) in startData.emojis" :key="index">
          {{ item }}</view>
      </view>
    </view>
    <!--附件-->
    <view v-show="startData.showFile" class="file" @tap.prevent.stop="">
      <view class="list flex-row">
        <view class="item flex-column" @tap="uploadImage(['album'])">
          <image src="../../../../static/message/album.png" mode="widthFix" class="icon"></image>
          <view class="text">相册</view>
        </view>
        <view class="item flex-column" @tap="chooseVideo()">
          <image src="../../../../static/message/photo.png" mode="widthFix" class="icon"></image>
          <view class="text">拍摄</view>
        </view>
        <view class="item flex-column" @tap="uploadFile()">
          <image src="../../../../static/message/wjj.png" mode="widthFix" class="icon"></image>
          <view class="text">文件</view>
        </view>
        <view class="item flex-column" @tap="showBottomModal">
          <image src="../../../../static/message/dd.png" mode="widthFix" class="icon"></image>
          <view class="text">订单</view>
        </view>
      </view>
    </view>
    <!--语音-->
    <my-voice v-show="startData.showVoice"></my-voice>
    <view v-if="startData.isShowBottomModal" class="bottom-modal">
      <!-- 这里放置底部弹框的内容 -->
      <view class="bottom-conter">
        <view class="ic"><uni-icons @click="hideBottomModal" type="closeempty" size="30"></uni-icons></view>
        <scroll-view scroll-y="true" refresher-enabled="true" :refresher-triggered="refreshTrigged.freshbol"
          @refresherrefresh="refresherrefresh" refresher-background="#f6f6f6" lower-threshold="60"
          @scrolltolower="loadingMore" class="con-middle">
          <view class="con-card" v-for="(item, index) in listorder.data" :key="index">
            <view class="con-title"><text class="con-t-t1">订单号:{{ item?.num }}</text><text class="con-t-t2">{{
              item?.status }}</text></view>
            <view class="con-l"></view>
            <view class="con-p">
              <view class="con-pt1">订单类型:</view>
              <view class="con-pt2">{{ item?.type }}</view>
            </view>
            <view class="con-p">
              <view class="con-pt1">需求描述:</view>
              <view class="con-pt2">{{ item?.demsg }}</view>
            </view>
            <view class="con-p">
              <view class="con-pt1">提交时间:</view>
              <view class="con-pt2">{{ item?.subtime }}</view>
            </view>
            <view class="con-send">
              <text @click="senOrder(item)">发送</text>
            </view>
          </view>
        </scroll-view>
      </view>
    </view>
  </view>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { dateDealDayYear } from "@/services/common";
import myVoice from "../../../../components/self-voice/index.vue";
import UniIcons from "@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue";
import ChatFn from "./chat-fn";
import { selectDemandList } from "@/services";
export default defineComponent({
  components: {
    myVoice,
    "uni-icons": UniIcons,
  },
  setup() {
    const {
      cheFn,
      send,
      senOrder,
      todoStore,
      openLocation,
      uploadImage,
      startVoice,
      endVoice,
      playVoice,
      toggleEdit,
      longPress,
      setScrollHeight,
      togglePicker,
      startData,
      uploadFile,
      chooseVideo
    } = ChatFn();
    // 列表
    const orderleix: any = {
      "0": {
        name: "gold",
        value: "来图加工",
      },
      "1": {
        name: "red",
        value: "夹具定制",
      },
      "2": {
        name: "green",
        value: "夹具设计",
      },
    };
    //类型
    const orderstate: any = {
      "0": {
        name: "gold",
        value: "定制中",
      },
      "1": {
        name: "red",
        value: "已完成",
      },
      "2": {
        name: "green",
        value: "已取消",
      },
    };
    const listorder = reactive<any>({
      data: [],
      pageSize: 5,
      pageNum: 1,
      totalCount: 0,
      isLoading: false,
      hasMore: true, // 初始假设有更多数据
    });
    const order = () => {
      if (listorder.isLoading) return;
      listorder.isLoading = true;
      selectDemandList({
        demandStatus: 0,
        page: listorder.pageNum,
        size: listorder.pageSize,
      })
        .then((res: any) => {
          const list = res?.data?.dataList.map((i: any) => {
            return {
              status: orderstate[i?.demandStatus]?.value,
              type: orderleix[i?.demandType]?.value,
              demsg: i?.requirementDescription,
              num: i?.demandNumber,
              subtime: dateDealDayYear(i?.createdTime),
            }
          })
          if (res.success) {
            listorder.data = [...listorder.data, ...list];
            listorder.isLoading = false;
            refreshTrigged.freshbol = false;
            console.log(listorder.data.length, "8888888888888888888888");
          } else {
            listorder.isLoading = false;
            listorder.hasMore = false;
          }
        })
        .catch((error) => {
          listorder.isLoading = false;
          listorder.hasMore = false;
          refreshTrigged.freshbol = false;
        });
    };
    onMounted(() => {
      order();
    });
    const refreshTrigged = reactive<any>({
      freshbol: false,
    });
    const refresherrefresh = () => {
      if (refreshTrigged.freshbol) {
        return;
      }

      refreshTrigged.freshbol = true;
      listorder.pageNum = 0;
      order();
    };
    const loadingMore = () => {
      console.log("触底3333333333", listorder.hasMore);
      if (!listorder.hasMore) {
        return;
      }
      listorder.pageNum++;
      order();
    };
    const previewImage = (a: any) => {
      uni.previewImage({
        urls: [a], // 要预览的图片列表
        current: 0 // 当前显示图片的索引
      });
    }

    const showBottomModal = () => {
      startData.isShowBottomModal = true;
    };
    const hideBottomModal = () => {
      startData.isShowBottomModal = false;
    };
    const uniPdf = (a: any) => {
      uni.downloadFile({
        url: a,
        success: function (res) {
          var filePath = res.tempFilePath;
          uni.openDocument({
            filePath: filePath,
            showMenu: true,
            success: function (res) {
              console.log('打开文档成功');
            }
          });
        }
      });
    }

    return {
      loadingMore,
      refresherrefresh,
      refreshTrigged,
      cheFn,
      chooseVideo,
      uniPdf,
      send,
      previewImage,
      hideBottomModal,
      showBottomModal,
      openLocation,
      uploadImage,
      startVoice,
      endVoice,
      playVoice,
      toggleEdit,
      longPress,
      setScrollHeight,
      togglePicker,
      startData,
      listorder,
      uploadFile,
      todoStore,
      senOrder
    };
  },
});
</script>

<style lang="scss" scoped>
@import "./chat.scss";
</style>

  

.container {
  height: 100vh;
  overflow: hidden;
}

/* #ifdef H5 */
.container {
  height: calc(100vh - 88rpx);
}

/* #endif */

.status_bar,
.container,
.header,
.emoji,
.file {
  background-color: #f3f3f3;
}

.header {
  border-bottom: 2rpx solid #eee;

  .center {
    font-weight: bold;
  }
}

.order {
  width: 60%;
  background-color: #fff !important;

  &::before {
    border-right: 30rpx solid #fff !important;
  }

  .title {
    font-size: 28rpx;
    overflow: hidden;
    padding: 10rpx;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }

  .box {
    width: 100%;
    height: 170rpx;
    margin-top: 10rpx;
  }
}

.emoji {
  height: 400rpx;
  padding: 0 0 20rpx 20rpx;
  position: relative;

  .list {
    width: 100%;
    height: 400rpx;
    padding: 20rpx 0;
    overflow-y: auto;

    .item {
      float: left;
      display: block;
      height: 60rpx;
      line-height: 60rpx;
      width: calc(100% / 12);
      margin-right: 20rpx;
    }
  }
}

.file {
  padding: 30rpx 20rpx;

  .list {
    overflow: hidden;
    padding-left: 10rpx;
    justify-content: flex-start;
  }

  .item {
    float: left;
    width: 110rpx;
    height: 110rpx;
    border-radius: 10rpx;
    margin-right: 40rpx;
    background-color: #fff;

    .icon {
      width: 50rpx;
    }

    .text {
      font-size: 24rpx;
      margin-top: 4rpx;
    }
  }
}

.oper {
  height: 110rpx;
  padding: 0 20rpx;
  box-sizing: border-box;
  border-top: 2rpx solid #eee;
  border-bottom: 2rpx solid #eee;

  .input {
    height: 80rpx;
    line-height: 80rpx;
    padding: 0 20rpx;
    font-size: 28rpx;
    border-radius: 10rpx;
    background-color: #fff;
    width: calc(100% - 120rpx - 20rpx - 40rpx - 60rpx);
  }

  .icon {
    width: 60rpx;
    height: 60rpx;
  }

  .btn {
    color: #fff;
    width: 90rpx;
    height: 52rpx;
    font-size: 24rpx;
    line-height: 52rpx;
    text-align: center;
    border-radius: 10rpx;
    background-color: #2ba245;
  }
}

.scroll {
  overflow-y: auto;
  transition: all 0.1s ease;
  height: calc(100vh - 88rpx - 110rpx - var(--status-bar-height));

  /* #ifdef MP-WEIXIN */
  height: calc(100vh - 88rpx - var(--status-bar-height));
  /* #endif */
  /* #ifdef H5 */
  height: calc(100vh - 88rpx - 110rpx - var(--status-bar-height));
  /* #endif */

  .item-space {
    height: 30rpx;
  }

  .time {
    color: #666;
    font-size: 24rpx;
    text-align: center;
    margin-bottom: 20rpx;
  }

  .cancel {
    width: 100%;
    height: 40rpx;
    text-align: center;
    margin-bottom: 30rpx;

    .text {
      color: #999;
      font-size: 24rpx;
    }
  }

  .item {
    margin: 0 30rpx 30rpx;
    align-items: flex-start;
    justify-content: flex-start;

    .face {
      width: 80rpx;
      height: 80rpx;
      border-radius: 100rpx;
    }

    .content {
      color: #000;
      font-size: 32rpx;
      min-height: 80rpx;
      border-radius: 10rpx;
      padding: 10rpx 24rpx;
      background-color: #fff;
      word-break: break-all;
      word-wrap: break-word;
      max-width: calc(100% - 100rpx - 120rpx);
      position: relative;

      &::before {
        content: "";
        width: 0;
        height: 0;
        border-right: 30rpx solid #fff;
        border-top: 20rpx solid transparent;
        border-bottom: 20rpx solid transparent;
        position: absolute;
        top: 24rpx;
      }

      .voice-icon {
        width: 32rpx;
        height: 40rpx;
        margin-right: 180rpx;
        margin-bottom: -8rpx;
      }
    }

    &.left {
      .face {
        margin-right: 30rpx;
      }

      .content::before {
        left: -20rpx;
      }
    }

    &.right {
      flex-direction: row-reverse;

      .face {
        margin-left: 30rpx;
      }

      .content {
        background-color: #a0ea6f;

        &::before {
          right: -20rpx;
          transform: rotate(180deg);
          border-right: 30rpx solid #a0ea6f;
        }

        .voice-icon {
          margin-right: 0;
          margin-left: 180rpx;
          transform: rotate(180deg);
        }
      }
    }
  }

  #bottom {
    height: 2rpx;
  }
}

//底部弹框

//底部弹框
.bottom-modal {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(11, 11, 11, 0.7);
  z-index: 1000;
  box-sizing: border-box;
}

.bottom-conter {
  position: absolute;
  width: 100%;
  height: 75%;
  overflow: auto;
  bottom: 0;
  background-color: #f1f1f1;
  display: flex;
  flex-direction: column;

  .ic {
    text-align: right;
    padding: 10rpx;
  }

  .con-middle {
    flex: 1;
    overflow: auto;
    padding: 40rpx;
  }

  .con-card {
    margin-bottom: 50rpx;
    border-radius: 20rpx;
    padding: 50rpx;
    background: #ffffff;
  }
}

.con-title {
  padding: 10rpx 0 25rpx;
  display: flex;
  justify-content: space-between;

  .con-t-t1 {
    font-size: 35rpx;
    // color: #5d5b5b;
    font-weight: bold;
  }

  .con-t-t2 {
    color: #9d9d9d;
    font-size: 30rpx;
  }
}

.con-l {
  border-top: 1rpx solid #d6d4d4;
}

.con-p {
  margin: 20rpx 0;
  display: flex;
  font-size: 30rpx;
  justify-content: space-between;

  .con-pt1 {
    color: #9d9d9d;
    white-space: nowrap;
  }

  .con-pt2 {
    color: #5a5959;
    line-height: 60rpx;
    margin-left: 20rpx;
  }
}

.con-send {
  text-align: center;
  margin: 50rpx 0 20rpx;

  text {
    color: #2878ff;
    border: 1rpx solid #2878ff;
    padding: 15rpx 30rpx;
    border-radius: 20rpx;
  }
}

.file-imager {
  width: 60rpx;
  height: 60rpx;
  right: 30rpx;
  position: absolute;
  transform: translateY(-50%);
  top: 50%;
}

.file-textr {
  position: absolute;
  left: 30rpx;
  top: 50%;
  line-height: 70rpx;
  padding: 10rpx;
  transform: translateY(-50%);
}

.file-imagel {
  width: 60rpx;
  height: 60rpx;
  position: absolute;
  transform: translateY(-50%);
  top: 50%;
}

.file-textl {
  position: absolute;
  right: 15rpx;
  top: 50%;
  padding: 10rpx;
  line-height: 70rpx;
  transform: translateY(-50%);
}

.chehui{
  text-align: center;
  white-space: nowrap;
  position: absolute;
  top:-160rpx;
  left: 0;
  padding: 20rpx 50rpx;
  color: #ffffff;
  border-radius: 20rpx;
  background-color: #4C4C4C;
}

  

import { onLoad } from "@dcloudio/uni-app";
import emoji from "../../../plugins/emoji";
import { useStore } from "../../../../store/pinia.js";
import { customSend, recallFn } from "../../../../services/index.js";
export default function ChatFn() {
  const todoStore: any = useStore();
  const innerAudioContext = uni.createInnerAudioContext();
  const recorderManager = uni.getRecorderManager();
  const startData = reactive<any>({
    emojis: emoji, //[],
    isShowBottomModal: false,
    showch: "",
    msgdata: "",
    isEdit: true,
    isFocus: false,
    showEmoji: false,
    showFile: false,
    showVoice: false,
    scrollHeight: "auto", // 内容区域高度
    statusBarHeight: 0, // 状态栏高度
    scrollViewId: "", // 滚动到最底部
    voicePlayingId: "", // 正在播放的消息ID
    sendContent: "",
    list: [],
    socketOpen: false,
    socketMsgQueue: [],
    fromUserId: uni.getStorageSync("userId"), //自己 "1712758061913542657", //uni.getStorageSync('userId'),
    fromUserFace: uni.getStorageSync("customerNickname"),//自己头像
    customerId: "",//对方
    customerNickname: "",
  });
  const initScrollBar = () => {
    setTimeout(() => {
      startData.scrollViewId = "";
      setTimeout(() => {
        startData.scrollViewId = "bottom";
        setTimeout(() => {
          startData.scrollViewId = "";
        }, 1);
      }, 1);
    }, 1);
  };
  const setScrollHeight = (descHeight = 0) => {
    // #ifdef MP-WEIXIN
    startData.scrollHeight = `calc(100vh - 110rpx - ${descHeight}px)`;
    // #endif
    // #ifdef APP-PLUS
    startData.scrollHeight = `calc(100vh - 110upx - ${descHeight}px)`;
    // #endif
    // #ifdef H5
    startData.scrollHeight = `calc(100vh - 110upx - 88rpx - ${descHeight}px)`;
    // #endif
  };

  const togglePicker = (height = 0, type = "") => {
    startData.showEmoji = false;
    startData.showFile = false;
    startData.showch = ""
    let status = height > 0 ? true : false;

    switch (type) {
      case "emoji":
        startData.isEdit = true;
        // startData.isFocus = bool;
        startData.showEmoji = status;
        break;
      case "file":
        startData.showFile = status;
        break;
    }

    // setTimeout(() => {
    setScrollHeight(height);
    initScrollBar();
    // }, 1)
  };
  // 切换语音与编辑
  const toggleEdit = (bool: any) => {
    startData.isEdit = bool;
    startData.isFocus = bool;
    setScrollHeight(0);
  };
  
  var socketOpen = false;
  const SocketMessage = () => {
    uni.sendSocketMessage<any>({
      data: JSON.stringify({
        cmd: 0, //详情见页底
        data: {
          accessToken:
            todoStore.accessToken,
          userId: startData.customerId, //对方//此token内容会在登录小程序后返回
        },
      }),
      success: (res: any) => {
        console.log("socketOpen", res);
      },
    });
  };
  const webSocketFn = () => {
    uni.connectSocket({
      url: "ws://192.168.2.135:8878/im",
    });
    uni.onSocketOpen(function (res) {
      console.log("res链接,", res);
      socketOpen = true;
      if (socketOpen) {
        SocketMessage();
      }
    });

    uni.onSocketMessage(function (res) {
      console.log("收到服务器内容2:", res?.data, +JSON.parse(res?.data));
      if (JSON.parse(res?.data)?.data?.messageType == 10) {
        const index = todoStore.msgList.findIndex(
          (obj: any) =>
            obj?.data.messageId === JSON.parse(res?.data)?.data?.messageId
        );
        // todoStore.msgList[index].data.messageType = 10
        todoStore.msgList.splice(index,1);
      }
      if (JSON.parse(res.data).cmd == 5) {
        todoStore.addMsgList(JSON.parse(res.data));
      }
    });
    uni.onSocketError(function (res) {
      console.log("WebSocket连接打开失败,请检查!");
    });
  };

  onMounted(() => {
    togglePicker(0);
    webSocketFn();
  });

  // 开始录音
  const startVoice = () => {
    startData.showVoice = true;
    recorderManager.start({});
  };
  // 结束录音
  const endVoice = () => {
    startData.showVoice = false;
    recorderManager.stop();
    // 结束录音
    recorderManager.onStop((res) => {
      console.log("res2结束录音数据", res);
      sendMsg(
        3,
        JSON.stringify({
          duration: res?.duration,
          tempFilePath: res?.tempFilePath,
        })
      );
    });
  };
  // 长按
  const longPress = (msg: any) => {
    startData.showch = msg?.data?.messageId;
  };
  // 撤回
  const cheFn = async (item: any) => {
    await recallFn({ messageId: item?.data?.messageId }).then((res: any) => {
      startData.msgdata = res?.msg;
      console.log('====================================');
      console.log(res);
      console.log('====================================');
      if (res?.msg=="消息发送已超过五分钟,无法撤回!") {
        uni.showLoading({title:"已超过五分钟"});
        setTimeout(function () {
          uni.hideLoading();
        }, 2000);
      }
    });
    startData.showch = "";
  };
  console.log(
    "第三方建设大街风扇电机开发机手打飞机.src",
    innerAudioContext.src
  );
  // 播放录音
  const playVoice = (item: any) => {
    console.log("语音播放", item);
    startData.voicePlayingId = item?.data?.messageId;
    if (!startData.voicePlayingId) {
      startData.voicePlayingId = "";
    } else {
      startData.voicePlayingId = item?.data?.messageId;
      // innerAudioContext.src = item.sendContent;
      innerAudioContext.src = item.data.sendContent
        ? JSON.parse(item.data.sendContent).tempFilePath
        : "";
      innerAudioContext.play();
    }
  };
  const uploadFile = () => {
    
    uni.chooseMessageFile({
      count: 1,
      type: "file",
      success: (res) => {
        const tempFilePath = res.tempFiles[0].path;
        // 上传PDF文件
        uni.showLoading({title:"上传中"});
        uni.uploadFile({
          url: "http://192.168.2.125:8009/im/file/uploadFile",
          header: {
            'Authorization': todoStore.token
          },
          filePath: tempFilePath,
          name: "file",
          success: (uploadRes) => {
            console.log(
              "文件上传成功",
              JSON.parse(uploadRes.data)?.data?.upload?.objectUrl
            );
            uni.hideLoading();
            console.log(
              "JSON.parse(uploadRes.data)",
              JSON.parse(uploadRes.data)
            );
            let data = JSON.stringify({
              size: JSON.parse(uploadRes.data)?.data?.fileSize,
              name: JSON.parse(uploadRes.data)?.data?.upload?.objectUrl,
              fileName: JSON.parse(uploadRes.data)?.data?.fileName,
            });
            sendMsg(2, data);
          },
          fail: (error) => {
            console.error("文件上传失败", error);
          },
        });
      },
      fail: (error) => {
        console.error("选择文件失败", error);
      },
    });
  };
  const chooseVideo = () => {
    uni.chooseVideo({
      sourceType: ["camera"],
      success: function (res: any) {
        console.log("====================================");
        console.log("dsds", res, res?.tempFilePath);
        let data = JSON.stringify({
          size: res?.size,
          tempFilePath: res?.tempFilePath,
        });
        uni.hideLoading();
        sendMsg(4, data);
      },
    });
  };
  const uploadImage = (sourceType = ["album"]) => {
    uni.chooseImage({
      sourceType,
      sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
      success: (chooseImageRes) => {
        const tempFilePaths: any = chooseImageRes.tempFilePaths;
        tempFilePaths.forEach((temp: any) => {
          uni.showLoading({title:"上传中"});
          uni.uploadFile({
            url: "http://192.168.2.125:8009/im/file/uploadImage",
            filePath: temp,
            header: {
              'Authorization': todoStore.token
            },
            name: "image",
            success: (uploadRes) => {
              console.log("相册", JSON.parse(uploadRes.data)?.data?.originUrl);
              uni.hideLoading();
              let data = JSON.parse(uploadRes.data)?.data?.originUrl;
              sendMsg(1, data);
            },
            fail: (err) => {
              uni.hideLoading();
            },
          });
        });
      },
    });
  };
  const sendMsg = async (type: any, centent: any) => {
    await customSend({
      dto: {
        recvUserId: startData?.customerId, //别人
        sendContent: centent,
        messageType: type,
      },
    }).then((res: any) => {
      console.log(res);
      // 初始化滚动条
      initScrollBar();
      if (res?.success) {
        uni.hideLoading();
        startData.sendContent = "";
      }
    });
  };
  const senOrder = (item: any) => {
    console.log("订单数据", item);
    startData.isShowBottomModal = false;
    sendMsg(5, JSON.stringify(item));
  };
  // 发送消息
  const send = async () => {
    sendMsg(0, startData.sendContent);
  };

  onLoad((option: any) => {
    console.log("optionoptionoption", option);

    uni.onKeyboardHeightChange((res) => {
      togglePicker(res.height);
    });

    setScrollHeight(0);

    // 初始化状态栏高度
    uni.getSystemInfo({
      success: (res) => {
        startData.statusBarHeight = res.statusBarHeight;
      },
    });

    // 结束录音
    recorderManager.onStop((res) => {
      console.log("res结束录音数据", res);
    });

    // 结束播放
    innerAudioContext.onEnded((res) => {
      startData.voicePlayingId = "";
    });

    // 设置标题
    uni.setNavigationBarTitle({ title: option.customerNickname });

    // 获取参数=
    startData.customerId = option.customerId;//对方
    startData.customerNickname = option.customerNickname;
    // startData.fromUserFace = option.customerHeadUrl;
    startData.emojis = emoji;


  });

  // 打开位置
  const openLocation = (sendContent: any) => {
    let { latitude, longitude } = JSON.parse(sendContent);
    uni.openLocation({ latitude, longitude });
  };
  return {
    send,
    senOrder,
    openLocation,
    uploadImage,
    startVoice,
    endVoice,
    playVoice,
    toggleEdit,
    longPress,
    setScrollHeight,
    togglePicker,
    startData,
    uploadFile,
    todoStore,
    chooseVideo,
    cheFn,
  };
}

  

posted @ 2024-07-09 10:15  zjxgdq  阅读(16)  评论(0编辑  收藏  举报