From c4f2cea1a915d71a370d95c46c5e5ddfe2279218 Mon Sep 17 00:00:00 2001
From: jinhhanhan <1683105490@qq.com>
Date: Fri, 5 Dec 2025 16:47:53 +0800
Subject: [PATCH] =?UTF-8?q?chore:=E5=8A=A0=E4=BA=86=E6=99=BA=E8=83=BD?=
=?UTF-8?q?=E4=BD=93?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.vue | 232 ++++++++++++-----
components/hover-nav/hover-nav.vue | 399 ++++++++++++++---------------
pages/index/index.vue | 2 +-
3 files changed, 350 insertions(+), 283 deletions(-)
diff --git a/App.vue b/App.vue
index 300ccf0..c1b448d 100644
--- a/App.vue
+++ b/App.vue
@@ -31,7 +31,6 @@
if (uni.getSystemInfoSync().platform == 'ios') {
uni.setStorageSync('initUrl', location.href);
}
- // DOM加载完成后,创建纯前端聊天窗口(无任何Dify残留)
this.$nextTick(() => {
this.createIndependentChatbot();
});
@@ -80,11 +79,9 @@
}
// #ifdef H5
- // 自动授权登录(未登录时)
if (!uni.getStorageSync('memberInfo')) {
this.getAuthInfo();
}
- // 已登录时同步会员信息
if (this.$store.state.token) {
this.$api.sendRequest({
url: '/api/member/info',
@@ -103,7 +100,6 @@
},
onShow: function(options) {
// #ifdef MP
- // 修复语法错误:l0 → 10
this.getAuthInfo();
if (this.$store.state.token) {
this.$api.sendRequest({
@@ -123,101 +119,179 @@
},
onHide: function() {},
methods: {
- /**
- * 纯前端聊天机器人(无Dify依赖)
- */
+ // 安全的 HTML 转义(防止 XSS)
+ htmlEncode(str) {
+ if (typeof str !== 'string') return '';
+ return str
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+ },
+
createIndependentChatbot() {
- console.log('创建纯前端聊天窗口...');
+ console.log('创建响应式智能客服窗口...');
- // 1. 移除所有旧的Dify相关元素(彻底清理残留)
- document.querySelectorAll('[id^="dify-"]').forEach(el => el.remove());
+ // 清除已存在的元素
+ document.querySelectorAll('[id^="independent-chat-"]').forEach(el => el.remove());
- // 2. 创建聊天按钮
+ // ========== 按钮 ==========
const chatBtn = document.createElement('div');
chatBtn.id = 'independent-chat-btn';
- chatBtn.style = `
- width: 56px; height: 56px; border-radius: 50%; background: #1C64F2;
- position: fixed; bottom: 30px; right: 30px; z-index: 999999;
- cursor: pointer; display: flex; align-items: center; justify-content: center;
- color: white; font-size: 24px; box-shadow: 0 4px 12px rgba(0,0,0,0.15);
+ chatBtn.innerHTML = '💬';
+ chatBtn.style.cssText = `
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ position: fixed;
+ bottom: calc(180px + env(safe-area-inset-bottom, 0px));
+ right: 0px;
+ z-index: 999999;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ font-size: 24px;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
+ background: linear-gradient(135deg, #ff9a9e, #fad0c4, #a1c4fd, #c2e9fb, #d4fc79, #96e6a1);
+ background-size: 300% 300%;
+ animation: rainbowPulse 4s ease infinite;
+ user-select: none;
+ -webkit-user-drag: none;
`;
- chatBtn.innerText = '💬';
document.body.appendChild(chatBtn);
- // 3. 创建聊天窗口
+ // ========== 聊天窗口 ==========
const chatWindow = document.createElement('div');
chatWindow.id = 'independent-chat-window';
- chatWindow.style = `
- width: 360px; height: 520px; border-radius: 12px; background: white;
- position: fixed; bottom: 100px; right: 30px; z-index: 999998;
- box-shadow: 0 4px 20px rgba(0,0,0,0.15); display: none;
- flex-direction: column; overflow: hidden;
+ chatWindow.style.cssText = `
+ position: fixed;
+ z-index: 999998;
+ border-radius: 12px;
+ background: white;
+ box-shadow: 0 4px 20px rgba(0,0,0,0.2);
+ display: none;
+ flex-direction: column;
+ overflow: hidden;
`;
document.body.appendChild(chatWindow);
- // 3.1 标题栏
+ // 头部
const chatHeader = document.createElement('div');
- chatHeader.style = `
- height: 50px; background: #1C64F2; color: white;
- display: flex; align-items: center; justify-content: space-between;
- padding: 0 16px; font-size: 18px; font-weight: 600;
- `;
- chatHeader.innerHTML = `
- 智能客服
- ×
+ chatHeader.style.cssText = `
+ height: 50px;
+ background: #1C64F2;
+ color: white;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 16px;
+ font-size: 18px;
+ font-weight: 600;
`;
+ chatHeader.innerHTML = `智能客服×`;
chatWindow.appendChild(chatHeader);
- // 3.2 聊天内容区
+ // 内容区
const chatContent = document.createElement('div');
- chatContent.style = `
- flex: 1; padding: 16px; overflow-y: auto;
+ chatContent.style.cssText = `
+ flex: 1;
+ padding: 16px;
+ overflow-y: auto;
background: #f9fafb;
`;
chatContent.innerHTML = `
-
-
🤖
-
- 您好!有什么可以帮到您的吗?
-
+
`;
chatWindow.appendChild(chatContent);
- // 3.3 输入区
+ // 输入区
const chatInputArea = document.createElement('div');
- chatInputArea.style = `
- height: 60px; display: flex; align-items: center;
- padding: 0 16px; border-top: 1px solid #eee;
+ chatInputArea.style.cssText = `
+ height: 60px;
+ display: flex;
+ align-items: center;
+ padding: 0 16px;
+ border-top: 1px solid #eee;
`;
const chatInput = document.createElement('input');
chatInput.type = 'text';
chatInput.placeholder = '请输入您的问题...';
- chatInput.style = `
- flex: 1; height: 36px; padding: 0 12px; border: 1px solid #ddd;
- border-radius: 18px; outline: none; font-size: 14px;
+ chatInput.style.cssText = `
+ flex: 1;
+ height: 36px;
+ padding: 0 12px;
+ border: 1px solid #ddd;
+ border-radius: 18px;
+ outline: none;
+ font-size: 14px;
`;
const sendBtn = document.createElement('button');
- sendBtn.innerText = '发送';
- sendBtn.style = `
- margin-left: 12px; padding: 6px 16px; background: #1C64F2;
- color: white; border: none; border-radius: 18px; cursor: pointer;
+ sendBtn.innerText = '发送'; // 横排文字
+ sendBtn.style.cssText = `
+ margin-left: 12px;
+ padding: 6px 16px;
+ background: #1C64F2;
+ color: white;
+ border: none;
+ border-radius: 18px;
+ cursor: pointer;
font-size: 14px;
+ white-space: nowrap; /* 防止换行 */
+ text-align: center; /* 居中 */
+ line-height: 1.5; /* 调整高度 */
`;
chatInputArea.appendChild(chatInput);
chatInputArea.appendChild(sendBtn);
chatWindow.appendChild(chatInputArea);
- // 4. 绑定事件
+ // ========== 响应式尺寸控制 ==========
+ const updateWindowSize = () => {
+ const isMobile = window.innerWidth <= 768;
+ if (isMobile) {
+ chatWindow.style.width = 'calc(90vw - 40px)';
+ chatWindow.style.maxWidth = '400px';
+ chatWindow.style.height = '70vh';
+ chatWindow.style.maxHeight = '600px';
+ chatWindow.style.right = '5vw';
+ chatWindow.style.bottom = 'calc(86px + env(safe-area-inset-bottom, 0px))';
+ } else {
+ chatWindow.style.width = '360px';
+ chatWindow.style.height = '520px';
+ chatWindow.style.maxWidth = 'none';
+ chatWindow.style.maxHeight = 'none';
+ chatWindow.style.right = '20px';
+ chatWindow.style.bottom = '86px';
+ }
+ chatContent.style.maxHeight = 'calc(100% - 110px)';
+ };
+
+ // 初始化并监听窗口变化
+ updateWindowSize();
+ window.addEventListener('resize', updateWindowSize);
+
+ // ========== 交互逻辑 ==========
let isShow = false;
- chatBtn.onclick = () => {
+ const toggleChat = () => {
isShow = !isShow;
chatWindow.style.display = isShow ? 'flex' : 'none';
+ if (isShow) {
+ updateWindowSize(); // 确保旋转/切换后尺寸正确
+ chatInput.focus();
+ }
};
+
+ chatBtn.onclick = toggleChat;
document.getElementById('close-chat-window').onclick = () => {
isShow = false;
chatWindow.style.display = 'none';
};
+
document.addEventListener('click', (e) => {
if (!chatBtn.contains(e.target) && !chatWindow.contains(e.target)) {
isShow = false;
@@ -225,43 +299,45 @@
}
});
- // 5. 发送消息逻辑
+ // 发送消息
const sendMessage = () => {
const msg = chatInput.value.trim();
if (!msg) return;
- // 显示用户消息
+ const safeMsg = this.htmlEncode(msg);
chatContent.insertAdjacentHTML('beforeend', `
-
-
- ${msg}
+
`);
chatInput.value = '';
chatContent.scrollTop = chatContent.scrollHeight;
- // 模拟回复
setTimeout(() => {
chatContent.insertAdjacentHTML('beforeend', `
-
-
🤖
-
- 已收到您的问题:"${msg}",我们会尽快回复!
+
+
🤖
+
+ 已收到您的问题:"${safeMsg}",我们会尽快回复!
`);
chatContent.scrollTop = chatContent.scrollHeight;
}, 800);
};
- sendBtn.onclick = sendMessage;
- chatInput.onkeydown = (e) => e.key === 'Enter' && sendMessage();
- console.log('纯前端聊天窗口创建完成');
+ sendBtn.onclick = sendMessage;
+ chatInput.onkeydown = (e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ sendMessage();
+ }
+ };
+
+ console.log('响应式智能客服窗口创建完成');
},
- /**
- * 原逻辑(授权/登录/分享等)
- */
getAuthInfo() {
// #ifdef H5
if (this.$util.isWeiXin()) {
@@ -355,12 +431,15 @@
@import './common/css/iconfont.css';
@import './common/css/icondiy.css';
@import './common/css/icon/extend.css';
+
page {
background: #f4f6fa;
}
body {
padding-bottom: 80px !important;
}
+
+ /* 聊天窗口滚动条美化 */
#independent-chat-window div::-webkit-scrollbar {
width: 4px;
}
@@ -368,4 +447,17 @@
background: #ddd;
border-radius: 2px;
}
+
+ /* 彩虹动画 */
+ @keyframes rainbowPulse {
+ 0% { background-position: 0% 50%; }
+ 50% { background-position: 100% 50%; }
+ 100% { background-position: 0% 50%; }
+ }
+
+ /* 强制固定定位,防止被其他样式干扰 */
+ #independent-chat-btn,
+ #independent-chat-window {
+ position: fixed !important;
+ }
\ No newline at end of file
diff --git a/components/hover-nav/hover-nav.vue b/components/hover-nav/hover-nav.vue
index 64fbeac..7579292 100644
--- a/components/hover-nav/hover-nav.vue
+++ b/components/hover-nav/hover-nav.vue
@@ -1,213 +1,188 @@
-
-
-
-
-
-
-
- 🤖
-
-
- {{ unreadCount > 99 ? '99+' : unreadCount }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pages/index/index.vue b/pages/index/index.vue
index e0828e4..e863f2f 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -122,7 +122,7 @@
-
+