feat: 调整客服配置
This commit is contained in:
@@ -1,13 +1,6 @@
|
|||||||
# ========================================
|
# ========================================
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
# ========================================
|
# ========================================
|
||||||
# 使用方式: npm run build
|
|
||||||
#
|
|
||||||
# 工作原理:
|
|
||||||
# 1. 此文件专门用于生产环境构建
|
|
||||||
# 2. 构建时会将环境变量嵌入到打包文件中
|
|
||||||
# 3. 确保 PostHog 等服务使用正确的生产配置
|
|
||||||
# ========================================
|
|
||||||
|
|
||||||
# 环境标识
|
# 环境标识
|
||||||
REACT_APP_ENV=production
|
REACT_APP_ENV=production
|
||||||
@@ -17,13 +10,8 @@ NODE_ENV=production
|
|||||||
REACT_APP_ENABLE_MOCK=false
|
REACT_APP_ENABLE_MOCK=false
|
||||||
|
|
||||||
# 🔧 调试模式(生产环境临时调试用)
|
# 🔧 调试模式(生产环境临时调试用)
|
||||||
# 开启后会在全局暴露 window.__DEBUG__ 和 window.__TEST_NOTIFICATION__ 调试 API
|
# 开启后会在全局暴露 window.__DEBUG__
|
||||||
# ⚠️ 警告: 调试模式会记录所有 API 请求/响应,调试完成后请立即关闭!
|
REACT_APP_ENABLE_DEBUG=false
|
||||||
# 使用方法:
|
|
||||||
# 1. 设置为 true 并重新构建
|
|
||||||
# 2. 在浏览器控制台使用 window.__DEBUG__.help() 查看命令
|
|
||||||
# 3. 调试完成后设置为 false 并重新构建
|
|
||||||
REACT_APP_ENABLE_DEBUG=true
|
|
||||||
|
|
||||||
# 后端 API 地址(生产环境)
|
# 后端 API 地址(生产环境)
|
||||||
REACT_APP_API_URL=http://49.232.185.254:5001
|
REACT_APP_API_URL=http://49.232.185.254:5001
|
||||||
@@ -49,20 +37,3 @@ TSC_COMPILE_ON_ERROR=true
|
|||||||
IMAGE_INLINE_SIZE_LIMIT=10000
|
IMAGE_INLINE_SIZE_LIMIT=10000
|
||||||
# Node.js 内存限制(适用于大型项目)
|
# Node.js 内存限制(适用于大型项目)
|
||||||
NODE_OPTIONS=--max_old_space_size=4096
|
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
|
|
||||||
|
|||||||
@@ -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 (
|
|
||||||
<div className="App">
|
|
||||||
{/* ========== vf_react原有内容保持不变 ========== */}
|
|
||||||
{/* 这里是您原有的App.jsx JSX代码 */}
|
|
||||||
{/* 例如: <Header /> */}
|
|
||||||
{/* 例如: <Router> <Routes> ... </Routes> </Router> */}
|
|
||||||
{/* ... 保持原有结构不变 ... */}
|
|
||||||
|
|
||||||
{/* ========== Bytedesk客服Widget ========== */}
|
|
||||||
{showBytedesk && (
|
|
||||||
<BytedeskWidget
|
|
||||||
config={bytedeskConfig}
|
|
||||||
autoLoad={true}
|
|
||||||
onLoad={handleBytedeskLoad}
|
|
||||||
onError={handleBytedeskError}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<div className="App">
|
|
||||||
// ... 您的原有代码 ...
|
|
||||||
|
|
||||||
{showBytedesk && (
|
|
||||||
<BytedeskWidget
|
|
||||||
config={bytedeskConfig}
|
|
||||||
autoLoad={true}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<div className="App">
|
|
||||||
// ... 您的原有代码 ...
|
|
||||||
|
|
||||||
{showBytedesk && (
|
|
||||||
<BytedeskWidget
|
|
||||||
config={bytedeskConfig}
|
|
||||||
autoLoad={true}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<div className="App">
|
|
||||||
// ... 您的原有代码 ...
|
|
||||||
|
|
||||||
{/* 自定义客服按钮 *\/}
|
|
||||||
<button onClick={toggleBytedesk} className="custom-service-button">
|
|
||||||
{showBytedesk ? '关闭客服' : '联系客服'}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* 客服Widget *\/}
|
|
||||||
{showBytedesk && (
|
|
||||||
<BytedeskWidget
|
|
||||||
config={bytedeskConfig}
|
|
||||||
autoLoad={true}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
*/
|
|
||||||
@@ -1,27 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* Bytedesk客服配置文件
|
* Bytedesk客服配置文件
|
||||||
* 通过代理访问 Bytedesk 服务器(解决 HTTPS 混合内容问题)
|
* 通过代理访问 Bytedesk 服务器(解决 HTTPS 混合内容问题)
|
||||||
*
|
- iframe 使用完整域名:https://valuefrontier.cn/bytedesk/chat/
|
||||||
* 环境变量配置(.env文件):
|
- 使用 HTTPS 协议,解决生产环境 Mixed Content 错误
|
||||||
* REACT_APP_BYTEDESK_ORG=df_org_uid
|
- 生产:前端 Nginx 代理 /bytedesk → 43.143.189.195
|
||||||
* REACT_APP_BYTEDESK_SID=df_wg_uid
|
- baseUrl 保持官方 CDN(用于加载 SDK 外部模块)
|
||||||
*
|
|
||||||
* 架构说明:
|
|
||||||
* - 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客服基础配置
|
|
||||||
*/
|
*/
|
||||||
export const bytedeskConfig = {
|
export const bytedeskConfig = {
|
||||||
// API服务地址(如果 SDK 需要调用 API)
|
// API服务地址(如果 SDK 需要调用 API)
|
||||||
@@ -61,9 +44,9 @@ export const bytedeskConfig = {
|
|||||||
|
|
||||||
// 聊天配置(必需)
|
// 聊天配置(必需)
|
||||||
chatConfig: {
|
chatConfig: {
|
||||||
org: BYTEDESK_ORG, // 组织ID
|
org: df_org_uid, // 组织ID
|
||||||
t: '1', // 类型: 1=人工客服, 2=机器人
|
t: '1', // 类型: 1=人工客服, 2=机器人
|
||||||
sid: BYTEDESK_SID, // 工作组ID
|
sid: df_wg_uid, // 工作组ID
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,45 +94,8 @@ export const getBytedeskConfigWithUser = (user) => {
|
|||||||
return config;
|
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 {
|
export default {
|
||||||
bytedeskConfig,
|
bytedeskConfig,
|
||||||
getBytedeskConfig,
|
getBytedeskConfig,
|
||||||
getBytedeskConfigWithUser,
|
getBytedeskConfigWithUser,
|
||||||
shouldShowCustomerService,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import ScrollToTop from './ScrollToTop';
|
|||||||
|
|
||||||
// Bytedesk客服组件
|
// Bytedesk客服组件
|
||||||
import BytedeskWidget from '../bytedesk-integration/components/BytedeskWidget';
|
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 包装组件
|
* ConnectionStatusBar 包装组件
|
||||||
@@ -74,7 +74,6 @@ function ConnectionStatusBarWrapper() {
|
|||||||
*/
|
*/
|
||||||
export function GlobalComponents() {
|
export function GlobalComponents() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const showBytedesk = shouldShowCustomerService(location.pathname);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -91,12 +90,10 @@ export function GlobalComponents() {
|
|||||||
<NotificationContainer />
|
<NotificationContainer />
|
||||||
|
|
||||||
{/* Bytedesk在线客服 - 根据路径条件性显示 */}
|
{/* Bytedesk在线客服 - 根据路径条件性显示 */}
|
||||||
{showBytedesk && (
|
<BytedeskWidget
|
||||||
<BytedeskWidget
|
config={getBytedeskConfig()}
|
||||||
config={getBytedeskConfig()}
|
autoLoad={true}
|
||||||
autoLoad={true}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user