<html lang="en">
<head>
    <meta charset="utf-8">
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
    <meta name="keywords" content="Golang Open Source LiveChat Software"/>
    <meta name="description" content="Golang Open Source LiveChat Software"/>
    <title>Live Chat Support</title>

    <!-- 防止闪烁：在页面渲染前应用主题 -->
    <script>
        (function() {
            // 1. 从 URL 参数获取主题
            const urlParams = new URLSearchParams(window.location.search);
            const themeParam = urlParams.get('theme');

            // 2. 从 localStorage 获取保存的主题
            const savedTheme = localStorage.getItem('theme');

            // 3. 检测是否在 iframe 中
            const isInIframe = window.parent !== window;

            // 4. 确定要使用的主题
            // 如果在 iframe 中且没有明确指定主题，默认使用暗色模式（避免闪烁）
            let theme;
            if (themeParam) {
                theme = themeParam;
            } else if (savedTheme) {
                theme = savedTheme;
            } else if (isInIframe) {
                // iframe 环境默认暗色，等待父页面发送实际主题
                theme = 'dark';
            } else {
                theme = 'light';
            }

            // 5. 立即设置HTML背景色和应用主题类
            if (theme === 'dark') {
                // 暗色模式：立即设置内联样式防止闪烁
                document.documentElement.style.backgroundColor = '#1a3d35';
                document.documentElement.style.color = '#FFFFFF';
                document.documentElement.classList.add('dark-mode-init');
            } else {
                // 白天模式：移除可能存在的暗色类和样式
                document.documentElement.classList.remove('dark-mode-init');
                document.documentElement.style.backgroundColor = '';
                document.documentElement.style.color = '';
            }

            // 6. 在脚本末尾立即尝试给body添加类（此时body可能还不存在）
            // 使用定时器快速重试，确保尽早添加
            let retryCount = 0;
            const maxRetries = 50; // 最多重试50次
            const applyBodyClass = function() {
                if (document.body) {
                    if (theme === 'dark') {
                        document.body.classList.add('dark-mode');
                        // 移除html的内联样式，让CSS接管
                        document.documentElement.style.backgroundColor = '';
                        document.documentElement.style.color = '';
                    } else {
                        // 白天模式：确保移除暗色类
                        document.body.classList.remove('dark-mode');
                    }
                    return true;
                } else if (retryCount < maxRetries) {
                    retryCount++;
                    setTimeout(applyBodyClass, 10); // 10ms后重试
                    return false;
                }
                return false;
            };
            applyBodyClass();
        })();
    </script>
    <link rel="stylesheet" href="/aicss/static/cdn/element-ui/2.15.1/theme-chalk/index.min.css">
    <script src="/aicss/static/cdn/vue/2.6.11/vue.min.js"></script>
    <script src="/aicss/static/cdn/element-ui/2.15.1/index.js"></script>
    <script src="/aicss/static/cdn/jquery/3.6.0/jquery.min.js"></script>

    <script src="/aicss/assets/js/functions.js?v=fgffdwersdccvcbv"></script>
    <script src="/aicss/assets/js/reconnecting-websocket.min.js"></script>
    <link rel="stylesheet" href="/aicss/static/css/common.css?v=sdsderfrgfgdfdf" />
    <link rel="stylesheet" href="/aicss/static/css/icono.min.css" />
    <link rel="stylesheet" href="/aicss/static/css/icon/iconfont.css?v=fgjlgfda"/>
    <link rel="stylesheet" href="/aicss/static/css/dark-mode.css" />
</head>
<body class="visitorBody">
<div id="app" class="chatCenter">
    <template>
        <!--Customer Service Code-->
        <div class="chatEntTitle" v-show="!isIframe">
            <el-badge type="success" is-dot class="item">
                <el-avatar class="chatEntTitleLogo" :size="35" :src="kefuInfo.avatar"></el-avatar>
            </el-badge>
            <div>
                <div>在线客服</div>
            </div>
        </div>
        <div class="chatEntBox">
            <div class="chatContext chatVisitorPage">
                <div class="chatBox">
                    <div class="chatNotice" v-on:click="getHistoryMessage" v-show="showLoadMore">
                        <a href="javascript:;" class="chatNoticeContent" style="color: #07a9fe;">加载更多消息</a>
                    </div>
                    <el-row :gutter="2" v-for="v in msgList" v-bind:class="{'chatBoxMe': v.is_kefu==false}">
                        <div class="chatTime" v-bind:class="{'chatTimeHide': v.show_time==false}"><span><{v.time}></span></div>
                        <div v-if="v.is_kefu==true" style="display: flex;">
                            <el-avatar style="margin-right:10px;flex-shrink: 0;" :size="36" :src="v.avator"></el-avatar>
                            <div class="chatMsgContent">
                                <div class="chatContent chatContent2 replyContentBtn" v-html="v.content"></div>
                            </div>
                        </div>
                        <div class="kefuMe" v-if="v.is_kefu==false" style="display: flex;justify-content: flex-end;">
                            <div class="chatContent chatContent2 replyContentBtn" v-html="v.content"></div>
                            <el-avatar style="margin-left:10px;flex-shrink: 0;" :size="36" :src="v.avator"></el-avatar>
                        </div>
                        <div class="clear"></div>
                    </el-row>
                </div>
            </div>
            <div class="chatBoxSend">
                <div class="visitorIconBox">
                    <el-tooltip content="Send emoji" placement="top">
                        <div class="iconBtn iconfont icon-xiaolian" style="margin-left:15px;font-size: 20px;cursor: pointer;" @click.stop="showFaceIcon==true?showFaceIcon=false:showFaceIcon=true"></div>
                    </el-tooltip>

                    <el-tooltip content="Upload image" placement="top">
                        <div class="iconBtn el-icon-picture" id="uploadImg" v-on:click="uploadImg('/uploadimg')" style="font-size: 20px;"></div>
                    </el-tooltip>
                    <el-tooltip content="Upload file" placement="top">
                        <div class="iconBtn el-icon-upload" id="uploadFile" v-on:click="uploadFile('/uploadfile')" style="font-size: 20px;"></div>
                    </el-tooltip>

                    <div style="display: none" title="Emoji" class="icono-smile visitorIconBtns visitorFaceBtn"></div>

                    <div class="clear"></div>
                </div>
                <div class="faceBox visitorFaceBox" v-show="showFaceIcon">
                    <ul class="faceBoxList">
                        <li v-on:click="faceIconClick(i)" class="faceIcon" v-for="(v,i) in face" :title="v.name"><img :src=v.path></li>
                    </ul>
                    <div class="clear"></div>
                </div>
                <div class="message-box-send">
                    <el-input :rows="2" type="textarea" resize="none" class="visitorEditorArea" @focus="scrollBottom;showIconBtns=false" @blur="scrollBottom;showIconBtns=false" v-model="messageContent" v-on:keyup.enter.native="chatToUser">
                    </el-input>
                    <div class="btn-box">
<el-button type="primary" size="mini" class="visitorEditorBtn" :loading="sendDisabled" :disabled="sendDisabled||messageContent==''" v-on:click="chatToUser();showIconBtns=false"><{ sendDisabled ? '发送中...' : '发送' }></el-button>
                    </div>
                </div>
            </div>
        </div>
        <div class="chatArticle">
            <h3 class="hotQuestionTitle">公告</h3>
            <div class="allNotice" v-html><{kefuInfo.allNotice}></div>
        </div>

        <audio id="chatMessageAudio"></audio>
        <audio id="chatMessageSendAudio"></audio>
    </template>
</div>
</body>
<script>
    var KEFU_ID='{{.KEFU_ID}}';
    var REFER='{{.Refer}}';

    // 主题切换函数
    function setTheme(theme) {
        if (theme === 'dark') {
            document.body.classList.add('dark-mode');
            localStorage.setItem('theme', 'dark');
        } else {
            document.body.classList.remove('dark-mode');
            localStorage.setItem('theme', 'light');
        }
    }

    // 监听来自父页面的主题变化消息
    window.addEventListener('message', function(event) {
        // 安全检查：可以添加 origin 验证
        // if (event.origin !== 'https://your-parent-domain.com') return;

        if (event.data && event.data.type === 'theme-change') {
            console.log('Received theme change:', event.data.theme);
            setTheme(event.data.theme);
        }
    });

    // 页面加载时，应用主题（已在 head 中预设）
    (function() {
        // 检查是否在 head 中已经设置了暗色模式
        const isDarkInit = document.documentElement.classList.contains('dark-mode-init');

        if (isDarkInit) {
            // 已在 head 中设置为暗色，直接应用
            document.body.classList.add('dark-mode');
            localStorage.setItem('theme', 'dark');
            // 移除临时类
            document.documentElement.classList.remove('dark-mode-init');
        } else {
            // 确保是亮色模式
            document.body.classList.remove('dark-mode');
            localStorage.setItem('theme', 'light');
        }

        // 通知父页面已准备好接收主题消息
        if (window.parent !== window) {
            window.parent.postMessage({ type: 'iframe-ready' }, '*');
        }
    })();
</script>
<script>
    var initVue=function(){
    new Vue({
        el: '#app',
        delimiters:["<{","}>"],
        data: {
            window:window,
            server:getWsBaseUrl()+"/aicss/ws_visitor",
            socket:null,
            msgList:[],
            msgListNum:[],
            messageContent:"",
            chatTitle:"Connecting...",
            visitor:{},
            face:[],
            showKfonline:false,
            socketClosed:false,
            focusSendConn:false,
            timer:null,
            sendDisabled:false,
            showIconBtns:false,
            showFaceIcon:false,
            isIframe:false,
            kefuInfo:{},
            showLoadMore:false,
            messages:{
                page:1,
                pagesize:5,
                list:[],
            },
        },
        methods: {
            initConn:function() {
                let socket = new ReconnectingWebSocket(this.server+"?visitor_id="+this.visitor.visitor_id);
                this.socket = socket
                this.socket.onmessage = this.OnMessage;
                this.socket.onopen = this.OnOpen;
                this.socket.onclose = this.OnClose;
                this.ping();
            },
            OnOpen:function() {
                console.log("ws:onopen");
                this.getNotice();
                this.socketClosed=false;
                this.focusSendConn=false;
            },
            OnMessage:function(e) {
                console.log("ws:onmessage");
                this.socketClosed=false;
                this.focusSendConn=false;
                const redata = JSON.parse(e.data);
                if (redata.type == "kfOnline") {
                    let msg = redata.data
                    if(this.showKfonline && this.visitor.to_id==msg.id){
                        return;
                    }
                    this.visitor.to_id=msg.id;
                    this.showTitle(msg.name+", 正正与您对话");
                    this.scrollBottom();
                    this.showKfonline=true;
                }
                if (redata.type == "transfer") {
                    var kefuId = redata.data
                    if(!kefuId){
                        return;
                    }
                    this.visitor.to_id=kefuId;
                }
                if (redata.type == "notice") {
                    let msg = redata.data
                    if(!msg){
                        return;
                    }
                    this.chatTitle=msg
                    $(".chatBox").append("<div class=\"chatTime\">"+this.chatTitle+"</div>");
                    this.scrollBottom();
                }
                if (redata.type == "message") {
                    let msg = redata.data
                    this.visitor.to_id=msg.id;

                    let content = {}
                    content.avator = msg.avator;
                    content.name = msg.name;
                    content.content =replaceContent(msg.content);
                    content.is_kefu = true;
                    content.time = msg.time;
                    this.msgList.push(content);

                    notify(msg.name, {
                        body: msg.content,
                        icon: msg.avator
                    },function(notification) {
                        window.focus();
                        notification.close();
                    });
                    this.scrollBottom();
                    flashTitle();
                    clearInterval(this.timer);
                    this.alertSound();
                }
                if (redata.type == "close") {
                    this.chatTitle="The conversation has ended";
                    $(".chatBox").append("<div class=\"chatTime\">"+this.chatTitle+"</div>");
                    this.scrollBottom();
                    this.socket.close();
                    this.focusSendConn=true;
                }
                if (redata.type == "force_close") {
                    this.chatTitle="The conversation was terminated by the agent";
                    $(".chatBox").append("<div class=\"chatTime\">"+this.chatTitle+"</div>");
                    this.scrollBottom();
                    this.socket.close();
                    this.socketClosed=true;
                }
                if (redata.type == "auto_close") {
                    this.chatTitle="The conversation timed out due to inactivity";
                    $(".chatBox").append("<div class=\"chatTime\">"+this.chatTitle+"</div>");
                    this.scrollBottom();
                    this.socket.close();
                    this.socketClosed=true;
                }
                window.parent.postMessage(redata,"*");
            },
            chatToUser:function() {
                var messageContent=this.messageContent.trim("\r\n");
                messageContent=messageContent.replace("\n","");
                messageContent=messageContent.replace("\r\n","");
                if(messageContent==""||messageContent=="\r\n"){
                    this.messageContent="";
                    return;
                }
                this.messageContent=messageContent;
                if(this.socketClosed){
                    this.$message({
                        message: 'Connection closed! Please refresh the page',
                        type: 'warning'
                    });
                    return;
                }
                this.sendDisabled=true;
                let _this=this;

                let content = {}
                content.avator=_this.visitor.avator;
                content.content = replaceContent(_this.messageContent);
                content.name = _this.visitor.name;
                content.is_kefu = false;
                content.time = _this.getNowDate();
                content.show_time=false;
                _this.msgList.push(content);
                _this.scrollBottom();

                let mes = {};
                mes.type = "visitor";
                mes.content = this.messageContent;
                mes.from_id = this.visitor.visitor_id;
                mes.to_id = this.visitor.to_id;
                mes.content = this.messageContent;
                $.post("/aicss/2/message",mes,function(res){
                    _this.sendDisabled=false;
                    if(res.code!=200){
                        _this.msgList.pop();
                        _this.$message({
                            message: res.msg,
                            type: 'error'
                        });
                        return;
                    }
                    _this.messageContent = "";
                    clearInterval(_this.timer);
                    _this.sendSound();
                });

            },
            OnClose:function() {
                console.log("ws:onclose");
                this.focusSendConn=true;
            },
            getUserInfo:function(){
                let obj=this.getCache("visitor_"+KEFU_ID);
                var visitor_id=""
                var to_id=KEFU_ID;
                if(obj){
                    visitor_id=obj.visitor_id;
                }
                let _this=this;
                var extra=getQuery("extra");
                $.post("/aicss/visitor_login",{visitor_id:visitor_id,refer:REFER,to_id:to_id,extra:extra},function(res){
                    if(res.code!=200){
                        _this.$message({
                            message: res.msg,
                            type: 'error'
                        });
                        _this.sendDisabled=true;
                        return;
                    }
                    _this.visitor=res.result;
                    _this.getHistoryMessage();
                    _this.setCache("visitor_"+KEFU_ID,res.result);
                    _this.initConn();
                });
            },
            getHistoryMessage:function(){
                let params={
                    page:this.messages.page,
                    pagesize: this.messages.pagesize,
                    visitor_id: this.visitor.visitor_id,
                }
                let _this=this;
                $.get("/aicss/2/messagesPages",params,function(res){
                    let msgList=res.result.list;
                    if(msgList.length>=_this.messages.pagesize){
                        _this.showLoadMore=true;
                    }else{
                        _this.showLoadMore=false;
                    }
                    for(let i in msgList){
                        let item = msgList[i];
                        let content = {}
                        if (item["mes_type"] == "kefu") {
                            item.is_kefu = true;
                            item.avator=item["kefu_avator"];

                        } else {
                            item.is_kefu = false;
                            item.avator=item["visitor_avator"];
                        }
                        item.time = item["create_time"];
                        item.content=replaceContent(item["content"]);
                        _this.msgList.unshift(item);
                    }
                    if(_this.messages.page==1){
                        _this.scrollBottom();
                    }
                    _this.messages.page++;
                });
            },
            scrollBottom:function(){
                var _this=this;
                this.$nextTick(function(){
                    $('.chatVisitorPage').scrollTop($(".chatVisitorPage")[0].scrollHeight);
                });
            },
            getNowDate : function() {
                var d = new Date(new Date());
                return d.getFullYear() + '-' + this.digit(d.getMonth() + 1) + '-' + this.digit(d.getDate())
                    + ' ' + this.digit(d.getHours()) + ':' + this.digit(d.getMinutes()) + ':' + this.digit(d.getSeconds());
            },
            digit : function (num) {
                return num < 10 ? '0' + (num | 0) : num;
            },
            setCache : function (key,obj){
                if(navigator.cookieEnabled&&typeof window.localStorage !== 'undefined'){
                    localStorage.setItem(key, JSON.stringify(obj));
                }
            },
            getCache : function (key){
                if(navigator.cookieEnabled&&typeof window.localStorage !== 'undefined') {
                    return JSON.parse(localStorage.getItem(key));
                }
            },
            getNotice : function (){
                let _this=this;
                $.get("/aicss/notice?kefu_id="+KEFU_ID,function(res) {
                    var code=res.code;
                    if(code!=200) return;
                    _this.kefuInfo=res.result;
                    _this.showTitle(_this.kefuInfo.nickname+" 为您服务.");
                    if(!_this.kefuInfo.welcome) return;
                    var msg={
                        content:replaceContent(_this.kefuInfo.welcome),
                        avator:_this.kefuInfo.avatar,
                        name :_this.kefuInfo.nickname,
                        time:_this.getNowDate(),
                        is_kefu:true,
                    }
                    _this.msgList.push(msg);
                    _this.scrollBottom();
                    _this.alertSound();
                });
            },
            initCss:function(){
                var _this=this;
                $(function () {
                    var faces=placeFace();
                    $.each(faceTitles, function (index, item) {
                        _this.face.push({"name":item,"path":faces[item]});
                    });

                    var windheight = $(window).height();
                    $(window).resize(function(){
                        var docheight = $(window).height();
                        $('body').scrollTop(99999999);
                    });
                });
            },
            ping:function(){
                let _this=this;
                let mes = {}
                mes.type = "ping";
                mes.data = "visitor:"+_this.visitor.visitor_id;
                setInterval(function () {
                    if(_this.socket!=null){
                        _this.socket.send(JSON.stringify(mes));
                    }
                },10000);
            },
            init:function(){
                var _this=this;
                this.initCss();
                $('body').click(function(){
                    clearFlashTitle();
                    window.parent.postMessage({type:"focus"},"*");
                    $('.faceBox').hide();
                });
                window.onfocus = function () {
                    clearFlashTitle();
                    window.parent.postMessage({type:"focus"},"*");
                    if(_this.socketClosed){
                        return;
                    }
                    if(!_this.focusSendConn){
                        return;
                    }
                    _this.initConn();
                    _this.scrollBottom();
                }
            },
            faceIconClick:function(index){
                $('.faceBox').hide();
                this.messageContent+="face"+this.face[index].name;
            },
            uploadImg:function (url){
                let _this=this;
                $('#uploadImg').after('<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png" id="uploadImgFile" name="file" style="display:none" >');
                $("#uploadImgFile").click();
                $("#uploadImgFile").change(function (e) {
                    var formData = new FormData();
                    var file = $("#uploadImgFile")[0].files[0];
                    formData.append("imgfile",file);
                    filter(file) && $.ajax({
                        url: url || '',
                        type: "post",
                        data: formData,
                        contentType: false,
                        processData: false,
                        dataType: 'JSON',
                        mimeType: "multipart/form-data",
                        success: function (res) {
                            if(res.code!=200){
                                _this.$message({
                                    message: res.msg,
                                    type: 'error'
                                });
                            }else{
                                _this.messageContent+='img[/' + res.result.path + ']';
                                _this.chatToUser();
                            }
                        },
                        error: function (data) {
                            console.log(data);
                        }
                    });
                });
            },
            uploadFile:function (url){
                let _this=this;
                $('#uploadFile').after('<input type="file" id="uploadRealFile" name="file2" style="display:none" >');
                $("#uploadRealFile").click();
                $("#uploadRealFile").change(function (e) {
                    var formData = new FormData();
                    var file = $("#uploadRealFile")[0].files[0];
                    formData.append("realfile",file);
                    console.log(formData);
                    $.ajax({
                        url: url || '',
                        type: "post",
                        data: formData,
                        contentType: false,
                        processData: false,
                        dataType: 'JSON',
                        mimeType: "multipart/form-data",
                        success: function (res) {
                            if(res.code!=200){
                                _this.$message({
                                    message: res.msg,
                                    type: 'error'
                                });
                            }else{
                                var data=JSON.stringify({
                                    name:res.result.name,
                                    ext:res.result.ext,
                                    size:res.result.size,
                                    path:'/' + res.result.path,
                                })
                                _this.messageContent+='attachment['+data+']';
                                _this.chatToUser();
                            }
                        },
                        error: function (data) {
                            console.log(data);
                        }
                    });
                });
            },
            onPasteUpload:function(event){
                let items = event.clipboardData && event.clipboardData.items;
                let file = null
                if (items && items.length) {
                    for (var i = 0; i < items.length; i++) {
                        if (items[i].type.indexOf('image') !== -1) {
                            file = items[i].getAsFile()
                        }
                    }
                }
                if (!file) {
                    return;
                }
                let _this=this;
                var formData = new FormData();
                formData.append('imgfile', file);
                $.ajax({
                    url: '/aicss/uploadimg',
                    type: "post",
                    data: formData,
                    contentType: false,
                    processData: false,
                    dataType: 'JSON',
                    mimeType: "multipart/form-data",
                    success: function (res) {
                        if(res.code!=200){
                            _this.$message({
                                message: res.msg,
                                type: 'error'
                            });
                        }else{
                            _this.messageContent+='img[/' + res.result.path + ']';
                            _this.chatToUser();
                        }
                    },
                    error: function (data) {
                        console.log(data);
                    }
                });
            },
            alertSound:function(){
                alertSound("chatMessageAudio",'/aicss/static/images/alert2.ogg');
            },
            sendSound:function(){
                alertSound("chatMessageSendAudio",'/aicss/static/images/sent.ogg');
            },
            sendAjax:function(url,method,params,callback){
                let _this=this;
                $.ajax({
                    type: method,
                    url: url,
                    data:params,
                    error:function(res){
                        var data=JSON.parse(res.responseText);
                        console.log(data);
                        if(data.code!=200){
                            _this.$message({
                                message: data.msg,
                                type: 'error'
                            });
                        }
                    },
                    success: function(data) {
                        if(data.code!=200){
                            _this.$message({
                                message: data.msg,
                                type: 'error'
                            });
                        }else if(data.result!=null){
                            callback(data.result);
                        }else{
                            callback(data);
                        }
                    }
                });
            },
            showTitle:function(title){
                $(".chatBox").append("<div class='chatNotice'><div class=\"chatNoticeContent\"><span>"+title+"</span></div></div>");
                this.scrollBottom();
            },
        },
        mounted:function() {
            document.addEventListener('paste', this.onPasteUpload)
            document.addEventListener('scroll',this.textareaBlur)
        },
        created: function () {
            this.init();
            this.getUserInfo();
        }
    })
    }
    if(KEFU_ID==""){
        var visitor_id="";
        if(window.localStorage){
            for(var i=0;i<localStorage.length;i++){
                var key = localStorage.key(i);
                if(key.indexOf("visitor_")==0){
                    var obj = JSON.parse(localStorage.getItem(key));
                    if(obj && obj.visitor_id){
                        visitor_id = obj.visitor_id;
                        break;
                    }
                }
            }
        }
        $.ajax({
            type: "get",
            url: "/kefu_idle?visitor_id="+visitor_id,
            success: function(data) {
                if(data.code==200 && data.msg=="ok"){
                    KEFU_ID=data.result;
                }else{
                    KEFU_ID="default";
                }
                initVue();
            },
            error: function(){
                KEFU_ID="default";
                initVue();
            }
        });
    }else{
        initVue();
    }
</script>
</html>