572 lines
24 KiB
TypeScript
572 lines
24 KiB
TypeScript
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||
import { nextTick, onBeforeUnmount, ref, watch } 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<Array<AnyObject>>([])
|
||
|
||
const scrollToView = ref<any>()
|
||
|
||
const platformID = ref<string>('')
|
||
|
||
const isShowEmoji = ref<boolean>(false) // 是否显示emoji
|
||
|
||
const editorCtx = ref<any>() // editor编辑器初始化
|
||
|
||
const readOnly = ref<boolean>(false)
|
||
|
||
/*************************************************
|
||
* 接收数据
|
||
*/
|
||
let useData: AnyObject = {}
|
||
let ebStore: AnyObject = {}
|
||
let jdStore: AnyObject = {}
|
||
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) // 饿百
|
||
if (store.state.storeInfo.allStoreInfo.StoreMaps && store.state.storeInfo.allStoreInfo.StoreMaps.length > 0) jdStore = store.state.storeInfo.allStoreInfo.StoreMaps.find((item: { vendorID: number }) => item.vendorID === 0) // 京东
|
||
|
||
// 修改标题
|
||
uni.setNavigationBarTitle({
|
||
title:
|
||
useData.vendorID == 1
|
||
? `【美团${useData.orderDesc}】${useData.userID === '0' ? '群发消息' : useData.userID}`
|
||
: useData.vendorID == 3 ? `【淘宝闪购】${useData.userID}` : `【京东】${useData.userID}`,
|
||
})
|
||
|
||
// 获取聊天数据
|
||
getChatDetail()
|
||
})
|
||
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 : useData.vendorID === 3 ? ebStore.vendorOrgCode : jdStore.vendorOrgCode,
|
||
vendorStoreID: useData.vendorID === 1 ? venderIDInfo.MT : useData.vendorID === 3 ? ebStore.vendorStoreID : jdStore.vendorStoreID,
|
||
vendorID: "" + useData.vendorID,
|
||
orderID: "" + useData.orderID ? useData.orderID : '0',
|
||
userID: useData.userID
|
||
}
|
||
await message.set_IM_msg_read(data)
|
||
}
|
||
|
||
|
||
/*************************************************
|
||
* 获取聊天详情
|
||
*/
|
||
const isItem = ref<boolean>(false)
|
||
async function getChatDetail() {
|
||
let venderIDInfo = store.state.storeInfo.vendorStoreIDS
|
||
let data = {
|
||
payLoad: JSON.stringify([{
|
||
vendorStoreID: useData.vendorID === 1 ? venderIDInfo.MT : useData.vendorID === 3 ? ebStore.vendorStoreID : jdStore.vendorStoreID,
|
||
vendorID: "" + useData.vendorID,
|
||
appID: useData.vendorID === 1 ? venderIDInfo.appID : useData.vendorID === 3 ? ebStore.vendorOrgCode : jdStore.vendorOrgCode,
|
||
userID: useData.userID
|
||
}])
|
||
}
|
||
let res = await message.get_IM_chat_detail(data)
|
||
// res = msgInfo.chatDetail // 模拟数据
|
||
|
||
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}`] || []
|
||
newMsg.forEach((element: any) => {
|
||
let resData = jxParse(element)
|
||
let msg_content = resData.msgContent.msg_type == 1 || resData.msgContent.msg_type == 11 ? 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
|
||
if (resData.msgContent != undefined) {
|
||
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 if(useData.vendorID === 3){
|
||
// 饿百
|
||
let newMsg = res.data[`${ebStore.vendorOrgCode}:${ebStore.vendorStoreID}:${useData.vendorID}:${useData.userID}`] || []
|
||
newMsg.map((element: any, index: number) => {
|
||
let resData = jxParse(element)
|
||
if (resData.msgContent != undefined) {
|
||
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 content = ''
|
||
if (resData.msgContent.payLoad.contentType == 1) {
|
||
content = 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)
|
||
content = ''
|
||
} 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)
|
||
content = 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)
|
||
content = 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(content) : content,
|
||
// msg_source: 2,
|
||
msg_source: resData.sendType === 'jx' ? 1 : 2,
|
||
msg_type: resData.msgContent.payLoad.contentType === '8' ? 1 : resData.msgContent.payLoad.contentType
|
||
}
|
||
newArr.push(msgList)
|
||
}
|
||
})
|
||
}else if(useData.vendorID === 0){
|
||
// 京东
|
||
let newMsg = res.data[`${jdStore.vendorOrgCode}:${jdStore.vendorStoreID}:${useData.vendorID}:${useData.userID}`] || []
|
||
newMsg.forEach((element:string) => {
|
||
let resData = jxParse(element)
|
||
if(resData.msgContent){
|
||
let msg = JSON.parse(resData.msgContent.extendJsonData)
|
||
let content = msg.body.type === 'text' ? msg.body.content : msg.body.type === 'image' ? msg.body.url : msg.body.content
|
||
// console.log(msg,'msg','获取聊天详情,resData',resData,'useData',useData.userID)
|
||
|
||
let msgList = {
|
||
sendType:'jd',
|
||
...msg,
|
||
msg_content: msg.body.type === 'text' ? analyEmoji(content) : msg.body.type === 'image' ? content : '未知' ,
|
||
msg_source: useData.userID === msg.from.pin ? 2 : 1, // 目前全是客户发的消息
|
||
msg_type: msg.body.type === 'text' ? 1 : msg.body.type === 'image' ? 2 : 99 // 目前只支持文本消息
|
||
}
|
||
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) {
|
||
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) {
|
||
console.log('查看编辑器是否聚焦', e)
|
||
isShowEmoji.value = false
|
||
}
|
||
|
||
/*************************************************
|
||
* 打开emoji
|
||
*/
|
||
function openEmoji() {
|
||
// uni.hideKeyboard()
|
||
readOnly.value = true
|
||
isShowEmoji.value = true
|
||
// hideKeyBoard()
|
||
}
|
||
function closeEmoji() {
|
||
isShowEmoji.value = false
|
||
closeReadOnly()
|
||
}
|
||
|
||
/*************************************************
|
||
* 选择emoji
|
||
*/
|
||
function selectEmoji(emoji: AnyObject) {
|
||
// readOnly.value = true
|
||
editorCtx.value.insertImage({
|
||
src: `https://www.jxc4.com/emoji/${emoji.symbol}.png`,
|
||
alt: emoji.text,
|
||
width: '20px',
|
||
height: '20px',
|
||
nowrap: true
|
||
})
|
||
|
||
// let timer = setTimeout(() => {
|
||
// readOnly.value = false
|
||
// clearTimeout(timer)
|
||
// }, 1000);
|
||
const timer = setTimeout(() => {
|
||
closeReadOnly()
|
||
clearTimeout(timer)
|
||
}, 2000)
|
||
}
|
||
|
||
// uni.onKeyboardHeightChange(res => {
|
||
// console.log(res, '监听键盘高度的变化', res.height)
|
||
// if (res.height) {
|
||
// isShowEmoji.value = false
|
||
// }
|
||
// })
|
||
// function hideKeyBoard() {
|
||
// // 只是解决软键盘的闪现
|
||
// var interval = setInterval(function () {
|
||
// uni.hideKeyboard();//隐藏软键盘
|
||
// console.log('刷新')
|
||
// }, 200);
|
||
// setTimeout(() => {
|
||
// clearInterval(interval);
|
||
// readOnly.value = false
|
||
// console.log('停止刷新')
|
||
// }, 2000);
|
||
// }
|
||
|
||
/*************************************************
|
||
* 发送消息
|
||
*/
|
||
function sendMessage() {
|
||
editorCtx.value.getContents({
|
||
complete(res: any) {
|
||
|
||
if (res.errMsg === 'getContents: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 : useData.vendorID === 3 ? ebStore.vendorOrgCode : jdStore.vendorOrgCode
|
||
let data = {
|
||
sendType: useData.vendorID === 1 ? "mt" : useData.vendorID === 3 ? "elm" : 'jd',
|
||
app_id: useData.vendorID === 1 ? venderIDInfo.appID : useData.vendorID === 3 ? ebStore.vendorOrgCode : jdStore.vendorOrgCode,
|
||
app_poi_code: useData.vendorID === 1 ? venderIDInfo.MT : useData.vendorID === 3 ? ebStore.vendorStoreID : jdStore.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: 0,
|
||
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: 1,
|
||
data: {
|
||
msg_content: Encrypt(msgData.msg, platformID.value),
|
||
msg_type: +msgData.type,
|
||
app_poi_code: "" + venderIDInfo.MT,
|
||
msg_id: +Math.round(new Date().getTime()).toString() + 184572,
|
||
app_id: +venderIDInfo.appID,
|
||
msg_source: 1,
|
||
order_id: useData.orderID,
|
||
cts: +Math.round(new Date().getTime() / 1000).toString(),
|
||
open_user_id: +useData.userID,
|
||
}
|
||
})
|
||
}
|
||
} else if(useData.vendorID === 3){
|
||
let chatDataItem = chatData.value.filter(item => item.msg_source === 2)
|
||
sendMsg = {
|
||
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-自定义
|
||
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
|
||
})
|
||
}
|
||
}
|
||
sendMsg = {
|
||
vendorOrgCode: ebStore.vendorOrgCode,
|
||
sendData: JSON.stringify({
|
||
vendorID: useData.vendorID,
|
||
data: { ...sendMsg }
|
||
})
|
||
}
|
||
}else if(useData.vendorID === 0){
|
||
sendMsg = {
|
||
vendorOrgCode: jdStore.vendorOrgCode,
|
||
sendData:JSON.stringify({
|
||
vendorID: 0,
|
||
storeId:jdStore.storeID,
|
||
data:{
|
||
id: '' + Math.round(new Date().getTime()).toString() + 184572 , // uuid //随机生成一个字符串
|
||
lang: "zh_CN",
|
||
type: "chat_message",
|
||
from: {
|
||
pin:chatData.value[0].to.pin,
|
||
app:'im.waiter', // 固定不变
|
||
clientType:'android'
|
||
},
|
||
to: {
|
||
pin:chatData.value[0].from.pin,
|
||
app:'im.customer', // 固定不变
|
||
},
|
||
body: {
|
||
type:msgData.type === 1 ? "text" : "image", // 消息类型
|
||
content:msgData.msg,
|
||
chatinfo:{
|
||
venderId:chatData.value[0].body.chatinfo.venderId,
|
||
askAllocateType:chatData.value[0].body.chatinfo.askAllocateType,
|
||
sid:chatData.value[0].body.chatinfo.sid,
|
||
source:chatData.value[0].body.chatinfo.source
|
||
},
|
||
template:{
|
||
source:'dd_msg_583984a984834b1889f853be6e449f39_e66c448b9fbe4704901925d3217081a3' // 文本固定不变 //卡片类消息必传
|
||
},
|
||
mt:60,
|
||
},
|
||
timestamp:new Date().getTime(), // 时间戳
|
||
clientTime:new Date().getTime() // 客户端时间
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
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()
|
||
}
|
||
|
||
// ******************** 监听IM新信息 *****************************
|
||
//#region
|
||
watch(() => store.state.storeInfo.imMessage, (val) => {
|
||
let resData = JSON.parse(val)
|
||
if (resData.open_user_id != useData.userID) return false
|
||
resData.sendType = 'mt'
|
||
if (platformID.value) resData.msg_content = Decrypt(resData.msg_content, platformID.value)
|
||
chatData.value.push(resData)
|
||
nextTick(() => {
|
||
scrollToView.value = 'msg' + (chatData.value.length - 1)
|
||
})
|
||
})
|
||
//#endregion
|
||
|
||
/*************************************************
|
||
* 关闭editor的只读属性
|
||
*/
|
||
function closeReadOnly() {
|
||
readOnly.value = false
|
||
}
|
||
|
||
/**
|
||
* 收尾 工作
|
||
*/
|
||
onBeforeUnmount(async () => {
|
||
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 |