Files
vf_react/public/index.html
zdl 21564ebf4d feat(bytedesk): 集成 Bytedesk 客服系统
新增 Bytedesk 在线客服功能,支持实时对话:

组件:
- BytedeskWidget: 客服浮窗组件(右下角)
- 配置文件: bytedesk.config.js 统一管理配置
- 环境变量示例: .env.bytedesk.example

集成方式:
- GlobalComponents 引入 BytedeskWidget
- public/index.html 加载 bytedesk-web.js 脚本
- 支持环境变量配置(ORG、SID、API_URL)

配置说明详见 src/bytedesk-integration/.env.bytedesk.example

🔧 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 17:26:42 +08:00

262 lines
8.8 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
/*!
=========================================================
* Argon Dashboard Chakra PRO - v1.0.0
=========================================================
* Product Page: https://www.creative-tim.com/product/argon-dashboard-chakra-pro
* Copyright 2022 Creative Tim (https://www.creative-tim.com/)
* Designed and Coded by Simmmple & Creative Tim
=========================================================
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
-->
<!DOCTYPE html>
<html lang="en" dir="ltr" layout="admin">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png" />
<link
rel="apple-touch-icon"
sizes="76x76"
href="%PUBLIC_URL%/apple-icon.png"
/>
<link rel="shortcut icon" type="image/x-icon" href="./favicon.png" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.png" or "favicon.png", "%PUBLIC_URL%/favicon.png" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>价值前沿——LLM赋能的分析平台</title>
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script>
window.difyChatbotConfig = {
token: 'DwN8qAKtYFQtWskM',
baseUrl: 'https://app.valuefrontier.cn',
inputs: {
// You can define the inputs from the Start node here
// key is the variable name
// e.g.
// name: "NAME"
},
systemVariables: {
// user_id: 'YOU CAN DEFINE USER ID HERE',
// conversation_id: 'YOU CAN DEFINE CONVERSATION ID HERE, IT MUST BE A VALID UUID',
},
userVariables: {
// avatar_url: 'YOU CAN DEFINE USER AVATAR URL HERE',
// name: 'YOU CAN DEFINE USER NAME HERE',
},
}
// 根据路径控制Dify机器人显示只在首页/和home页/home显示
function controlDifyChatbot() {
const path = window.location.pathname;
const chatbotButton = document.getElementById('dify-chatbot-bubble-button');
const chatbotWindow = document.getElementById('dify-chatbot-bubble-window');
// 只在首页(/)和home页(/home)显示Dify机器人
// const shouldShowDify = (path === '/' || path === '/home');
// 完全不显示Dify机器人只使用Bytedesk客服
const shouldShowDify = false
if (chatbotButton) {
chatbotButton.style.display = shouldShowDify ? 'block' : 'none';
// 同时设置visibility确保完全隐藏
chatbotButton.style.visibility = shouldShowDify ? 'visible' : 'hidden';
}
if (chatbotWindow) {
chatbotWindow.style.display = shouldShowDify ? '' : 'none';
}
console.log('[Dify] Path:', path, 'Should show:', shouldShowDify, 'Button found:', !!chatbotButton);
}
// 轮询检查Dify按钮因为Dify脚本加载是异步的
let difyCheckCount = 0;
const difyCheckInterval = setInterval(function() {
const button = document.getElementById('dify-chatbot-bubble-button');
if (button || difyCheckCount > 50) { // 最多检查5秒
if (button) {
console.log('[Dify] Button found, applying control');
controlDifyChatbot();
}
clearInterval(difyCheckInterval);
}
difyCheckCount++;
}, 100);
// 页面加载时执行
window.addEventListener('load', function() {
setTimeout(controlDifyChatbot, 1000);
});
// 监听路由变化React Router使用pushState
window.addEventListener('popstate', controlDifyChatbot);
// 监听pushState和replaceState捕获React Router导航
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;
history.pushState = function() {
originalPushState.apply(history, arguments);
setTimeout(controlDifyChatbot, 50);
};
history.replaceState = function() {
originalReplaceState.apply(history, arguments);
setTimeout(controlDifyChatbot, 50);
};
// 使用MutationObserver监听DOM变化捕获Dify按钮插入
const observer = new MutationObserver(function(mutations) {
for (const mutation of mutations) {
if (mutation.addedNodes.length > 0) {
for (const node of mutation.addedNodes) {
if (node.id && (node.id.includes('dify') || node.id.includes('chatbot'))) {
console.log('[Dify] Detected chatbot element insertion:', node.id);
setTimeout(controlDifyChatbot, 100);
break;
}
}
}
}
});
// 观察body的变化
window.addEventListener('DOMContentLoaded', function() {
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false
});
});
</script>
<script
src="https://app.valuefrontier.cn/embed.min.js"
id="DwN8qAKtYFQtWskM"
defer>
</script>
<style>
#dify-chatbot-bubble-button {
background-color: #1C64F2 !important;
width: 60px !important;
height: 60px !important;
box-shadow: 0 4px 12px rgba(28, 100, 242, 0.3) !important;
transition: all 0.3s ease !important;
}
#dify-chatbot-bubble-button:hover {
transform: scale(1.1) !important;
box-shadow: 0 6px 16px rgba(28, 100, 242, 0.4) !important;
}
#dify-chatbot-bubble-window {
width: 42rem !important;
height: 80vh !important;
max-height: calc(100vh - 2rem) !important;
position: fixed !important;
bottom: 100px !important;
right: 20px !important;
border-radius: 16px !important;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15) !important;
border: 1px solid rgba(28, 100, 242, 0.1) !important;
z-index: 9999 !important;
}
/* 确保Dify聊天窗口中的超链接正确显示 */
#dify-chatbot-bubble-window a,
#dify-chatbot-bubble-window a:link,
#dify-chatbot-bubble-window a:visited,
#dify-chatbot-bubble-window a:hover,
#dify-chatbot-bubble-window a:active {
color: #1C64F2 !important;
text-decoration: underline !important;
cursor: pointer !important;
pointer-events: auto !important;
}
/* 确保超链接在Dify消息区域中可见 */
#dify-chatbot-bubble-window .message-content a,
#dify-chatbot-bubble-window .markdown-content a,
#dify-chatbot-bubble-window [class*="message"] a {
color: #0066cc !important;
text-decoration: underline !important;
font-weight: 500 !important;
}
/* 桌面端大屏优化 */
@media (min-width: 1440px) {
#dify-chatbot-bubble-window {
width: 45rem !important;
height: 85vh !important;
}
}
/* 平板端适配 */
@media (max-width: 1024px) and (min-width: 641px) {
#dify-chatbot-bubble-window {
width: 38rem !important;
height: 75vh !important;
right: 15px !important;
bottom: 90px !important;
}
}
/* 移动端适配 */
@media (max-width: 640px) {
#dify-chatbot-bubble-window {
width: calc(100vw - 20px) !important;
height: 85vh !important;
max-height: 85vh !important;
right: 10px !important;
bottom: 80px !important;
left: 10px !important;
}
#dify-chatbot-bubble-button {
width: 56px !important;
height: 56px !important;
}
}
</style>
</body>
</html>