chore:ai智能客服可以正常对话
This commit is contained in:
@@ -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
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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请求地址
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ export default {
|
|||||||
// 是否启用流式响应
|
// 是否启用流式响应
|
||||||
enableStreaming: {
|
enableStreaming: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: false
|
||||||
},
|
},
|
||||||
// 流式响应速度(字符/秒)
|
// 流式响应速度(字符/秒)
|
||||||
streamSpeed: {
|
streamSpeed: {
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user