Files
zsw-jx-store/src/subPages/messageChild/msgChat/msgChat.ts
2026-03-17 17:43:31 +08:00

572 lines
24 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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_content5订单卡片类型商家只能接收消息不支持给用户发送消息只支持单聊 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