import { onLoad, onShow } from '@dcloudio/uni-app' import { nextTick, onBeforeUnmount, ref } from 'vue' import { store } from "@/store" import message from '@/api/https/message' import toast from '@/utils/toast' import { Decrypt, Encrypt, jxParse } from '@/utils/tools' // import { msgInfo } from '@/api/mockData/index' import useGlobalFunc from '@/composables/useGlobalFunc' import merchant from '@/api/https/merchant' import { qiniuyun } from '@/utils/qiniuUploader' import { getStorage } from "@/utils/storage"; const { analyEmoji } = useGlobalFunc() const qiniuyunUploadImg = qiniuyun() // 七牛云sdk /************************************************* * 聊天详情 */ const msgChatFn = function () { /************************************************* * 数据 */ const chatData = ref>([]) const scrollToView = ref() const platformID = ref('589') const isShowEmoji = ref(false) // 是否显示emoji const editorCtx = ref() // editor编辑器初始化 const readOnly = ref(false) // edotor编辑器的可读性 /************************************************* * 接收数据 */ let useData: AnyObject = {} let ebStore: AnyObject = {} let detailTime: any = null // 计时器 onLoad((potion: any) => { let res:any = getStorage('vendorUserInfo') if(JSON.stringify(potion) === '{}') { useData = { userID:res.userID, NewMessageNum:0, orderDesc:` #${res.orderSeq}`, vendorID:res.vendorID, orderID:res.venderOrderID } }else{ let useInfo: AnyObject = JSON.parse(potion.data) useData = useInfo } if (store.state.storeInfo.allStoreInfo.StoreMaps && store.state.storeInfo.allStoreInfo.StoreMaps.length > 0) ebStore = store.state.storeInfo.allStoreInfo.StoreMaps.find((item: { vendorID: number }) => item.vendorID === 3) // 饿百 // 修改标题 uni.setNavigationBarTitle({ title: useData.vendorID == 1 ? `【美团${useData.orderDesc}】${useData.userID === '0' ? '群发消息' : useData.userID}` : `【淘宝闪购】${useData.userID}`, }) // 获取聊天数据 getChatDetail(0) detailTime = setInterval(() => { getChatDetail(1) }, 4000) }) onShow(async () => { if (useData.NewMessageNum == 0) return await SetMsgRead() }) /************************************************* * 设置消息为已读 */ async function SetMsgRead() { let venderIDInfo = store.state.storeInfo.vendorStoreIDS let data = { appID: useData.vendorID === 1 ? venderIDInfo.appID : ebStore.vendorOrgCode, vendorStoreID: useData.vendorID === 1 ? venderIDInfo.MT : ebStore.vendorStoreID, vendorID: "" + useData.vendorID, orderID: "" + useData.orderID ? useData.orderID : '0', userID: useData.userID } await message.set_IM_msg_read(data) } /************************************************* * 获取聊天详情 */ const isItem = ref(false) async function getChatDetail(num: number) { let venderIDInfo = store.state.storeInfo.vendorStoreIDS let data = { payLoad: JSON.stringify([{ vendorStoreID: useData.vendorID === 1 ? venderIDInfo.MT : ebStore.vendorStoreID, vendorID: "" + useData.vendorID, appID: useData.vendorID === 1 ? venderIDInfo.appID : ebStore.vendorOrgCode, userID: useData.userID }]) } let res = await message.get_IM_chat_detail(data) // res = msgInfo.chatDetail // 模拟数据 // console.log('res1111111111', res) if (res.code == 0) { let newArr: any = [] if (useData.vendorID === 1) { platformID.value = venderIDInfo.appID // 获取平台数据 let newMsg = res.data[`${venderIDInfo.appID}:${venderIDInfo.MT}:${useData.vendorID}:${useData.userID}`] || [] if (newMsg.length > chatData.value && num != 0) { (newMsg.splice(chatData.value.length - 1)).forEach((element: any) => { let resData = jxParse(element) if (resData.msgContent != undefined) { let msg_content = resData.msgContent.msg_type == 1 ? analyEmoji(Decrypt(resData.msgContent.msg_content, platformID.value)) : Decrypt(resData.msgContent.msg_content, platformID.value) if (resData.msgContent.msg_type == 4) msg_content = resData.msgContent.app_spu_codes // 商品skuid let msgList = { sendType: resData.sendType, ...resData.msgContent, msg_content, // msg_type: resData.msgContent.msg_type == 1 ? (!isCloudEmoji(Decrypt(resData.msgContent.msg_content, platformID.value)) ? resData.msgContent.msg_type : 'emoji') : resData.msgContent.msg_type } newArr.push(msgList) } }) } else { newMsg.forEach((element: any) => { let resData = jxParse(element) if (resData.msgContent != undefined) { let msg_content = resData.msgContent.msg_type == 1 ? analyEmoji(Decrypt(resData.msgContent.msg_content, platformID.value)) : Decrypt(resData.msgContent.msg_content, platformID.value) if (resData.msgContent.msg_type == 4) msg_content = resData.msgContent.app_spu_codes // 商品skuid let msgList = { sendType: resData.sendType, ...resData.msgContent, msg_content, // msg_type: resData.msgContent.msg_type == 1 ? (!isCloudEmoji(Decrypt(resData.msgContent.msg_content, platformID.value)) ? resData.msgContent.msg_type : 'emoji') : resData.msgContent.msg_type } // msg_type 1:文字,2:图片,3:语音,注意b2c不支持语音,4:商品卡片,发送商品卡片类型则不关注msg_content,5:订单卡片类型商家只能接收消息,不支持给用户发送消息,只支持单聊 11:群文字,12:群图片,13:群语音,注意b2c不支持语音,14:群商品卡片 https://tscc.meituan.com/home/docDetail/10090 newArr.push(msgList) } }) } } else { // 饿百 let newMsg = res.data[`${ebStore.vendorOrgCode}:${ebStore.vendorStoreID}:${useData.vendorID}:${useData.userID}`] || [] if (num === 1) newArr = chatData.value if (newMsg.length !== 0 && newMsg.length === chatData.value.length) return if (newMsg.length > chatData.value.length && num != 0) { let arr = newMsg arr.map((element: any, index: number) => { let resData = JSON.parse(element) if (resData.msgContent) { if (resData.msgContent.payload) resData.msgContent.payLoad = resData.msgContent.payload let findIndex = newArr.findIndex((item: { payLoad: { msgId: any } }) => item.payLoad.msgId === resData.msgContent.payLoad.msgId) // 消息id,唯一性 if (findIndex === -1) { let msg = JSON.parse(resData.msgContent.payLoad.content) if (msg.text) { msg.text = msg.text.replace(/^["']|["']$/g, '') //正则 去掉字符串中的首尾双引号 resData.msgContent.payLoad.contentType = 1 } let str = '' if (resData.msgContent.payLoad.contentType == 1) { str = msg.text } else if (resData.msgContent.payLoad.contentType == 2 || resData.msgContent.payLoad.contentType == 3 || resData.msgContent.payLoad.contentType == 4) { analyUrl({ mediaID: msg.mediaId, platformShopID: '' + ebStore.vendorStoreID }, index) str = '' } else { if(resData.msgContent.payLoad.contentType == 101 && msg.type == 7){ // 101、自定义消息-商品卡片 analyUrl({ mediaID: msg.data.item.id, platformShopID: '' + ebStore.vendorStoreID }, index) }else if(resData.msgContent.payLoad.contentType == 101 && msg.type == 10052){ let json = JSON.parse(msg.data) let json1 = JSON.parse(resData.msgContent['payLoad'].content) str = json.shortTitle resData.msgContent['payLoad'] = { ...resData.msgContent['payLoad'], content:{ ...json1, data:JSON.parse(json1.data) } } }else{ if (msg.elements && msg.elements.length) { // contentType 为'8' let findItem = msg.elements.filter((item: { elementType: number }) => item.elementType === 1) str = findItem && findItem.length > 0 ? JSON.parse(findItem[0].elementContent).text.replace('@商家', '') : '' } } } let msgList = { sendType: resData.sendType, ...resData.msgContent, msg_content: resData.msgContent.payLoad.contentType === 1 || resData.msgContent.payLoad.contentType === '8' ? analyEmoji(str) : str, // msg_source: 2, msg_source: resData.sendType === 'jx' ? 1 : 2, msg_type: resData.msgContent.payLoad.contentType === '8' ? 1 : resData.msgContent.payLoad.contentType // msg_type: element.sendType === 'jx' ? 1 : 2 } newArr.push(msgList) } } }) } else { newMsg.map((element: any, index: number) => { let resData = JSON.parse(element) if (resData.msgContent) { if (resData.msgContent.payload) resData.msgContent.payLoad = resData.msgContent.payload let msg = JSON.parse(resData.msgContent.payLoad.content) if (msg.text) { msg.text = msg.text.replace(/^["']|["']$/g, '') //正则 去掉字符串中的首尾双引号 resData.msgContent.payLoad.contentType = 1 } let str = '' if (resData.msgContent.payLoad.contentType == 1) { str = msg.text } else if (resData.msgContent.payLoad.contentType == 2 || resData.msgContent.payLoad.contentType == 3 || resData.msgContent.payLoad.contentType == 4) { // contentType为2图片、3语音、4视频时 analyUrl({ mediaID: msg.mediaId, platformShopID: '' + ebStore.vendorStoreID }, index) str = '' } else { if(resData.msgContent.payLoad.contentType == 101 && msg.type == 7){ // 101、自定义消息-商品卡片 analyUrl({ mediaID: msg.data.item.id, platformShopID: '' + ebStore.vendorStoreID }, index) }else if(resData.msgContent.payLoad.contentType == 101 && msg.type == 10052){ let json = JSON.parse(msg.data) let json1 = JSON.parse(resData.msgContent['payLoad'].content) str = json.shortTitle resData.msgContent['payLoad'] = { ...resData.msgContent['payLoad'], content:{ ...json1, data:JSON.parse(json1.data) } } }else{ if (msg.elements && msg.elements.length) { let findItem = msg.elements.filter((item: { elementType: number }) => item.elementType === 1) str = findItem && findItem.length > 0 ? JSON.parse(findItem[0].elementContent).text.replace('@商家', '') : '' } } } let msgList = { sendType: resData.sendType, ...resData.msgContent, msg_content: resData.msgContent.payLoad.contentType === 1 || resData.msgContent.payLoad.contentType === '8' ? analyEmoji(str) : str, msg_source: resData.sendType === 'jx' ? 1 : 2, msg_type: resData.msgContent.payLoad.contentType === '8' ? 1 : resData.msgContent.payLoad.contentType } newArr.push(msgList) } }) } } chatData.value = newArr isItem.value = true scrollToView.value = 'msg' + (chatData.value.length - 1) } else { toast('获取聊天信息异常') } } /************************************************* * 获取url by mediaId */ async function analyUrl(params: AnyObject, index: number) { if (chatData.value[index] && !chatData.value[index].msg_content) return let res = await message.get_url_by_mediaID(params) if (chatData.value[index].msg_content.length === 0) chatData.value[index].msg_content = res.code === '0' ? res.data : '' } /************************************************* * 选择图片 */ function selectImg() { if (useData.vendorID === 3) return toast('暂不支持该功能') uni.chooseImage({ success: (res: any) => { res.tempFiles.forEach((item: AnyObject) => { uploadImg(item.path) }) }, }) } /************************************************* * 图片上传 * @param {Object} 图片内容 */ async function uploadImg(img: string) { let suffix = img.indexOf('.png') === -1 ? '.jpg' : '.png' let params = { suffix, } let res = await merchant.get_qiniu_upload_token(params) if (res.code == 0) { let filePath = img qiniuyunUploadImg.upload( filePath, (res: any) => { // 得到图片网址 let url = 'https://image.jxc4.com/' let imgUrl = url + res.key sendClick({ msg: imgUrl, type: 2 }) }, (err: AnyObject) => { toast('上传失败,请重试', 2) }, { uploadURL: 'https://up-z2.qiniup.com/', key: res.data.fileName, uptoken: res.data.token, } ) } else { toast('上传失败', 2) } } /************************************************* * 编辑器初始化完成时触发 */ function onEditorReady() { uni.createSelectorQuery().select('#editor').context((res: any) => { editorCtx.value = res.context }).exec() } /************************************************* * 编辑器的内容(实时) */ function onInput(params: any) { // console.log('params', params) } /************************************************* * 失去焦点 */ function onBlur(e: any) { console.log('失去焦点', e.detail.delta.ops) // isShowEmoji.value = false } /** * 编辑器聚焦时 */ function onFocus(e: any) { isShowEmoji.value = false } /************************************************* * 打开emoji */ function openEmoji() { // uni.hideKeyboard() readOnly.value = true isShowEmoji.value = true } function closeEmoji() { isShowEmoji.value = false closeReadOnly() } /************************************************* * 选择emoji */ function selectEmoji(emoji: AnyObject) { editorCtx.value.insertImage({ src: `https://www.jxc4.com/emoji/${emoji.symbol}.png`, alt: emoji.text, width: '20px', height: '20px', nowrap: true }) const timer = setTimeout(() => { closeReadOnly() clearTimeout(timer) }, 2000) } /************************************************* * 发送消息 */ function sendMessage() { editorCtx.value.getContents({ complete(res: any) { if (res.errMsg === 'ok') { let str = '' res.delta.ops.forEach((item: any) => { let type = typeof item.insert if (type === 'string') { str = str + item.insert } else { str = str + item.attributes.alt } }) str = str.replace(/\n/g, '') // 除去回车符 if (str.length > 0) { // console.log('str', str) sendClick({ msg: str, type: 1 }) editorCtx.value.clear() closeReadOnly() } } } }) // sendClick({ msg: initValue.value, type: 1 }) // initValue.value = '' // editorCtx.value.clear() } /************************************************* * 发送数据 */ async function sendClick(msgData: AnyObject) { let venderIDInfo = useData.vendorID === 1 ? store.state.storeInfo.vendorStoreIDS : ebStore.vendorOrgCode let data = { sendType: useData.vendorID === 1 ? "mt" : "elm", app_id: useData.vendorID === 1 ? venderIDInfo.appID : ebStore.vendorOrgCode, app_poi_code: useData.vendorID === 1 ? venderIDInfo.MT : ebStore.vendorStoreID, cts: Math.round(new Date().getTime() / 1000).toString(), msg_content: msgData.type === 1 ? analyEmoji(msgData.msg) : msgData.msg, msg_id: Math.round(new Date().getTime()).toString(), msg_source: 1, msg_type: msgData.type, open_user_id: useData.userID, order_id: useData.orderID, app_spu_codes: "" } chatData.value.push(data) nextTick(() => { // 滚动信息到底部 scrollToView.value = 'msg' + (chatData.value.length - 1) }) let sendMsg = {} if (useData.vendorID === 1) { sendMsg = { vendorOrgCode: platformID.value, sendData: JSON.stringify({ vendorID: useData.vendorID, data: { msg_content: Encrypt(msgData.msg, platformID.value), msg_type: +Number(msgData.type), app_poi_code: "" + venderIDInfo.MT, msg_id: +Math.round(new Date().getTime()).toString() + 184572, app_id: useData.vendorID === 1 ? +venderIDInfo.appID : +ebStore.vendorOrgCode, msg_source: 1, order_id: useData.orderID, cts: +Math.round(new Date().getTime() / 1000).toString(), open_user_id: +useData.userID, } }) } } else { let chatDataItem = chatData.value.filter(item => item.msg_source === 2) // vendorOrgCode console.log('chatDataItem', chatDataItem) sendMsg = { // platformShopId: ebStore.vendorStoreID, platformShopId: chatDataItem[0].platformShopId, subBizType: 'SEND_MESSAGE', bizType: 'IM', payload: { receiverIds: chatDataItem[0].payLoad.receiverIds, groupId: chatDataItem[0].payLoad.groupId, msgId: '' + Math.round(new Date().getTime()).toString() + 184572, contentType: '' + msgData.type, // 1-普通文本 2-图片 3-语音 4-视频 101-自定义 // contentType: '2', // 1-普通文本 2-图片 3-语音 4-视频 101-自定义 content: msgData.type == 1 ? JSON.stringify({ text: msgData.msg }) : JSON.stringify({ mediaId: msgData.msg, fileType: 0, // 必传 int类型 0-jpg图片, 2-png图片 size: 1 // 必传 int类型 图片大小, 单位字节, 不超过3*1024*1024 }) // content: JSON.stringify({ // mediaId: '3XLsJLhrcwmB0amFxycl3M8V1FWno0Fq_S6rKTRupMI48Wnr5wVjHqWM0b4zjG34', // fileType: 0, // size: 87668 // }) } } sendMsg = { vendorOrgCode: ebStore.vendorOrgCode, sendData: JSON.stringify({ vendorID: useData.vendorID, data: { ...sendMsg } }) } } let res = await message.send_to_vendor(sendMsg) if (res.code == 0) { } else { uni.jxAlert({ title: '提示', content: `发送失败:${res.desc || res.data}`, success: () => { chatData.value.pop() } }) } SetMsgRead() } /************************************************* * 关闭editor的只读属性 */ function closeReadOnly() { readOnly.value = false } /** * 收尾 工作 */ onBeforeUnmount(async () => { clearInterval(detailTime) if (useData.NewMessageNum == 0) return await SetMsgRead() }) return { scrollToView, // 滚动到底部 chatData, // 聊天信息 isItem, // 聊天界面的数据是否请求完毕 isShowEmoji, // emoji是否发生偏移 onEditorReady, // 编辑器初始化 onInput, // 编辑器的内容(实时) onBlur, // 编辑器失去焦点 onFocus, // 编辑器聚焦时 selectImg, // 选择图片 openEmoji, // 打开emoji closeEmoji, // 关闭emoji selectEmoji, // 选择emoji sendMessage, // 发送消息 readOnly, // 是否为只读 closeReadOnly // 关闭editor的只读属性 } } export default msgChatFn