(function() { const script = document.currentScript; const src = script.src; const queryString = src.substring(src.indexOf('?') + 1); const urlParams = new URLSearchParams(queryString); const uuidUrl = urlParams.get('uuid'); const isCn = src.includes('saasflow.cn') const capsuleStyleStr = ` @media screen and (max-width: 769px) { .sfchat-capsule { /* keep floating button visible on mobile */ } .sflow-chat-plugin { width: 80% !important; left: 10% !important; margin-left: 0 !important; height: 70vh !important; } .sflow-chat-plugin-content{ z-index: 999; } .sflow-chat-plugin-iframe{ overflow: visible !important; } } .chatai-animated { border: 2px solid #5D7EFF !important; border-radius: 50% !important; animation: pulse-scale 2s infinite !important; box-sizing: border-box !important; overflow: hidden !important; } @keyframes pulse-scale { 0% { transform: translate(-50%, -50%) scale(0.8); } 100% { transform: translate(-50%, -50%) scale(1); } } .sfchat-capsule { position: fixed; width: 70px; background: #3E69FF; border-radius: 50px; top: 40%; right: 10px; z-index: 999; display: flex; flex-direction: column; align-items: center; padding: 0px 0; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.06); } .sfchat-capsule.useAvatar-capsule{ width: 200px; height: 200px; background: transparent !important; } .sfchat-capsule.useAvatar-capsule.large{ width: 200px; height: 200px; } .sfchat-capsule.useAvatar-capsule.medium{ width: 100px; height: 100px; } .sfchat-capsule.useAvatar-capsule.small{ width: 50px; height: auto; } .use-avatar-box{ width: 100%; height: 100%; position: relative; cursor: pointer; } .use-avatar-box.small{ width: 36px; height: 36px; border-radius: 50%; position: relative; overflow: hidden; } .use-avatar-box.medium{ width: 100px; height: 100px; border-radius: 20px; position: relative; overflow: hidden; } .use-avatar-box.large{ width: 180px; height: 180px; border-radius: 10px; position: relative; overflow: hidden; } .sfchat-capsule.useAvatar-capsule .use-avatar-box .video-avatar{ object-fit: cover; } .useAvatar-capsule .avatar-float-content{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .useAvatar-capsule .avatar-float-content-box{ width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; cursor: pointer; padding-bottom: 30px; box-sizing: border-box; } .use-avatar-box.medium .avatar-float-content-box{ padding-bottom: 20px; } .use-avatar-box.medium .avatar-float-content-box .img-icon{ width: 20px; height: 20px; } .use-avatar-box.medium .avatar-float-content-box .avatar-float-content-word{ font-size: 12px; } .use-avatar-box.small .avatar-float-content-box{ padding-bottom: 10px; } .useAvatar-capsule .img-icon{ width: 28px; height: 28px; margin-bottom: 5px; } .useAvatar-capsule .avatar-float-content-word{ color: white; font-size: 12px; font-weight: 500; text-align: center; } .sfchat-capsule .phone, .sfchat-capsule .email, .sfchat-capsule .chatAi, .sfchat-capsule .wx_qrcode_dom { width: 50px; display: flex; height: 33%; justify-content: center; align-items: center; position: relative; cursor: pointer; height: 50px; } .chat-widget-item { height: 75px; width: 100%; display: flex; justify-content: center; align-items: center; flex-direction: column; padding: 0px 0; border-bottom: 1px solid #eee; box-sizing: content-box; } .chat-widget-item:last-child { border: none; padding-bottom: 6px; } .chat-widget-item-content { position: relative; display: flex; align-items: center; justify-content: center; flex-direction: column; } .chat-widget-item a { text-decoration: none; color: inherit; } .chat-widget-item-content-box{ } .chat-widget-item-content .chatai-widget-item-word{ // position: absolute; font-size: 12px; bottom: -26px; white-space: nowrap; color: #aaa; left: 53%; // transform: translateX(-50%); color: #436ff6; margin-top: 6px; } .sfchat-capsule .chatAi { cursor: pointer; background: #436ff6; position: relative; border-radius: 50%; } .sfchat-capsule .chatAi:before { content: ""; display: block; position: absolute; top: 50%; left: 50%; width: 130%; height: 130%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); -webkit-animation: scale2 1s linear infinite alternate; animation: pulse-scale 1s linear infinite alternate; background-color: #436ff6; border-radius: 50%; opacity: 0.4; } .sfchat-capsule .chatAi .chatAi-content{ position: relative; display: flex; align-items: center; justify-content: center; } .sfchat-capsule .chatAi .chatAi-content img{ height: 30px; width: 30px; } .sfchat-capsule .chat-widget-item .email img, .sfchat-capsule .chat-widget-item .phone img{ height: 26px; width: 26px !important; } .sfchat-capsule .chatAi .chatAi-content .chatai-zx-word{ position: absolute; font-size: 12px; bottom: -40px; white-space: nowrap; color: #aaa; left: 50%; transform: translateX(-50%); color: #436ff6; } .sfchat-capsule .chatAi .customicon{ width: 34px; height: 34px; border-radius: 50%; } .sfchat-capsule hr { height: 1px; width: 20px; color: #698AFF; margin: 0 16px; } .sfchat-capsule .email img , .sfchat-capsule .phone img { width: 1.35rem; } .sfchat-capsule img { width: 1.75rem; position: relative; left: 1px; } .sfchat-capsule .text { display: none; position: absolute; right: 80px; height: 50px; background: #FFFFFF; box-shadow: 0px 5px 20px 0px rgba(122, 132, 165, 0.3); border-radius: 10px; padding: 0 10px; font-size: 14px; z-index: 9999; color: #698AFF !important; } .sfchat-capsule .text p{ color: #698AFF !important; } .sfchat-email-menu { position: absolute; right: 80px; top: -6px; background: #ffffff; border: 1px solid rgba(62, 105, 255, 0.2); box-shadow: 0 8px 20px rgba(122, 132, 165, 0.25); border-radius: 8px; padding: 6px; z-index: 10000; min-width: 160px; } .sfchat-email-menu button { display: block; width: 100%; border: none; background: #ffffff; color: #3E69FF; font-size: 13px; padding: 6px 8px; text-align: left; cursor: pointer; } .sfchat-email-menu button:hover { background: rgba(62, 105, 255, 0.08); } .sfchat-capsule .wx-qrcode-text{ padding: 10px 10px !important; } .sfchat-capsule .chatAi .text { width: 120px; height: 60px; } .sfchat-capsule .chatAi .text .chatai-text-words{ display: flex; flex-direction: column; justify-content: center; align-items: flex-start; height: 60px; } .sfchat-capsule .chatAi .text .chatai-text-word1{ font-weight: 500; color: #436ff6; line-height: 16px; font-size: 16px; } .sfchat-capsule .chatAi .text .chatai-text-word2{ font-size: 12px; line-height: 12px; margin-top: 8px; color: #999; white-space: nowrap; } .sfchat-capsule .email .text { width: 170px; } .sfchat-capsule .phone .text { width: 140px; } .sfchat-capsule p { position: relative; width: 100%; height: 100%; text-align: center; display: flex; justify-content: center; align-items: center; margin: 0; } /* .sfchat-capsule .wechat .text{ width: 320px; height: 320px; text-align: center; } */ .sfchat-capsule span { position: absolute; display: inline-block; border: 1px dashed transparent; border-top: 7px solid transparent; border-bottom: 7px solid transparent; border-left: 12px solid #fff; top: 36%; right: -12px; } .chatai-sf-list-container { position: absolute; display: none; top: -75px; left: -360px; transition: 1.3s; opacity: 0; } .chatai-sf-list-aiimg { position: absolute; right: -40px; top: 46px; width: 30px; height: 30px; cursor: pointer; top: 50%; transform: translateY(-100%); } .chatai-sf-list-aiimg img { width: 30px; } .chatai-sf-list { position: relative; height: 230px; overflow: hidden; width: 300px; padding: 0; margin: 0; pointer-events: none; } .chatai-sf-list li { position: absolute; right: 0; padding: 0 10px; opacity: 0; transition: opacity 1s, top 1s; background-color: white; height: 50px; display: flex; align-items: center; box-shadow: 0 0 20px #eee; border-radius: 10px 20px 0px 10px; text-align: left; margin: 0; color: black; white-space: pre-wrap; width: max-content; } .chatai-sf-list li.li-hide { opacity: 0 !important; } .chatai-sf-list li:nth-child(-n+2) { opacity: 1; } .chatai-sf-list li:nth-child(1) { top: 0; } .chatai-sf-list li:nth-child(2) { top: 70px; } .chatai-sf-list li:nth-child(3) { top: 140px; } .chatai-sf-list li:nth-child(4) { top: 210px; } .chatai-sf-list.fade-out { opacity: 0; } .chatai-sf-list.fade-in { opacity: 1; } .chatAi-red-dot { position: absolute; top: -3px; right: -3px; width: 1.1rem; height: 1.1rem; background: #ff3b30; border-radius: 50%; z-index: 10; box-shadow: 0 0 2px #fff; border: 2px solid #fff; pointer-events: none; color: white; font-size: 12px; display: flex; justify-content: center; align-items: center; } ` const capsuleStyle = document.createElement("style") capsuleStyle.innerHTML = capsuleStyleStr document.head.appendChild(capsuleStyle) const chatLayerStyleStr = ` .sflow-chat-shade { top: 0; left: 0; width: 100%; height: 100%; display: none; z-index: 19891014; background-color: rgb(0, 0, 0); opacity: 0.3; } .sflow-chat-plugin, .sflow-chat-shade { position: fixed; pointer-events: auto; } .sflow-chat-plugin.sflow-chat-small{ width: 46vh; height: 77.5vh; left: auto; right: 1.5%; top: auto; bottom: 5%; } .sflow-chat-plugin.sflow-chat-small .sflow-chat-plugin-min{ display: none; } .sflow-chat-plugin-max{ display: none !important; } .sflow-chat-plugin-iframe { overflow-y: auto; -webkit-overflow-scrolling: touch; } .sflow-chat-plugin { bottom: 2%; right: 5%; margin: 0; padding: 0; background-color: #fff; -webkit-background-clip: content; border-radius: 12px; box-shadow: 1px 1px 50px rgba(0, 0, 0, .3); position: fixed; margin-left: -35%; margin-top: 20px; overflow: hidden; display: none; transition: 0.09s; z-index: 19891015000; width: 360px; height: 607px; } .sflow-chat-plugin-move { display: none; position: fixed; *position: absolute; left: 0; top: 0; width: 100%; height: 100%; /* cursor: move; */ opacity: 0; filter: alpha(opacity=0); background-color: #fff; z-index: 2147483647; } .sflow-chat-plugin-title { padding: 0 80px 0 20px; height: 50px; line-height: 50px; border-bottom: 1px solid #f0f0f0; font-size: 14px; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-radius: 2px 2px 0 0; } .sflow-chat-plugin-lan-sf .sflow-chat-plugin-title { background-color: #285cd1; color: white; } .sflow-chat-plugin-title { display:flex; align-items:center; } .sflow-chat-plugin-title img{ width: 30px; height: 30px; } .sflow-chat-plugin-content { position: relative; width: 100%; height: calc(100% - 50px); } .sflow-chat-plugin-content iframe { width: 100%; height: 100%; } .sflow-chat-plugin-setwin { position: absolute; right: 15px; *right: 0; top: 16px; font-size: 0; line-height: initial; } .sflow-chat-plugin-resize { position: absolute; width: 15px; height: 15px; right: 0; bottom: 0; cursor: se-resize; } .sflow-chat-plugin-setwin span { position: relative; width: 16px; height: 16px; line-height: 18px; margin-left: 10px; text-align: center; font-size: 16px; cursor: pointer; color: #000; _overflow: hidden; } .sflow-chat-plugin-btn a, .sflow-chat-plugin-setwin span { display: inline-block; *display: inline; *zoom: 1; vertical-align: top; } .sflow-chat-plugin-setwin span { position: relative; width: 16px; height: 16px; line-height: 18px; margin-left: 10px; text-align: center; font-size: 16px; cursor: pointer; color: #000; _overflow: hidden; } .sflow-chat-plugin-btn a, .sflow-chat-plugin-setwin span { display: inline-block; *display: inline; *zoom: 1; vertical-align: top; } .sflow-chat-plugin-setwin span { position: relative; width: 16px; height: 16px; line-height: 18px; margin-left: 10px; text-align: center; font-size: 16px; cursor: pointer; color: #000; _overflow: hidden; } .sflow-chat-plugin-setwin .sflow-chat-plugin-close { cursor: pointer; } ` const chatLayerStyle = document.createElement("style") chatLayerStyle.innerHTML = chatLayerStyleStr document.head.appendChild(chatLayerStyle) class chatLayer { shade = null; layer = null; maxScreen = false settingInfo = {} chatSettingInfo = {} isWhite = false chatBubbleShow = true chatBubbleTimer = null chatBots = [] layoutMode = 'big' language = "zh" pendingShow = false pendingShowForce = false chatEndStartTimerInfo = {} constructor() { this.settingInfo.uuid = uuidUrl } createShade() { const shadeDom = document.createElement("div") shadeDom.id = "sflow-chat-shade1" shadeDom.className = "sflow-chat-shade" this.shade = shadeDom document.body.appendChild(shadeDom) } createLayerIframe() { const layerDom = document.createElement("div") layerDom.id = "sflow-chat-plugin1" layerDom.className = "sflow-chat-plugin sflow-chat-plugin-iframe sflow-chat-plugin-lan-sf" this.layoutMode = this.chatSettingInfo.chatAIwidgetStyleSize || 'big' if (this.chatSettingInfo.chatAIwidgetStyleSize && this.chatSettingInfo.chatAIwidgetStyleSize === 'small') { layerDom.className = "sflow-chat-plugin sflow-chat-plugin-iframe sflow-chat-plugin-lan-sf sflow-chat-small" } let chatUrl = "https://chatbot.easiiodev.ai" // let chatUrl = "http://localhost:1002" // if (isCn) { // chatUrl = "https://chat.saasflow.cn" // } else { // chatUrl = "https://chat.sflow.io" // } const isWhite = this.chatSettingInfo.chatAiTitleColor === '#FFFFFF' const resolvedAvatarUrl = this.resolveAssetUrl(this.chatSettingInfo.chatAiAvatarUrl, chatUrl) const avatarUrl = resolvedAvatarUrl || `${chatUrl}/img/default-robot-avatar.svg` this.isWhite = isWhite let toolIcons = [ `${chatUrl}/img/ai_chat_icons/minimize.svg`, `${chatUrl}/img/ai_chat_icons/maximize.svg`, `${chatUrl}/img/ai_chat_icons/close.svg` ] if (isWhite) { toolIcons = [ `${chatUrl}/img/ai_chat_icons/minimize_dark.svg`, `${chatUrl}/img/ai_chat_icons/maximize_dark.svg`, `${chatUrl}/img/ai_chat_icons/close_dark.svg` ] } layerDom.innerHTML = `
${this.chatSettingInfo.chatAiName || "AI Chatbot"}
` this.layer = layerDom document.body.appendChild(layerDom) if (this.shade) { this.shade.style.display = 'none' } } createCapsule() { const capsule = document.createElement("div") let isChatNeedHr = true if (this.chatSettingInfo.enableChatAiEmail == 0 && this.chatSettingInfo.enableChatAiPhone == 0) { isChatNeedHr = false } let isEmailNeedHr = true if (this.chatSettingInfo.enableChatAiDisplay == 0 && this.chatSettingInfo.enableChatAiPhone == 0) { isEmailNeedHr = false } const isCustomicon = [ 'techwithsoul.live', 'mikejohns.ceo', 'digitalmindstate.com', 'techthisout.shop', 'www.techthisout.ai' ].includes(window.location.hostname) // Define chatUrl for this function let chatUrl = "https://chatbot.easiiodev.ai" // default icon const resolvedCapsuleAvatarUrl = this.resolveAssetUrl(this.chatSettingInfo.chatAiAvatarUrl, chatUrl) let chatAiIconUrl = resolvedCapsuleAvatarUrl || `${chatUrl}/img/default-robot-avatar.svg` if (isCustomicon && resolvedCapsuleAvatarUrl) { chatAiIconUrl = resolvedCapsuleAvatarUrl } let chatDomStr = `
1
chatAi
${this.language === 'en' ? 'Online Chat' : '在线咨询'}
${ this.language === 'en' ? 'Online Chat' : '在线客服' }
${this.language === 'en' ? 'Real-time answers' : '实时解答使用问题'}
` let emailDomStr = `
email
${this.language === 'en' ? 'Email' : '联系邮箱'}

${this.settingInfo.email || ""}

` let phoneDomStr = `
phone
${this.language === 'en' ? 'Phone' : '联系电话'}

${this.settingInfo.phone || ""}

` let weixinDomStr = `
二维码
${this.chatSettingInfo.chatAiContactQrcodeLabel || (this.language === 'en' ? 'WhatsApp' : '微信咨询')}

二维码

` if (!this.chatSettingInfo.enableChatAiDisplay) chatDomStr = '' if (!this.chatSettingInfo.enableChatAiEmail) emailDomStr = '' if (!this.chatSettingInfo.enableChatAiPhone) phoneDomStr = '' if (!this.chatSettingInfo.chatAiContactWxQrcode) weixinDomStr = '' let chatAiPosition = { top: "40%", right: "10px" } if (this.chatSettingInfo.chatAiFloatToolPosition) { switch (this.chatSettingInfo.chatAiFloatToolPosition) { case 'top-left': chatAiPosition = { top: "5%", right: "none" } break; case 'center-left': chatAiPosition = { top: "40%", right: "none" } break; case 'bottom-left': chatAiPosition = { top: "70%", right: "none" } break; case 'top-right': chatAiPosition = { top: "5%", right: "30px" } break; case 'center-right': break; case 'bottom-right': chatAiPosition = { top: "60%", right: "30px" } break; case 'top-center': chatAiPosition = { top: "5%", right: "calc(50% - 25px)" } break; case 'center-center': chatAiPosition = { top: "48%", right: "calc(50% - 25px)" } break; case 'bottom-center': chatAiPosition = { top: "90%", right: "calc(50% - 25px)" } break; case 'custom': try { const chatAiFloatToolPosition = JSON.parse(this.chatSettingInfo.chatAiFloatToolPositionCustom) console.log('chatAiFloatToolPosition', chatAiFloatToolPosition) chatAiPosition = { top: chatAiFloatToolPosition.y, right: `calc(100vw - ${chatAiFloatToolPosition.x} - 50px)`, } } catch (error) { console.log('err', error) } break; default: break; } } let useAvatarAsFloatingTool = 0 let iconSize = "small" let chatIconSetting = {} try { chatIconSetting = JSON.parse(this.chatSettingInfo.chatIconSetting) useAvatarAsFloatingTool = chatIconSetting.useAvatarAsFloatingTool || 0 iconSize = chatIconSetting.iconSize || "small" } catch (error) { } // let sfchatCapsuleContentStr = ` // ${this.settingInfo.uuid ? chatDomStr : ''} let sfchatCapsuleContentStr = ` ${this.settingInfo.uuid ? chatDomStr : ''} ${this.settingInfo.phone ? phoneDomStr : ''} ${this.settingInfo.email ? emailDomStr : ''} ${this.settingInfo.email ? weixinDomStr : ''} ` if (useAvatarAsFloatingTool === 1) { const isVideoType = this.checkIsVideo(this.chatSettingInfo.chatAiAvatarUrl) const floatingAvatarUrl = resolvedCapsuleAvatarUrl || `${chatUrl}/img/default-robot-avatar.svg` const that = this function navToChatFloatPage() { if (chatIconSetting.open == 1 && chatIconSetting.floatingLink) { window.open(chatIconSetting.floatingLink, '_blank') return } that.open() } window.navToChatFloatPage = navToChatFloatPage sfchatCapsuleContentStr = `
${isVideoType ? `` : ` avatar` } ${chatIconSetting.open ? `
${chatIconSetting.floatingIcon ? `` : '' } ${chatIconSetting.floatingText ? `
${chatIconSetting.floatingText}
` : '' }
` : '' }
` } // this.chatSettingInfo.chatAiTitleColor = "#ffffff"; // capsule.innerHTML = ` //
// ${sfchatCapsuleContentStr} //
// ` capsule.innerHTML = `
${sfchatCapsuleContentStr}
` document.body.appendChild(capsule) let email = document.querySelector(".sfchat-capsule .email") if (email) { let email_text = document.querySelector(".sfchat-capsule .email .text") const showEmailMenu = () => { const existingMenu = document.querySelector(".sfchat-email-menu") if (existingMenu) { existingMenu.remove() } const menu = document.createElement("div") menu.className = "sfchat-email-menu" const copyBtn = document.createElement("button") copyBtn.textContent = this.language === 'en' ? "Copy email" : "复制邮箱" copyBtn.addEventListener("click", () => { if (navigator.clipboard && email && email.href) { navigator.clipboard.writeText(email.href.replace(/^mailto:/, '')) } menu.remove() }) const openBtn = document.createElement("button") openBtn.textContent = this.language === 'en' ? "Open email" : "打开邮箱" openBtn.addEventListener("click", () => { if (email && email.href) { window.location.href = email.href } menu.remove() }) menu.appendChild(copyBtn) menu.appendChild(openBtn) email.appendChild(menu) const handleOutside = (event) => { if (!menu.contains(event.target) && !email.contains(event.target)) { menu.remove() document.removeEventListener("click", handleOutside) } } setTimeout(() => { document.addEventListener("click", handleOutside) }, 0) } email.addEventListener('mouseover', function () { email_text.style.display = 'block' }) email.addEventListener('mouseout', function () { email_text.style.display = 'none' }) email.addEventListener('click', function (event) { event.preventDefault() showEmailMenu() }) } let phone = document.querySelector(".sfchat-capsule .phone") if (phone) { let phone_text = document.querySelector(".sfchat-capsule .phone .text") phone.addEventListener('mouseover', function () { phone_text.style.display = 'block' }) phone.addEventListener('mouseout', function () { phone_text.style.display = 'none' }) } let chatAi = document.querySelector(".sfchat-capsule .chatAi") if (chatAi) { let chatAi_text = document.querySelector(".sfchat-capsule .chatAi .text") chatAi.addEventListener('mouseover', function () { chatAi_text.style.display = 'block' }) chatAi.addEventListener('mouseout', function () { chatAi_text.style.display = 'none' }) chatAi.onclick = () => { this.open() } } let weixin = document.querySelector(".sfchat-capsule .wx_qrcode_dom") if (weixin) { let weixin_text = document.querySelector(".sfchat-capsule .wx_qrcode_dom .wx-qrcode-text") weixin.addEventListener('mouseover', function () { weixin_text.style.display = 'block' }) weixin.addEventListener('mouseout', function () { weixin_text.style.display = 'none' }) } if (this.chatSettingInfo.enableChatAiWidgetAnimation === 1) { // this.createChatBubble() } } checkIsVideo(url) { const videoType = [ "mov", "mp4", "avi", "flv", "3gp", "webm", "rmvb", "wmv", "asf", "asx", "vob", "dat", "mkv", ]; return videoType.includes( url.split(".")[url.split(".").length - 1].toLowerCase() ); } resolveAssetUrl(url, chatUrl) { if (!url) return url if (url.startsWith("/")) return `${chatUrl}${url}` return url } async createChatBubble() { this.chatBubbleShow = true let sfbots = [] if (this.chatBots.length) { sfbots = [...this.chatBots].filter(item => { return !this.checkIsVideo(item.icon || '') }) } else { const baseChatUrl = "https://chatbot.easiiodev.ai" sfbots = [{ icon: this.resolveAssetUrl(this.chatSettingInfo.chatAiAvatarUrl, baseChatUrl) || `${baseChatUrl}/img/default-robot-avatar.svg` }] try { const { data: { getSfbotCharactersBySfbotId: botCharacters } } = await getSfbotCharactersBySfbotId(this.chatSettingInfo.id) if (botCharacters.length) { sfbots = sfbots.concat(botCharacters).filter(item => { return item.title !== 'ChatAI default' }) } } catch (error) { } sfbots = sfbots.filter(item => { return !this.checkIsVideo(item.icon || '') }) this.chatBots = [...sfbots] } //
  • let chatAiWidgetAnimationGreetingStr = this.chatSettingInfo.chatAiWidgetAnimationGreeting let chatAiWidgetAnimationGreeting = [] try { chatAiWidgetAnimationGreeting = JSON.parse(chatAiWidgetAnimationGreetingStr) } catch (error) { } if (!chatAiWidgetAnimationGreeting.length) return console.log('chatAiWidgetAnimationGreeting', chatAiWidgetAnimationGreeting) let chatAiWidgetAnimationGreetings = '' let chatAiWidgetAnimationGreetingStyleStr = '' let liHeightTop = 0 chatAiWidgetAnimationGreeting.forEach((item, index) => { // 几行文本 const line = (item.content || '').split('\n').length if (item.link && item.link.includes('http')) { chatAiWidgetAnimationGreetings += `
  • ${item.content}
  • ` } else { chatAiWidgetAnimationGreetings += `
  • ${item.content}
  • ` } let beishu = Math.ceil(line / 2) let liHtight = beishu * 50 chatAiWidgetAnimationGreetingStyleStr += ` .chatai-sf-list li:nth-child(${index + 1}) { top: ${liHeightTop}px; } .chatai-sf-list li.li_${index} { height: ${liHtight}px; } ` liHeightTop += (liHtight + 20) }) // 若不需要显示动画的图标 if (this.chatSettingInfo.enableChatAiWidgetAnimationIconShow == 0) { chatAiWidgetAnimationGreetingStyleStr += ` .chatai-sf-list-container{ left: -330px; } ` } const animationStyle = document.createElement("style") animationStyle.innerHTML = chatAiWidgetAnimationGreetingStyleStr document.head.appendChild(animationStyle) const enableChatAiWidgetAnimationIconShow = this.chatSettingInfo.enableChatAiWidgetAnimationIconShow //
  • Hi, I'm ChatAI
  • //
  • I can give you quick answers to \n popular questions.
  • //
  • Do you need my help?
  • const chatBubbleStr = ` ${enableChatAiWidgetAnimationIconShow == 0 ? '' : `
    ` } ` let that = this let curMoveFrequency = 1 // 显示次数 const chatAiWidgetAnimationGreetingShowTimes = this.chatSettingInfo.chatAiWidgetAnimationGreetingShowTimes || 0 let currentChatAiWidgetAnimationGreetingShowTimes = 0 const bubbleMove = () => { this.chatEndStartTimerInfo.show = setTimeout(function () { var list = document.querySelector('.chatai-sf-list'); var firstItem = list.querySelector('.chatai-sf-list li:first-child'); var fourthItem = list.querySelector(`.chatai-sf-list li:nth-child(${chatAiWidgetAnimationGreeting.length})`); firstItem.classList.add('fade-out'); fourthItem.classList.add('fade-in'); that.chatEndStartTimerInfo.startshow = setTimeout(function () { list.removeChild(firstItem); list.insertBefore(firstItem, fourthItem.nextSibling); // 重新计算li的top值 var listItems = list.querySelectorAll('li'); let liHeightTop = 0 for (let index = 0; index < listItems.length; index++) { const listItem = listItems[index]; listItem.style.top = liHeightTop + 'px' const liHtight = Number(listItem.offsetHeight) liHeightTop += (liHtight + 20) } firstItem.classList.remove('fade-out'); fourthItem.classList.remove('fade-in'); curMoveFrequency++ if (curMoveFrequency % chatAiWidgetAnimationGreeting.length === chatAiWidgetAnimationGreeting.length - 1) { currentChatAiWidgetAnimationGreetingShowTimes++ if (chatAiWidgetAnimationGreetingShowTimes && currentChatAiWidgetAnimationGreetingShowTimes >= chatAiWidgetAnimationGreetingShowTimes) { that.closeChatBubble() } else { that.chatEndStartTimerInfo.startshowsleep = setTimeout(() => { bubbleMove() }, 1000 * 7); } } else { bubbleMove() } }, 1000); }, 1000); } const chataiSfListContainerDom = document.createElement('div') chataiSfListContainerDom.className = 'chatai-sf-list-container' if (!this.chatSettingInfo.enableChatAiEmail && !this.chatSettingInfo.enableChatAiPhone) { chataiSfListContainerDom.style.top = '-70px' } chataiSfListContainerDom.innerHTML = chatBubbleStr const sfchatCapsule = document.querySelector('.sfchat-capsule') sfchatCapsule.appendChild(chataiSfListContainerDom) const chatAiImgDom = document.querySelector('.chatai-sf-list-aiimg') if (chatAiImgDom) { chatAiImgDom.onclick = () => { this.open() } this.create30SliceImg() } setTimeout(() => { if (this.chatBubbleShow) { this.chatBubbleShow = false chataiSfListContainerDom.style.display = 'inline-block' setTimeout(() => { chataiSfListContainerDom.style.opacity = 1 bubbleMove() }, 500); } }, 1000 * 20); } create30SliceImg() { // 创建每30s更换头像的定时器 if (this.chatBots.length > 1) { let currBotImgIndex = 0 this.chatBubbleTimer = setInterval(() => { currBotImgIndex++ const chatAIImg = document.querySelector('.chatai-sf-list-aiimg img') chatAIImg.src = this.chatBots[currBotImgIndex % this.chatBots.length].icon }, 1000 * 30); } } closeChatBubble() { this.chatBubbleShow = false const chataiSfListContainerDom = document.querySelector('.chatai-sf-list-container') if (chataiSfListContainerDom) { chataiSfListContainerDom.style.opacity = 0 setTimeout(() => { chataiSfListContainerDom.style.display = 'none' chataiSfListContainerDom.remove() }, 1200); } clearInterval(this.chatBubbleTimer) clearTimeout(this.chatEndStartTimerInfo.show) clearTimeout(this.chatEndStartTimerInfo.startshow) clearTimeout(this.chatEndStartTimerInfo.startshowsleep) this.chatEndStartTimerInfo.show = setTimeout(() => { // this.createChatBubble() }, 1000 * 40); } init() { if (this.layer) return this.createShade() this.createLayerIframe() this.screenEventInit() } screenEventInit() { const minBtn = document.querySelector(".sflow-chat-plugin-min") const maxBtn = document.querySelector(".sflow-chat-plugin-max") const closeBtn = document.querySelector(".sflow-chat-plugin-close") minBtn.onclick = this.min.bind(this) maxBtn.onclick = this.max.bind(this) closeBtn.onclick = this.close.bind(this) } min() { this.shade.style.display = 'none' this.layer.style.display = 'none' // Show the floating capsule when minimized const existingCapsule = document.querySelector('.sfchat-capsule') if (!existingCapsule) { this.createCapsule() } else { existingCapsule.style.display = 'flex' } } max() { this.maxScreen = !this.maxScreen let maxMinIcons = [ "/icons/favicon-32x32.png", "/icons/favicon-16x16.png" ] if (this.isWhite) { maxMinIcons = [ "/icons/favicon-96x96.png", "/icons/favicon-32x32.png" ] } if (this.maxScreen) { if (this.layoutMode === 'small') { this.layer.style.width = '70vw' this.layer.style.height = '83vh' document.querySelector(".sflow-chat-plugin-max img").src = maxMinIcons[0] } else { this.layer.style.width = '100vw' this.layer.style.height = '100vh' document.querySelector(".sflow-chat-plugin-max img").src = maxMinIcons[0] this.layer.style.marginLeft = "0px" this.layer.style.marginTop = "0px" this.layer.style.left = "0px" } } else { if (this.layoutMode === 'small') { this.layer.style.width = '58vh' this.layer.style.height = '83vh' document.querySelector(".sflow-chat-plugin-max img").src = maxMinIcons[1] } else { this.layer.style.width = '70vw' this.layer.style.height = '650px' document.querySelector(".sflow-chat-plugin-max img").src = maxMinIcons[1] this.layer.style.marginLeft = "-35%" this.layer.style.marginTop = "20px" this.layer.style.left = "50%" } } } close() { this.min() return this.layer.remove() this.shade.remove() this.layer = null this.shade = null this.maxScreen = false } open() { this.closeChatBubble() this.init() // this.shade.style.display = "block" this.layer.style.opacity = "0" this.layer.style.display = "block" this.fadeIn(this.layer) // Hide the floating capsule when chat window is opened const existingCapsule = document.querySelector('.sfchat-capsule') if (existingCapsule) { existingCapsule.style.display = 'none' } } async set({ uuid, email, phone, language }) { this.settingInfo.uuid = uuid if (language) this.language = language this.settingInfo.email = email this.settingInfo.phone = phone const result = await getChatInfo(uuid) const isExist = document.querySelector('.sfchat-capsule') if (isExist) return if (result && result.data && result.data.getOrgSfbotFromUuid) { // 匹配是否在忽略目录 try { if (result.data.getOrgSfbotFromUuid.floatToolIgnoresPages) { const floatToolIgnoresPages = JSON.parse(result.data.getOrgSfbotFromUuid.floatToolIgnoresPages) if (Array.isArray(floatToolIgnoresPages) && floatToolIgnoresPages.length) { const findPage = floatToolIgnoresPages.find(item => { if (item.title.includes(window.location.pathname)) { return true } }) if (findPage) { return } } } } catch (error) { } this.chatSettingInfo = result.data.getOrgSfbotFromUuid if (!language && this.chatSettingInfo.language) { const sfbotLang = this.chatSettingInfo.language.toLowerCase() if (sfbotLang === 'en' || sfbotLang === 'en-us') this.language = 'en' else if (sfbotLang === 'zh' || sfbotLang === 'zh-cn') this.language = 'zh' } // 判断浏览器是不是手机 if (/Mobi|Android|iPhone/i.test(navigator.userAgent)) { try { let chatIconSetting = JSON.parse(this.chatSettingInfo.chatIconSetting) if (chatIconSetting.iconSize === 'large') { this.chatSettingInfo = { ...this.chatSettingInfo, chatIconSetting: '{}' } } } catch (error) { } } this.settingInfo.email = this.chatSettingInfo.contactEmail || this.settingInfo.email this.settingInfo.phone = this.chatSettingInfo.contactPhone || this.settingInfo.phone } if (this.pendingShow) { const allowAutoPopup = Number(this.chatSettingInfo.chatAiComponentsAutoPupop) === 1 if (this.pendingShowForce || allowAutoPopup) { this.open() } this.pendingShow = false this.pendingShowForce = false } if (!this.chatSettingInfo.enableChatAiFloatTool) return this.createCapsule() // 自动弹出逻辑(移动端不自动弹出,仅保留悬浮按钮) if (this.chatSettingInfo.chatAiComponentsAutoPupop == 1) { const isMobileDevice = (/Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent)) || (window.matchMedia && window.matchMedia('(max-width: 769px)').matches) if (!isMobileDevice) { let pupopTime = Number(this.chatSettingInfo.chatAiComponentsAutoPupopTime) || 3; setTimeout(() => { if (this.layer) { return } this.show(); }, pupopTime * 1000); } } } fadeOut(element) { var speed = speed || 30; var num = 10; var st = setInterval(() => { num--; element.style.opacity = num / 10; if (num <= 0) { clearInterval(st); } }, speed); } fadeIn(element, speed) { var speed = speed || 20; var num = 0; var st = setInterval(() => { num++; element.style.opacity = num / 10; if (num >= 10) { clearInterval(st); } }, speed); } show(force) { const hasSettingInfo = this.chatSettingInfo && this.chatSettingInfo.id if (!hasSettingInfo) { this.pendingShow = true this.pendingShowForce = !!force return } if (!force && Number(this.chatSettingInfo.chatAiComponentsAutoPupop) !== 1) { return } this.open() } } const getSfApiUrl = () => { return "https://chatbot.easiiodev.ai" } const getChatInfo = (uuid) => { return new Promise((resolve, reject) => { fetch(`${getSfApiUrl()}/graphql`, { method: 'POST', body: JSON.stringify({ query: ` query getOrgSfbotFromUuid($uuid: String!) { getOrgSfbotFromUuid(uuid: $uuid){ id contactPhone contactEmail chatAiName chatAiAvatarUrl chatAiTitleColor enableChatAiFloatTool enableChatAiDisplay enableChatAiEmail enableChatAiPhone enableChatAiWidgetAnimation enableShopping chatAiWidgetAnimationGreeting chatAiFloatToolPosition chatAiFloatToolPositionCustom enableChatAiWidgetAnimationIconShow chatAiWidgetAnimationGreetingShowTimes chatIconSetting floatToolIgnoresPages chatAIwidgetStyleSize chatAiComponentsAutoPupop chatAiComponentsAutoPupopTime chatAiContactWxQrcode chatAiContactQrcodeLabel language } } `, variables: { uuid: uuid, }, }), headers: { 'Content-Type': 'application/json', }, }).then(res => res.json()).then((res) => { if (res.errors && res.errors.length) { resolve(null) } else { resolve(res) } }).catch((err) => { resolve(null) }) }) } const getSfbotCharactersBySfbotId = (sfbotId) => { return new Promise((resolve, reject) => { fetch(`${getSfApiUrl()}/graphql`, { method: 'POST', body: JSON.stringify({ query: ` query getSfbotCharactersBySfbotId($sfbotId: Int!) { getSfbotCharactersBySfbotId(sfbotId: $sfbotId){ id icon title } } `, variables: { sfbotId: sfbotId, }, }), headers: { 'Content-Type': 'application/json', }, }).then(res => res.json()).then((res) => { if (res.errors && res.errors.length) { resolve(null) } else { resolve(res) } }).catch((err) => { resolve(null) }) }) } const chatlayer = new chatLayer() window.chatlayer = chatlayer }())