;(function () {
const defaultData = {
id: '1',
show_guide: false,
float_icon: '',
domain_url: 'http://localhost:5173',
header_font_color: 'rgb(100, 106, 115)',
x_type: 'right',
y_type: 'bottom',
x_value: '-5',
y_value: '33',
}
const script_id_prefix = 'sqlbot-assistant-float-script-'
const guideHtml = `
`
}
/**
* 初始化引导
* @param {*} root
*/
const initGuide = (root) => {
root.insertAdjacentHTML('beforeend', guideHtml)
const button = root.querySelector('.sqlbot-assistant-button')
const close_icon = root.querySelector('.sqlbot-assistant-close')
const close_func = () => {
root.removeChild(root.querySelector('.sqlbot-assistant-tips'))
root.removeChild(root.querySelector('.sqlbot-assistant-mask'))
localStorage.setItem('sqlbot_assistant_mask_tip', true)
}
button.onclick = close_func
close_icon.onclick = close_func
}
const initChat = (root, data) => {
// 添加对话icon
root.insertAdjacentHTML('beforeend', chatButtonHtml(data))
// 添加对话框
root.insertAdjacentHTML('beforeend', getChatContainerHtml(data))
// 按钮元素
const chat_button = root.querySelector('.sqlbot-assistant-chat-button')
const chat_button_img = root.querySelector('.sqlbot-assistant-chat-button > img')
// 对话框元素
const chat_container = root.querySelector('#sqlbot-assistant-chat-container')
// 引导层
const mask_content = root.querySelector('.sqlbot-assistant-mask > .sqlbot-assistant-content')
const mask_tips = root.querySelector('.sqlbot-assistant-tips')
chat_button_img.onload = (event) => {
if (mask_content) {
mask_content.style.width = chat_button_img.width + 'px'
mask_content.style.height = chat_button_img.height + 'px'
if (data.x_type == 'left') {
mask_tips.style.marginLeft =
(chat_button_img.naturalWidth > 500 ? 500 : chat_button_img.naturalWidth) - 64 + 'px'
} else {
mask_tips.style.marginRight =
(chat_button_img.naturalWidth > 500 ? 500 : chat_button_img.naturalWidth) - 64 + 'px'
}
}
}
const viewport = root.querySelector('.sqlbot-assistant-openviewport')
const closeviewport = root.querySelector('.sqlbot-assistant-closeviewport')
const close_func = () => {
chat_container.style['display'] =
chat_container.style['display'] == 'block' ? 'none' : 'block'
chat_button.style['display'] = chat_container.style['display'] == 'block' ? 'none' : 'block'
}
close_icon = chat_container.querySelector('.sqlbot-assistant-chat-close')
chat_button.onclick = close_func
close_icon.onclick = close_func
const viewport_func = () => {
if (chat_container.classList.contains('sqlbot-assistant-enlarge')) {
chat_container.classList.remove('sqlbot-assistant-enlarge')
viewport.classList.remove('sqlbot-assistant-viewportnone')
closeviewport.classList.add('sqlbot-assistant-viewportnone')
} else {
chat_container.classList.add('sqlbot-assistant-enlarge')
viewport.classList.add('sqlbot-assistant-viewportnone')
closeviewport.classList.remove('sqlbot-assistant-viewportnone')
}
}
const drag = (e) => {
if (['touchmove', 'touchstart'].includes(e.type)) {
chat_button.style.top = e.touches[0].clientY - chat_button_img.naturalHeight / 2 + 'px'
chat_button.style.left = e.touches[0].clientX - chat_button_img.naturalWidth / 2 + 'px'
} else {
chat_button.style.top = e.y - chat_button_img.naturalHeight / 2 + 'px'
chat_button.style.left = e.x - chat_button_img.naturalWidth / 2 + 'px'
}
chat_button.style.width = chat_button_img.naturalWidth + 'px'
chat_button.style.height = chat_button_img.naturalHeight + 'px'
}
if (data.is_draggable) {
chat_button.addEventListener('drag', drag)
chat_button.addEventListener('dragover', (e) => {
e.preventDefault()
})
chat_button.addEventListener('dragend', drag)
chat_button.addEventListener('touchstart', drag)
chat_button.addEventListener('touchmove', drag)
}
viewport.onclick = viewport_func
closeviewport.onclick = viewport_func
}
/**
* 第一次进来的引导提示
*/
function initsqlbot_assistant(data) {
const sqlbot_div = document.createElement('div')
const root = document.createElement('div')
const sqlbot_root_id = 'sqlbot-assistant-root-' + data.id
root.id = sqlbot_root_id
initsqlbot_assistantStyle(sqlbot_div, sqlbot_root_id, data)
sqlbot_div.appendChild(root)
document.body.appendChild(sqlbot_div)
const sqlbot_assistant_mask_tip = localStorage.getItem('sqlbot_assistant_mask_tip')
if (sqlbot_assistant_mask_tip == null && data.show_guide) {
initGuide(root)
}
initChat(root, data)
}
// 初始化全局样式
function initsqlbot_assistantStyle(root, sqlbot_assistantId, data) {
style = document.createElement('style')
style.type = 'text/css'
style.innerText = `
/* 放大 */
#sqlbot-assistant .sqlbot-assistant-enlarge {
width: 50%!important;
height: 100%!important;
bottom: 0!important;
right: 0 !important;
}
@media only screen and (max-width: 768px){
#sqlbot-assistant .sqlbot-assistant-enlarge {
width: 100%!important;
height: 100%!important;
right: 0 !important;
bottom: 0!important;
}
}
/* 引导 */
#sqlbot-assistant .sqlbot-assistant-mask {
position: fixed;
z-index: 10001;
background-color: transparent;
height: 100%;
width: 100%;
top: 0;
left: 0;
}
#sqlbot-assistant .sqlbot-assistant-mask .sqlbot-assistant-content {
width: 64px;
height: 64px;
box-shadow: 1px 1px 1px 9999px rgba(0,0,0,.6);
position: absolute;
${data.x_type}: ${data.x_value}px;
${data.y_type}: ${data.y_value}px;
z-index: 10001;
}
#sqlbot-assistant .sqlbot-assistant-tips {
position: fixed;
${data.x_type}:calc(${data.x_value}px + 75px);
${data.y_type}: calc(${data.y_value}px + 0px);
padding: 22px 24px 24px;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #3370FF;
z-index: 10001;
}
#sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-arrow {
position: absolute;
background: #3370FF;
width: 10px;
height: 10px;
pointer-events: none;
transform: rotate(45deg);
box-sizing: border-box;
/* left */
${data.x_type}: -5px;
${data.y_type}: 33px;
border-left-color: transparent;
border-bottom-color: transparent
}
#sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-title {
font-size: 20px;
font-weight: 500;
margin-bottom: 8px;
}
#sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-button {
text-align: right;
margin-top: 24px;
}
#sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-button button {
border-radius: 4px;
background: #FFF;
padding: 3px 12px;
color: #3370FF;
cursor: pointer;
outline: none;
border: none;
}
#sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-button button::after{
border: none;
}
#sqlbot-assistant .sqlbot-assistant-tips .sqlbot-assistant-close {
position: absolute;
right: 20px;
top: 20px;
cursor: pointer;
}
#sqlbot-assistant-chat-container {
width: 450px;
height: 600px;
display:none;
}
@media only screen and (max-width: 768px) {
#sqlbot-assistant-chat-container {
width: 100%;
height: 70%;
right: 0 !important;
}
}
#sqlbot-assistant .sqlbot-assistant-chat-button{
position: fixed;
${data.x_type}: ${data.x_value}px;
${data.y_type}: ${data.y_value}px;
cursor: pointer;
z-index:10000;
}
#sqlbot-assistant #sqlbot-assistant-chat-container{
z-index:10000;position: relative;
border-radius: 8px;
border: 1px solid #ffffff;
background: linear-gradient(188deg, rgba(235, 241, 255, 0.20) 39.6%, rgba(231, 249, 255, 0.20) 94.3%), #EFF0F1;
box-shadow: 0px 4px 8px 0px rgba(31, 35, 41, 0.10);
position: fixed;bottom: 16px;right: 16px;overflow: hidden;
}
#sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate{
top: 18px;
right: 15px;
position: absolute;
display: flex;
align-items: center;
line-height: 18px;
}
#sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate .sqlbot-assistant-chat-close{
margin-left:15px;
cursor: pointer;
}
#sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate .sqlbot-assistant-openviewport{
cursor: pointer;
}
#sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-operate .sqlbot-assistant-closeviewport{
cursor: pointer;
}
#sqlbot-assistant #sqlbot-assistant-chat-container .sqlbot-assistant-viewportnone{
display:none;
}
#sqlbot-assistant #sqlbot-assistant-chat-container #sqlbot-assistant-chat-iframe-${data.id}{
height:100%;
width:100%;
border: none;
}
#sqlbot-assistant #sqlbot-assistant-chat-container {
animation: appear .4s ease-in-out;
}
@keyframes appear {
from {
height: 0;;
}
to {
height: 600px;
}
}`.replaceAll('#sqlbot-assistant ', `#${sqlbot_assistantId} `)
root.appendChild(style)
}
function getParam(src, key) {
const url = new URL(src)
return url.searchParams.get(key)
}
function parsrCertificate(config) {
const certificateList = config.certificate
if (!certificateList?.length) {
return null
}
const list = certificateList.map((item) => formatCertificate(item)).filter((item) => !!item)
return JSON.stringify(list)
}
function isEmpty(obj) {
return obj == null || typeof obj == 'undefined'
}
function formatCertificate(item) {
const { type, source, target, target_key, target_val } = item
let source_val = null
if (type.toLocaleLowerCase() == 'localstorage') {
source_val = localStorage.getItem(source)
}
if (type.toLocaleLowerCase() == 'sessionstorage') {
source_val = sessionStorage.getItem(source)
}
if (type.toLocaleLowerCase() == 'cookie') {
source_val = getCookie(source)
}
if (type.toLocaleLowerCase() == 'custom') {
source_val = source
}
if (isEmpty(source_val)) {
return null
}
return {
target,
key: target_key || source,
value: (target_val && eval(target_val)) || source_val,
}
}
function getCookie(key) {
if (!key || !document.cookie) {
return null
}
const cookies = document.cookie.split(';')
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim()
if (cookie.startsWith(key + '=')) {
return decodeURIComponent(cookie.substring(key.length + 1))
}
}
return null
}
function registerMessageEvent(id, data) {
const iframe = document.getElementById(`sqlbot-assistant-chat-iframe-${id}`)
const url = iframe.src
const eventName = 'sqlbot_assistant_event'
window.addEventListener('message', (event) => {
if (event.data?.eventName === eventName) {
if (event.data?.messageId !== id) {
return
}
if (event.data?.busi == 'ready' && event.data?.ready) {
const certificate = parsrCertificate(data)
console.log(certificate)
params = {
busi: 'certificate',
certificate,
eventName,
messageId: id,
}
const contentWindow = iframe.contentWindow
contentWindow.postMessage(params, url)
}
}
})
}
function loadScript(src, id) {
const domain_url = getDomain(src)
let url = `${domain_url}/api/v1/system/assistant/info/${id}`
if (domain_url.includes('5173')) {
url = url.replace('5173', '8000')
}
fetch(url)
.then((response) => response.json())
.then((res) => {
const data = res.data
const config_json = data.configuration
let tempData = Object.assign(defaultData, { id, domain_url })
if (config_json) {
const config = JSON.parse(config_json)
Object.assign(tempData, config)
tempData = Object.assign(tempData, config)
}
initsqlbot_assistant(tempData)
if (data.type == 1) {
registerMessageEvent(id, tempData)
// postMessage the certificate to iframe
}
})
}
function getDomain(src) {
return src.substring(0, src.indexOf('/assistant.js'))
}
function init() {
const sqlbotScripts = document.querySelectorAll(`script[id^="${script_id_prefix}"]`)
const scriptsArray = Array.from(sqlbotScripts)
const src_list = scriptsArray.map((script) => script.src)
src_list.forEach((src) => {
const id = getParam(src, 'id')
const propName = script_id_prefix + id + '-state'
if (window[propName]) {
return true
}
window[propName] = true
loadScript(src, id)
})
}
window.addEventListener('load', init)
})()