- 新增 scriptService 对接话术接口,cs-chat 支持关键词自动回复 - chat-history 增加 waitChatImReady,修复私聊/群聊/客服历史加载 - 恢复 dashouduan/guanshiduan 兼容页跳转 fighter 保留旧二维码 - 商家我的页头像与标签挤压样式优化 Co-authored-by: Cursor <cursoragent@cursor.com>
128 lines
3.5 KiB
JavaScript
128 lines
3.5 KiB
JavaScript
// utils/scriptService.js — 客服话术拉取与自动回复匹配
|
|
import request from './request.js';
|
|
|
|
const DEFAULT_SCRIPTS = {
|
|
chat_image_confirm: {
|
|
title: '温馨提示',
|
|
content: '平台禁止任何违法违规行为,聊天内容仅限于商家与接单员正常业务对接。严禁赌博、诈骗及其他非法行为,违者后果自负。',
|
|
confirm_text: '确认',
|
|
cancel_text: '取消',
|
|
},
|
|
cs_welcome: {
|
|
content: '你好,请问有什么可以帮到您的?',
|
|
},
|
|
};
|
|
|
|
const textCache = {};
|
|
const TEXT_CACHE_TTL = 5 * 60 * 1000;
|
|
|
|
function fitModalBtn(text, fallback) {
|
|
const t = (text || fallback || '确定').trim();
|
|
if (t && t.length <= 4) return t;
|
|
return fallback || '确定';
|
|
}
|
|
|
|
function openConfirmModal(script, onConfirm, onCancel) {
|
|
wx.showModal({
|
|
title: ((script.title || '提示').trim()).slice(0, 32),
|
|
content: script.content || '',
|
|
confirmText: fitModalBtn(script.confirm_text, '确认'),
|
|
cancelText: fitModalBtn(script.cancel_text, '取消'),
|
|
success: (res) => {
|
|
if (res.confirm) onConfirm && onConfirm();
|
|
else onCancel && onCancel();
|
|
},
|
|
fail: () => onCancel && onCancel(),
|
|
});
|
|
}
|
|
|
|
function mergeScript(sceneKey, remote) {
|
|
const base = DEFAULT_SCRIPTS[sceneKey] || {};
|
|
if (!remote) return { ...base };
|
|
return { ...base, ...remote };
|
|
}
|
|
|
|
export async function fetchScripts(sceneKeys) {
|
|
if (!sceneKeys || !sceneKeys.length) return {};
|
|
|
|
const now = Date.now();
|
|
const cached = {};
|
|
const needFetch = [];
|
|
|
|
sceneKeys.forEach((key) => {
|
|
const entry = textCache[key];
|
|
if (entry && now - entry.time < TEXT_CACHE_TTL) {
|
|
cached[key] = entry.data;
|
|
} else {
|
|
needFetch.push(key);
|
|
}
|
|
});
|
|
|
|
if (needFetch.length) {
|
|
try {
|
|
const res = await request({
|
|
url: '/peizhi/huashuhq',
|
|
method: 'POST',
|
|
data: { scene_keys: needFetch },
|
|
});
|
|
const payload = (res && res.data && res.data.code === 200) ? res.data.data || {} : {};
|
|
needFetch.forEach((key) => {
|
|
textCache[key] = { time: now, data: payload[key] };
|
|
cached[key] = payload[key];
|
|
});
|
|
} catch (e) {
|
|
console.warn('fetchScripts failed', e);
|
|
}
|
|
}
|
|
|
|
const result = {};
|
|
sceneKeys.forEach((key) => {
|
|
result[key] = mergeScript(key, cached[key]);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
export async function showConfirmByScene(sceneKey, onConfirm, onCancel) {
|
|
try {
|
|
const data = await fetchScripts([sceneKey]);
|
|
openConfirmModal(data[sceneKey] || mergeScript(sceneKey, null), onConfirm, onCancel);
|
|
} catch (e) {
|
|
openConfirmModal(mergeScript(sceneKey, null), onConfirm, onCancel);
|
|
}
|
|
}
|
|
|
|
export async function matchAutoReply(userText) {
|
|
if (!userText || !userText.trim()) {
|
|
return { matched: false, content: '', reply_type: 'text' };
|
|
}
|
|
try {
|
|
const res = await request({
|
|
url: '/peizhi/huashu_match',
|
|
method: 'POST',
|
|
data: {
|
|
scene_key: 'cs_auto_reply',
|
|
user_text: userText.trim(),
|
|
},
|
|
});
|
|
if (res && res.data && res.data.code === 200 && res.data.data) {
|
|
return res.data.data;
|
|
}
|
|
} catch (e) {
|
|
console.warn('matchAutoReply failed', e);
|
|
}
|
|
return { matched: false, content: '', reply_type: 'text' };
|
|
}
|
|
|
|
export async function getWelcomeText() {
|
|
const data = await fetchScripts(['cs_welcome']);
|
|
const script = data.cs_welcome || DEFAULT_SCRIPTS.cs_welcome;
|
|
return script.content || DEFAULT_SCRIPTS.cs_welcome.content;
|
|
}
|
|
|
|
export default {
|
|
fetchScripts,
|
|
showConfirmByScene,
|
|
matchAutoReply,
|
|
getWelcomeText,
|
|
};
|