Files
zsw-jx-store/src/subPages/messageChild/msgChat/msgChat.ts
2025-12-10 16:28:35 +08:00

573 lines
25 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 } 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>('589')
const isShowEmoji = ref<boolean>(false) // 是否显示emoji
const editorCtx = ref<any>() // editor编辑器初始化
const readOnly = ref<boolean>(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<boolean>(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_content5订单卡片类型商家只能接收消息不支持给用户发送消息只支持单聊 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