From e753437b86c160d142dbe197a1ae0685957ebf5f Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Thu, 20 Nov 2025 14:30:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E5=AE=A2=E6=9C=8D?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.production | 33 +-- src/bytedesk-integration/App.jsx.example | 237 ------------------ .../config/bytedesk.config.js | 66 +---- src/components/GlobalComponents.js | 13 +- 4 files changed, 13 insertions(+), 336 deletions(-) delete mode 100644 src/bytedesk-integration/App.jsx.example diff --git a/.env.production b/.env.production index 272cb4db..3eb056e9 100644 --- a/.env.production +++ b/.env.production @@ -1,13 +1,6 @@ # ======================================== # 生产环境配置 # ======================================== -# 使用方式: npm run build -# -# 工作原理: -# 1. 此文件专门用于生产环境构建 -# 2. 构建时会将环境变量嵌入到打包文件中 -# 3. 确保 PostHog 等服务使用正确的生产配置 -# ======================================== # 环境标识 REACT_APP_ENV=production @@ -17,13 +10,8 @@ NODE_ENV=production REACT_APP_ENABLE_MOCK=false # 🔧 调试模式(生产环境临时调试用) -# 开启后会在全局暴露 window.__DEBUG__ 和 window.__TEST_NOTIFICATION__ 调试 API -# ⚠️ 警告: 调试模式会记录所有 API 请求/响应,调试完成后请立即关闭! -# 使用方法: -# 1. 设置为 true 并重新构建 -# 2. 在浏览器控制台使用 window.__DEBUG__.help() 查看命令 -# 3. 调试完成后设置为 false 并重新构建 -REACT_APP_ENABLE_DEBUG=true +# 开启后会在全局暴露 window.__DEBUG__ +REACT_APP_ENABLE_DEBUG=false # 后端 API 地址(生产环境) REACT_APP_API_URL=http://49.232.185.254:5001 @@ -49,20 +37,3 @@ TSC_COMPILE_ON_ERROR=true IMAGE_INLINE_SIZE_LIMIT=10000 # Node.js 内存限制(适用于大型项目) NODE_OPTIONS=--max_old_space_size=4096 - -# ======================================== -# Bytedesk 客服系统配置 -# ======================================== -# Bytedesk 服务器地址(使用相对路径,通过 Nginx 代理) -# ⚠️ 重要:生产环境必须使用相对路径,避免 Mixed Content 错误 -# Nginx 配置:location /bytedesk-api/ { proxy_pass http://43.143.189.195/; } -REACT_APP_BYTEDESK_API_URL=/bytedesk-api - -# 组织 UUID(从管理后台 -> 设置 -> 组织信息 -> 组织UUID) -REACT_APP_BYTEDESK_ORG=df_org_uid - -# 工作组 UUID(从管理后台 -> 客服管理 -> 工作组 -> 工作组UUID) -REACT_APP_BYTEDESK_SID=df_wg_uid - -# 客服类型(2=人工客服, 1=机器人) -REACT_APP_BYTEDESK_TYPE=2 diff --git a/src/bytedesk-integration/App.jsx.example b/src/bytedesk-integration/App.jsx.example deleted file mode 100644 index b7bccc9d..00000000 --- a/src/bytedesk-integration/App.jsx.example +++ /dev/null @@ -1,237 +0,0 @@ -/** - * vf_react App.jsx集成示例 - * - * 本文件展示如何在vf_react项目中集成Bytedesk客服系统 - * - * 集成步骤: - * 1. 将bytedesk-integration文件夹复制到src/目录 - * 2. 在App.jsx中导入BytedeskWidget和配置 - * 3. 添加BytedeskWidget组件(代码如下) - * 4. 配置.env文件(参考.env.bytedesk.example) - */ - -import React, { useState, useEffect } from 'react'; -import { useLocation } from 'react-router-dom'; // 如果使用react-router -import BytedeskWidget from './bytedesk-integration/components/BytedeskWidget'; -import { getBytedeskConfig, shouldShowCustomerService } from './bytedesk-integration/config/bytedesk.config'; - -// ============================================================================ -// 方案一: 全局集成(推荐) -// 适用场景: 客服系统需要在所有页面显示 -// ============================================================================ - -function App() { - // ========== vf_react原有代码保持不变 ========== - // 这里是您原有的App.jsx代码 - // 例如: const [user, setUser] = useState(null); - // 例如: const [theme, setTheme] = useState('light'); - // ... 保持原有逻辑不变 ... - - // ========== Bytedesk集成代码开始 ========== - - const location = useLocation(); // 获取当前路径 - const [showBytedesk, setShowBytedesk] = useState(false); - - // 根据页面路径决定是否显示客服 - useEffect(() => { - const shouldShow = shouldShowCustomerService(location.pathname); - setShowBytedesk(shouldShow); - }, [location.pathname]); - - // 获取Bytedesk配置 - const bytedeskConfig = getBytedeskConfig(); - - // 客服加载成功回调 - const handleBytedeskLoad = (bytedesk) => { - console.log('[App] Bytedesk客服系统加载成功', bytedesk); - }; - - // 客服加载失败回调 - const handleBytedeskError = (error) => { - console.error('[App] Bytedesk客服系统加载失败', error); - }; - - // ========== Bytedesk集成代码结束 ========== - - return ( -
- {/* ========== vf_react原有内容保持不变 ========== */} - {/* 这里是您原有的App.jsx JSX代码 */} - {/* 例如:
*/} - {/* 例如: ... */} - {/* ... 保持原有结构不变 ... */} - - {/* ========== Bytedesk客服Widget ========== */} - {showBytedesk && ( - - )} -
- ); -} - -export default App; - - -// ============================================================================ -// 方案二: 带用户信息集成 -// 适用场景: 需要将登录用户信息传递给客服端 -// ============================================================================ - -/* -import React, { useState, useEffect, useContext } from 'react'; -import { useLocation } from 'react-router-dom'; -import BytedeskWidget from './bytedesk-integration/components/BytedeskWidget'; -import { getBytedeskConfigWithUser, shouldShowCustomerService } from './bytedesk-integration/config/bytedesk.config'; -import { AuthContext } from './contexts/AuthContext'; // 假设您有用户认证Context - -function App() { - // 获取登录用户信息 - const { user } = useContext(AuthContext); - - const location = useLocation(); - const [showBytedesk, setShowBytedesk] = useState(false); - - useEffect(() => { - const shouldShow = shouldShowCustomerService(location.pathname); - setShowBytedesk(shouldShow); - }, [location.pathname]); - - // 根据用户信息生成配置 - const bytedeskConfig = user - ? getBytedeskConfigWithUser(user) - : getBytedeskConfig(); - - return ( -
- // ... 您的原有代码 ... - - {showBytedesk && ( - - )} -
- ); -} - -export default App; -*/ - - -// ============================================================================ -// 方案三: 条件性加载 -// 适用场景: 只在特定条件下显示客服(如用户已登录、特定用户角色等) -// ============================================================================ - -/* -import React, { useState, useEffect } from 'react'; -import BytedeskWidget from './bytedesk-integration/components/BytedeskWidget'; -import { getBytedeskConfig } from './bytedesk-integration/config/bytedesk.config'; - -function App() { - const [user, setUser] = useState(null); - const [showBytedesk, setShowBytedesk] = useState(false); - - useEffect(() => { - // 只有在用户登录且为普通用户时显示客服 - if (user && user.role === 'customer') { - setShowBytedesk(true); - } else { - setShowBytedesk(false); - } - }, [user]); - - const bytedeskConfig = getBytedeskConfig(); - - return ( -
- // ... 您的原有代码 ... - - {showBytedesk && ( - - )} -
- ); -} - -export default App; -*/ - - -// ============================================================================ -// 方案四: 动态控制显示/隐藏 -// 适用场景: 需要通过按钮或其他交互控制客服显示 -// ============================================================================ - -/* -import React, { useState } from 'react'; -import BytedeskWidget from './bytedesk-integration/components/BytedeskWidget'; -import { getBytedeskConfig } from './bytedesk-integration/config/bytedesk.config'; - -function App() { - const [showBytedesk, setShowBytedesk] = useState(false); - const bytedeskConfig = getBytedeskConfig(); - - const toggleBytedesk = () => { - setShowBytedesk(prev => !prev); - }; - - return ( -
- // ... 您的原有代码 ... - - {/* 自定义客服按钮 *\/} - - - {/* 客服Widget *\/} - {showBytedesk && ( - - )} -
- ); -} - -export default App; -*/ - - -// ============================================================================ -// 重要提示 -// ============================================================================ - -/** - * 1. CSS样式兼容性 - * - Bytedesk Widget使用Shadow DOM,不会影响您的全局样式 - * - Widget的样式可通过config中的theme配置调整 - * - * 2. 性能优化 - * - Widget脚本采用异步加载,不会阻塞页面渲染 - * - 建议在非关键页面(如登录、支付页)隐藏客服 - * - * 3. 错误处理 - * - 如果客服脚本加载失败,不会影响主应用 - * - 建议添加onError回调进行错误监控 - * - * 4. 调试模式 - * - 查看浏览器控制台的[Bytedesk]前缀日志 - * - 检查Network面板确认脚本加载成功 - * - * 5. 生产部署 - * - 确保.env文件配置正确(特别是REACT_APP_BYTEDESK_API_URL) - * - 确保CORS已在后端配置(允许您的前端域名) - * - 在管理后台配置正确的工作组ID(sid) - */ diff --git a/src/bytedesk-integration/config/bytedesk.config.js b/src/bytedesk-integration/config/bytedesk.config.js index 2a433f4b..727123ff 100644 --- a/src/bytedesk-integration/config/bytedesk.config.js +++ b/src/bytedesk-integration/config/bytedesk.config.js @@ -1,27 +1,10 @@ /** * Bytedesk客服配置文件 * 通过代理访问 Bytedesk 服务器(解决 HTTPS 混合内容问题) - * - * 环境变量配置(.env文件): - * REACT_APP_BYTEDESK_ORG=df_org_uid - * REACT_APP_BYTEDESK_SID=df_wg_uid - * - * 架构说明: - * - iframe 使用完整域名:https://valuefrontier.cn/bytedesk/chat/ - * - 使用 HTTPS 协议,解决生产环境 Mixed Content 错误 - * - 本地:CRACO 代理 /bytedesk → valuefrontier.cn/bytedesk - * - 生产:前端 Nginx 代理 /bytedesk → 43.143.189.195 - * - baseUrl 保持官方 CDN(用于加载 SDK 外部模块) - * - * ⚠️ 注意:需要前端 Nginx 配置 /bytedesk/ 代理规则 - */ - -// 从环境变量读取配置 -const BYTEDESK_ORG = process.env.REACT_APP_BYTEDESK_ORG || 'df_org_uid'; -const BYTEDESK_SID = process.env.REACT_APP_BYTEDESK_SID || 'df_wg_uid'; - -/** - * Bytedesk客服基础配置 + - iframe 使用完整域名:https://valuefrontier.cn/bytedesk/chat/ + - 使用 HTTPS 协议,解决生产环境 Mixed Content 错误 + - 生产:前端 Nginx 代理 /bytedesk → 43.143.189.195 + - baseUrl 保持官方 CDN(用于加载 SDK 外部模块) */ export const bytedeskConfig = { // API服务地址(如果 SDK 需要调用 API) @@ -61,9 +44,9 @@ export const bytedeskConfig = { // 聊天配置(必需) chatConfig: { - org: BYTEDESK_ORG, // 组织ID + org: df_org_uid, // 组织ID t: '1', // 类型: 1=人工客服, 2=机器人 - sid: BYTEDESK_SID, // 工作组ID + sid: df_wg_uid, // 工作组ID }, }; @@ -111,45 +94,8 @@ export const getBytedeskConfigWithUser = (user) => { return config; }; -/** - * 根据页面路径判断是否显示客服 - * - * @param {string} pathname - 当前页面路径 - * @returns {boolean} 是否显示客服 - */ -export const shouldShowCustomerService = (pathname) => { - // 在以下页面隐藏客服(黑名单) - const blockedPages = [ - // '/home', // 登录页 - ]; - - // 检查是否在黑名单 - if (blockedPages.some(page => pathname.startsWith(page))) { - return false; - } - - // 默认所有页面都显示客服 - return true; - - /* ============================================ - 白名单模式(备用,需要时取消注释) - ============================================ - const allowedPages = [ - '/', // 首页 - '/home', // 主页 - '/products', // 产品页 - '/pricing', // 价格页 - '/contact', // 联系我们 - ]; - - // 只在白名单页面显示客服 - return allowedPages.some(page => pathname.startsWith(page)); - ============================================ */ -}; - export default { bytedeskConfig, getBytedeskConfig, getBytedeskConfigWithUser, - shouldShowCustomerService, }; diff --git a/src/components/GlobalComponents.js b/src/components/GlobalComponents.js index f6231c23..8ca4e954 100644 --- a/src/components/GlobalComponents.js +++ b/src/components/GlobalComponents.js @@ -14,7 +14,7 @@ import ScrollToTop from './ScrollToTop'; // Bytedesk客服组件 import BytedeskWidget from '../bytedesk-integration/components/BytedeskWidget'; -import { getBytedeskConfig, shouldShowCustomerService } from '../bytedesk-integration/config/bytedesk.config'; +import { getBytedeskConfig } from '../bytedesk-integration/config/bytedesk.config'; /** * ConnectionStatusBar 包装组件 @@ -74,7 +74,6 @@ function ConnectionStatusBarWrapper() { */ export function GlobalComponents() { const location = useLocation(); - const showBytedesk = shouldShowCustomerService(location.pathname); return ( <> @@ -91,12 +90,10 @@ export function GlobalComponents() { {/* Bytedesk在线客服 - 根据路径条件性显示 */} - {showBytedesk && ( - - )} + ); }