|
|
|
|
import { cloneDeep, isEmpty, olog } from "@/utils/utils";
|
|
|
|
|
import { v4 as uuid } from "uuid";
|
|
|
|
|
|
|
|
|
|
export const replaceTemplateString = (str, replacements) => {
|
|
|
|
|
let result = str;
|
|
|
|
|
let keys = str.match(/{{(.*?)}}/g).map(key => key.replace(/{{|}}/g, ''));
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
|
|
|
let replaceValue = replacements[i];
|
|
|
|
|
let template = new RegExp(`{{${keys[i]}}}`, 'g');
|
|
|
|
|
result = result.replace(template, replaceValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const autoLinkText = (text) => {
|
|
|
|
|
return text;
|
|
|
|
|
// let regex = /(https?:\/\/[^\s]+)/g;
|
|
|
|
|
|
|
|
|
|
// let newText = text.replace(regex, '<a href="$1" target="_blank">$1</a>');
|
|
|
|
|
// return newText;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
// +8618777396951 lyj
|
|
|
|
|
{
|
|
|
|
|
"to": "+8613317835586", // qqs
|
|
|
|
|
"msgtype": "text",
|
|
|
|
|
"msgcontent": "{\"body\":\"txtmsgtest\"}"
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
const mediaMsg = {
|
|
|
|
|
contentToSend: (msg) => ({
|
|
|
|
|
action: 'message',
|
|
|
|
|
actionId: msg.id,
|
|
|
|
|
renderId: msg.id,
|
|
|
|
|
to: msg.to,
|
|
|
|
|
msgcontent: {
|
|
|
|
|
[msg.type]: { link: msg.data.dataUri, caption: msg.text },
|
|
|
|
|
...(msg.context ? { context: msg.context, message_origin: msg.message_origin.msgOrigin } : {}),
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
contentToRender: (msg) => ({
|
|
|
|
|
...msg,
|
|
|
|
|
actionId: msg.id,
|
|
|
|
|
conversationid: msg.id.split('.')[0],
|
|
|
|
|
...(msg.context
|
|
|
|
|
? {
|
|
|
|
|
reply: {
|
|
|
|
|
id: msg.message_origin.id,
|
|
|
|
|
message: msg.message_origin.text,
|
|
|
|
|
title: msg.message_origin.senderName || 'Reference',
|
|
|
|
|
titleColor: msg.message_origin?.senderName !== 'me' ? '#a791ff' : '#128c7e',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
: {}),
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
export const sentMsgTypeMapped = {
|
|
|
|
|
text: {
|
|
|
|
|
type: 'text',
|
|
|
|
|
contentToSend: (msg) => ({
|
|
|
|
|
action: 'message',
|
|
|
|
|
actionId: msg.id,
|
|
|
|
|
renderId: msg.id,
|
|
|
|
|
to: msg.to,
|
|
|
|
|
msgtype: 'text',
|
|
|
|
|
msgcontent: { body: msg.text, preview_url: true, ...(msg.context ? { context: msg.context, message_origin: msg.message_origin.msgOrigin } : {}) },
|
|
|
|
|
}),
|
|
|
|
|
contentToRender: (msg) => ({
|
|
|
|
|
...msg,
|
|
|
|
|
whatsapp_msg_type: 'text',
|
|
|
|
|
actionId: msg.id,
|
|
|
|
|
conversationid: msg.id.split('.')[0],
|
|
|
|
|
originText: msg.text,
|
|
|
|
|
text: autoLinkText(msg.text),
|
|
|
|
|
...(msg.context
|
|
|
|
|
? {
|
|
|
|
|
reply: {
|
|
|
|
|
id: msg.message_origin.id,
|
|
|
|
|
message: msg.message_origin.text,
|
|
|
|
|
title: msg.message_origin.senderName || 'Reference',
|
|
|
|
|
titleColor: msg.message_origin?.senderName !== 'me' ? '#a791ff' : '#128c7e',
|
|
|
|
|
photoURL: msg.message_origin?.data?.uri || '',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
: {}),
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
photo: {
|
|
|
|
|
type: 'image',
|
|
|
|
|
contentToSend: (msg) => ({
|
|
|
|
|
...mediaMsg.contentToSend({...msg, type: 'image'}),
|
|
|
|
|
msgtype: 'image',
|
|
|
|
|
}),
|
|
|
|
|
contentToRender: (msg) => ({
|
|
|
|
|
...msg,
|
|
|
|
|
...mediaMsg.contentToRender(msg),
|
|
|
|
|
whatsapp_msg_type: 'image',
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
video: {
|
|
|
|
|
type: 'video',
|
|
|
|
|
contentToSend: (msg) => ({
|
|
|
|
|
...mediaMsg.contentToSend(msg),
|
|
|
|
|
msgtype: 'video',
|
|
|
|
|
}),
|
|
|
|
|
contentToRender: (msg) => ({
|
|
|
|
|
...msg,
|
|
|
|
|
...mediaMsg.contentToRender(msg),
|
|
|
|
|
whatsapp_msg_type: 'video',
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
whatsappTemplate: {
|
|
|
|
|
contentToSend: (msg) => ({ action: 'message', actionId: msg.id, renderId: msg.id, to: msg.to, msgtype: 'template', msgcontent: msg.template }),
|
|
|
|
|
contentToRender: (msg) => {
|
|
|
|
|
const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({ ...r, [v.type]: v }), {}) : null;
|
|
|
|
|
// const templateParam = (templateDataMapped?.body?.parameters || []).map(e => e.text);
|
|
|
|
|
// const fillTemplate = templateParam.length ? replaceTemplateString(msg.template_origin.components.body?.[0]?.text || '', templateParam) : (msg.template_origin.components.body?.[0]?.text || '');
|
|
|
|
|
// const footer = msg.template_origin.components?.footer?.[0]?.text || '';
|
|
|
|
|
return {
|
|
|
|
|
...msg,
|
|
|
|
|
actionId: msg.id,
|
|
|
|
|
conversationid: msg.id.split('.')[0],
|
|
|
|
|
type: 'text',
|
|
|
|
|
title: msg.template_origin.components.header?.[0]?.text || '',
|
|
|
|
|
text: autoLinkText(templateDataMapped?.body?.text || ''), // msg.template_origin.components.body?.[0]?.text || '',
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const whatsappMsgMapped = {
|
|
|
|
|
'whatsapp.inbound_message.received': {
|
|
|
|
|
getMsg: (result) => {
|
|
|
|
|
console.log('whatsapp.inbound_message.received', result);
|
|
|
|
|
return isEmpty(result?.whatsappInboundMessage) ? null : { ...result.whatsappInboundMessage, conversationid: result.conversationid, messageorigin: result.messageorigin };
|
|
|
|
|
},
|
|
|
|
|
contentToRender: (contentObj) => {
|
|
|
|
|
console.log('whatsapp.inbound_message.received to render', contentObj);
|
|
|
|
|
// const contentObj = result?.whatsappInboundMessage || result; // debug:
|
|
|
|
|
return parseRenderMessageItem(contentObj);
|
|
|
|
|
},
|
|
|
|
|
contentToUpdate: () => null,
|
|
|
|
|
},
|
|
|
|
|
'whatsapp.message.updated': {
|
|
|
|
|
getMsg: (result) => {
|
|
|
|
|
console.log('getMsg', result);
|
|
|
|
|
return isEmpty(result?.whatsappMessage) ? null : { ...result.whatsappMessage, conversationid: result.conversationid };
|
|
|
|
|
},
|
|
|
|
|
contentToRender: (contentObj) => {
|
|
|
|
|
if ((contentObj?.status === 'failed' )) {
|
|
|
|
|
contentObj = {
|
|
|
|
|
...contentObj,
|
|
|
|
|
type: 'error',
|
|
|
|
|
text: {body: `❌ ${whatsappError?.[contentObj.errorCode] || contentObj.errorMessage}` }, // contentObj.errorMessage // Message failed to send.
|
|
|
|
|
id: contentObj.id,
|
|
|
|
|
wamid: contentObj.id,
|
|
|
|
|
};
|
|
|
|
|
return parseRenderMessageItem(contentObj);
|
|
|
|
|
}
|
|
|
|
|
// * 仅更新消息状态, 没有输出
|
|
|
|
|
return null;
|
|
|
|
|
},
|
|
|
|
|
contentToUpdate: (msgcontent) => ({
|
|
|
|
|
...msgcontent,
|
|
|
|
|
...parseRenderMessageItem(msgcontent),
|
|
|
|
|
id: msgcontent.wamid,
|
|
|
|
|
status: msgStatusRenderMapped[(msgcontent?.status || 'failed')],
|
|
|
|
|
sender: 'me',
|
|
|
|
|
dateString: msgcontent.status==='failed' ? `发送失败 ${whatsappError?.[msgcontent.errorCode] || msgcontent.errorMessage} ❌` : '',
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
export const msgStatusRenderMapped = {
|
|
|
|
|
'accepted': 'waiting', // 'sent', // 接口的发送请求
|
|
|
|
|
'sent': 'sent',
|
|
|
|
|
'delivered': 'received',
|
|
|
|
|
'read': 'read',
|
|
|
|
|
'failed': 'failed',
|
|
|
|
|
};
|
|
|
|
|
export const receivedMsgTypeMapped = {
|
|
|
|
|
...cloneDeep(whatsappMsgMapped),
|
|
|
|
|
'message': {
|
|
|
|
|
// 发送消息的同步记录 status: 'accepted'
|
|
|
|
|
getMsg: (result) => ({ ...result, conversationid: result.actionId.split('.')[0] }),
|
|
|
|
|
contentToRender: () => null,
|
|
|
|
|
contentToUpdate: (msgcontent) => ({
|
|
|
|
|
...msgcontent,
|
|
|
|
|
actionId: msgcontent.actionId,
|
|
|
|
|
id: msgcontent.wamid,
|
|
|
|
|
status: msgStatusRenderMapped[(msgcontent?.status || 'failed')],
|
|
|
|
|
conversationid: msgcontent.actionId.split('.')[0], // msgcontent.conversation.sn,
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
'error': {
|
|
|
|
|
// 发送消息的同步返回: 发送失败时
|
|
|
|
|
getMsg: (result) => result,
|
|
|
|
|
contentToRender: () => null,
|
|
|
|
|
contentToUpdate: (msgcontent) => ({ ...msgcontent, id: msgcontent.actionId, status: msgcontent?.status || 'failed', dateString: `发送失败 ${msgcontent.error.message} ❌`, conversationid: msgcontent.actionId.split('.')[0], }),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
export const whatsappMsgTypeMapped = {
|
|
|
|
|
error: {
|
|
|
|
|
type: (_m) => ({ type: 'system' }),
|
|
|
|
|
data: (msg) => ({ id: msg.wamid, text: msg.errorCode ? msg.errorMessage : msg.text.body }),
|
|
|
|
|
},
|
|
|
|
|
text: {
|
|
|
|
|
type: 'text',
|
|
|
|
|
data: (msg) => ({ id: msg.wamid, text: autoLinkText(msg.text.body), originText: msg.text.body }),
|
|
|
|
|
renderForReply: (msg) => ({ id: msg.wamid, message: msg.text.body }),
|
|
|
|
|
},
|
|
|
|
|
image: {
|
|
|
|
|
type: 'photo',
|
|
|
|
|
data: (msg) => ({
|
|
|
|
|
id: msg.wamid,
|
|
|
|
|
text: msg.image.caption,
|
|
|
|
|
data: { id: msg.wamid, uri: msg.image.link, width: '100%', height: 200, alt: msg.image.caption, },
|
|
|
|
|
originText: msg.image?.caption || '',
|
|
|
|
|
onOpen: () => {
|
|
|
|
|
console.log('Open image', msg.image.link);
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
renderForReply: (msg) => ({
|
|
|
|
|
id: msg.wamid, photoURL: msg.image.link, width: '100%', height: 200, alt: '',
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
sticker: {
|
|
|
|
|
type: 'photo',
|
|
|
|
|
data: (msg) => ({
|
|
|
|
|
id: msg.wamid,
|
|
|
|
|
data: { id: msg.wamid, uri: msg.sticker.link, width: '100%', height: 120, alt: '' },
|
|
|
|
|
}),
|
|
|
|
|
renderForReply: (msg) => ({
|
|
|
|
|
id: msg.wamid, photoURL: msg.sticker.link, width: '100%', height: 200, alt: '', message: '[表情]'
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
video: {
|
|
|
|
|
type: 'video',
|
|
|
|
|
data: (msg) => ({
|
|
|
|
|
id: msg.wamid,
|
|
|
|
|
data: {
|
|
|
|
|
id: msg.wamid,
|
|
|
|
|
videoURL: msg.video.link,
|
|
|
|
|
status: {
|
|
|
|
|
click: true,
|
|
|
|
|
loading: 0,
|
|
|
|
|
download: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
renderForReply: (msg) => ({
|
|
|
|
|
id: msg.wamid, videoURL: msg.video.link, photoURL: msg.video.link, message: msg.video?.caption || '[视频]', width: 200, height: 200, alt: '',
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
audio: {
|
|
|
|
|
type: 'audio',
|
|
|
|
|
data: (msg) => ({
|
|
|
|
|
id: msg.wamid,
|
|
|
|
|
data: {
|
|
|
|
|
audioURL: msg.audio.link,
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
// unsupported: { type: 'system', data: (msg) => ({ text: 'Message type is currently not supported.' }) },
|
|
|
|
|
unsupported: { type: 'text', data: (msg) => ({ text: '[暂不支持此消息类型]' }) },
|
|
|
|
|
reaction: {
|
|
|
|
|
type: 'text',
|
|
|
|
|
data: (msg) => ({ id: msg.wamid, text: msg.reaction?.emoji || '', }),
|
|
|
|
|
},
|
|
|
|
|
document: {
|
|
|
|
|
type: 'file',
|
|
|
|
|
data: (msg) => ({ id: msg.wamid, title: msg.document?.filename || '', text: msg.document?.caption || msg.document?.filename || '', data: { uri: msg.document.link, extension: 'PDF', status: { click: false, download: true, loading: 0, } }, originText: msg.document?.caption || msg.document?.filename || '', }),
|
|
|
|
|
renderForReply: (msg) => ({
|
|
|
|
|
id: msg.wamid, message: msg.document?.caption || msg.document?.filename || '',
|
|
|
|
|
}),
|
|
|
|
|
},
|
|
|
|
|
// location: 'location',
|
|
|
|
|
// contact: 'contact',
|
|
|
|
|
// 'contact-card': 'contact-card',
|
|
|
|
|
// 'contact-card-with-photo': 'contact-card-with-photo',
|
|
|
|
|
// 'contact-card-with-photo-and-label': 'contact-card-with-photo-and-label',
|
|
|
|
|
template: {
|
|
|
|
|
type: 'text',
|
|
|
|
|
data: (msg) => {
|
|
|
|
|
const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({...r, [v.type]: v}), {}) : null;
|
|
|
|
|
return { id: msg.wamid, text: autoLinkText(templateDataMapped?.body?.text || templateDataMapped?.body?.parameters?.[0]?.text || ''), title: msg.template.name }
|
|
|
|
|
},
|
|
|
|
|
renderForReply: (msg) => {
|
|
|
|
|
const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({ ...r, [v.type]: v }), {}) : null;
|
|
|
|
|
return { id: msg.wamid, message: templateDataMapped?.body?.text || templateDataMapped?.body?.parameters?.[0]?.text || '', title: `${msg.template.name}` };
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* render received msg
|
|
|
|
|
*/
|
|
|
|
|
export const parseRenderMessageItem = (msg) => {
|
|
|
|
|
console.log('parseRenderMessageItem', msg);
|
|
|
|
|
return {
|
|
|
|
|
msgOrigin: msg,
|
|
|
|
|
date: msg?.sendTime || msg?.createTime || '',
|
|
|
|
|
...(whatsappMsgTypeMapped?.[msg.type]?.data(msg) || {}),
|
|
|
|
|
conversationid: msg.conversationid,
|
|
|
|
|
...(typeof whatsappMsgTypeMapped[msg.type].type === 'function' ? whatsappMsgTypeMapped[msg.type].type(msg) : { type: whatsappMsgTypeMapped[msg.type].type || 'text' }),
|
|
|
|
|
// type: whatsappMsgTypeMapped?.[msg.type]?.type || 'text',
|
|
|
|
|
from: msg.from,
|
|
|
|
|
sender: msg.from,
|
|
|
|
|
senderName: msg?.customerProfile?.name || msg.from,
|
|
|
|
|
// title: msg.customerProfile.name,
|
|
|
|
|
customer_name: msg?.customerProfile?.name || '',
|
|
|
|
|
whatsapp_name: msg?.customerProfile?.name || '',
|
|
|
|
|
whatsapp_phone_number: msg.from,
|
|
|
|
|
whatsapp_msg_type: msg.type,
|
|
|
|
|
...((isEmpty(msg.context) && isEmpty(msg.reaction)) || msg.context?.forwarded === true
|
|
|
|
|
? {}
|
|
|
|
|
: {
|
|
|
|
|
reply: {
|
|
|
|
|
/**
|
|
|
|
|
* reply: { message: msg.messageorigin, title: 'React from', titleColor: '#1ba784' }
|
|
|
|
|
*/
|
|
|
|
|
title: msg.messageorigin?.customerProfile?.name || 'me',
|
|
|
|
|
...(typeof whatsappMsgTypeMapped[msg?.messageorigin?.type]?.renderForReply === 'function'
|
|
|
|
|
? whatsappMsgTypeMapped[msg.messageorigin.type].renderForReply(msg.messageorigin)
|
|
|
|
|
: {}),
|
|
|
|
|
titleColor: msg.messageorigin?.customerProfile?.name ? '#a791ff' : "#128c7e",
|
|
|
|
|
},
|
|
|
|
|
origin: msg.context,
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 从数据库读取的记录
|
|
|
|
|
*/
|
|
|
|
|
export const parseRenderMessageList = (messages, conversationid = null) => {
|
|
|
|
|
return messages.map((msg, i) => {
|
|
|
|
|
const msgContent = msg.msgtext_AsJOSN;
|
|
|
|
|
msgContent.template = msg.msgtype === 'template' ? { ...msgContent.template, ...msg.template_AsJOSN } : {};
|
|
|
|
|
const msgType = msgContent.type;
|
|
|
|
|
// const parseMethod = msgContent.bizType === 'whatsapp' ? cloneDeep(whatsappMsgTypeMapped) : {};
|
|
|
|
|
return {
|
|
|
|
|
msgOrigin: msgContent,
|
|
|
|
|
...(whatsappMsgTypeMapped?.[msgType]?.data(msgContent) || {}),
|
|
|
|
|
type: msgContent.type,
|
|
|
|
|
...(typeof whatsappMsgTypeMapped[msgType].type === 'function' ? whatsappMsgTypeMapped[msgType].type(msg) : { type: whatsappMsgTypeMapped[msgType].type || 'text' }),
|
|
|
|
|
date: msgContent?.sendTime || msg.msgtime || '',
|
|
|
|
|
from: msgContent.from,
|
|
|
|
|
sender: msgContent.from,
|
|
|
|
|
senderName: msgContent?.customerProfile?.name || msgContent.from,
|
|
|
|
|
...(msg.msg_direction === 'outbound'
|
|
|
|
|
? {
|
|
|
|
|
sender: 'me',
|
|
|
|
|
senderName: 'me',
|
|
|
|
|
status: msgStatusRenderMapped[msgContent?.status || 'failed'],
|
|
|
|
|
dateString: msgStatusRenderMapped[msgContent?.status || 'failed'] === 'failed' ? `发送失败 ${whatsappError?.[msgContent.errorCode] || msgContent.errorMessage} ❌` : '',
|
|
|
|
|
}
|
|
|
|
|
: {}),
|
|
|
|
|
...((isEmpty(msg.messageorigin_AsJOSN) && isEmpty(msgContent.context))
|
|
|
|
|
// ...((isEmpty(msg.messageorigin_AsJOSN) || isEmpty(msgContent.context))
|
|
|
|
|
? {}
|
|
|
|
|
: {
|
|
|
|
|
reply: {
|
|
|
|
|
message: msg.messageorigin_AsJOSN?.text?.body || msg.messageorigin_AsJOSN?.text,
|
|
|
|
|
title: msg.messageorigin_AsJOSN?.customerProfile?.name || msg.messageorigin_AsJOSN?.senderName || 'me',
|
|
|
|
|
...(typeof whatsappMsgTypeMapped[msg.messageorigin_AsJOSN?.type]?.renderForReply === 'function'
|
|
|
|
|
? whatsappMsgTypeMapped[msg.messageorigin_AsJOSN?.type].renderForReply(msg.messageorigin_AsJOSN)
|
|
|
|
|
: {}),
|
|
|
|
|
// titleColor: msg.messageorigin_AsJOSN?.customerProfile?.name ? '#a791ff' : "#128c7e",
|
|
|
|
|
titleColor: msg.messageorigin_direction === 'inbound' ? '#a791ff' : "#128c7e",
|
|
|
|
|
},
|
|
|
|
|
origin: msg.messageorigin_AsJOSN,
|
|
|
|
|
}),
|
|
|
|
|
// conversationid: conversationid,
|
|
|
|
|
// title: msg.customerProfile.name,
|
|
|
|
|
whatsapp_msg_type: msgContent.type,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
export const whatsappError = {
|
|
|
|
|
'131026': '[131026] 消息无法投递(未注册/使用旧版/未同意政策).',
|
|
|
|
|
'131047': '[131047] 会话超过24小时.',
|
|
|
|
|
'131053': '[131053] 文件上传失败.',
|
|
|
|
|
'131048': '[131048] 账户被风控.', // 消息发送太多, 达到垃圾数量限制
|
|
|
|
|
'131031': '[131031] 账户已锁定.',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 系统弹窗通知
|
|
|
|
|
*/
|
|
|
|
|
export const handleNotification = (title, _options) => {
|
|
|
|
|
var notification;
|
|
|
|
|
const options = {
|
|
|
|
|
requireInteraction: true, // 设置手动关闭
|
|
|
|
|
tag: 'global-sales-notification', // 通知ID,同类通知建议设置相同ID,避免通知过多遮挡桌面
|
|
|
|
|
// icon: '/favicon.ico', // 通知图标
|
|
|
|
|
..._options,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 检查用户是否同意接受通知
|
|
|
|
|
if (Notification.permission === 'granted') {
|
|
|
|
|
notification = new Notification(title, options);
|
|
|
|
|
} else if (Notification.permission !== 'denied') {
|
|
|
|
|
Notification.requestPermission().then(function (permission) {
|
|
|
|
|
if (permission === 'granted') {
|
|
|
|
|
notification = new Notification(title, options);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// 用户拒绝通知权限
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知弹窗被点击后的回调
|
|
|
|
|
notification.onclick = () => {
|
|
|
|
|
// window.parent.parent.focus();
|
|
|
|
|
window.focus(); // 显示当前标签页
|
|
|
|
|
notification.close(); // 关闭通知,适用于设置了手动关闭的通知
|
|
|
|
|
};
|
|
|
|
|
};
|