feat(api): 添加电话接通率API接口
refactor(cache): 将缓存系统重构为独立模块并添加测试页面 fix: 修复客户详情中电话接通率显示格式问题 refactor: 移除各页面中的缓存逻辑,统一使用缓存store feat: 在客户详情中添加通话分析API调用 fix: 修正导出客户API的URL路径 chore: 更新开发环境配置注释
This commit is contained in:
@@ -94,6 +94,7 @@
|
||||
import { ref, watch, computed } from 'vue';
|
||||
import { SimpleChatService } from '@/utils/ChatService.js';
|
||||
import MarkdownIt from 'markdown-it';
|
||||
import https from '@/utils/https'
|
||||
|
||||
// 定义props
|
||||
const props = defineProps({
|
||||
@@ -115,6 +116,7 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
console.log(999999999,props.selectedContact);
|
||||
// 分析结果状态
|
||||
const basicAnalysisResult = ref(''); // 基础信息分析结果
|
||||
const sopAnalysisResult = ref(''); // SOP通话分析结果
|
||||
@@ -349,16 +351,20 @@ ${callData.length > 0 && callData[0].record_context ? callData[0].record_context
|
||||
|
||||
|
||||
try {
|
||||
await chatService.sendMessage(
|
||||
query,
|
||||
(update) => {
|
||||
sopAnalysisResult.value = update.content;
|
||||
},
|
||||
() => {
|
||||
isSopAnalysisLoading.value = false;
|
||||
console.log('SOP通话分析完成');
|
||||
}
|
||||
);
|
||||
// await chatService.sendMessage(
|
||||
// query,
|
||||
// (update) => {
|
||||
// sopAnalysisResult.value = update.content;
|
||||
// },
|
||||
// () => {
|
||||
// isSopAnalysisLoading.value = false;
|
||||
// console.log('SOP通话分析完成');
|
||||
// }
|
||||
// );
|
||||
const res= await https.get('http://192.168.3.112:6002/api/v1/call',{
|
||||
wechat_id:props.selectedContact.wechat_id
|
||||
})
|
||||
sopAnalysisResult.value = res.data.report_content;
|
||||
} catch (error) {
|
||||
console.error('SOP通话分析失败:', error);
|
||||
sopAnalysisResult.value = `分析失败: ${error.message}`;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<p>今日通话 <i class="info-icon" @mouseenter="showTooltip('totalCalls', $event)" @mouseleave="hideTooltip">ⓘ</i></p>
|
||||
</div>
|
||||
<div class="kpi-item">
|
||||
<div class="kpi-value">{{ props.kpiData.successRate }}%</div>
|
||||
<div class="kpi-value">{{ props.kpiData.successRate }}</div>
|
||||
<p>电话接通率 <i class="info-icon" @mouseenter="showTooltip('successRate', $event)" @mouseleave="hideTooltip">ⓘ</i></p>
|
||||
</div>
|
||||
<div class="kpi-item">
|
||||
|
||||
@@ -142,64 +142,8 @@ import UserDropdown from "@/components/UserDropdown.vue";
|
||||
import Loading from "@/components/Loading.vue";
|
||||
import {getCustomerAttendance,getTodayCall,getProblemDistribution,getTableFillingRate,getAverageResponseTime,
|
||||
getWeeklyActiveCommunicationRate,getTimeoutResponseRate,getCustomerCallInfo,getCustomerChatInfo,getCustomerFormInfo,
|
||||
getConversionRateAndAllocatedData,getCustomerAttendanceAfterClass4,getPayMoneyCustomers,getSalesFunnel,getGoldContactTime,getAvgCallTime} from "@/api/api.js"
|
||||
|
||||
// 缓存系统
|
||||
const cache = new Map();
|
||||
const CACHE_DURATION = 30 * 60 * 1000; // 30分钟缓存时长
|
||||
|
||||
// 生成缓存键
|
||||
const getCacheKey = (apiName, params = {}) => {
|
||||
const sortedParams = Object.keys(params)
|
||||
.sort()
|
||||
.reduce((result, key) => {
|
||||
result[key] = params[key];
|
||||
return result;
|
||||
}, {});
|
||||
return `${apiName}_${JSON.stringify(sortedParams)}`;
|
||||
};
|
||||
|
||||
// 检查缓存是否有效
|
||||
const isValidCache = (cacheData) => {
|
||||
return cacheData && (Date.now() - cacheData.timestamp) < CACHE_DURATION;
|
||||
};
|
||||
|
||||
// 设置缓存
|
||||
const setCache = (key, data) => {
|
||||
cache.set(key, {
|
||||
data,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
};
|
||||
|
||||
// 获取缓存
|
||||
const getCache = (key) => {
|
||||
const cacheData = cache.get(key);
|
||||
if (isValidCache(cacheData)) {
|
||||
return cacheData.data;
|
||||
}
|
||||
// 如果缓存过期,删除它
|
||||
if (cacheData) {
|
||||
cache.delete(key);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// 缓存包装器函数
|
||||
const withCache = async (apiName, apiFunction, params = {}) => {
|
||||
const cacheKey = getCacheKey(apiName, params);
|
||||
const cachedData = getCache(cacheKey);
|
||||
|
||||
if (cachedData) {
|
||||
console.log(`[缓存命中] ${apiName}:`, cachedData);
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
console.log(`[API调用] ${apiName}`);
|
||||
const result = await apiFunction(params);
|
||||
setCache(cacheKey, result);
|
||||
return result;
|
||||
};
|
||||
getConversionRateAndAllocatedData,getCustomerAttendanceAfterClass4,getPayMoneyCustomers,getSalesFunnel,getGoldContactTime,
|
||||
getAvgCallTime,getCallSuccessRate} from "@/api/api.js"
|
||||
|
||||
// 路由实例
|
||||
const router = useRouter();
|
||||
@@ -220,7 +164,6 @@ const getRequestParams = () => {
|
||||
if (routeUserName) {
|
||||
params.user_name = routeUserName
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
@@ -329,6 +272,8 @@ const formInfo = ref({});
|
||||
const callRecords = ref([]);
|
||||
// 聊天记录
|
||||
const chatRecords = ref([]);
|
||||
// 电话接通率
|
||||
const callSuccessRate = ref(0)
|
||||
|
||||
// MOCK DATA (Should ideally come from a store or API)
|
||||
const MOCK_DATA = reactive({
|
||||
@@ -366,24 +311,27 @@ async function getCoreKpi() {
|
||||
const hasParams = params.user_name
|
||||
|
||||
// 今日通话数据
|
||||
const res = await withCache('getTodayCall', () => getTodayCall(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const res = await getTodayCall(hasParams ? params : undefined)
|
||||
if (res.code === 200) {
|
||||
kpiDataState.totalCalls = res.data.today_call
|
||||
}
|
||||
|
||||
// 转化率、分配数据量、加微率
|
||||
const conversionRes = await withCache('getConversionRateAndAllocatedData', () => getConversionRateAndAllocatedData(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const conversionRes = await getConversionRateAndAllocatedData(hasParams ? params : undefined)
|
||||
if (conversionRes.code === 200) {
|
||||
kpiDataState.conversionRate = conversionRes.data.conversion_rate || 0
|
||||
kpiDataState.assignedData = conversionRes.data.all_count || 0
|
||||
kpiDataState.wechatAddRate = conversionRes.data.plus_v_conversion_rate || 0
|
||||
}
|
||||
|
||||
}
|
||||
// 平均通话时长
|
||||
const avgCallTimeRes = await withCache('getAvgCallTime', () => getAvgCallTime(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const avgCallTimeRes = await getAvgCallTime(hasParams ? params : undefined)
|
||||
if (avgCallTimeRes.code === 200) {
|
||||
kpiDataState.avgDuration = avgCallTimeRes.data.call_time || 0
|
||||
}
|
||||
// 电话接通率
|
||||
const callSuccessRateRes = await getCallSuccessRate(hasParams ? params : undefined)
|
||||
if (callSuccessRateRes.code === 200) {
|
||||
kpiDataState.successRate = callSuccessRateRes.data.call_success_rate || 0
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取核心KPI数据失败:', error)
|
||||
} finally {
|
||||
@@ -398,25 +346,25 @@ async function getStatisticsData() {
|
||||
const hasParams = params.user_name
|
||||
|
||||
// 获取表单填写率
|
||||
const fillingRateRes = await withCache('getTableFillingRate', () => getTableFillingRate(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const fillingRateRes = await getTableFillingRate(hasParams ? params : undefined)
|
||||
if (fillingRateRes.code === 200) {
|
||||
statisticsData.formCompletionRate = fillingRateRes.data.filling_rate
|
||||
}
|
||||
|
||||
// 获取平均响应时间
|
||||
const avgResponseRes = await withCache('getAverageResponseTime', () => getAverageResponseTime(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const avgResponseRes = await getAverageResponseTime(hasParams ? params : undefined)
|
||||
if (avgResponseRes.code === 200) {
|
||||
statisticsData.averageResponseTime = avgResponseRes.data.average_minutes
|
||||
}
|
||||
|
||||
// 获取客户沟通率
|
||||
const communicationRes = await withCache('getWeeklyActiveCommunicationRate', () => getWeeklyActiveCommunicationRate(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const communicationRes = await getWeeklyActiveCommunicationRate(hasParams ? params : undefined)
|
||||
if (communicationRes.code === 200) {
|
||||
statisticsData.customerCommunicationRate = communicationRes.data.communication_rate
|
||||
}
|
||||
|
||||
// 获取超时响应率
|
||||
const timeoutRes = await withCache('getTimeoutResponseRate', () => getTimeoutResponseRate(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const timeoutRes = await getTimeoutResponseRate(hasParams ? params : undefined)
|
||||
if (timeoutRes.code === 200) {
|
||||
statisticsData.timeoutResponseRate = timeoutRes.data.overtime_rate_600
|
||||
statisticsData.severeTimeoutRate = timeoutRes.data.overtime_rate_800
|
||||
@@ -434,7 +382,7 @@ async function getUrgentProblem() {
|
||||
const params = getRequestParams()
|
||||
const hasParams = params.user_name
|
||||
|
||||
const res = await withCache('getProblemDistribution', () => getProblemDistribution(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const res = await getProblemDistribution(hasParams ? params : undefined)
|
||||
if(res.code === 200) {
|
||||
// 将API返回的对象格式转换为数组格式
|
||||
const problemDistributionCount = res.data.problem_distribution_count
|
||||
@@ -453,7 +401,7 @@ async function getTimeline() {
|
||||
const params = getRequestParams()
|
||||
const hasParams = params.user_name
|
||||
// 前6个阶段
|
||||
const res = await withCache('getCustomerAttendance', () => getCustomerAttendance(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const res = await getCustomerAttendance(hasParams ? params : undefined)
|
||||
if(res.code === 200) {
|
||||
// 处理时间线数据
|
||||
if (res.data.timeline) {
|
||||
@@ -471,7 +419,7 @@ async function getTimeline() {
|
||||
}
|
||||
}
|
||||
// 后4个阶段
|
||||
const classRes = await withCache('getCustomerAttendanceAfterClass4', () => getCustomerAttendanceAfterClass4(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const classRes = await getCustomerAttendanceAfterClass4(hasParams ? params : undefined)
|
||||
if(classRes.code === 200) {
|
||||
// 处理课1-4阶段的客户数据
|
||||
if (classRes.data.class_customers_list) {
|
||||
@@ -547,7 +495,7 @@ async function getTimeline() {
|
||||
}
|
||||
}
|
||||
// 成交阶段
|
||||
const payRes = await withCache('getPayMoneyCustomers', () => getPayMoneyCustomers(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const payRes = await getPayMoneyCustomers(hasParams ? params : undefined)
|
||||
if(payRes.code === 200) {
|
||||
// 处理成交阶段的客户数据
|
||||
if (payRes.data.pay_money_customers_list) {
|
||||
@@ -577,7 +525,7 @@ async function getCustomerForm() {
|
||||
customer_name: selectedContact.value.name,
|
||||
}
|
||||
try {
|
||||
const res = await withCache('getCustomerFormInfo', () => getCustomerFormInfo(params), params)
|
||||
const res = await getCustomerFormInfo(params)
|
||||
if(res.code === 200) {
|
||||
formInfo.value = res.data
|
||||
}
|
||||
@@ -596,7 +544,7 @@ async function getCustomerChat() {
|
||||
customer_name: selectedContact.value.name,
|
||||
}
|
||||
try {
|
||||
const res = await withCache('getCustomerChatInfo', () => getCustomerChatInfo(params), params)
|
||||
const res = await getCustomerChatInfo(params)
|
||||
if(res.code === 200) {
|
||||
chatRecords.value = res.data
|
||||
} else {
|
||||
@@ -617,7 +565,7 @@ async function getCustomerCall() {
|
||||
customer_name: selectedContact.value.name,
|
||||
}
|
||||
try {
|
||||
const res = await withCache('getCustomerCallInfo', () => getCustomerCallInfo(params), params)
|
||||
const res = await getCustomerCallInfo(params)
|
||||
if(res.code === 200) {
|
||||
callRecords.value = res.data
|
||||
console.log('Call Records Data from API:', res.data)
|
||||
@@ -631,6 +579,7 @@ async function getCustomerCall() {
|
||||
const kpiData = computed(() => kpiDataState);
|
||||
// COMPUTED PROPERTIES
|
||||
const selectedContact = computed(() => {
|
||||
console.log(999999999,formattedCustomersList.value);
|
||||
// 优先从API数据中查找
|
||||
if (formattedCustomersList.value.length > 0) {
|
||||
return formattedCustomersList.value.find((c) => c.id === selectedContactId.value) || null;
|
||||
@@ -672,6 +621,7 @@ const formattedCustomersList = computed(() => {
|
||||
}
|
||||
|
||||
return customersList.value?.map(customer => ({
|
||||
wechat_id: customer.customer_wechat_id,
|
||||
id: customer.customer_name, // 使用客户姓名作为唯一标识
|
||||
name: customer.customer_name,
|
||||
phone: customer.phone,
|
||||
@@ -871,7 +821,7 @@ const SalesFunnel = ref([])
|
||||
async function CenterGetSalesFunnel() {
|
||||
const params = getRequestParams()
|
||||
const hasParams = params.user_name
|
||||
const res = await withCache('getSalesFunnel', () => getSalesFunnel(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const res = await getSalesFunnel(hasParams ? params : undefined)
|
||||
if(res.code === 200){
|
||||
SalesFunnel.value = res.data
|
||||
/**
|
||||
@@ -894,56 +844,15 @@ const goldContactTime = ref([])
|
||||
async function CenterGetGoldContactTime() {
|
||||
const params = getRequestParams()
|
||||
const hasParams = params.user_name
|
||||
const res = await withCache('getGoldContactTime', () => getGoldContactTime(hasParams ? params : undefined), hasParams ? params : {})
|
||||
const res = await getGoldContactTime(hasParams ? params : undefined)
|
||||
if(res.code === 200){
|
||||
goldContactTime.value = res.data
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存管理功能
|
||||
// 清除所有缓存
|
||||
function clearCache() {
|
||||
cache.clear()
|
||||
}
|
||||
|
||||
// 清除特定缓存
|
||||
function clearSpecificCache(apiName, params = {}) {
|
||||
const key = getCacheKey(apiName, params)
|
||||
cache.delete(key)
|
||||
console.log(`已清除缓存: ${key}`)
|
||||
}
|
||||
|
||||
// 获取缓存信息并清理过期缓存
|
||||
function getCacheInfo() {
|
||||
const now = Date.now()
|
||||
const validCaches = []
|
||||
const expiredCaches = []
|
||||
|
||||
for (const [key, data] of cache.entries()) {
|
||||
if (isValidCache(data)) {
|
||||
validCaches.push({
|
||||
key,
|
||||
timestamp: data.timestamp,
|
||||
age: Math.round((now - data.timestamp) / 1000) + 's'
|
||||
})
|
||||
} else {
|
||||
expiredCaches.push(key)
|
||||
cache.delete(key)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
validCount: validCaches.length,
|
||||
expiredCount: expiredCaches.length,
|
||||
validCaches,
|
||||
expiredCaches
|
||||
}
|
||||
}
|
||||
|
||||
// 强制刷新所有数据(清除缓存并重新调用所有API)
|
||||
// 强制刷新所有数据(重新调用所有API)
|
||||
async function forceRefreshAllData() {
|
||||
console.log('开始强制刷新所有数据...')
|
||||
clearCache()
|
||||
|
||||
// 重新调用所有API
|
||||
await Promise.all([
|
||||
@@ -951,7 +860,6 @@ async function forceRefreshAllData() {
|
||||
getStatisticsData(),
|
||||
getUrgentProblem(),
|
||||
getTimeline(),
|
||||
getCustomerPayMoney(),
|
||||
CenterGetSalesFunnel(),
|
||||
CenterGetGoldContactTime(),
|
||||
// 客户相关数据需要在选中客户后才能获取
|
||||
@@ -975,19 +883,11 @@ onMounted(async () => {
|
||||
await getUrgentProblem()
|
||||
await getCustomerCall()
|
||||
await getTimeline()
|
||||
await getCustomerPayMoney()
|
||||
|
||||
// 输出初始缓存信息
|
||||
getCacheInfo()
|
||||
|
||||
// 开发环境下暴露缓存管理函数到全局对象,方便调试
|
||||
// 开发环境下暴露数据刷新函数到全局对象,方便调试
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
window.saleCache = {
|
||||
clearCache,
|
||||
clearSpecificCache,
|
||||
getCacheInfo,
|
||||
forceRefreshAllData,
|
||||
cache
|
||||
window.saleData = {
|
||||
forceRefreshAllData
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user