EASE CS

zhangfeng123 test

// ==UserScript==
// @name         EASE CS
// @namespace    https://greasyfork.org/zh-CN/scripts/517307-ease-cs
// @version      1.17
// @description  zhangfeng123 test
// @author       张峰
// @match        https://25825.sh.absoloop.com/*
// @icon         http://maxiang.io/favicon.ico
// @require      https://greasyfork.org/scripts/455943-ajaxhooker/code/ajaxHooker.js?version=1124435
// @grant        none
// @license      WTFPL
// ==/UserScript==

(function () {
    'use strict';
    console.log('脚本触发');
    // 初始化登录状态
    function setStyles(element, styles) {
        for (let property in styles) {
            if (styles.hasOwnProperty(property)) {
                element.style[property] = styles[property];
            }
        }
    }
    // 创建一个按钮元素
    const floatButton = document.createElement('img');
    floatButton.innerHTML = '客服'; // 设置按钮文本
    floatButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/fd6d646b65efe59aa26ebf44ceb5f27d.png';
    // 设置按钮样式,使其悬浮在右下角
    const floatButtonStyles = {
        position: 'fixed',
        bottom: '60px',
        right: '50px',
        width: '50px',
        height: '50px',
        cursor: 'pointer',
        // 可以添加更多样式属性
    };
    setStyles(floatButton, floatButtonStyles);

    // 为按钮添加点击事件监听器
    floatButton.addEventListener('click', showDialog);


    function showDialog() {
        const container = document.getElementById('container');
        if (container) {
            container.remove();
            return;
        }
        const loginDiv = document.getElementById('loginDiv');
        if (loginDiv) {
            loginDiv.remove();
            // 如果 loginDiv 存在,则不执行与 loginDiv 相关的操作
            console.log('loginDiv 已移除,不执行 showLoginPrompt');
            return;
        }
        let token = localStorage.getItem('token')
        if (token) {
            showPasswordChangePrompt();
        } else {
            showLoginPrompt(); // 如果未登录,则显示登录的界面
        }
    }

    // 创建并显示登录界面
    function showPasswordChangePrompt() {
        console.log('显示修改密码或退出登录窗口');

        // 定义样式对象
        const containerStyles = {
            position: 'fixed',
            top: '50%',
            left: '50%',
            width: '316px', // 稍微调整宽度以适应内容
            height: '480px', // 高度自动以适应内容
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            transform: 'translate(-50%, -50%)',
            backgroundColor: '#EEF6FF',
            padding: '20px',
            boxShadow: '0 0 5px rgba(0, 0, 0, 0.5)',
            borderRadius: '18px',
            zIndex: 1000
        };
        const imageStyles = {
            width: '20px',
            height: '20px',
            marginRight: '10px', // 图片与标题之间的间距
        };
        const titleStyles = {
            // ...(可以根据需要调整,但不需要 position: 'absolute')
            display: 'flex',
            alignItems: 'center',
        };
        // 创建并设置图片
        const image = document.createElement('img');
        image.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/fd6d646b65efe59aa26ebf44ceb5f27d.png';
        image.alt = '登录图标'; // 提供替代文本以增强可访问性
        setStyles(image, imageStyles);

        const actionRowStyles = {
            display: 'flex',
            justifyContent: 'space-between',
            width: '100%',
            marginBottom: '10px', // 给下方的按钮一些空间
            marginTop: '30px'
        };
        const buttonStyles = {
            padding: '10px 20px',
            boxSizing: 'border-box',
            margin: '38px 0px',
            backgroundColor: '#FFFFFF',
            color: '#333333',
            border: 'none',
            borderRadius: '5px',
            cursor: 'pointer',
            fontSize: '16px',
            width: '316px',
            textAlign: 'left',
            fontSize: '14px'
        };

        const logoutbuttonStyles = {
            width: '70px',
            height: '26px',
            color: '#999999',
            border: '1px solid #999999',
            borderRadius: '18px',
            cursor: 'pointer',
            fontSize: '12px',
        };

        // 创建容器div
        const container = document.createElement('div');
        container.id = 'container'
        setStyles(container, containerStyles);

        // 创建标题
        const titleContainerStyles = {
            display: 'flex',
            width: '100%'
        };
        const titleContainer = document.createElement('div');
        setStyles(titleContainer, titleContainerStyles);
        const title = document.createElement('h2'); // 使用h2标签可能更合适
        title.textContent = '亿点连接智能客服助手';
        setStyles(title, titleStyles);
        container.appendChild(titleContainer);
        titleContainer.appendChild(image);
        titleContainer.appendChild(title);
        //主页
        const mainAccout = document.createElement('div');
        const mainAccoutStyles = {
            width: '100%',
            height: '100%',
        };
        setStyles(mainAccout, mainAccoutStyles);
        container.appendChild(mainAccout);
        // 创建包含XXXX和退出登录按钮的行
        const actionRow = document.createElement('div');
        setStyles(actionRow, actionRowStyles);

        const actionText = document.createElement('span');
        const userName = JSON.parse(localStorage.getItem('userData')).userName;
        if (userName && userName.length >= 2) {
            // 构建新的字符串,只显示首字、*** 和最后一个字
            const maskedUserName = userName.charAt(0) + '***' + userName.charAt(userName.length - 1);

            // 设置 span 元素的文本内容为新的字符串
            actionText.textContent = maskedUserName;
        } else {
            // 如果用户名不存在或长度小于2,则直接显示用户名(或空字符串)
            actionText.textContent = userName;
        }
        actionRow.appendChild(actionText);

        const logoutButton = document.createElement('button');
        logoutButton.textContent = '退出登录';
        setStyles(logoutButton, logoutbuttonStyles);
        logoutButton.addEventListener('click', function () {
            // 显示确认对话框
            const userConfirmed = window.confirm('确定要退出登录吗?');

            if (userConfirmed) {
                // 用户点击了确定
                console.log('退出登录');
                localStorage.removeItem('userData');
                localStorage.removeItem('token');
                window.location.reload();
                startAjaxHooking()

                const container = document.getElementById('container');
                if (container) {
                    container.remove();
                }
            }
        });
        actionRow.appendChild(logoutButton);

        mainAccout.appendChild(actionRow);

        // 创建修改密码按钮
        const changePasswordButton = document.createElement('button');
        changePasswordButton.textContent = '修改密码';
        setStyles(changePasswordButton, buttonStyles);

        // 创建密码修改表单的容器
        const passwordFormContainer = document.createElement('div');
        setStyles(passwordFormContainer, {
            display: 'none', // 初始隐藏
            marginTop: '20px', // 样式示例
        });

        // 创建旧密码输入框
        const inputStyle = {
            width: '280px',
            height: '46px',
            borderRadius: '10px',
            fontSize: '14px',
            backgroundColor: '#FFFFFF',
            marginBottom: '14px',
            padding: '0 15px'
        };
        const oldPasswordInput = document.createElement('input');
        oldPasswordInput.type = 'text';
        oldPasswordInput.placeholder = '旧密码';
        setStyles(oldPasswordInput, inputStyle);
        // 创建新密码输入框
        const newPasswordInput = document.createElement('input');
        newPasswordInput.type = 'password';
        newPasswordInput.placeholder = '新密码';
        setStyles(newPasswordInput, inputStyle);
        // 创建重复新密码输入框
        const confirmNewPasswordInput = document.createElement('input');
        confirmNewPasswordInput.type = 'password';
        confirmNewPasswordInput.placeholder = '重复新密码';
        setStyles(confirmNewPasswordInput, inputStyle);
        const passwordValiStyle = {
            color: '#999999',
            fontSize: '12px',
        };
        const passwordVali = document.createElement('label');
        passwordVali.textContent = '密码长度6位以上,需包含数字、字母'
        setStyles(passwordVali, passwordValiStyle);
        // 创建确认修改按钮
        const confirmButtonStyles = {
            margin: '38px 5px',
            backgroundColor: '#5D55F4',
            color: '#FFFFFF',
            border: 'none',
            borderRadius: '5px',
            cursor: 'pointer',
            fontSize: '16px',
            width: '280px',
            height: '50px',
            textAlign: 'center'
        };
        const confirmButton = document.createElement('button');
        confirmButton.textContent = '确认修改';
        setStyles(confirmButton, confirmButtonStyles);
        // 将输入框和确认按钮添加到表单容器中
        passwordFormContainer.appendChild(oldPasswordInput);
        passwordFormContainer.appendChild(document.createElement('br')); // 添加换行符作为分隔
        passwordFormContainer.appendChild(newPasswordInput);
        passwordFormContainer.appendChild(document.createElement('br')); // 添加换行符作为分隔
        passwordFormContainer.appendChild(confirmNewPasswordInput);
        passwordFormContainer.appendChild(document.createElement('br')); // 添加换行符作为分隔
        passwordFormContainer.appendChild(passwordVali);
        passwordFormContainer.appendChild(document.createElement('br')); // 添加换行符作为分隔
        passwordFormContainer.appendChild(confirmButton);

        // 将表单容器添加到主容器中
        container.appendChild(passwordFormContainer);

        // 为修改密码按钮添加点击事件监听器
        changePasswordButton.addEventListener('click', function () {
            passwordFormContainer.style.display = 'block'; // 显示表单
            mainAccout.style.display = 'none';
        });

        // 为确认按钮添加点击事件监听器
        confirmButton.addEventListener('click', function () {
            // 获取输入框的值
            const oldPassword = oldPasswordInput.value;
            const newPassword = newPasswordInput.value;
            const confirmPassword = confirmNewPasswordInput.value;

            // 检查所有项是否填写
            if (!oldPassword || !newPassword || !confirmPassword) {
                alert('请填写全部的项');
                return;
            }

            // 检查新密码和旧密码是否相同
            if (oldPassword === newPassword) {
                alert('新密码不能与旧密码相同');
                return;
            }

            // 检查新密码是否包含至少6位,且包含数字和字母
            const passwordPattern = /^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z\d]{6,}$/;
            if (!passwordPattern.test(newPassword)) {
                alert('密码长度6位以上,需包含数字、字母');
                return;
            }

            // 检查新密码和重复新密码是否匹配
            if (newPassword !== confirmPassword) {
                alert('新密码和重复新密码不一致');
                return;
            }
            let params = JSON.parse(localStorage.getItem('userData'))
            let token = localStorage.getItem('token')
            params.password = newPassword
            delete params.createTime
            fetch('https://cs-admin-ts.billionconnect.net/api/manager/user/update', {
                method: 'POST',
                headers: {
                    'token': token
                },
                body: object2formdata(params)
            })
                .then(response => response.json())
                .then(data => {
                    if (data.key == '0000') { // 假设API返回的数据中有一个success字段表示是否成功
                        alert('修改密码成功');
                        // 隐藏表单
                        passwordFormContainer.style.display = 'none';
                        // 显示主账号页面
                        mainAccout.style.display = 'block';
                    } else {
                        alert('修改密码失败: ' + data.message); // 假设API返回的数据中有一个message字段表示错误信息
                    }
                })
                .catch(error => {
                    console.error('请求失败:', error);
                    alert('修改密码请求失败,请稍后再试');
                });
        });

        // 这里可以添加点击修改密码按钮后的逻辑,比如打开一个模态框或跳转到修改密码页面
        // changePasswordButton.addEventListener('click', someFunction);
        mainAccout.appendChild(changePasswordButton);

        // 将容器添加到文档的body中
        document.body.appendChild(container);
    }
    // 将按钮添加到文档的body中
    document.body.appendChild(floatButton);
    // 创建并显示登录界面
    function showLoginPrompt() {
        console.log('执行登陆');

        // 定义样式对象
        const loginDivStyles = {
            position: 'fixed',
            top: '50%',
            left: '50%',
            width: '316px', // 稍微调整宽度以适应内容
            height: '480px', // 高度自动以适应内容
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            transform: 'translate(-50%, -50%)',
            backgroundColor: '#EEF6FF',
            padding: '20px',
            boxShadow: '0 0 5px rgba(0, 0, 0, 0.5)',
            borderRadius: '18px',
            zIndex: 1000
        };
        const loginFormStyles = {

            width: '300px',
            height: '400px',
            display: 'flex',
            flexDirection: 'column',
            justifyContent: 'center',
            alignItems: 'center',
        };
        const loginDiv = document.createElement('div');
        loginDiv.id = 'loginDiv'
        setStyles(loginDiv, loginDivStyles);

        const titleStyles = {
            // ...(可以根据需要调整,但不需要 position: 'absolute')
            display: 'flex',
            alignItems: 'center',
        };
        // 创建标题
        const titleContainerStyles = {
            display: 'flex',
            width: '100%',
            justifyContent: 'space-between',
            flexWrap: 'nowrap',
        };
        const titleContainer = document.createElement('div');
        setStyles(titleContainer, titleContainerStyles);
        const title = document.createElement('h2'); // 使用h2标签可能更合适
        title.textContent = '亿点连接智能客服助手';
        setStyles(title, titleStyles);
        loginDiv.appendChild(titleContainer);
        // 创建并设置图片
        const imageStyles = {
            width: '20px',
            height: '20px',
            marginRight: '10px', // 图片与标题之间的间距
        };
        const imageStylesClose = {
            width: '10px',
            height: '10px',
            cursor: 'pointer',
        };
        const image = document.createElement('img');
        const imageClose = document.createElement('img');
        image.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/fd6d646b65efe59aa26ebf44ceb5f27d.png';
        imageClose.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/01897dee246aa40213a8b3e7026db2d4.png';
        image.alt = '登录图标'; // 提供替代文本以增强可访问性
        imageClose.alt = '关闭图标'; // 提供替代文本以增强可访问性
        setStyles(image, imageStyles);
        setStyles(imageClose, imageStylesClose);
        const titleContainerLeft = document.createElement('div');
        const titleContainerRight = document.createElement('div');
        titleContainerLeft.style.display = 'flex';
        titleContainerLeft.appendChild(image);
        titleContainerLeft.appendChild(title);
        titleContainerRight.appendChild(imageClose);
        titleContainer.appendChild(titleContainerLeft);
        titleContainer.appendChild(titleContainerRight);
        imageClose.addEventListener('click', closeLoginPrompt);
        function closeLoginPrompt() {
            const container = document.getElementById('container');
            if (container) {
                container.remove();
                return;
            }
            const loginDiv = document.getElementById('loginDiv');
            if (loginDiv) {
                loginDiv.remove();
                // 如果 loginDiv 存在,则不执行与 loginDiv 相关的操作
                console.log('loginDiv 已移除,不执行 showLoginPrompt');
                return;
            }
        }
        const LogininputStyle = {
            width: '280px',
            height: '46px',
            borderRadius: '10px',
            fontSize: '14px',
            backgroundColor: '#FFFFFF',
            marginBottom: '14px',
            padding: '0 15px'
        };
        const form = document.createElement('form');
        setStyles(form, loginFormStyles);
        form.onsubmit = handleLogin;
        const usernameDiv = document.createElement('div');
        const usernameInput = document.createElement('input');
        usernameInput.type = 'text';
        usernameInput.name = 'username';
        usernameInput.placeholder = '账号';
        usernameInput.required = true;
        setStyles(usernameInput, LogininputStyle);

        const passwordDiv = document.createElement('div');
        const passwordInput = document.createElement('input');
        passwordInput.type = 'password';
        passwordInput.name = 'password';
        passwordInput.placeholder = '密码';
        passwordInput.required = true;
        setStyles(passwordInput, LogininputStyle);

        const confirmButtonStyles = {
            margin: '38px 5px',
            backgroundColor: '#5D55F4',
            color: '#FFFFFF',
            border: 'none',
            borderRadius: '5px',
            cursor: 'pointer',
            fontSize: '16px',
            width: '280px',
            height: '50px',
            textAlign: 'center'
        };
        const submitButton = document.createElement('button');
        submitButton.type = 'submit';
        submitButton.textContent = '登录';
        setStyles(submitButton, confirmButtonStyles);
        form.appendChild(usernameDiv);
        usernameDiv.appendChild(usernameInput);
        usernameDiv.appendChild(document.createElement('br'));
        form.appendChild(passwordDiv);
        passwordDiv.appendChild(passwordInput);
        passwordDiv.appendChild(document.createElement('br'));
        form.appendChild(submitButton);

        loginDiv.appendChild(form);
        document.body.appendChild(loginDiv);
    }
    setTimeout(function () {
        let token = localStorage.getItem('token')
        if (token) {
            startAjaxHooking(); // 启动 AJAX 拦截
        } else {
            showLoginPrompt()
        }
    }, 100);
    function object2formdata(params) {
        let formdata = new FormData();
        for (let key in params) {
            formdata.append(key, params[key]);
        }
        return formdata;
    };
    // 处理登录逻辑
    function handleLogin(event) {
        event.preventDefault();
        const form = event.target;
        const userName = form.username.value;
        const password = form.password.value;

        // 使用 fetch API 发送 POST 请求
        fetch('https://cs-admin-ts.billionconnect.net/api/manager/login', {
            method: 'POST', // 指定请求方法为 POST
            body: object2formdata({ userName: userName, password: password })// 将用户名和密码作为 JSON 数据发送
        })
            .then(response => {
                // 检查响应状态
                if (!response.ok) {
                    throw new Error('Network response was not ok ' + response.statusText);
                }
                // 解析响应为 JSON
                return response.json();
            })
            .then(data => {
                console.log('data', data);

                // 假设服务器在登录成功时返回一个包含成功状态的对象
                if (data.key == '0000') { // 根据实际响应结构调整条件
                    // 登录成功,执行相应逻辑
                    localStorage.setItem('userData', JSON.stringify(data.data.managerUser));
                    localStorage.setItem('token', data.data.TOKEN); // 如果服务器返回了token,则存储它
                    // 移除登录界面(注意:这里应该有一个更好的方式来管理UI的显示和隐藏)
                    document.body.removeChild(form.parentElement);
                    startAjaxHooking(); // 启动 AJAX 拦截(确保这个函数在当前作用域内可访问)
                } else {
                    // 登录失败,显示错误消息
                    alert('Invalid username or password, or other login error.');
                }
            })
            .catch(error => {
                // 处理网络错误或解析错误
                console.error('There has been a problem with your fetch operation:', error);
                alert('Failed to log in due to a network error.');
            });
    }

    /* global ajaxHooker*/
    function startAjaxHooking() {
        let token = localStorage.getItem('token')

        if (token) {
            console.log('有token了');
            let serviceData = JSON.parse(localStorage.getItem('serviceData')) || [];
            let currentServiceData = {
                serviceId: '',
                memories: [],
            }
            let lastProcessedMsgId = null;
            let currentWebSocket = null;
            ajaxHooker.hook(request => {

                if (request.url.includes('/Visitors') && !request.url.includes('/Messages')) {
                    console.log('访客');
                    if (currentWebSocket && currentWebSocket.readyState === WebSocket.OPEN) {
                        console.log('关闭旧的 WebSocket 连接以处理新请求');
                        currentWebSocket.close();
                    }
                    request.response = res => {
                        const json = JSON.parse(res.responseText);
                        console.log('lastChatMessage', json.lastChatMessage, 'res.sessionServiceId', res.sessionServiceId);

                        const memories = [];
                        let matchedServiceData = null;

                        // 遍历 serviceData 查找匹配的 serviceId
                        for (let i = 0; i < serviceData.length; i++) {
                            if (serviceData[i].serviceId === json[0].serviceSessionId) {
                                matchedServiceData = serviceData[i];
                                break;
                            }
                        }

                        // 如果没有找到匹配的,则创建一个新的 currentServiceData
                        if (!matchedServiceData) {
                            matchedServiceData = {
                                serviceId: json[0].serviceSessionId,
                                memories: [],
                            };
                            serviceData.push(matchedServiceData);
                        }
                        if (json && json[0].lastChatMessage && json[0].lastChatMessage.body.bodies[0].type == "txt") {
                            console.log('lastChatMessage', json[0], json[0].lastChatMessage);
                            matchedServiceData.memories.push({

                                role: 'user',
                                content: json[0].lastChatMessage.body.bodies[0].msg
                            });
                            currentServiceData.serviceId = json[0].serviceSessionId
                            currentServiceData.memories.push({ role: 'user', content: json[0].lastChatMessage.body.bodies[0].msg })
                            if (!serviceData.some(sd => sd.serviceId === currentServiceData.serviceId)) {
                                serviceData.push(currentServiceData);
                            }

                            localStorage.setItem('serviceData', JSON.stringify(serviceData))
                            let currentMsgId = json[0].lastChatMessage.msgId;
                            if (currentMsgId !== lastProcessedMsgId) {
                                lastProcessedMsgId = currentMsgId;
                                localStorage.setItem('currentMsgId', currentMsgId);
                                // 关闭旧的 WebSocket 连接
                                if (currentWebSocket) {
                                    console.log('关闭旧的 WebSocket 连接');

                                    currentWebSocket.close();
                                }

                                let currentDataArray = {}
                                JSON.parse(localStorage.getItem('serviceData')).forEach(element => {
                                    if (element.serviceId === currentServiceData.serviceId) {
                                        currentDataArray = element
                                    }
                                });
                                console.log('currentDataArray', currentDataArray);
                                const lastTwentyMemories = currentDataArray.memories.slice(-20);
                                // 使用解析出的数据建立 WebSocket 连接
                                const wsUrl = 'wss://bot-api-ts.billionconnect.net/chat_completion';
                                currentWebSocket = new WebSocket(wsUrl);
                                currentWebSocket.onopen = function (event) {
                                    console.log('WebSocket is open now.', json[0]);
                                    const messageBody = json[0].lastChatMessage.body.bodies[0].msg;
                                    const messageData = {
                                        q: messageBody,
                                        user_id: "test",
                                        bot: "mall_h5",
                                        stream: true,
                                        source: "default",
                                        new_thread: false,
                                        memories: lastTwentyMemories
                                    };
                                    console.log('messageData', messageData);
                                    currentWebSocket.send(JSON.stringify(messageData));
                                    let serviceData = JSON.parse(localStorage.getItem('serviceData'))
                                    serviceData.forEach(element => {
                                        element.msgIds = []
                                        if (element.serviceId === json[0].serviceSessionId) {
                                            element.msgIds.push(json[0].lastChatMessage.msgId)
                                        }
                                    })
                                    localStorage.setItem('serviceData', JSON.stringify(serviceData))
                                };

                                currentWebSocket.onmessage = function (event) {
                                    let parseData = JSON.parse(event.data);
                                    if (parseData.finish && currentMsgId) {
                                        let serviceData = JSON.parse(localStorage.getItem('serviceData'))
                                        function storeMessage(msg, id, serviceId) {
                                            let conversationData = JSON.parse(localStorage.getItem('conversationData')) || [];
                                            let serviceIndex = conversationData.findIndex(s => s.serviceId == serviceId);
                                
                                            if (serviceIndex === -1) {
                                                // 如果没有找到对应的 serviceId,则创建一个新的
                                                conversationData.push({
                                                    serviceId: serviceId,
                                                    conversation: [{ msgId: id, msg: msg }]
                                                });
                                            } else {
                                                // 如果找到了对应的 serviceId,则向 conversation 数组中添加新的消息
                                                conversationData[serviceIndex].conversation.push({ msgId: id, msg: msg });
                                            }
                                
                                            // 将更新后的 conversationData 存储回 localStorage
                                            console.log('conversationData', conversationData);
                                
                                            localStorage.setItem('conversationData', JSON.stringify(conversationData));
                                        }
                                        storeMessage(parseData.msg.content, currentMsgId, currentServiceData.serviceId);
                                        serviceData.forEach(element => {
                                            if (element.msgIds.includes(currentMsgId)) {
                                                element.memories.push({ role: 'assistant', content: parseData.msg.content })
                                            }
                                        })
                                        localStorage.setItem('serviceData', JSON.stringify(serviceData))
                                        injectDivBelowTarget(parseData.msg.content, currentMsgId, currentServiceData.serviceId);
                                        console.log('WebSocket message received:消息为', parseData, document);

                                    }
                                };

                                currentWebSocket.onclose = function (event) {
                                    console.log('WebSocket is closed now.');
                                };

                                currentWebSocket.onerror = function (error) {
                                    console.error('WebSocket error observed:', error);
                                };
                            } else {
                                console.error('报错了已处理过此消息 ID');
                            }
                        }
                    };
                } else if (request.url.includes('/Messages')) {
                    console.log('客服发的消息');
                    request.response = res => {
                        const json = JSON.parse(res.responseText);

                        let matchedServiceData = null;
                        if (json && json.sessionServiceId) {
                            // 遍历 serviceData 查找匹配的 serviceId
                            for (let i = 0; i < serviceData.length; i++) {
                                if ((serviceData[i].serviceId === json.sessionServiceId)) {
                                    matchedServiceData = serviceData[i];
                                    break;
                                }
                            }

                            // 如果没有找到匹配的,则创建一个新的 currentServiceData
                            if (!matchedServiceData) {
                                matchedServiceData = {
                                    serviceId: json.sessionServiceId,
                                    memories: [],
                                };
                                serviceData.push(matchedServiceData);
                            }
                            if (json && json.sessionServiceId && json.body.bodies[0].type == "txt") {
                                console.log('lastChatMessage', json, json.body.bodies[0].msg);
                                matchedServiceData.memories.push({

                                    role: 'assistant',
                                    content: json.body.bodies[0].msg
                                });
                                currentServiceData.serviceId = json.sessionServiceId
                                console.log('currentServiceData', currentServiceData);

                                currentServiceData.memories.push({ role: 'assistant', content: json.body.bodies[0].msg })
                                if (!serviceData.some(sd => sd.serviceId === currentServiceData.serviceId)) {
                                    serviceData.push(currentServiceData);
                                }

                                localStorage.setItem('serviceData', JSON.stringify(serviceData))

                            }
                        } else if (json && json.messages && json.messages.length > 0) {
                            console.log('信回话');
                            let conversationData = JSON.parse(localStorage.getItem('conversationData')) || [];
                            // 处理不包含 sessionServiceId 但包含 messages 的情况
                            json.messages.forEach(message => {
                                let conversationItem = conversationData.find(item => item.serviceId === message.sessionServiceId);
                                if (conversationItem) {
                                    console.log('conversationItem', conversationItem);

                                    // 假设每个 conversationItem 都有一个 messages 数组来存储消息
                                    conversationItem.conversation.forEach(item => {
                                        let messageItem = json.messages.find(msg => msg.msgId === message.msgId);
                                        if (messageItem) {
                                            console.log('messageItem', messageItem);
                                            if (item.msgId == messageItem.msgId) {

                                                setTimeout(() => {
                                                    injectMessageBelowTarget(item.msg, messageItem.msgId)
                                                }, 100);
                                            }
                                            // 更新 DOM 节点,假设你有一个函数 updateMessageNode 来处理这个
                                            // updateMessageNode(messageItem.domId, message.content);
                                        }
                                    })
                                }
                            });

                            // 更新本地存储中的 conversationData
                            localStorage.setItem('conversationData', JSON.stringify(conversationData));
                        } else {
                            // 处理其他情况
                        }


                    };

                }
            });
        }
    }

    //用来循环注入消息记录的方法
    function injectMessageBelowTarget(msg, id) {
        console.log('injectMessageBelowTarget', msg, id);

        const allTargetPs = document.querySelectorAll('li.ui-itm-txtmsg.left>div>p');

        let targetElement = null;
        for (let p of allTargetPs) {
            console.log('p', p.textContent.trim(), id);
            if (p.textContent.trim() == id) {
                targetElement = p;
                break;
            }
        }
        if (!targetElement) {
            console.warn('未找到内容为 id 的 p 元素');
            return;
        }

        const targetElementParent = targetElement.parentElement;
        const scrollContainer = targetElementParent.parentElement.parentElement;
        if (!scrollContainer || !targetElementParent) {
            console.warn('滚动容器或目标 p 元素的父元素不存在');
            return;
        }

        const newDiv = document.createElement('div');
        const showMoreButton = document.createElement('img'); // 修改为图片
        showMoreButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0e36eef2990308d9e1474b54a880b4a7.png'; // 替换为您的图片路径
        showMoreButton.alt = '显示/收起';
        showMoreButton.style.cursor = 'pointer'; // 添加鼠标指针样式
        showMoreButton.style.display = 'inline-block'; // 设置为内联块元素以控制尺寸
        showMoreButton.style.width = '10px'; // 设置图片宽度
        showMoreButton.style.height = '10px'; // 设置图片高度

        newDiv.style.display = 'block';
        newDiv.style.whiteSpace = 'nowrap';
        newDiv.style.overflow = 'hidden';
        newDiv.style.textOverflow = 'ellipsis';
        newDiv.textContent = msg;

        const wrapperDiv = document.createElement('div');
        wrapperDiv.classList.add('message-wrapper');
        wrapperDiv.style.marginTop = '10px';
        wrapperDiv.style.border = '2px solid #C1BDFF';
        wrapperDiv.style.minWidth = '92%';
        wrapperDiv.style.padding = '10px';
        wrapperDiv.style.overflowWrap = 'break-word';
        wrapperDiv.style.position = 'relative'; // 添加相对定位以包含图片
        wrapperDiv.appendChild(newDiv);

        // 将图片添加到 wrapperDiv 的最右侧
        const imageContainer = document.createElement('div');
        imageContainer.style.position = 'absolute';
        imageContainer.style.top = '10px'; // 调整以匹配 padding
        imageContainer.style.right = '10px'; // 调整以匹配 padding
        imageContainer.style.width = '10px'; // 调整以匹配 padding
        imageContainer.style.height = '10px'; // 调整以匹配 padding
        imageContainer.appendChild(showMoreButton);
        wrapperDiv.appendChild(imageContainer);

        let isExpanded = false;

        showMoreButton.addEventListener('click', function () {
            if (isExpanded) {
                newDiv.style.whiteSpace = 'nowrap';
                newDiv.style.overflow = 'hidden';
                showMoreButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0e36eef2990308d9e1474b54a880b4a7.png'; // 替换为折叠状态的图片路径
                isExpanded = false;
                // 显示分隔线和按钮
                const divider = newDiv.querySelector('.divider');
                const buttonContainer = newDiv.querySelector('.button-container');
                if (divider && buttonContainer) {
                    divider.style.display = 'none';
                    buttonContainer.style.display = 'none';
                }
            } else {
                newDiv.style.whiteSpace = 'normal';
                newDiv.style.overflow = 'visible';
                showMoreButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0e36eef2990308d9e1474b54a880b4a7.png'; // 替换为展开状态的图片路径
                isExpanded = true;
                // 隐藏分隔线和按钮
                const divider = newDiv.querySelector('.divider');
                const buttonContainer = newDiv.querySelector('.button-container');
                if (divider && buttonContainer) {
                    divider.style.display = 'block';
                    buttonContainer.style.display = 'flex';
                }
            }
            // updateScrollContainer()
            updateUlTransform(isExpanded)
        });

        const divider = document.createElement('div');
        divider.classList.add('divider');
        divider.style.borderBottom = '1px solid #ccc';
        divider.style.margin = '8px 0';
        divider.style.display = 'none'; // 初始设置为隐藏,如果内容未展开则显示

        const buttonContainer = document.createElement('div');
        buttonContainer.classList.add('button-container');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.justifyContent = 'flex-end';
        buttonContainer.style.marginTop = '8px';
        buttonContainer.style.display = 'none'; // 初始设置为隐藏,如果内容未展开则显示
        // 假设的函数,用于根据按钮标签返回图片 URL
        function getImageButtonSrc(label, isSelected = false) {
            const imageMap = {
                '赞': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/947377f9136b2c940d166adeaaedd89f.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/ec3e90ee2281341de801042d689452d7.png'
                },
                '踩': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/40449052b747590860def90ffba6266c.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/c01367999ce71e05ba103a5c7c181a5e.png'
                },
                '复制': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0145f6561c80202e022c5b07145b0077.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0145f6561c80202e022c5b07145b0077.png',
                },

                '填充': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/090fcd83546c4f2675b0b9b506815881.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/090fcd83546c4f2675b0b9b506815881.png',
                },
            };
            return imageMap[label] ? (isSelected ? imageMap[label].selected : imageMap[label].unselected) : 'default-icon.png'; // 如果没有找到对应的标签,返回默认图片(确保这个URL也是有效的)
        }

        const buttons = ['赞', '踩', '复制', '填充'].map(label => {
            const button = document.createElement('button');
            button.classList.add('action-button');
            button.style.marginRight = '8px';
            button.style.backgroundImage = 'none'; // 确保没有背景图干扰
            button.style.border = 'none'; // 可选:移除边框,根据样式需求来决定
            button.style.padding = '0'; // 可选:移除内边距,确保图片正确显示
            button.style.width = '14px'; // 设置按钮宽度,或者让图片自然大小显示
            button.style.height = '14px'; // 设置按钮高度,或者让图片自然比例显示(如果不设置高度,图片会保持比例)

            // 创建一个 img 元素并设置其 src 属性
            const img = document.createElement('img');
            img.src = getImageButtonSrc(label, false);
            img.alt = label; // 设置替代文本,这对于无障碍访问很重要
            // 可选:设置图片的宽度和高度,或者让 CSS 管理这些样式
            img.style.width = '14px'; // 如果希望图片填充按钮宽度,可以这样设置
            img.style.height = '14px'; // 保持图片比例

            // 将 img 元素添加到 button 元素中
            button.appendChild(img);

            // 假设 newDiv 和 targetElementParent 在此上下文中是可访问的
            // 注意:这里的 newDiv 应该是在外部作用域中定义的,确保它在这里可以访问
            const pElements = targetElementParent.querySelectorAll('p');
            const userMsgContent = pElements[0] ? pElements[0].textContent : '';
            const msgId = pElements[1] ? pElements[1].textContent : '';

            // 为不同的按钮添加事件监听器
            const handleClick = (eventLabel) => {
                return (event) => {
                    if (label === '赞' || label === '踩') {
                        let currentSrc = event.target.src;
                        let newSelectedState = !currentSrc.includes('selected');
                        let newSrc = getImageButtonSrc(label, newSelectedState);

                        event.target.src = newSrc; // 更新图像
                    }
                    if (eventLabel === '赞') {
                        sendReview(1, newDiv.textContent, msgId, userMsgContent);
                    } else if (eventLabel === '踩') {
                        sendReview(2, newDiv.textContent, msgId, userMsgContent);
                    } else if (eventLabel === '复制') {
                        copyToClipboard(newDiv.textContent);
                    } else if (eventLabel === '填充') {
                        fillTextArea(newDiv.textContent);
                    }
                };
            };

            button.addEventListener('click', handleClick(label, newDiv));
            return button;
        });

        buttons[buttons.length - 1].style.marginRight = '0';
        buttonContainer.append(...buttons);

        // 在内容未展开时添加分隔线和按钮
        newDiv.appendChild(divider);
        newDiv.appendChild(buttonContainer);
        // 发送评论的函数
        function formatDate(date) {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            const hours = String(date.getHours()).padStart(2, '0');
            const minutes = String(date.getMinutes()).padStart(2, '0');
            const seconds = String(date.getSeconds()).padStart(2, '0');

            return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
        }
        function sendReview(reviewType, aiMsg, msgId, userMsg) {
            const url = 'https://w-ts.billionconnect.com/api/aloy-h5/pub/user/review/message/report';
            let data = JSON.parse(localStorage.getItem('userData'));
            console.log('aiMsg,userMsg', aiMsg, msgId, userMsg);
            let obj = {
                userName: data.id,
                msgId: msgId,
                userMsgContent: userMsg,
                aiMsgContent: aiMsg,
                reviewType: reviewType,
                reviewCreatedDate: formatDate(new Date())
            }

            let params = {
                jsonString: JSON.stringify([obj]),
                robotName: 'mall_h5'
            }

            fetch(url, {
                method: 'POST',
                headers: {
                    // 如果需要认证,可以在这里添加 Authorization 头部
                    // 'Authorization': 'Bearer YOUR_TOKEN'
                },
                body: object2formdata(params),
            })
                .then(response => {
                    if (!response.ok) {
                        throw new Error('Network response was not ok ' + response.statusText);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('Review sent successfully:', data);
                })
                .catch(error => {
                    console.error('There was a problem with the fetch operation:', error);
                });
        }

        // 复制文本到剪贴板的函数(与之前相同)
        function copyToClipboard(text) {
            if (!navigator.clipboard) {
                // Fallback for browsers that don't support direct clipboard access
                const textArea = document.createElement("textarea");
                textArea.value = text;
                textArea.style.position = "fixed";  // Avoid scrolling to bottom
                textArea.style.top = "-9999px";
                document.body.appendChild(textArea);
                textArea.focus();
                textArea.select();
                const success = document.execCommand('copy');
                document.body.removeChild(textArea);
                if (success) {
                    console.log('Text copied to clipboard');
                } else {
                    console.error('Failed to copy text to clipboard');
                }
            } else {
                navigator.clipboard.writeText(text).then(function () {
                    console.log('Text copied to clipboard');
                }, function (err) {
                    console.error('Failed to copy text to clipboard:', err);
                });
            }
        }

        // 填充文本到 textarea 的函数
        function fillTextArea(text) {
            // 找到类名为 ui-cmp-msgeditor 的 div 元素
            const msgEditorDiv = document.querySelector('.ui-cmp-msgeditor');
            if (msgEditorDiv) {
                // 在该 div 元素中找到 textarea 元素
                const textarea = msgEditorDiv.querySelector('textarea');
                if (textarea) {
                    // 将文本设置为 textarea 的值
                    textarea.value = text;
                    console.log('Text filled into textarea');
                } else {
                    console.error('Textarea not found within .ui-cmp-msgeditor');
                }
            } else {
                console.error('.ui-cmp-msgeditor div not found');
            }
        }
        // Temporary add to document to calculate height
        document.body.appendChild(wrapperDiv);
        const newDivHeight = wrapperDiv.offsetHeight;
        document.body.removeChild(wrapperDiv);

        targetElementParent.insertAdjacentElement('afterend', wrapperDiv);
        requestAnimationFrame(() => {
            // 更新滚动容器的滚动位置
            // updateScrollContainer();
            updateUlTransform();
        });
        function updateUlTransform() {
            // 获取父容器,它有一个类名为 'em-msg-max-height'
            const parentContainer = document.querySelector('.em-msg-max-height');
            const ulElement = parentContainer.querySelector('ul');
            let yOffset = 0;
            yOffset = parentContainer.clientHeight - ulElement.clientHeight;
            console.log('yOffset', yOffset);

            ulElement.style.transform = `translateY(${yOffset}px)`;
            ulElement.style.transition = 'transform 0.3s ease';

        }
        // function storeMessage(msg, id, serviceId) {
        //     let conversationData = JSON.parse(localStorage.getItem('conversationData')) || [];
        //     let serviceIndex = conversationData.findIndex(s => s.serviceId == serviceId);

        //     if (serviceIndex === -1) {
        //         // 如果没有找到对应的 serviceId,则创建一个新的
        //         conversationData.push({
        //             serviceId: serviceId,
        //             conversation: [{ msgId: id, msg: msg }]
        //         });
        //     } else {
        //         // 如果找到了对应的 serviceId,则向 conversation 数组中添加新的消息
        //         conversationData[serviceIndex].conversation.push({ msgId: id, msg: msg });
        //     }

        //     // 将更新后的 conversationData 存储回 localStorage
        //     console.log('conversationData', conversationData);

        //     localStorage.setItem('conversationData', JSON.stringify(conversationData));
        // }
        // storeMessage(msg, id, serviceId);
    }



    // 注入消息到页面中的函数(保持不变)
    function injectDivBelowTarget(msg, id, serviceId) {
        const allPs = document.querySelectorAll('p');
        let targetElement = null;
        for (let p of allPs) {
            if (p.textContent.trim() === id) {
                targetElement = p;
                break;
            }
        }

        if (!targetElement) {
            console.warn('未找到内容为 id 的 p 元素');
            return;
        }

        const targetElementParent = targetElement.parentElement;
        const scrollContainer = targetElementParent.parentElement.parentElement;
        if (!scrollContainer || !targetElementParent) {
            console.warn('滚动容器或目标 p 元素的父元素不存在');
            return;
        }

        const newDiv = document.createElement('div');
        const showMoreButton = document.createElement('img'); // 修改为图片
        showMoreButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0e36eef2990308d9e1474b54a880b4a7.png'; // 替换为您的图片路径
        showMoreButton.alt = '显示/收起';
        showMoreButton.style.cursor = 'pointer'; // 添加鼠标指针样式
        showMoreButton.style.display = 'inline-block'; // 设置为内联块元素以控制尺寸
        showMoreButton.style.width = '10px'; // 设置图片宽度
        showMoreButton.style.height = '10px'; // 设置图片高度

        newDiv.style.display = 'block';
        newDiv.style.whiteSpace = 'nowrap';
        newDiv.style.overflow = 'hidden';
        newDiv.style.textOverflow = 'ellipsis';
        newDiv.textContent = msg;

        const wrapperDiv = document.createElement('div');
        wrapperDiv.classList.add('message-wrapper');
        wrapperDiv.style.marginTop = '10px';
        wrapperDiv.style.border = '2px solid #C1BDFF';
        wrapperDiv.style.minWidth = '92%';
        wrapperDiv.style.padding = '10px';
        wrapperDiv.style.overflowWrap = 'break-word';
        wrapperDiv.style.position = 'relative'; // 添加相对定位以包含图片
        wrapperDiv.appendChild(newDiv);

        // 将图片添加到 wrapperDiv 的最右侧
        const imageContainer = document.createElement('div');
        imageContainer.style.position = 'absolute';
        imageContainer.style.top = '10px'; // 调整以匹配 padding
        imageContainer.style.right = '10px'; // 调整以匹配 padding
        imageContainer.style.width = '10px'; // 调整以匹配 padding
        imageContainer.style.height = '10px'; // 调整以匹配 padding
        imageContainer.appendChild(showMoreButton);
        wrapperDiv.appendChild(imageContainer);

        let isExpanded = false;

        showMoreButton.addEventListener('click', function () {
            if (isExpanded) {
                newDiv.style.whiteSpace = 'nowrap';
                newDiv.style.overflow = 'hidden';
                showMoreButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0e36eef2990308d9e1474b54a880b4a7.png'; // 替换为折叠状态的图片路径
                isExpanded = false;
                // 显示分隔线和按钮
                const divider = newDiv.querySelector('.divider');
                const buttonContainer = newDiv.querySelector('.button-container');
                if (divider && buttonContainer) {
                    divider.style.display = 'none';
                    buttonContainer.style.display = 'none';
                }
            } else {
                newDiv.style.whiteSpace = 'normal';
                newDiv.style.overflow = 'visible';
                showMoreButton.src = 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0e36eef2990308d9e1474b54a880b4a7.png'; // 替换为展开状态的图片路径
                isExpanded = true;
                // 隐藏分隔线和按钮
                const divider = newDiv.querySelector('.divider');
                const buttonContainer = newDiv.querySelector('.button-container');
                if (divider && buttonContainer) {
                    divider.style.display = 'block';
                    buttonContainer.style.display = 'flex';
                }
            }
            // updateScrollContainer()
            updateUlTransform(isExpanded)
        });

        const divider = document.createElement('div');
        divider.classList.add('divider');
        divider.style.borderBottom = '1px solid #ccc';
        divider.style.margin = '8px 0';
        divider.style.display = 'none'; // 初始设置为隐藏,如果内容未展开则显示

        const buttonContainer = document.createElement('div');
        buttonContainer.classList.add('button-container');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.justifyContent = 'flex-end';
        buttonContainer.style.marginTop = '8px';
        buttonContainer.style.display = 'none'; // 初始设置为隐藏,如果内容未展开则显示
        // 假设的函数,用于根据按钮标签返回图片 URL
        function getImageButtonSrc(label, isSelected = false) {
            const imageMap = {
                '赞': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/947377f9136b2c940d166adeaaedd89f.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/ec3e90ee2281341de801042d689452d7.png'
                },
                '踩': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/40449052b747590860def90ffba6266c.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/c01367999ce71e05ba103a5c7c181a5e.png'
                },
                '复制': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0145f6561c80202e022c5b07145b0077.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/0145f6561c80202e022c5b07145b0077.png',
                },

                '填充': {
                    selected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/090fcd83546c4f2675b0b9b506815881.png',
                    unselected: 'https://emov-hongkong.oss-cn-hongkong.aliyuncs.com/h5store/090fcd83546c4f2675b0b9b506815881.png',
                },
            };
            return imageMap[label] ? (isSelected ? imageMap[label].selected : imageMap[label].unselected) : 'default-icon.png'; // 如果没有找到对应的标签,返回默认图片(确保这个URL也是有效的)
        }

        const buttons = ['赞', '踩', '复制', '填充'].map(label => {
            const button = document.createElement('button');
            button.classList.add('action-button');
            button.style.marginRight = '8px';
            button.style.backgroundImage = 'none'; // 确保没有背景图干扰
            button.style.border = 'none'; // 可选:移除边框,根据样式需求来决定
            button.style.padding = '0'; // 可选:移除内边距,确保图片正确显示
            button.style.width = '14px'; // 设置按钮宽度,或者让图片自然大小显示
            button.style.height = '14px'; // 设置按钮高度,或者让图片自然比例显示(如果不设置高度,图片会保持比例)

            // 创建一个 img 元素并设置其 src 属性
            const img = document.createElement('img');
            img.src = getImageButtonSrc(label, false);
            img.alt = label; // 设置替代文本,这对于无障碍访问很重要
            // 可选:设置图片的宽度和高度,或者让 CSS 管理这些样式
            img.style.width = '14px'; // 如果希望图片填充按钮宽度,可以这样设置
            img.style.height = '14px'; // 保持图片比例

            // 将 img 元素添加到 button 元素中
            button.appendChild(img);

            // 假设 newDiv 和 targetElementParent 在此上下文中是可访问的
            // 注意:这里的 newDiv 应该是在外部作用域中定义的,确保它在这里可以访问
            const pElements = targetElementParent.querySelectorAll('p');
            const userMsgContent = pElements[0] ? pElements[0].textContent : '';
            const msgId = pElements[1] ? pElements[1].textContent : '';

            // 为不同的按钮添加事件监听器
            const handleClick = (eventLabel) => {
                return (event) => {
                    if (label === '赞' || label === '踩') {
                        let currentSrc = event.target.src;
                        let newSelectedState = !currentSrc.includes('selected');
                        let newSrc = getImageButtonSrc(label, newSelectedState);

                        event.target.src = newSrc; // 更新图像
                    }
                    if (eventLabel === '赞') {
                        sendReview(1, newDiv.textContent, msgId, userMsgContent);
                    } else if (eventLabel === '踩') {
                        sendReview(2, newDiv.textContent, msgId, userMsgContent);
                    } else if (eventLabel === '复制') {
                        copyToClipboard(newDiv.textContent);
                    } else if (eventLabel === '填充') {
                        fillTextArea(newDiv.textContent);
                    }
                };
            };

            button.addEventListener('click', handleClick(label, newDiv));
            return button;
        });

        buttons[buttons.length - 1].style.marginRight = '0';
        buttonContainer.append(...buttons);

        // 在内容未展开时添加分隔线和按钮
        newDiv.appendChild(divider);
        newDiv.appendChild(buttonContainer);
        // 发送评论的函数
        function formatDate(date) {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            const hours = String(date.getHours()).padStart(2, '0');
            const minutes = String(date.getMinutes()).padStart(2, '0');
            const seconds = String(date.getSeconds()).padStart(2, '0');

            return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
        }
        function sendReview(reviewType, aiMsg, msgId, userMsg) {
            const url = 'https://w-ts.billionconnect.com/api/aloy-h5/pub/user/review/message/report';
            let data = JSON.parse(localStorage.getItem('userData'));
            console.log('aiMsg,userMsg', aiMsg, msgId, userMsg);
            let obj = {
                userName: data.id,
                msgId: msgId,
                userMsgContent: userMsg,
                aiMsgContent: aiMsg,
                reviewType: reviewType,
                reviewCreatedDate: formatDate(new Date())
            }

            let params = {
                jsonString: JSON.stringify([obj]),
                robotName: 'mall_h5'
            }

            fetch(url, {
                method: 'POST',
                headers: {
                    // 如果需要认证,可以在这里添加 Authorization 头部
                    // 'Authorization': 'Bearer YOUR_TOKEN'
                },
                body: object2formdata(params),
            })
                .then(response => {
                    if (!response.ok) {
                        throw new Error('Network response was not ok ' + response.statusText);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('Review sent successfully:', data);
                })
                .catch(error => {
                    console.error('There was a problem with the fetch operation:', error);
                });
        }

        // 复制文本到剪贴板的函数(与之前相同)
        function copyToClipboard(text) {
            if (!navigator.clipboard) {
                // Fallback for browsers that don't support direct clipboard access
                const textArea = document.createElement("textarea");
                textArea.value = text;
                textArea.style.position = "fixed";  // Avoid scrolling to bottom
                textArea.style.top = "-9999px";
                document.body.appendChild(textArea);
                textArea.focus();
                textArea.select();
                const success = document.execCommand('copy');
                document.body.removeChild(textArea);
                if (success) {
                    console.log('Text copied to clipboard');
                } else {
                    console.error('Failed to copy text to clipboard');
                }
            } else {
                navigator.clipboard.writeText(text).then(function () {
                    console.log('Text copied to clipboard');
                }, function (err) {
                    console.error('Failed to copy text to clipboard:', err);
                });
            }
        }

        // 填充文本到 textarea 的函数
        function fillTextArea(text) {
            // 找到类名为 ui-cmp-msgeditor 的 div 元素
            const msgEditorDiv = document.querySelector('.ui-cmp-msgeditor');
            if (msgEditorDiv) {
                // 在该 div 元素中找到 textarea 元素
                const textarea = msgEditorDiv.querySelector('textarea');
                if (textarea) {
                    // 将文本设置为 textarea 的值
                    textarea.value = text;
                    console.log('Text filled into textarea');
                } else {
                    console.error('Textarea not found within .ui-cmp-msgeditor');
                }
            } else {
                console.error('.ui-cmp-msgeditor div not found');
            }
        }
        // Temporary add to document to calculate height
        document.body.appendChild(wrapperDiv);
        const newDivHeight = wrapperDiv.offsetHeight;
        document.body.removeChild(wrapperDiv);

        targetElementParent.insertAdjacentElement('afterend', wrapperDiv);
        requestAnimationFrame(() => {
            // 更新滚动容器的滚动位置
            // updateScrollContainer();
            updateUlTransform();
        });
        function updateScrollContainer() {
            console.log('updateScrollContainer');
            const rect = targetElement.getBoundingClientRect();
            const containerRect = scrollContainer.getBoundingClientRect();
            let scrollTop = scrollContainer.scrollTop;
            let offset = rect.top - containerRect.top + scrollTop;

            if (isExpanded) {
                scrollTop += newDivHeight - rect.height;
            } else {
                scrollTop = offset - rect.height;
            }

            scrollContainer.scrollTop = scrollTop;
            console.log('scrollTop', scrollTop);

        }
        function updateUlTransform() {
            // 获取父容器,它有一个类名为 'em-msg-max-height'
            const parentContainer = document.querySelector('.em-msg-max-height');
            const ulElement = parentContainer.querySelector('ul');
            let yOffset = 0;
            yOffset = parentContainer.clientHeight - ulElement.clientHeight;
            console.log('yOffset', yOffset);

            ulElement.style.transform = `translateY(${yOffset}px)`;
            ulElement.style.transition = 'transform 0.3s ease';

        }
        function storeMessage(msg, id, serviceId) {
            let conversationData = JSON.parse(localStorage.getItem('conversationData')) || [];
            let serviceIndex = conversationData.findIndex(s => s.serviceId == serviceId);

            if (serviceIndex === -1) {
                // 如果没有找到对应的 serviceId,则创建一个新的
                conversationData.push({
                    serviceId: serviceId,
                    conversation: [{ msgId: id, msg: msg }]
                });
            } else {
                // 如果找到了对应的 serviceId,则向 conversation 数组中添加新的消息
                conversationData[serviceIndex].conversation.push({ msgId: id, msg: msg });
            }

            // 将更新后的 conversationData 存储回 localStorage
            console.log('conversationData', conversationData);

            localStorage.setItem('conversationData', JSON.stringify(conversationData));
        }
        storeMessage(msg, id, serviceId);
    }
})();