This commit is contained in:
wtq
2025-11-13 14:42:30 +08:00
commit 7d879ff3bc
349 changed files with 54558 additions and 0 deletions

View File

@@ -0,0 +1,573 @@
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