天天看點

微信小程式即時通訊(融雲sdk)

we

記錄一下我在使用融雲sdk中遇到的問題

使用前要去融雲那邊新增賬號申請appid 然後開通小程式服務,就可以下載下傳小程式案例了

融雲的sdk中的

小程式聊天中加載的資源更多的是網絡資源(七牛雲上的外鍊位址)

app聊天加載的更多的是類似base64的資源

融雲那邊有提供比較完整的案例

但是是分開的一個是IM聊天室案例

一個是calllib音視訊案例 這兩個案例無法同時使用

因為sdk的版本不同會導緻沖突(官方說是相容性還沒有做好)

建議使用

sdk2

版本,這個版本兩個都可以使用

1、初始化(這個問題是我最後才解決掉的,一定要初始化好,不然就算能用也會有很多問題)

2、實時擷取消息加載到自己的聊天清單中

3、解決首次登入的初始化問題還有第二次登入的初始化問題

(這個問題比較有意思,因為我當時是分開處理化的,先初始化IM聊天室,在連結上之後再次擷取那邊的token去初始化音視訊的sdk,反正就不對的,要一起初始化)

4、在小程式開始運作并且連結上融雲那邊的服務會後設定全局監聽(可以讓不管處于哪一個界面都可以,收到消息通知,當然僅限于小程式内,就是小程式處于show狀态的時候,切換到背景就收不到了,因為小程式不支援背景強制喚醒,這裡的話可以去關聯公衆号,通過讓使用者在公衆号上綁定使用者資訊,擷取唯一辨別,去實作離線推送,關于公衆号授權的内容可以參考這個連結),具體關聯上怎麼推送的話,要去公衆平台裡申請和設定消息模闆,具體咋推送的就要靠後端勒

5、接下來就是判斷被聊天的使用者是否線上,是否需要被推送

6、現在就是打音視訊的界面需要判斷是接聽方還是呼叫方去通過不同的字段去展示不同的界面,當然聊天室也要判斷是目前使用者還是對方使用者去顯示到兩側

7、我們也嘗試過微信小程式消息推送(結果就是能退過來,但是次數限制是硬傷,訂一次推送一次,不滿足需求)

8、在聊天室中發送定位資訊時,要使用wx.getLocation和 wx.chooseLocation去選擇位址具體的位址表述圖檔可以使用高德那邊的api把經緯度傳過去然後傳回位址描述圖,前端沒辦法單獨處理,我是沒有想到辦法

參考這個連結去高德api看

https://restapi.amap.com/v3/staticmap?markers=-1,http://www.5imoban.net/view/demoimg/jrzb_position_icon.png,0:${longitude},${latitude}&key=ee95e52bf08006f63fd29bcfbcf21df0&zoom=17&size=360*200&location=${longitude},${latitude}

9、設定使用者聊天的時間展示,當然寫資料都融雲那邊的接口給我們的,給我們的是毫秒,不是給使用者看的東西,所有要前台處理一下,但使用js對每一條資料都處理總感覺很慢,wxml行間也不允許處理過的内容,是以我使用wxs

var filter = {
  getDateTime: function (value) {
    //不能使用 new Date()
      var now = getDate();
      var time = getDate(value);
      var year = time.getFullYear();
      var month = time.getMonth() + 1;
      var date = time.getDate();
      var hour = time.getHours();
      var minute = time.getMinutes();
      var second = time.getSeconds();
      month = month < 10 ? "0" + month : month;
      date = date < 10 ? "0" + date : date;
      hour = hour < 10 ? "0" + hour : hour;
      minute = minute < 10 ? "0" + minute : minute;
      second = second < 10 ? "0" + second : second;
      if(now.getFullYear() == year){
        if(now.getDate() == date){
          return hour + ":" + minute + ":" + second;
        }else{
          return  month + "-" + date + " " + hour + ":" + minute + ":" + second;
        }
      }else{
        return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second;
      }
  }
}
// 導出對外暴露的屬性
module.exports = {
  getDateTime: filter.getDateTime
}
           

具體使用

<wxs module="filter" src="./message.wxs"></wxs>
<view style='margin:16rpx 0'>{{filter.getDateTime(message.sentTime)}}</view>
           

10、 確定每次使用者進入到聊天界面時,界面要定位到最後一條資訊哪裡(因為聊天資訊一般都比較多會有滾動條的存在,是以要讓滾動條在最後一天資料哪裡,這個時候你可能會覺得直接滾到底部就可以了,但是當時圖檔消息時内容高度較高就顯得不合适了)

這裡使用小程式那邊的

scroll-view

元件 這個元件有一個

scroll-into-view

屬性可以讓滾動條滾動到指定位置,具體操作就是通過擷取到消息監聽器監聽來的資料的唯一辨別去修改那個屬性的值去實作的

11、還有監聽挂斷時的重複觸發回調的問題

const gotoView = (context,first) => {
  context.setData({
    toView: context.data.messageList[context.data.messageList.length - 1].messageUId
  })
 
}
Page({
	data:{
		toView:null, // 用來定位最後一天的消息的辨別
		messageList:[] // 目前的聊天記錄
	},
	收到消息後觸發的方法:funtion(){
		...這是處理messageList的内容
		gotoView(this)
	},
	我發送某種消息:funtion(){
		...這是處理messageList的内容
		gotoView(this)
	}
})
           

12、視訊通話時切換前後攝像頭

this.livePusher = wx.createLivePusherContext()
 this.livePusher.switchCamera({})
           

以上是我遇到的部分問題

這是我關于初始化和設定的一些方法,為了有更好的拓展性,我寫在小程式的app.js中友善全局使用

具體的sdk版本可以參考我的版本去下載下傳

const RongIMLib = require('./libs/RongIMLib.wx-1.2.4.js');
const RongRTC = require('./libs//RongRTC-wechat-minip-3.2.2.js');
const RongCallLib = require('./libs//RongCallLib-wechat-minip-3.2.2.js');
import {
  request
} from './request/index'
// const { co } = require('./helper');
var commandWatcher = function (result) {
  console.log("----------------", result, result.messageType, result.messageType == "InviteMessage")
  if (result.messageType == "InviteMessage") {
    wx.navigateTo({
      url: '/pages/call/call?data=' + JSON.stringify(result)
    })
  }
}
// 
function appletOnLine(type){
  request({
      url:'login/appletOnLine',
      data:{
        token:wx.getStorageSync('token'),
        applet_type:type
      }
  }).then(res => {
    console.log(res)
  })
}
const {
  appkey,
  msUrls,
  apps,
  serverUrl
} = require('./config');
var layout = function () {
  if (userListModle) {
    userListModle.setData({
      conversationList: []
    })
  }
}
var appType = (id,content) => {
  request({
    url: "wechat/selectExpertType",
    data: {
      id
    }
  }).then((res) => {
    console.log(res)
    if (res.data.data.account !== null && (res.data.data.account.applet_type === 0 || res.data.data.account.applet_type === null)) {
      request({
        url: "wechat/sendMessage",
        data: {
          id: id,
          name:wx.getStorageSync('name'),
          mobile: wx.getStorageSync('phone'),
          content
        }
      }).then((res) => {})
    }
  })

}
let RongIMClient = null;
let userListModle = null;
let ChatRoom = null;
let reconnect = () => {
  var callback = {
    onSuccess: function (userId) {
      console.log('Reconnect successfully. ' + userId);
    },
    onTokenIncorrect: async function () {
      let result
      console.log('token無效');
      wx.showToast({
        title: '登入過期,請重新登入',
        icon: "none"
      })
      wx.clearStorageSync()
    },
    onError: function (errorCode) {
      console.log(errorcode);
    }
  };
  var config = {
    // 預設 false, true 啟用自動重連,啟用則為必選參數
    auto: true,
    // 網絡嗅探位址 [http(s)://]cdn.ronghub.com/RongIMLib-2.2.6.min.js 可選
    url: 'cdn.ronghub.com/RongIMLib-2.2.6.min.js',
    // 重試頻率 [100, 1000, 3000, 6000, 10000, 18000] 機關為毫秒,可選
    rate: [100, 1000, 3000, 6000, 10000]
  };
  RongIMClient.reconnect(callback, config);
}
var getList = (context) => {
  return new Promise((r, j) => {
    RongIMClient.getInstance().getConversationList({
      onSuccess: function (list) {
        request({
          url: 'index/communicationList',
          data: {
            token: wx.getStorageSync("token"),
            pageNo: context.data.pageNo,
            pageSize: context.data.pageSize,
            name: context.data.name
          }
        }).then(res => {
          if (res.data.status == 1) {
            let ryData;
            let my = [];
            res.data.page.list.forEach(ele => {
              my.push(ele.user_id)
            })
            console.log(my)
            ryData = list.filter(e => {
              if (e.targetId != wx.getStorageSync('userId')) {
                return my.includes(parseInt(e.targetId))
              }
            })
            ryData.forEach(e => {
              e.zj = res.data.page.list.filter((element) => {
                return element.user_id == e.targetId
              })[0]
            })
            r(ryData)
          }
        })
      },
      onError: function (error) {
        j(error)
        getList(context)
      }
    }, null)
  })
}
var getHistory = (targetId, timestrap, count) => {
  console.log(targetId, timestrap, count)
  console.log(RongIMLib.ConversationType)
  var conversationType = RongIMLib.ConversationType.PRIVATE; //單聊, 其他會話選擇相應的消息類型即可
  var targetId = targetId; // 想擷取自己和誰的曆史消息,targetId 指派為對方的 userId。類型: string
  var timestrap = timestrap; // 預設傳 null,若從頭開始擷取曆史消息,請指派為 0, timestrap = 0;
  var count = Number(count); // 每次擷取的曆史消息條數,範圍 0-20 條,可以多次擷取
  if (count == 0) {
    count = 8
  }
  return new Promise((r, j) => {
    RongIMLib.RongIMClient.getInstance().getHistoryMessages(conversationType, targetId, timestrap, count, {
      onSuccess: function (list, hasMsg) {
        // console.log(list, hasMsg)
        r({
          list,
          hasMsg
        })
        // list => Message 數組。
        // hasMsg => 是否還有曆史消息可以擷取。
      },
      onError: function (error) {
        console.log('GetHistoryMessages, errorcode:' + error);
        getHistory(targetId, timestrap, count)
        j(error)
      }
    });
  })

}
var ImageMessage = (targetId, base64Str, imageUri, extra) => {
  console.log(extra)
  return new Promise((r, j) => {
    extra = {
      ...extra,
      id1: wx.getStorageSync('userId'),
      id2: ChatRoom.data.targetId,
      xm1: ChatRoom.data.my.name,
      xm2: ChatRoom.data.your.name,
      tx1: ChatRoom.data.my.headPortrait,
      tx2: ChatRoom.data.your.headPortrait,
    }
    var msg = new RongIMLib.ImageMessage({
      content: base64Str,
      imageUri: imageUri,
      extra
    });
    var conversationType = RongIMLib.ConversationType.PRIVATE; // 單聊, 其他會話選擇相應的會話類型即可
    targetId = String(targetId); // 目标 Id
    RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
      onSuccess: function (message) {
        // message 為發送的消息對象并且包含伺服器傳回的消息唯一 Id 和發送消息時間戳
        if (message.senderUserId == message.targetId) {
          message.direction = 'receiver'
        } else {
          message.direction = 'sender'
        }
        console.log(message)
        appType(targetId,'您有一條圖檔消息')
        r(message)
        console.log('Send successfully');
      },
      onError: function (errorCode, message) {
        j(message)
        console.log('發送失敗:' + message + errorCode);
      }
    });
  })
}
var LocationMessage = (targetId, latitude, longitude, poi, content) => {
  let extra = {
    id1: wx.getStorageSync('userId'),
    id2: ChatRoom.data.targetId,
    xm1: ChatRoom.data.my.name,
    xm2: ChatRoom.data.your.name,
    tx1: ChatRoom.data.my.headPortrait,
    tx2: ChatRoom.data.your.headPortrait,
  }

  return new Promise((r, j) => {
    var msg = new RongIMLib.LocationMessage({
      latitude: latitude,
      longitude: longitude,
      poi: poi,
      content: content,
      extra
    });

    var conversationType = RongIMLib.ConversationType.PRIVATE; // 單聊, 其他會話選擇相應的會話類型即可
    targetId = String(targetId); // 目标 Id
    RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
      onSuccess: function (message) {
        // message 為發送的消息對象并且包含伺服器傳回的消息唯一 Id 和發送消息時間戳
        console.log(message, 'Send successfully');
        if (message.senderUserId == message.targetId) {
          message.direction = 'receiver'
        } else {
          message.direction = 'sender'
        }
        appType(targetId,'您有一條地理定位消息')
        r(message)
      },
      onError: function (errorCode, message) {
        var info = '';
        j(message)
        switch (errorCode) {
          case RongIMLib.ErrorCode.TIMEOUT:
            info = '逾時';
            break;
          case RongIMLib.ErrorCode.UNKNOWN:
            info = '未知錯誤';
            break;
          case RongIMLib.ErrorCode.REJECTED_BY_BLACKLIST:
            info = '在黑名單中,無法向對方發送消息';
            break;
          case RongIMLib.ErrorCode.NOT_IN_DISCUSSION:
            info = '不在讨論組中';
            break;
          case RongIMLib.ErrorCode.NOT_IN_GROUP:
            info = '不在群組中';
            break;
          case RongIMLib.ErrorCode.NOT_IN_CHATROOM:
            info = '不在聊天室中';
            break;
        }
        console.log('發送失敗:' + info + errorCode);
      }
    });
  })

}
var RegisterMessage = (targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra, ) => {
  return new Promise((r, j) => {

    extra = {
      ...extra,
      id1: wx.getStorageSync('userId'),
      id2: ChatRoom.data.targetId,
      xm1: ChatRoom.data.my.name,
      xm2: ChatRoom.data.your.name,
      tx1: ChatRoom.data.my.headPortrait,
      tx2: ChatRoom.data.your.headPortrait,
    }
    let content = mediaUrl;
    var messageName = 'VoiceMessage'; // 消息名稱
    var objectName = 'RC:VcMsg'; // 消息内置名稱,請按照此格式命名
    var isCounted = true; // 消息計數
    var isPersited = true; // 消息儲存
    var mesasgeTag = new RongIMLib.MessageTag(isCounted, isPersited); // 消息是否儲存是否計數,true true 計數且儲存,false false 不計數不儲存
    var prototypes = ['content', 'duration', 'extra']; // 消息類中的屬性名
    RongIMClient.registerMessageType(messageName, objectName, mesasgeTag, prototypes);
    var conversationType = RongIMLib.ConversationType.PRIVATE; //單聊, 其他會話選擇相應的會話類型即可
    targetId = String(targetId); // 想擷取自己和誰的曆史消息,targetId 指派為對方的 Id
    var msg = new RongIMClient.RegisterMessage.VoiceMessage({
      content,
      extra,
      duration
    });
    RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
      onSuccess: function (message) {
        console.log(message)
        if (message.senderUserId == message.targetId) {
          message.direction = 'receiver'
        } else {
          message.direction = 'sender'
        }
        appType(targetId,'您收到一條語音消息')
        r(message)
        console.log('發送自定義消息成功');
      },
      onError: function (errorCode) {
        j(errorCode)
        console.log('發送自定義消息失敗');
      }
    });
  })

}
var RegisterMessage1 = (targetId, name, sightUrl, fileUrl, fileType, fileSize, duration, extra, ) => {
  return new Promise((r, j) => {

    extra = {
      ...extra,
      id1: wx.getStorageSync('userId'),
      id2: ChatRoom.data.targetId,
      xm1: ChatRoom.data.my.name,
      xm2: ChatRoom.data.your.name,
      tx1: ChatRoom.data.my.headPortrait,
      tx2: ChatRoom.data.your.headPortrait,
    }
    // let content = {
    //   name,
    //   mediaUrl,
    //   fileUrl,
    //   fileType,
    //   fileSize,
    //   duration
    // }
    let content = {
      content: sightUrl,
      sightUrl,
      duration
    };
    var messageName = 'SightMessage'; // 消息名稱
    var objectName = 'RC:SightMsg'; // 消息内置名稱,請按照此格式命名
    var isCounted = true; // 消息計數
    var isPersited = true; // 消息儲存
    var mesasgeTag = new RongIMLib.MessageTag(isCounted, isPersited); // 消息是否儲存是否計數,true true 計數且儲存,false false 不計數不儲存
    var prototypes = ['message', 'duration', 'extra']; // 消息類中的屬性名
    RongIMClient.registerMessageType(messageName, objectName, mesasgeTag, prototypes);
    var conversationType = RongIMLib.ConversationType.PRIVATE; //單聊, 其他會話選擇相應的會話類型即可
    targetId = String(targetId); // 想擷取自己和誰的曆史消息,targetId 指派為對方的 Id
    var msg = new RongIMClient.RegisterMessage.SightMessage({
      message: {
        content
      },
      extra,
      duration
    });
    RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
      onSuccess: function (message) {
        console.log(message)
        if (message.senderUserId == message.targetId) {
          message.direction = 'receiver'
        } else {
          message.direction = 'sender'
        }
        appType(targetId,'您有一條視訊消息')
        r(message)
        console.log('發送自定義消息成功');
      },
      onError: function (errorCode) {
        j(errorCode)
        console.log('發送自定義消息失敗');
      }
    });
  })

}
var TextMessage = (targetId, content, extra) => {
  return new Promise((r, j) => {
    extra = {
      ...extra,
      id1: wx.getStorageSync('userId'),
      id2: ChatRoom.data.targetId,
      xm1: ChatRoom.data.my.name,
      xm2: ChatRoom.data.your.name,
      tx1: ChatRoom.data.my.headPortrait,
      tx2: ChatRoom.data.your.headPortrait,
    }
    var msg = new RongIMLib.TextMessage({
      content,
      extra
    });
    // request({
    //   url: 'rongyun/pushWx',
    //   data: {
    //     token:wx.getStorageSync("token"),
    //     thing2:content

    //   }
    // })
    var conversationType = RongIMLib.ConversationType.PRIVATE; // 單聊, 其他會話選擇相應的會話類型即可
    targetId = String(targetId); // 目标 Id
    RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
      onSuccess: function (message) {
        // message 為發送的消息對象并且包含伺服器傳回的消息唯一 Id 和發送消息時間戳
        console.log(message)
        appType(targetId,content)
        if (message.senderUserId == message.targetId) {
          message.direction = 'receiver'
        } else {
          message.direction = 'sender'
        }
        r(message)
        console.log('Send successfully');
      },
      onError: function (errorCode, message) {
        j(errorCode)
        console.log('發送失敗: ' + message + errorCode);
      }
    });
  })
}
var clearUnreadCount = (targetId) => {

  var conversationType = RongIMLib.ConversationType.PRIVATE;
  var targetId = String(targetId);
  RongIMClient.getInstance().clearUnreadCount(conversationType, targetId, {
    onSuccess: function (message) {
      console.log(message)
      // 清除未讀消息成功
      // if (getCurrentPages()[0].route != "pages/conversation/chat" ) {
      getList(userListModle)
      // }
    },
    onError: function (error) {
      console.log(error)

      // error => 清除未讀消息數錯誤碼
    }
  });


}
var ReadReceiptMessage = (targetId, messageUId, lastMessageSendTime, type = 1) => {
  console.log(targetId, messageUId, lastMessageSendTime, type)
  var conversationType = RongIMLib.ConversationType.PRIVATE; // 單聊, 其他會話選擇相應的會話類型即可
  var msg = new RongIMLib.ReadReceiptMessage({
    messageUId,
    lastMessageSendTime,
    type
  })
  targetId = String(targetId)
  RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
    onSuccess: function (message) {
      // message 為發送的消息對象并且包含伺服器傳回的消息唯一 Id 和發送消息時間戳
      console.log(message, 'Send successfully');
    },
    onError: function (errorCode, message) {
      var info = '';
      switch (errorCode) {
        case RongIMLib.ErrorCode.TIMEOUT:
          info = '逾時';
          break;
        case RongIMLib.ErrorCode.UNKNOWN:
          info = '未知錯誤';
          break;
        case RongIMLib.ErrorCode.REJECTED_BY_BLACKLIST:
          info = '在黑名單中,無法向對方發送消息';
          break;
        case RongIMLib.ErrorCode.NOT_IN_DISCUSSION:
          info = '不在讨論組中';
          break;
        case RongIMLib.ErrorCode.NOT_IN_GROUP:
          info = '不在群組中';
          break;
        case RongIMLib.ErrorCode.NOT_IN_CHATROOM:
          info = '不在聊天室中';
          break;
      }
      console.log('發送失敗:' + info + errorCode);
    }
  });
}
// 初始化融雲
function connectIM(context, token) {
  RongIMClient = RongIMLib.RongIMClient;
  RongIMLib.RongIMClient.init(appkey);
  // let RongIMClient = RongIMLib.RongIMClient;
  // RongIMLib.RongIMClient.init(appkey);

  // console.log(RongIMClient.Conversation.get)
  // console.log(RongIMClient.getInstance().getFileToken)

  /* 連接配接狀态監聽器 */
  RongIMClient.setConnectionStatusListener({
    onChanged: function (status) {
      /* status 辨別目前連接配接狀态 */
      switch (status) {
        case RongIMLib.ConnectionStatus.CONNECTED:
          console.log('連結成功');
          wx.showToast({
            title: '連結成功',
            icon: "none"
          })
          break;
        case RongIMLib.ConnectionStatus.CONNECTING:
          console.log('正在連結');
          break;
        case RongIMLib.ConnectionStatus.DISCONNECTED:
          console.log('斷開連接配接');
          wx.showToast({
            title: '斷開連接配接',
            icon: "none"
          })
          break;
        case RongIMLib.ConnectionStatus.KICKED_OFFLINE_BY_OTHER_CLIENT:
          console.log('其他裝置登入');
          wx.showToast({
            title: '其他裝置登入',
            icon: "none"
          })
          break;
        case RongIMLib.ConnectionStatus.DOMAIN_INCORRECT:
          console.log('域名不正确');
          wx.showToast({
            title: '域名不正确',
            icon: "none"
          })
          break;
        case RongIMLib.ConnectionStatus.NETWORK_UNAVAILABLE:
          console.log('網絡不可用');

          reconnect()
          wx.showToast({
            title: '網絡不可用',
            icon: "none"
          })
          break;
      }
    }
  });

  /* 消息監聽器 */
  RongIMClient.setOnReceiveMessageListener({
    onReceived: function (message) {
      console.log(message)
      if (userListModle) {
        userListModle.getList(message)
      }
      if (ChatRoom && ChatRoom.data.targetId == message.targetId) {
        ChatRoom.setNewMessage(message)
      }
    }
  });

  var config = {
    timeout: 20000,
    RongIMLib: RongIMLib,
    RongRTC: RongRTC,
    url: msUrls[0].url
  };
  var rongCallLib = RongCallLib.init(config);
  context.globalData.Service.rongCallLib = rongCallLib
  console.log(111, commandWatcher)
  rongCallLib.commandWatch(commandWatcher);
  console.log(token)
  RongIMClient.connect(token, {
    onSuccess: function (userId) {
      console.log('連接配接成功, 使用者 ID 為', userId);
      // 連接配接已成功, 此時可通過 getConversationList 擷取會話清單并展示
    },
    onTokenIncorrect: function () {
      console.log('連接配接失敗, 失敗原因: token 無效');
    },
    onError: function (errorCode) {
      var info = '';
      switch (errorCode) {
        case RongIMLib.ErrorCode.TIMEOUT:
          info = '逾時';
          break;
        case RongIMLib.ConnectionState.UNACCEPTABLE_PAROTOCOL_VERSION:
          info = '不可接受的協定版本';
          break;
        case RongIMLib.ConnectionState.IDENTIFIER_REJECTED:
          info = 'appkey不正确';
          break;
        case RongIMLib.ConnectionState.SERVER_UNAVAILABLE:
          info = '伺服器不可用';
          break;
      }
      console.log(info);
    }
  });
  context.globalData.Service = {
    ...context.globalData.Service,
    Status: {},
    Conversation: {},
    User: {},
    CONNECTION_STATUS: {},
    RongIMClient: RongIMClient.getInstance(),
    RongIMLib: RongIMLib,
    getList,
    layout,
    getHistory,
    ConversationType: RongIMLib.ConversationType,
    MessageType: RongIMClient.MessageType,
  }

}

App({

  setList(context) {

    userListModle = context
  },
  setChat(context) {
    setChat(context)
  },
 
  setChatRoom(context) {
    ChatRoom = context
  },
  onHide() {
    if(wx.getStorageSync('status') == 2){
      appletOnLine(0)
    }
  },
  onShow(){
    if(wx.getStorageSync('status') == 2){
      appletOnLine(1)
    }
  },
  setConversationList(conversationList) {
    if (chatList) {
    
      chatList.communicationList(conversationList)
    }
  },
  connectIM(token) {
    console.log(token, '開始初始化')
    connectIM(this, token)
  },
  onLaunch: function () {
    // 展示本地存儲能力
    let token = wx.getStorageSync('RYtoken')
    if (token) {
      this.connectIM(token)
    }
    if (wx.getStorageSync('userId') && wx.getStorageSync('token')) {}
    const updateManager = wx.getUpdateManager()
    updateManager.onCheckForUpdate(function (res) {
      // 請求完新版本資訊的回調
      console.log(res.hasUpdate)
    })
    updateManager.onUpdateReady(function () {
      wx.showModal({
        title: '更新提示',
        content: '新版本已經準備好,是否重新開機應用?',
        success(res) {
          if (res.confirm) {
            // 新的版本已經下載下傳好,調用 applyUpdate 應用新版本并重新開機
            updateManager.applyUpdate()
          }
        }
      })
    })
    updateManager.onUpdateFailed(function () {
      // 新版本下載下傳失敗
    })
    wx.login({
      success: res => {
        // 發送 res.code 到背景換取 openId, sessionKey, unionId
      }
    })
    // 擷取使用者資訊
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.userInfo']) {
          // 已經授權,可以直接調用 getUserInfo 擷取頭像昵稱,不會彈框
          wx.getUserInfo({
            success: res => {
              // 可以将 res 發送給背景解碼出 unionId
              this.globalData.userInfo = res.userInfo

              // 由于 getUserInfo 是網絡請求,可能會在 Page.onLoad 之後才傳回
              // 是以此處加入 callback 以防止這種情況
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  },
  TextMessage(targetId, content, extra = {}) {
    return TextMessage(targetId, content, extra)
  },
  ImageMessage(targetId, base64Str, imageUri, extra = {}) {
    return ImageMessage(targetId, base64Str, imageUri, extra)
  },
  RegisterMessage(targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra = {}) {
    return RegisterMessage(targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra)
  },
  RegisterMessage1(targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra = {}) {
    return RegisterMessage1(targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra)
  },
  ReadReceiptMessage({
    targetId,
    messageUId,
    lastMessageSendTime,
    type
  }) {
    ReadReceiptMessage(targetId, messageUId, lastMessageSendTime, type)
  },
  clearUnreadCount(targetId) {
    clearUnreadCount(targetId)
  },
  LocationMessage(targetId, latitude, longitude, poi, content) {
    return LocationMessage(targetId, latitude, longitude, poi, content)
  },
  reconnect() {
    reconnect()
  },
  onReceiveMessage(message) {
    console.log(message)
    wx.navigateTo({
      url: '../../call/call?data=' + JSON.stringify(message)
    })
    return false
  },
  globalData: {
    Service: {
      Status: {},
      Conversation: {},
      User: {},
      CONNECTION_STATUS: {},
      getList,
      layout,
      getHistory,
      rongCallLib: null,
      ConversationType: RongIMLib.ConversationType,
    },
    userInfo: null,
    statusBarHeight: wx.getSystemInfoSync()['statusBarHeight'],
   
  }
})
           

這個是我聊天界面的js(在官方案例的基礎上修改了,目前還沒有整理好)

import {
  request
} from "../../request/index"
let clear = true
let timer = null;
let dangDate = null;
let LTID = null
let timeInt = 4*60*60
const scale = wx.getSystemInfoSync().windowWidth / 750
//  通話配置
const callUtils = require('../../utils/util');
const Config = require('../../config.js');
const common = require('../common');
let newW = false
const {
  co
} = require('../../helper');
const {
  apps,
  serverUrl,
  msUrls
} = Config;
const reg = /^\w{1,15}$/;
let doLogin = false;

//  預設配置
const utils = require('../utils/utils.js');
const {
  adapterHeight
} = utils.getAdapterheight();


const {
  globalData,
  setChatRoom,
  TextMessage,
  ImageMessage,
  LocationMessage,
  RegisterMessage,
  RegisterMessage1,
  clearUnreadCount
} = getApp();
const {
  Service: {
    Status,
    Message,
    File,
    Conversation,
    RongIMClient,
    RongIMLib,
    getHistory
  }
} = globalData;
// 
const RongEmoji = require('../lib/RongIMEmoji-2.2.6.js');
RongEmoji.init();

const softKeyboardHeight = 210;

const getToView = (context) => {
  let {
    messageList
  } = context.data;
  let index = messageList.length - 1;
  let message = messageList[index] || {};
  return message.uId || '';
};
const setNewMessage = (context, newMessage) => {
  console.log(newMessage, 1111111111111, getCurrentPages())
  if (newMessage.senderUserId == newMessage.targetId) {
    newMessage.direction = 'receiver'
  } else {
    newMessage.direction = 'sender'
  }
  context.data.messageList.push(newMessage)
  context.setData({
    messageList: context.data.messageList
  })
  if (clear) {
    console.log('qimhcji')
    clearUnreadCount(newMessage.targetId)
  }
  gotoView(context)
}
const imgBase64 = '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';
const setKeyboardPos = (context, keyboardHeight, adapterHeight) => {
  keyboardHeight = keyboardHeight || 0;
  let data;
  let isScroll = (keyboardHeight > 0);
  if (isScroll) {
    data = {
      bottom: adapterHeight + keyboardHeight,
      isShowEmojiSent: false,
      toView: getToView(context)
    };
  } else {
    data = {
      bottom: adapterHeight + keyboardHeight,
      isShowEmojiSent: false
    };
  }
  context.setData(data);
};

const showSoftKeyboard = (context, display) => {
  context.setData({
    display: display,
    bottom: softKeyboardHeight,
    isShowKeyboard: false,
    toView: getToView(context)
  });
};
const hideSoftKeyboard = (context) => {
  context.setData({
    display: {
      emoji: 'none',
      more: 'none'
    }
  });
};

const hideKeyboard = (context) => {
  let keyboardHeight = 0;
  let {
    adapterHeight
  } = context.data;
  setKeyboardPos(context, keyboardHeight, adapterHeight);
  hideSoftKeyboard(context);
};

const formatEmojis = () => {
  let list = RongEmoji.list;
  return utils.sliceArray(list, {
    size: 24
  });
};

const getMessageList = (context, params) => {
  let {
    position
  } = params;
  let event = params.type == 4 ? Message.getChatRoomMessageList : Message.getList;
  return event(params).then((result) => {
    let messages = result.messageList;
    let hasMore = result.hasMore;

    let {
      messageList,
      playingVoice,
      playingMusicComponent
    } = context.data;
    messageList = messages.concat(messageList);
    let toView = '';
    if (params.position == 0) {
      let index = messageList.length - 1;
      let message = messageList[index] || {};
      toView = message.uId || '';
    }
    let isFirst = (position == 0);
    if (!hasMore && !isFirst) {
      // 灰條提示
      toView = 'message-notify-without';
      context.setData({
        hasMore: hasMore
      });
    }

    if (isFirst) {
      context.setData({
        messageList: messageList,
        isAllowScroll: true,
        toView: toView
      });
    } else {
      context.setData({
        messageList: messageList,
        isAllowScroll: true
      });
    }

  });
};

const updatePlayStatus = (context, {
  newMusicComponent,
  isPlaying
}, callback) => {
  let {
    data: {
      messageList,
      playingMusicComponent
    }
  } = context;
  callback = callback || utils.noop;
  messageList.map((message) => {
    callback(message);
    return message;
  });
  if (playingMusicComponent) {
    playingMusicComponent.setData({
      isPlaying
    });
  }
  if (newMusicComponent) {
    context.setData({
      playingMusicComponent: newMusicComponent,
      messageList
    });
  } else {
    context.setData({
      messageList
    });
  }

};

const stopPlayMusic = (context) => {
  let newMusicComponent = null,
    isPlaying = false;
  updatePlayStatus(context, {
    newMusicComponent,
    isPlaying
  }, (message) => {
    utils.extend(message, {
      isPlaying
    });
  });
};

const getImageUrls = (context) => {
  let {
    messageList
  } = context.data;
  return messageList.filter(message => {
    return message.name == 'ImageMessage';
  }).map(message => {
    return message.content.imageUri;
  });
};
const byAccount = (context, type) => {
  request({
    url: 'my/byAccount',
    data: {
      accountId: type == 'my' ? wx.getStorageSync('userId') : context.data.userId
    }
  }).then(e => {
    if (e.data.status == 1) {
      context.setData({
        [type]: e.data.data
      })
    }
  })
}
const mygetHistory = (context, first) => {
  console.log(context.data.targetId, context.data.timestrap, context.data.count)
  getHistory(context.data.targetId, context.data.timestrap, context.data.count).then(({
    list,
    hasMsg
  }) => {
    list = [...list, ...context.data.messageList]
    console.log(list, hasMsg)
    list.forEach(element => {
      if (element.senderUserId == element.targetId) {
        element.direction = 'receiver'
      } else {
        element.direction = 'sender'
      }
    })
    context.setData({
      messageList: list,
      hasMsg: hasMsg,
      timestrap: list[0].sentTime
    })
    if (first) {
      gotoView(context,true)
    }
  })
}
const onLoad = (context, query) => {
  clear = true
  newW = true
  setChatRoom(context)
  let {
    title,
    type,
    targetId
  } = query;
  wx.setNavigationBarTitle({
    title
  });
  context.setData({
    adapterHeight: adapterHeight,
    type,
    targetId,
    userId: targetId
  });
  mygetHistory(context, true);
  byAccount(context, 'my');
  byAccount(context, 'your');
  let keyboardHeight = 0;

  setKeyboardPos(context, keyboardHeight, adapterHeight);
  // app.setChat(context)
  let position = 0;
  let count = 15;
  // getMessageList(context, { type, targetId, position, count });

  // Message.watch((message) => {
  //   if (message.isOffLineMessage) {
  //     return;
  //   }
  //   if (message.type == type && message.targetId === targetId) {
  //     let { messageList } = context.data;
  //     // console.log(message,1111111111111111111111111111)
  //     messageList.push(message);
  //     context.setData({
  //       messageList,
  //       toView: message.uId
  //     });
  //     Conversation.clearUnreadCount({
  //       type, targetId
  //     });
  //   }
  // });
};

const onUnload = (context) => {
  clear = false
  newW = false
  let {
    playingVoice,
    playingMusicComponent
  } = context.data;
  if (playingVoice) {
    playingMusicComponent.stop();
  }
  if (playingMusicComponent) {
    playingMusicComponent.stop();
  }
  // Message.unwatch();
};

const showVoice = (context) => {
  let {
    adapterHeight
  } = context.data;
  context.setData({
    isShowKeyboard: false
  });
  hideKeyboard(context);
};

const showKeyboard = (context) => {
  context.setData({
    isShowKeyboard: true
  });
  hideKeyboard(context);
};
  const gotoView = (context,first) => {

    context.setData({
      toView: context.data.messageList[context.data.messageList.length - 1].messageUId
    })
    if (timer === null && !first && newW) {
      console.log("Start")
      timer = setInterval(() => {
        dangDate = parseInt(dangDate) + 1
        // console.log(dangDate)
        if (dangDate > timeInt) {
          context.showpjPopup()
          dangDate = 0
          wx.setStorageSync(LTID, 0)
          clearInterval(timer)
          timer = null
        }
      }, 1000);
    }
  }
const recorderManager = wx.getRecorderManager()

const startRecording = (context) => {

  wx.getSetting({
    success(res) {
      console.log(res.authSetting)
      // res.authSetting = {
      //   "scope.userInfo": true,
      //   "scope.userLocation": true
      // }
      wx.authorize({
        scope: 'scope.record',
        success() {
          // 使用者已經同意小程式使用錄音功能,後續調用 wx.startRecord 接口不會彈窗詢問
          wx.startRecord()
        }
      })
    }
  })
  // setTimeout(function () {
  //   wx.stopRecord() // 結束錄音
  // }, 1000)
  context.setData({
    isRecording: true
  });
  let record = () => {
    recorderManager.start({
      format: 'aac'
    });
  };
  wx.getSetting({
    success(res) {
      if (!res.authSetting['scope.record']) {
        wx.authorize({
          scope: 'scope.record',
          success: record
        })
      } else {
        record();
      }
    }
  })
};

const stopRecording = (context) => {
  context.setData({
    isRecording: false
  });
  let {
    type,
    targetId,
    messageList
  } = context.data
  recorderManager.onStop((res) => {
    console.log('recorder stop', res)
    var {
      tempFilePath,

      fileSize
    } = res;
    console.log(tempFilePath, duration);
    var duration = res.duration
    duration = Math.ceil(duration / 1000)
    var fileType = RongIMLib.FileType.IMAGE;
    RongIMClient.getFileToken(fileType, {
      onSuccess: function (data) {
        console.log('上傳 token 為', data.token);
        return wxUpload({
          path: tempFilePath,
          name: 'voice.aac'
        }, data.token).then(result => {
          console.log(result)
          let content = {
            // remoteUrl: file.downloadUrl,
            // duration: Math.ceil(duration / 1000)
          };
          let qiniuHash, qiniuName;
          const {
            data
          } = result;
          const {
            hash,
            name
          } = JSON.parse(data);
          qiniuHash = hash, qiniuName = name;
          console.log(RongIMClient.getFileUrl(fileType, qiniuHash, qiniuName, res))
          return RongIMClient.getFileUrl(fileType, qiniuHash, qiniuName, {
            onSuccess: (e) => {
              console.log(e.downloadUrl)
              var mediaUrl = e.downloadUrl
              var fileUrl = e.downloadUrl
              let extra = {}
              RegisterMessage(targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra).then((e) => {
                messageList.push(e)
                context.setData({
                  messageList: messageList
                })
                gotoView(context)
              })
              // ImageMessage(targetId,tempFilePath,e.downloadUrl, extra ).then(e => {
              //   messageList.push(e)
              //   context.setData({
              //     messageList: messageList
              //   })
              //   gotoView(context)
              // }).catch(e => {
              //   wx.showToast({
              //     title: '發送失敗~',
              //     icon: "none"
              //   })
              // })
            },
            onError: (e) => {
              console.log(e)
            }
          });

          // Message.sendImage({
          //   type,
          //   targetId,
          //   imageUri,
          //   extra,
          //   content: imgBase64
          // }).then(message => {});
        });

      },
      onError: function (error) {
        console.log('get file token error', error);
      }
    })
    //   File.upload({
    //     path: tempFilePath,
    //     name: 'voice.aac'
    //   }, 2).then(file => {
    //     console.log(file)
    //     let content = {
    //       remoteUrl: file.downloadUrl,
    //       duration: Math.ceil(duration / 1000)
    //     };
    //     let {
    //       type,
    //       targetId,
    //       messageList
    //     } = context.data;
    //     Message.sendVoice({
    //       type,
    //       targetId,
    //       content
    //     }).then(message => {
    //       messageList.push(message);
    //       context.setData({
    //         messageList,
    //         toView: message.uId
    //       });
    //     });
    //   });
  })
  recorderManager.stop();
};
const uploadBos = (url, fileInfo, header) => {
  return new Promise((resolve, reject) => {
    const fileData = wx.getFileSystemManager().readFileSync(fileInfo.path);
    wx.request({
      url: url,
      header: header,
      method: 'POST',
      data: fileData,
      success: function (res) {
        console.log(res);
        let data = {
          downloadUrl: url, //上傳成功的 url 即為下載下傳 url
          isBosRes: true // 判斷是否是百度傳回
        }
        resolve(data);
      },
      fail: reject
    })
  })

}
const wxUpload = (fileInfo, token) => {
  return new Promise((resolve, reject) => {
    const uploadTask = wx.uploadFile({
      url: Config.qiniuHost,
      filePath: fileInfo.path,
      name: 'file',
      formData: {
        token: token
      },
      success: resolve,
      fail: function (err) {
        console.log(err)
        // console.log('upload qiniu failed', err);
        // uploadBos(bosUrl, fileInfo, bosHeaders).then(function(res) {
        //   resolve(res);
        // },function(err) {
        //   reject(err)
        // });
      }
    })
    wx.showLoading({
      title: '上傳中',
    })
    uploadTask.onProgressUpdate(res => {
      if (res.progress == 100) {
        wx.hideLoading({
          complete: (res) => { },
        })
      }
      console.log('上傳進度', res.progress)
      console.log('已經上傳的資料長度', res.totalBytesSent)
      console.log('預期需要上傳的資料總長度', res.totalBytesExpectedToSend)
    })
  });
};

const showEmojis = (context) => {
  showSoftKeyboard(context, {
    emoji: 'block',
    more: 'none'
  });
};

const showMore = (context) => {
  showSoftKeyboard(context, {
    emoji: 'none',
    more: 'block'
  });
};

const selectEmoji = (context, event) => {
  var content = context.data.content;
  var {
    emoji
  } = event.target.dataset;
  content = content + emoji;
  context.setData({
    content: content,
    isShowEmojiSent: true
  });
};

const sendText = (context) => {
  let {
    content,
    type,
    targetId,
    messageList
  } = context.data;
  // console.log(content)
  // console.log(content, type, targetId, messageList)
  
  context.setData({
    content: '',
    isShowEmojiSent: false
  });

  TextMessage(targetId, content).then(e => {
    messageList.push(e)
    context.setData({
      messageList: messageList
    })
    gotoView(context)
  }).catch(e => {
    wx.showToast({
      title: '發送失敗~',
      icon: "none"
    })
  })
  // content = {
  //   content,
  //   extra
  // }
  // console.log(content)
  // content = JSON.stringify(content)
  // if (content.length == 0) {
  //   return;
  // }
  // Message.sendText({
  //   type,
  //   targetId,
  //   content,
  // }).then(message => {
  //   message.content.extra = extra
  //   message.extra = extra
  //   messageList.push(message);
  //   context.setData({
  //     messageList,
  //     toView: message.uId
  //   });
  // });
};

const getMoreMessages = (context) => {
  let {
    type,
    targetId,
    hasMore,
    messageList
  } = context.data;
  messageList = messageList || [];
  let firstMessage = messageList[0] || {};
  let position = firstMessage.sentTime || 0;
  let count = 5;
  if (context.data.hasMsg) {
    // context.data.timestrap ++ ;
    context.setData({
      isAllowScroll: false,
    });
    mygetHistory(context);
    // , { type, targetId, position, count }
  } else {
    context.setData({
      isAllowScroll: false,
    });
    wx.showToast({
      title: '沒有更多消息了',
      icon: "none",
    })
  }
};

const sendImage = (context) => {
  wx.chooseImage({
    count: 1,
    sizeType: ['original'],
    sourceType: ['album', 'camera'],
    success: (res) => {
      let {
        tempFilePaths,
        tempFiles
      } = res;
      let tempFilePath = tempFilePaths[0];
      console.log('tempFilePath', tempFilePath)
      // ImageMessage
      wx.getImageInfo({
        src: tempFilePath,
        success: (res) => {
          let extra = utils.compress(res);
          let {
            type,
            targetId,
            messageList
          } = context.data;

          let name = 'RC:ImgMsg';
          let content = {
            imageUri: tempFilePath,
            extra
          };
          console.log(res, content)
          var fileType = RongIMLib.FileType.IMAGE;
          RongIMClient.getFileToken(fileType, {
            onSuccess: function (data) {
              console.log('上傳 token 為', data.token);
              return wxUpload({
                path: tempFilePath,
                name: 'image.png'
              }, data.token).then(result => {
                console.log(result)
                let qiniuHash, qiniuName;
                const {
                  data
                } = result;
                const {
                  hash,
                  name
                } = JSON.parse(data);
                qiniuHash = hash, qiniuName = name;
                console.log(RongIMClient.getFileUrl(fileType, qiniuHash, qiniuName, res))
                return RongIMClient.getFileUrl(fileType, qiniuHash, qiniuName, {
                  onSuccess: (e) => {
                    ImageMessage(targetId, tempFilePath, e.downloadUrl, extra).then(e => {
                      messageList.push(e)
                      context.setData({
                        messageList: messageList
                      })
                      gotoView(context)
                    }).catch(e => {
                      wx.showToast({
                        title: '發送失敗~',
                        icon: "none"
                      })
                    })
                  },
                  onError: (e) => {
                    console.log(e)
                  }
                });
              });
            },
            onError: function (error) {
              console.log('get file token error', error);
            }
          })
        }
      })
    }
  })
};

const sendFile = (context) => {
  let {
    type,
    targetId,
    messageList
  } = context.data;

  wx.chooseMessageFile({
    count: 1,
    type: 'file',
    success: function (res) {
      let {
        tempFiles
      } = res;
      let {
        name,
        size,
        type: fileType
      } = tempFiles[0];
      File.upload(tempFiles[0], 4).then(result => {
        const {
          downloadUrl: fileUrl
        } = result;
        console.log(fileUrl)
        let content = {
          name,
          size,
          type: fileType,
          fileUrl
        };
        let message = Message.create({
          type: 4,
          targetId,
          name: 'RC:FileMsg',
          content
        });
        messageList.push(message);
        context.setData({
          messageList,
          toView: message.uId
        });
        Message.sendFile({
          type,
          targetId,
          name,
          size,
          fileUrl
        })
      });
    }
  })
}
const sendAudio = (context) => {
  let {
    type,
    targetId,
    messageList
  } = context.data;
  context.login()
}
const sendVideo = (context) => {
  wx.chooseVideo({
    count: 1,
    sourceType: ['album', 'camera'],
    success: (res) => {
      console.log('tempFilePath', res)
      let extra = utils.compress(res);
      let {
        type,
        targetId,
        messageList
      } = context.data;
      let content = {
        imageUri: tempFilePath,
      };
      var {
        tempFilePath,
        fileSize,
        duration
      } = res;
      console.log(tempFilePath, duration);
      var fileType = RongIMLib.FileType.IMAGE;
      RongIMClient.getFileToken(fileType, {
        onSuccess: function (data) {
          console.log('上傳 token 為', data.token);
          return wxUpload({
            path: tempFilePath,
            name: 'voice.mp'
          }, data.token).then(result => {
            console.log(result)
            let content = {
              // remoteUrl: file.downloadUrl,
              // duration: Math.ceil(duration / 1000)
            };
            let qiniuHash, qiniuName;
            const {
              data
            } = result;
            const {
              hash,
              name
            } = JSON.parse(data);
            qiniuHash = hash, qiniuName = name;
            console.log(RongIMClient.getFileUrl(fileType, qiniuHash, qiniuName, res))
            return RongIMClient.getFileUrl(fileType, qiniuHash, qiniuName, {
              onSuccess: (e) => {
                console.log(e.downloadUrl)
                var mediaUrl = e.downloadUrl
                var fileUrl = e.downloadUrl
                let extra = {}
                RegisterMessage1(targetId, name, mediaUrl, fileUrl, fileType, fileSize, duration, extra).then((e) => {
                  messageList.push(e)
                  context.setData({
                    messageList: messageList
                  })
                  gotoView(context)
                })

              },
              onError: (e) => {
                console.log(e)
              }
            });
          });
        },
        onError: function (error) {
          console.log('get file token error', error);
        }
      })
    }
  })
}
const sendMusic = (context) => {
  let {
    content,
    type,
    targetId,
    messageList
  } = context.data;
  Message.sendMusic({
    type,
    targetId
  }).then(message => {
    messageList.push(message);
    context.setData({
      messageList,
      toView: message.uId
    });
  });
};

const playVoice = (context, event) => {
  let voiceComponent = event.detail;
  let {
    playingVoice
  } = context.data;
  if (playingVoice) {
    let playingId = playingVoice.__wxExparserNodeId__;
    let voiceId = voiceComponent.__wxExparserNodeId__;
    // 兩次播放為同個音頻,狀态保持不變 
    if (playingId == voiceId) {
      return;
    }
    let {
      innerAudioContext
    } = playingVoice.data;
    playingVoice.setData({
      isPlaying: false
    });
    innerAudioContext.stop();
  }
  context.setData({
    playingVoice: voiceComponent
  });
};

const playMusic = (context, event) => {
  let newMusicComponent = event.detail;
  let {
    playingMusicComponent,
    messageList
  } = context.data;
  let {
    properties: {
      message: {
        messageUId: newPlayId
      }
    }
  } = newMusicComponent
  let playingId = '';

  // 連續點選播放不同音樂
  if (playingMusicComponent) {
    let {
      properties: {
        message
      }
    } = playingMusicComponent;
    playingId = message.messageUId;
    //先停止上一個,再播放
    let isDiffMusic = (playingId != newPlayId);
    if (isDiffMusic) {
      let {
        innerAudioContext
      } = playingMusicComponent.data;
      playingMusicComponent.setData({
        isPlaying: false
      });
      innerAudioContext.stop();
    }
  }
  let isPlaying = false;
  updatePlayStatus(context, {
    newMusicComponent,
    isPlaying
  }, (message) => {
    let {
      messageUId
    } = message;
    // 預設為未播放狀态
    isPlaying = false;
    if (messageUId == newPlayId) {
      isPlaying = true;
    }
    utils.extend(message, {
      isPlaying
    });
  });
};

const previewImage = (context, event) => {
  let currentImageUrl = event.detail;
  let urls = getImageUrls(context);
  if (utils.isEmpty(urls)) {
    urls.push(currentImageUrl);
  }
  wx.previewImage({
    current: currentImageUrl,
    urls: urls
  })
};

const stopMusic = (context, event) => {
  let musicComponent = event.detail;
  let {
    properties: {
      message: {
        messageUId
      }
    }
  } = musicComponent;

  let {
    messageList,
    playingMusicComponent
  } = context.data;
  if (playingMusicComponent) {
    let {
      data: {
        innerAudioContext
      }
    } = playingMusicComponent;
    innerAudioContext.stop();
  }
  musicComponent.setData({
    isPlaying: false
  });
  stopPlayMusic(context);
};
// call用到的方法
const expertRecord = (context) => {
  if (context.data.count == 0) {
    request({
      url: 'index/expertRecord',
      data: {
        token: wx.getStorageSync("token"),
        id: context.data.userId
        // 
      }
    }).then((e) => {
      if (e.data.status === 1) {
        context.setData({
          count: 1
        })
      }
    })
  }

}
Page({
  data: {
    count: 8,
    timestrap: 0,
    hasMsg: true,
    my: {},
    your: {},
    pjvalue: 0,
    // call中用到的data
    userId: '',
    isHiddenTip: true,
    pjshow: false,
    apps,
    appkeys: apps.map(item => item.appkey),
    appkeyIndex: 0,
    msUrls: msUrls.map(item => item.title),
    msUrl: msUrls[0],
    // 預設data
    content: '',
    messageList: [],
    bottom: 0,
    adapterHeight: 0,
    display: {
      emoji: 'none',
      more: 'none'
    },
    emojis: formatEmojis(),
    isShowEmojiSent: false,
    isRecording: false,
    isShowKeyboard: false,
    hasMore: true,
    toView: '',
    playingVoice: null,
    playingMusicComponent: null,
    isAllowScroll: true,
    scrollTop: 0
  },
  evaluateExpert() {
    request({
      url: "index/evaluateExpert",
      data: {
        token: wx.getStorageSync('token'),
        id: this.data.userId,
        level: this.data.pjvalue
      }
    }).then(res => {
      if (res.data.status == 1) {
        wx.showToast({
          title: res.data.msg,
        })
        this.onpjClose()
      }
    })
  },
  onpjChange(event) {
    this.setData({
      pjvalue: event.detail,
    });
  },
  showpjPopup() {
    if (wx.getStorageSync('status') == 1) {
      this.setData({ pjshow: true });
    }
  },

  onpjClose() {
    this.setData({ pjshow: false, pjvalue: 0 });
  },
  expertRecord: function () {
    expertRecord(this)
  },
  hideKeyboard: function () {
    hideKeyboard(this);
  },
  selectEmoji: function (event) {
    selectEmoji(this, event);
  },
  sendText: function () {
    // if (timer === null) {
    //   timer = setInterval(() => {
    //     dangDate = parseInt(dangDate) + 1
    //     console.log(dangDate)
    //     if (dangDate > timeInt) {
    //       this.showpjPopup()
    //       dangDate = 0
    //       clearInterval(timer)
    //       timer = null
    //     }
    //   }, 1000);
    // }
    sendText(this);
  },
  getMoreMessages: function (event) {
    getMoreMessages(this);
  },
  sendImage: function () {

    // if (timer === null) {
    //   timer = setInterval(() => {
    //     dangDate = parseInt(dangDate) + 1
    //     if (dangDate > timeInt) {
    //       this.showpjPopup()
    //       dangDate = 0
    //       clearInterval(timer)
    //       timer = null
    //     }
    //   }, 1000);
    // }

    sendImage(this);
  },
  sendFile: function () {
    // if (timer === null) {
    //   timer = setInterval(() => {
    //     dangDate = parseInt(dangDate) + 1
    //     if (dangDate > timeInt) {
    //       this.showpjPopup()
    //       dangDate = 0
    //       clearInterval(timer)
    //       timer = null
    //     }
    //   }, 1000);
    // }
    sendFile(this);
  },
  sendAudio: function () {
    // if (timer === null) {
    //   timer = setInterval(() => {
    //     dangDate = parseInt(dangDate) + 1
    //     if (dangDate > timeInt) {
    //       this.showpjPopup()
    //       dangDate = 0
    //       clearInterval(timer)
    //       timer = null
    //     }
    //   }, 1000);
    // }
    sendAudio(this)
  },
  sendVideo: function () {

    // if (timer === null) {
    //   timer = setInterval(() => {
    //     dangDate = parseInt(dangDate) + 1
    //     if (dangDate > timeInt) {
    //       this.showpjPopup()
    //       dangDate = 0
    //       clearInterval(timer)
    //       timer = null
    //     }
    //   }, 1000);

    // }
    sendVideo(this)
  },
  sendMusic: function () {

    // if (timer === null) {
    //   timer = setInterval(() => {
    //     dangDate = parseInt(dangDate) + 1
    //     if (dangDate > timeInt) {
    //       this.showpjPopup()
    //       dangDate = 0
    //       clearInterval(timer)
    //       timer = null
    //     }
    //   }, 1000);

    // }
    sendMusic(this);
  },
  showVoice: function () {

    showVoice(this);
  },
  showKeyboard: function () {
    showKeyboard(this);
  },
  startRecording: function () {
    startRecording(this);
  },
  stopRecording: function () {
    stopRecording(this);
  },
  showEmojis: function () {
    showEmojis(this);
  },
  showMore: function () {
    showMore(this);
  },
  gotoView(){
    gotoView(this)
  },
  // 以下是事件
  onLoad: function (query) {
    onLoad(this, query)
    LTID = wx.getStorageSync('LT' + wx.getStorageSync('userId') + query.targetId)
    console.log()
    if (dangDate === null) {
      if (LTID) {
        dangDate = LTID ? LTID : 0
      } else {
        wx.setStorageSync('LT' + wx.getStorageSync('userId') + query.targetId, 0)
        dangDate = 0
      }
    }
    console.log('LT' + wx.getStorageSync('userId') + query.targetId,LTID,dangDate)
    query.count && this.setData({
      count: query.count
    })
  },
  onUnload: function () {
    onUnload(this);
    console.log(LTID, LTID !== null)
    if (LTID !== null) {
      console.log('LT' + wx.getStorageSync('userId') + this.data.targetId, dangDate)
      wx.setStorageSync('LT' + wx.getStorageSync('userId') + this.data.targetId, dangDate)
      LTID = null
      dangDate = null
    }
    clearTimeout(timer)
    timer = null
  },
  onInput: function (event) {
    this.setData({
      content: event.detail.value
    });
  },
  onFocus: function (event) {
    let {
      height
    } = event.detail;
    let adapterHeight = 0;
    setKeyboardPos(this, height, adapterHeight);
    hideSoftKeyboard(this);
  },
  onPlayVoice: function (event) {
    playVoice(this, event);
  },
  setNewMessage(newMessage) {
    setNewMessage(this, newMessage)
  },
  onPlayMusic: function (event) {
    playMusic(this, event);
  },
  onMusicStop: function (event) {
    stopMusic(this, event);
  },
  onPreviewImage: function (event) {
    previewImage(this, event);
  },
  onHide: function () {
    hideKeyboard(this);
    stopPlayMusic(this);
  },
  // call的方法
  async login() {
    if (doLogin) {
      return;
    }
    doLogin = true;
    let context = this;
    let {
      data: {
        userId,
        msUrl,
        appkeyIndex
      }
    } = context;
    console.log(userId, msUrl, appkeyIndex)
    let isUserEmpty = callUtils.isEmpty(userId);
    if (isUserEmpty) {
      context.setData({
        isHiddenTip: !isUserEmpty
      });
      doLogin = false;
      return;
    }

    const {
      appkey,
      secret
    } = apps[appkeyIndex];

    wx.showLoading({
      title: '登入中',
      mask: true
    })
    let result;
    try {
      result = await co(wx.request)({
        url: serverUrl,
        method: 'POST',
        data: {
          appkey,
          secret,
          userId,
          name: userId,
          portrait: `portrait-${userId}`,
        },
      });
    } catch (error) {
      doLogin = false;
      wx.hideLoading();
      common.showToast(`擷取 Token 失敗 ${error.statusCode}`);
      return;
    }

    wx.hideLoading();

    const {
      token,
      code,
      msg
    } = result.data;
    if (code !== 200) {
      console.error(code, msg);
      return;
    }

    // app.setServiceConf(appkey, msUrl.url);

    wx.navigateTo({
      url: `../main/main?token=${encodeURIComponent(token)}&userId=${userId}&appkey=${appkey}`,
    });

    doLogin = false;
  },
  call1() {
    if (timer === null) {
      console.log("Start")
      timer = setInterval(() => {
        dangDate = parseInt(dangDate) + 1
        // console.log(dangDate)
        if (dangDate > timeInt) {
          this.showpjPopup()
          dangDate = 0
          clearInterval(timer)
          timer = null
        }
      }, 1000);
    }
    wx.navigateTo({
      url: '../call/call?type=2&targetId=' + this.data.targetId,
    })
  },
  call2() {
    if (timer === null) {
      console.log("Start")
      timer = setInterval(() => {
        dangDate = parseInt(dangDate) + 1
        // console.log(dangDate)
        if (dangDate > timeInt) {
          this.showpjPopup()
          dangDate = 0
          clearInterval(timer)
          timer = null
        }
      }, 1000);
    }
    wx.navigateTo({
      url: '../call/call?type=0&targetId=' + this.data.targetId,
    })
  },

  selectLocation() {
    let that = this
    let {
      messageList
    } = that.data;
    wx.getLocation({
      type: 'gcj02',
      altitude: 'true',
      success(res) {
        const latitude = res.latitude
        const longitude = res.longitude
        const speed = res.speed
        const accuracy = res.accuracy
        let context = `https://restapi.amap.com/v3/staticmap?markers=-1,http://www.5imoban.net/view/demoimg/jrzb_position_icon.png,0:${longitude},${latitude}&key=ee95e52bf08006f63fd29bcfbcf21df0&zoom=17&size=360*200&location=${longitude},${latitude}`

        wx.chooseLocation({
          latitude,
          longitude,
          complete: (res) => {
            console.log(res)
            if (res.latitude) {
              LocationMessage(that.data.targetId, res.latitude, res.longitude, res.address, context).then(ele => {
                console.log(ele)
                messageList.push(ele)
                that.setData({
                  messageList: messageList
                })
                gotoView(that)
              })
            }
          }
        })
      }
    })

  },
  onShow(){
    // let context = this
    // mygetHistory(context, true);
  }

})
           

這個是我打電話界面的js(也是還沒整理)優化的餘地還是很多的,奈何沒有時間)

// pages/call/call.js
import {
  request
} from "../../request/index"
let count = true;
let timer;
// const { TextMessage } = getApp()
const common = require('../common');
const utils = require('../../utils/util.js');
let TextMessage = null;
let rongCallLib = null;
let RongIMLib = null;

// const {Service:{rongCallLib,RongIMLib}} = getApp().globalData
// console.log(getApp().globalData)
// console.log(Call,ConversationType,MessageType,Connection)
// const  rongCallLib
let hungupCount = false
function backNav() {
  console.log(hungupCount)
  if (hungupCount) {
    console.log('執行')
    wx.navigateBack({
      complete: (res) => { },
    })
    hungupCount = false
  }

}
const conversationTypes = [
  { type: 1, label: '單聊' },
  { type: 3, label: '群聊' }
];
const MediaTypes = [
  { type: 2, label: '視訊通話' },
  { type: 1, label: '音頻通話' },
];
const Status = {
  // 空閑
  FREE: 0,
  // 等待接聽或挂斷,暫未加入房間,包含呼入、呼出場景
  WAITING: 1,
  // 通話中,即已經加入房間,群聊狀态下有一人曾接通過即進入到通話中狀态
  TALKING: 2,
}
let that;
Page({

  /**
   * 頁面的初始資料
   */
  desc: '',
  back: true,
  data: {
    crtUserId: '',

    // 通話狀态
    status: Status.FREE,
    // 根據 status 變化修改,computed
    free: true,
    waiting: false,
    talking: false,
    // 群呼中途邀請标記
    inviting: false,
    // 被邀請人
    inviteUserIds: '',
    // 是否為呼入
    callin: false,
    // 目前通話的 targetId,單聊為對方 userId,群聊為 groupId
    crtTargetId: '',
    // 目前的通話類型
    crtConversationType: 0,
    // 目前通話中的人員,不包含自己,單聊時長度為 1,群聊時長度 >= 1,當長度為 0 時需挂斷目前通話
    // 某些條件下,對方可能無法發送 hungupMessage 資訊,如直接關閉應用、殺程序
    crtMembers: [],
    statusCall: true,
    // 輸入選項
    conversationTypeOptions: conversationTypes.map(item => item.label),
    mediaTypeOptions: MediaTypes.map(item => item.label),
    message: null,
    // 輸入表單
    userId: '',
    groupId: '',
    conversationTypeIndex: 0,
    conversationType: conversationTypes[0].type,
    mediaTypeIndex: 0,
    mediaType: '',
    player: null,
    // 推送視訊流
    pusher: null,
    targetId: '',
    // 拉取視訊流:{ [userId]: mediaStream }
    streams: {
    },
    type: '',
    back: true,
    showUser: {},
    senderUserId: '',
    show: true,
    hungupfalse: false
  },

  /**
   * 生命周期函數--監聽頁面加載
   */
  // 接聽
  inputUserId(e) {
    const userId = e.detail.value;
    this.setData({ userId });
  },
  onLoad: function (options) {
    TextMessage = getApp().TextMessage
    rongCallLib = getApp().globalData.Service.rongCallLib
    RongIMLib = getApp().globalData.Service.RongIMLib
    console.log(rongCallLib)
    count = true
    that = this
    hungupCount = true
    // Connection.watch((status) => {
    //   console.log('status:', status);
    // });
    this.audioCtx = wx.createInnerAudioContext()
    this.audioCtx.src = '/image/1.mp3'
    this.audioCtx.loop = true
    this.audioCtx.play()
    console.log(options.data && JSON.parse(options.data))

    if (options.data) {
      // timer = setTimeout(() => {
      //   if(that.data.back){
      //     wx.showToast({
      //       title: '逾時,未接通',
      //       icon:"none",
      //       success(){

      //         setTimeout(() => {
      //           wx.navigateBack({
      //             complete: (res) => {},
      //           })
      //         },200)
      //       }
      //     })
      //   }
      // },12000)
      this.setData({
        message: JSON.parse(options.data),
        senderUserId: JSON.parse(options.data).senderUserId
      })
      console.log(this.data.senderUserId, 11111111)
      this.setData({
        mediaType: this.data.message.content.mediaType
      })
      request({
        url: 'my/byAccount',
        data: {
          accountId: this.data.message.senderUserId,
        }
      }).then(e => {
        if (e.data.status == 1) {
          that.setData({
            showUser: e.data.data
          })
        }
      })
    }
    if (options.targetId) {
      console.log('我撥打')
      this.setData({
        mediaType: options.type == 0 ? 1 : 2
      })
      request({
        url: 'my/byAccount',
        data: {
          accountId: options.targetId
        }
      }).then(e => {
        if (e.data.status == 1) {
          that.setData({
            showUser: e.data.data
          })
        }
      })
      that.setData({
        userId: options.targetId,
        type: options.type
      }, () => {
        that.call()
      })
    }

    rongCallLib.videoWatch(this.onVideoChange1.bind(this));
    // this.onReceiveMessage(JSON.parse(options.data))
    rongCallLib.commandWatch(this.onVideoChange.bind(this));

  },
  onReceiveMessage(message) {
    // const { MessageType, ConversationType } = app.getService();
    console.log(message)
    const { messageType, conversationType, targetId, senderUserId, content } = message;
  },
  onVideoChange1(video) {
    const { type, userId, data } = video;
    if (type === 'added') {
      // 添加音視訊節點
      console.log(userId == that.data.userId, userId, that.data.userId)
      this.setData({
        hungupfalse: true
      })
      if (userId == wx.getStorageSync('userId')) {
        that.setData({
          pusher: video
        })
      } else {

        that.setData({
          back: false,
          show: false,
          player: video
        })
      }

    } else if (type === 'removed') {
      // 删除對應音視訊節點
      this.audioCtx.pause()
      wx.showToast({
        title: '通話結束',
        icon: "none"
      })
      this.setData({
        pusher: null,
        player: null
      })
      setTimeout(() => {
        backNav()
      }, 400);
    } else if (type === 'leave') {
      // 删除對應音視訊節點
      this.audioCtx.pause()
      this.setData({
        pusher: null,
        player: null
      })

      if (that.data.back) {
        this.audioCtx.pause()
        wx.showToast({
          title: '通話結束',
          icon: "none"
        })
        setTimeout(() => {
          backNav()

        }, 400);
      }

    }
  },
  getSummaryText(status) {
    var text;
    switch (status) {
      // case 1:
      //   text = '己方已取消';
      //   break;
      // case 2:
      //   text = '己方已拒絕';
      //   break;
      // case 3:
      //   text = '己方挂斷';
      //   break;
      case 4:
        text = `己方忙碌中, 不處理`;
        break;
      case 5:
        text = '己方未接聽';
        break;
      // default:
      //   text = '未知原因';
    }
    return text;
  },
  onVideoChange(video) {
    const { type, userId, data } = video;
    const { streams } = this.data;
    console.log('commandWatch =>', video, video.content);
    if (video.messageType == "SummaryMessage") {
      var status = video.content.status;
      var promptText = this.getSummaryText(status);
      console.log(promptText)
      if (promptText) {
        wx.showToast({
          title: promptText,
          icon: "none"
        })
      }

      // if (status === 5) { // 自己未接聽, 回到初始狀态
      //   context.callStep = CallStep.READY_TO_CALL;
      // }
    }
    if (video.messageType == "HungupMessage" && video.content && video.content.reason) {
      let data = {
        1: '己方取消已發出的通話請求',
        2: '己方拒絕收到的通話請求',
        3: '己方挂斷',
        4: '己方忙碌',
        5: '己方未接聽',
        6: '目前引擎不支援',
        7: '己方網絡出錯',
        8: '其他端已經接聽',
        11: '對方取消已發出的通話請求',
        12: '對方拒絕收到的通話請求',
        13: '通話過程對方挂斷',
        14: '對方忙碌',
        15: '對方未接聽',
        16: '對方引擎不支援',
        17: '對方網絡錯誤',
        18: 'im ipc服務已斷開',
      }
      console.log(data[video.content.reason])
      this.setData({
        desc: data[video.content.reason]
      })
      // this.hungup()
      wx.showToast({
        title: data[video.content.reason],
        icon: "none",
        success() {
          setTimeout(() => {
            backNav()

          }, 300)
        },
        complete(res) {
        }
      })
    }
    // if(this.data.hungupfalse && video.content && video.content.reason == 13 ){
    //   console.log('未接通被挂斷')
    //   wx.showToast({
    //     title: data[video.content.reason],
    //     icon:"none",
    //     success(){
    //       setTimeout(() => {
    //         wx.navigateBack({
    //           complete: (res) => {},
    //         })
    //       },200)
    //     }
    //   })
    // }
    if (that.data.message && video.content && video.content.messageName == "HungupMessage") {
      console.log()

      this.audioCtx.pause()
      // if(this.data.player){
      //   wx.showToast({
      //     title: '對方已取消',
      //     icon:"none",
      //     success(){
      //       setTimeout(() => {
      //         wx.navigateBack({
      //           complete: (res) => {},
      //         })
      //       },200)
      //     }
      //   })
      // }

    }
    if (video.content && video.content.messageName == "AcceptMessage") {
      wx.hideLoading({
        complete: (res) => { },
      })
      this.audioCtx.pause()
      wx.showToast({
        title: '已接聽',
      })
    }
    console.log(video.content && video.content.messageName == "InviteMessage")
    if (video.content && video.content.messageName == "InviteMessage") {
      console.log(video)
      that.setData({
        callin: true,
      })
      console.log(that.data)
    }
    function getSeconds(s) {
      var sTime = parseInt(s);// 秒
      var mTime = 0;// 分
      var hTime = 0;// 時
      if (sTime > 60) {//如果秒數大于60,将秒數轉換成整數
        //擷取分鐘,除以60取整數,得到整數分鐘
        mTime = parseInt(sTime / 60);
        //擷取秒數,秒數取佘,得到整數秒數
        sTime = parseInt(sTime % 60);
        //如果分鐘大于60,将分鐘轉換成小時
        if (mTime > 60) {
          //擷取小時,擷取分鐘除以60,得到整數小時
          hTime = parseInt(mTime / 60);
          //擷取小時後取佘的分,擷取分鐘除以60取佘的分
          mTime = parseInt(mTime % 60);
        }
      }
      var result = '';
      if (sTime >= 0 && sTime < 10) {
        result = "0" + parseInt(sTime) + "";
      } else {
        result = "" + parseInt(sTime) + "";
      }
      if (mTime >= 0 && mTime < 10) {
        result = "0" + parseInt(mTime) + ":" + result;
      } else {
        result = "" + parseInt(mTime) + ":" + result;
      }
      if (hTime >= 0 && hTime < 10) {
        result = "0" + parseInt(hTime) + ":" + result;
      } else {
        result = "" + parseInt(hTime) + ":" + result;
      }
      return result;
    }
    if (video.messageType == "SummaryMessage") {
      that.setData({
        player: null,
        pusher: null
      })
      // wx.showToast({
      //   icon:"none",
      //   title: '語音逾時未接通',
      // })
      // wx.navigateBack({
      //   complete: (res) => {
      //     console.log("挂斷")
      //   },
      // })
      backNav()
      this.audioCtx.pause()
      console.log(video.senderUserId, '-----------------')
      if (video.senderUserId == wx.getStorageSync('userId') && count) {
        count = false
        let targetId = video.targetId
        let content = getSeconds(video.content.duration / 1000)
        console.log('取消時呼叫方', video.content)
        if (video.content.duration > 0) {
          content = '通話結束:' + content
        } else {
          content = '[語音未接通]'
        }
        console.log(content)
        TextMessage(targetId, content).then(e => {
          console.log(e)
          let pages = getCurrentPages()[getCurrentPages().length - 1]
          pages.data.messageList.push(e)
          pages.setData({
            messageList: pages.data.messageList
          }, () => {
            pages.gotoView()
          })
          // wx.navigateBack({
          //   complete: (res) => {},
          // })
        }).catch(e => {
          console.log(e)
          wx.showToast({
            title: '發送失敗~',
            icon: "none"
          })
        })
      }

    }

  },
  setStatus(status) {
    const free = status === Status.FREE;
    const data = {
      status,
      free,
      talking: status === Status.TALKING,
      waiting: status === Status.WAITING,
    };
    if (free) {
      data.crtTargetId = '';
      data.crtConversationType = 0;
      data.crtMembers = [];
      data.pusher = null;
      data.streams = {};
    }
    this.setData(data);
  },
  async call() {
    var CallType = RongIMLib.VoIPMediaType;
    console.log('222222222222', CallType, this.data.type == 0 ? CallType.MEDIA_AUDIO : CallType.MEDIA_VIDEO)
    this.setData({
      mediaType: this.data.type == 0 ? CallType.MEDIA_AUDIO : CallType.MEDIA_VIDEO
    })
    var params = {
      conversationType: RongIMLib.ConversationType.PRIVATE,
      targetId: this.data.userId,
      inviteUserIds: [this.data.userId],
      mediaType: this.data.type == 0 ? CallType.MEDIA_AUDIO : CallType.MEDIA_VIDEO
      // RongIMLib.VoIPMediaType.MEDIA_VEDIO
    };
    console.log(this.data.type, params)
    wx.showLoading({
      title: '呼叫中...',
    })
    rongCallLib.call(params, (error) => {
      console.log(error)
      wx.hideLoading({
        complete: (res) => { },
      })

      if (error) {
        if (error.code == 4) {
          that.setData({
            back: false
          })
          this.hungup(1)
        } else {
          that.setData({
            back: true
          })
          this.hungup()
        }
        // wx.showToast({
        //   title: error.info,
        //   icon:"none"
        // })
        wx.hideLoading({
          complete: (res) => { },
        })
        // wx.showToast({
        //   title: '呼叫失敗',
        //   icon:"none"
        // })
        this.audioCtx.pause()
        console.error('發起通話失敗', error);
      }
    });
  },
  accept() {
    //  setTimeout(()=>{
    //   console.log(that,that.data)
    //  })
    console.log(this.data.mediaType)
    var params = {
      conversationType: that.data.message.conversationType,
      targetId: that.data.message.targetId,
      mediaType: this.data.mediaType
    };
    console.log(params)
    this.audioCtx.pause()
    rongCallLib.accept(params, function (error) {
      that.setData({
        senderUserId: that.data.message.senderUserId,
        message: null
      })
      if (error) {
        console.error('接聽通話失敗', error);
        wx.showToast({
          title: '接聽通話失敗',
          icon: "none",
          success: () => {
            setTimeout(() => {
              backNav()


            }, 300)
          }
        })
      }
    });
  },
  async reject() {
    var params = {
      conversationType: RongIMLib.ConversationType.PRIVATE,
      targetId: this.data.senderUserId
    };
    rongCallLib.reject(params, function (error) {
      if (error) {
        console.error('拒絕通話失敗', error);
      }
    });
  },
  async hungup(a) {
    wx.hideLoading()
    console.log(11111, '挂斷', this.data.type, this.data.userId, this.data.senderUserId)
    var params = {
      conversationType: RongIMLib.ConversationType.PRIVATE,
      targetId: this.data.type ? this.data.userId : this.data.senderUserId
    };
    console.log(212, params)

    if (a.currentTarget) {
      this.setData({
        statusCall: false
      })
    }
    rongCallLib.hungup(params, function (error) {
      console.log(error)
      if (a != 1) {
        console.log(error)

        setTimeout(() => {
          backNav()

        }, 400);
      } else {
        // that.call()
      }

      if (error) {
        console.error('挂斷通話失敗', error);
        // wx.showToast({
        //   title: error.msg,
        //   icon:"none"
        // })
        setTimeout(() => {
          backNav()

        }, 400);
      }
    });
  },
  onUnload() {
    // clearTimeout(timer)
    this.audioCtx.pause()
    if (this.data.statusCall) {
      this.hungup(1)
      this.data.message ? console.log("拒接") : console.log("挂斷")
      // this.data.message ?  '' :  this.data.pusher ? this.hungup(1) : ''
      that.setData({
        player: null,
        pusher: null
      })
    }
  }
})  
           

w