chore:ai智能客服可以正常对话

This commit is contained in:
2025-12-08 17:16:10 +08:00
parent 4cf19e417f
commit 7dbf455341
6 changed files with 55 additions and 63 deletions

View File

@@ -11,14 +11,16 @@ export default {
async sendMessage(message, options = {}) { async sendMessage(message, options = {}) {
try { try {
// 获取AI配置 // 获取AI配置
const aiConfig = store.getters.globalAIAgentConfig const aiConfig = store.getters.globalAIKefuConfig
// const new_conversationId = await this.generateConversationId()
// 构建Dify API请求参数 // 构建Dify API请求参数
const params = { const params = {
url: '/api/ai/chat', // 后端代理接口 url: '/api/kefu/chat', // 后端代理接口
data: { data: {
message: message, message: message,
conversation_id: options.conversationId || this.generateConversationId(), // conversation_id: options.conversationId ?? new_conversationId,
user_id: store.state.memberInfo?.id || 'anonymous', user_id: store.state.memberInfo?.id || 'anonymous',
stream: options.stream || false, // 是否流式响应 stream: options.stream || false, // 是否流式响应
// Dify API参数 // Dify API参数
@@ -32,15 +34,6 @@ export default {
} }
} }
// 如果有Dify配置添加API密钥
if (aiConfig?.difyApiKey) {
params.header['Authorization'] = `Bearer ${aiConfig.difyApiKey}`
}
if (aiConfig?.difyBaseUrl) {
params.header['X-Dify-Url'] = aiConfig.difyBaseUrl
}
// 发送请求 // 发送请求
const response = await http.sendRequest({ const response = await http.sendRequest({
...params, ...params,
@@ -63,20 +56,8 @@ export default {
*/ */
async sendStreamMessage(message, onChunk, onComplete) { async sendStreamMessage(message, onChunk, onComplete) {
try { try {
const aiConfig = store.getters.globalAIAgentConfig
// 检查配置
if (!aiConfig?.difyBaseUrl || !aiConfig?.difyApiKey) {
throw new Error('未配置Dify服务')
}
// 创建WebSocket连接或使用Server-Sent Events
if (aiConfig?.difyWsUrl) {
return this.connectWebSocket(message, onChunk, onComplete)
} else {
// 使用HTTP流式请求 // 使用HTTP流式请求
return this.sendHttpStream(message, onChunk, onComplete) return this.sendHttpStream(message, onChunk, onComplete)
}
} catch (error) { } catch (error) {
console.error('流式消息发送失败:', error) console.error('流式消息发送失败:', error)
@@ -89,7 +70,7 @@ export default {
*/ */
connectWebSocket(message, onChunk, onComplete) { connectWebSocket(message, onChunk, onComplete) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const aiConfig = store.getters.globalAIAgentConfig const aiConfig = store.getters.globalAIKefuConfig
const wsUrl = aiConfig.difyWsUrl const wsUrl = aiConfig.difyWsUrl
if (!wsUrl) { if (!wsUrl) {
@@ -181,10 +162,10 @@ export default {
* HTTP流式请求 * HTTP流式请求
*/ */
async sendHttpStream(message, onChunk, onComplete) { async sendHttpStream(message, onChunk, onComplete) {
const aiConfig = store.getters.globalAIAgentConfig const aiConfig = store.getters.globalAIKefuConfig
const params = { const params = {
url: '/api/ai/chat-stream', url: '/api/kefu/chat-stream',
data: { data: {
message: message, message: message,
conversation_id: this.generateConversationId(), conversation_id: this.generateConversationId(),
@@ -203,11 +184,10 @@ export default {
// 使用fetch API进行流式请求H5环境 // 使用fetch API进行流式请求H5环境
// #ifdef H5 // #ifdef H5
try { try {
const response = await fetch(`${aiConfig.difyBaseUrl}/chat-messages`, { const response = await fetch(`/api/kefu/chat-messages`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': `Bearer ${aiConfig.difyApiKey}`
}, },
body: JSON.stringify({ body: JSON.stringify({
inputs: {}, inputs: {},
@@ -286,7 +266,7 @@ export default {
if (response.code === 0 || response.success) { if (response.code === 0 || response.success) {
return { return {
success: true, success: true,
content: response.data?.answer || response.data?.content || response.data, content: response.data?.answer || response.data?.content || response.data?.reply|| response.data,
conversationId: response.data?.conversation_id, conversationId: response.data?.conversation_id,
messageId: response.data?.message_id messageId: response.data?.message_id
} }
@@ -298,8 +278,27 @@ export default {
/** /**
* 生成会话ID * 生成会话ID
*/ */
generateConversationId() { async generateConversationId() {
return 'conv_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9) // 构建Dify API请求参数
const params = {
url: '/api/kefu/createConversation', // 后端代理接口
data: {
uniacid: store.state.uniacid,
user_id: store.state.memberInfo?.id || 'anonymous',
member_id: store.state.memberInfo?.id || '',
},
header: {
'Content-Type': 'application/json'
}
}
// 发送请求
const response = await http.sendRequest({
...params,
async: false // 使用Promise方式
})
return this.handleResponse(response, options)
}, },
/** /**
@@ -307,24 +306,17 @@ export default {
*/ */
async getServiceStatus() { async getServiceStatus() {
try { try {
const aiConfig = store.getters.globalAIAgentConfig
if (!aiConfig?.difyBaseUrl || !aiConfig?.difyApiKey) {
return {
available: false,
reason: '未配置Dify服务'
}
}
// 简单的健康检查 // 简单的健康检查
const response = await http.sendRequest({ const response = await http.sendRequest({
url: '/api/ai/health', url: '/api/kefu/health',
async: false async: false
}) })
const available = response?.data?.status === 'healthy';
return { return {
available: response.success, available,
reason: response.success ? '服务正常' : '服务异常' reason: available ? '服务正常' : '服务异常'
} }
} catch (error) { } catch (error) {
@@ -341,7 +333,7 @@ export default {
async clearConversation(conversationId) { async clearConversation(conversationId) {
try { try {
const response = await http.sendRequest({ const response = await http.sendRequest({
url: '/api/ai/clear-conversation', url: '/api/kefu/clear-conversation',
data: { conversation_id: conversationId }, data: { conversation_id: conversationId },
async: false async: false
}) })

View File

@@ -14,18 +14,18 @@ try {
// 调试版本,配置说明 // 调试版本,配置说明
const devCfg = { const devCfg = {
// 商户ID // 商户ID
uniacid: 460, //825 uniacid: 1, //825
//api请求地址 //api请求地址
baseUrl: 'https://xcx30.5g-quickapp.com/', baseUrl: 'https://dev.aigc-quickapp.com/',
// baseUrl: 'http://localhost:8010/', // baseUrl: 'http://localhost:8010/',
// 图片域名 // 图片域名
imgDomain: 'https://xcx30.5g-quickapp.com/', imgDomain: 'https://dev.aigc-quickapp.com/',
//imgDomain: 'http://localhost:8010/', //imgDomain: 'http://localhost:8010/',
// H5端域名 // H5端域名
h5Domain: 'https://xcx30.5g-quickapp.com/', h5Domain: 'https://dev.aigc-quickapp.com/',
// h5Domain: 'http://localhost:8010/', // h5Domain: 'http://localhost:8010/',
// // api请求地址 // // api请求地址

View File

@@ -313,7 +313,7 @@ export default {
// 是否启用流式响应 // 是否启用流式响应
enableStreaming: { enableStreaming: {
type: Boolean, type: Boolean,
default: true default: false
}, },
// 流式响应速度(字符/秒) // 流式响应速度(字符/秒)
streamSpeed: { streamSpeed: {

View File

@@ -5,7 +5,7 @@
<!-- AI智能助手 --> <!-- AI智能助手 -->
<view class="btn-item" v-if="fixBtnShow && enableAIChat" @click="openAIChat" :style="{backgroundImage:'url('+(aiAgentimg?aiAgentimg:'')+')',backgroundSize:'100% 100%'}"> <view class="btn-item" v-if="fixBtnShow && enableAIChat" @click="openAIChat" :style="{backgroundImage:'url('+(aiAgentimg?aiAgentimg:'')+')',backgroundSize:'100% 100%'}">
<text class="ai-icon" v-if="!aiAgentimg">🤖</text> <text class="ai-icon" v-if="!aiAgentimg"></text>
<!-- 未读消息小红点 --> <!-- 未读消息小红点 -->
<view v-if="unreadCount > 0" class="unread-badge"> <view v-if="unreadCount > 0" class="unread-badge">
<text class="badge-text">{{ unreadCount > 99 ? '99+' : unreadCount }}</text> <text class="badge-text">{{ unreadCount > 99 ? '99+' : unreadCount }}</text>
@@ -73,17 +73,17 @@
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
'globalAIAgentConfig', 'globalAIKefuConfig',
'aiUnreadCount' 'aiUnreadCount'
]), ]),
aiAgentimg() { aiAgentimg() {
return this.globalAIAgentConfig?.icon || this.$util.getDefaultImage().aiAgent || '' // AI智能助手的头像 return this.globalAIKefuConfig?.icon || this.$util.getDefaultImage().aiAgent || '' // AI智能助手的头像
}, },
unreadCount() { unreadCount() {
return this.aiUnreadCount return this.aiUnreadCount
}, },
enableAIChat() { enableAIChat() {
return this.globalAIAgentConfig?.enable || true // 是否开启AI智能助手 return this.globalAIKefuConfig?.enable || true // 是否开启AI智能助手
}, },
}, },
methods: { methods: {

View File

@@ -89,15 +89,15 @@ export default {
computed: { computed: {
...mapGetters([ ...mapGetters([
'globalAIAgentConfig' 'globalAIKefuConfig'
]), ]),
/// ---- 关于AI客服的配置支持远程配置 ---- /// ---- 关于AI客服的配置支持远程配置 ----
userAvatar() { userAvatar() {
return this.globalAIAgentConfig?.userAvatar || '/static/images/user-avatar.png' return this.globalAIKefuConfig?.userAvatar || '/static/images/user-avatar.png'
}, },
aiAvatar() { aiAvatar() {
return this.globalAIAgentConfig?.aiAvatar || '/static/images/ai-avatar.png' return this.globalAIKefuConfig?.aiAvatar || '/static/images/ai-avatar.png'
}, },
/// ---- others ---- /// ---- others ----
containerHeight() { containerHeight() {

View File

@@ -60,7 +60,7 @@ const store = new Vuex.Store({
cartChange: 0, cartChange: 0,
bottomNavHidden: false, // 底部导航是否隐藏true隐藏false显示 bottomNavHidden: false, // 底部导航是否隐藏true隐藏false显示
aiUnreadCount: 10, // AI未读消息数量 aiUnreadCount: 10, // AI未读消息数量
globalAIAgentConfig: null, // AI客服配置 globalAIKefuConfig: null, // AI客服配置
globalStoreConfig: null, // 门店配置 globalStoreConfig: null, // 门店配置
globalStoreInfo: null, // 门店信息 globalStoreInfo: null, // 门店信息
defaultStoreInfo: null, // 默认门店 defaultStoreInfo: null, // 默认门店
@@ -140,9 +140,9 @@ const store = new Vuex.Store({
setBottomNavHidden(state, value) { setBottomNavHidden(state, value) {
state.bottomNavHidden = value; state.bottomNavHidden = value;
}, },
setGlobalAIAgentConfig(state, value) { setglobalAIKefuConfig(state, value) {
state.globalAIAgentConfig = value; state.globalAIKefuConfig = value;
uni.setStorageSync('globalAIAgentConfig', value); // 初始化数据调用 uni.setStorageSync('globalAIKefuConfig', value); // 初始化数据调用
}, },
setGlobalStoreConfig(state, value) { setGlobalStoreConfig(state, value) {
state.globalStoreConfig = value; state.globalStoreConfig = value;
@@ -208,7 +208,7 @@ const store = new Vuex.Store({
}, },
getters: { getters: {
// AI智能助手配置 // AI智能助手配置
globalAIAgentConfig: state => state.globalAIAgentConfig, globalAIKefuConfig: state => state.globalAIKefuConfig,
// AI未读消息数量 // AI未读消息数量
aiUnreadCount: state => state.aiUnreadCount, aiUnreadCount: state => state.aiUnreadCount,
}, },
@@ -237,7 +237,7 @@ const store = new Vuex.Store({
this.commit('setMapConfig', data.map_config); this.commit('setMapConfig', data.map_config);
this.commit('setGlobalAIAgentConfig', data.ai_agent_config); this.commit('setglobalAIKefuConfig', data.ai_agent_config);
this.commit('setGlobalStoreConfig', data.store_config); this.commit('setGlobalStoreConfig', data.store_config);