260 lines
8.7 KiB
TypeScript
260 lines
8.7 KiB
TypeScript
|
|
import { Knex } from 'knex';
|
||
|
|
import { db } from '../database';
|
||
|
|
|
||
|
|
export class MerchantBehaviorAnalysisService {
|
||
|
|
/**
|
||
|
|
* 分析商户行为数据
|
||
|
|
* @param params 分析参数
|
||
|
|
* @param traceInfo 追踪信息
|
||
|
|
* @returns 分析结果
|
||
|
|
*/
|
||
|
|
public static async analyzeMerchantBehavior(
|
||
|
|
params: {
|
||
|
|
merchantId: string;
|
||
|
|
timeRange?: { start: string; end: string };
|
||
|
|
behaviors?: string[];
|
||
|
|
},
|
||
|
|
traceInfo: {
|
||
|
|
tenantId: string;
|
||
|
|
shopId: string;
|
||
|
|
taskId: string;
|
||
|
|
traceId: string;
|
||
|
|
businessType: 'TOC' | 'TOB';
|
||
|
|
}
|
||
|
|
): Promise<{
|
||
|
|
merchantId: string;
|
||
|
|
timestamp: string;
|
||
|
|
behaviorPatterns: Array<{
|
||
|
|
behavior: string;
|
||
|
|
frequency: number;
|
||
|
|
averageDuration: number;
|
||
|
|
peakTime: string;
|
||
|
|
trend: 'increasing' | 'decreasing' | 'stable';
|
||
|
|
}>;
|
||
|
|
insights: string[];
|
||
|
|
}> {
|
||
|
|
try {
|
||
|
|
const merchantId = params.merchantId;
|
||
|
|
const timestamp = new Date().toISOString();
|
||
|
|
|
||
|
|
// 模拟行为数据
|
||
|
|
const behaviorPatterns = [
|
||
|
|
{
|
||
|
|
behavior: 'login',
|
||
|
|
frequency: Math.floor(Math.random() * 50) + 10,
|
||
|
|
averageDuration: Math.floor(Math.random() * 30) + 5,
|
||
|
|
peakTime: '10:00-12:00',
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
behavior: 'product_management',
|
||
|
|
frequency: Math.floor(Math.random() * 30) + 5,
|
||
|
|
averageDuration: Math.floor(Math.random() * 60) + 15,
|
||
|
|
peakTime: '14:00-16:00',
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
behavior: 'order_processing',
|
||
|
|
frequency: Math.floor(Math.random() * 40) + 8,
|
||
|
|
averageDuration: Math.floor(Math.random() * 45) + 10,
|
||
|
|
peakTime: '9:00-11:00',
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
behavior: 'inventory_management',
|
||
|
|
frequency: Math.floor(Math.random() * 25) + 3,
|
||
|
|
averageDuration: Math.floor(Math.random() * 50) + 12,
|
||
|
|
peakTime: '15:00-17:00',
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
behavior: 'financial_operations',
|
||
|
|
frequency: Math.floor(Math.random() * 15) + 2,
|
||
|
|
averageDuration: Math.floor(Math.random() * 40) + 18,
|
||
|
|
peakTime: '16:00-18:00',
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
// 生成洞察
|
||
|
|
const insights = [
|
||
|
|
`商户 ${merchantId} 的登录频率为 ${behaviorPatterns[0].frequency} 次,呈 ${this.getTrendDescription(behaviorPatterns[0].trend)} 趋势`,
|
||
|
|
`产品管理行为的平均持续时间为 ${behaviorPatterns[1].averageDuration} 分钟,峰值时间为 ${behaviorPatterns[1].peakTime}`,
|
||
|
|
`订单处理行为的频率为 ${behaviorPatterns[2].frequency} 次,呈 ${this.getTrendDescription(behaviorPatterns[2].trend)} 趋势`,
|
||
|
|
`库存管理行为的平均持续时间为 ${behaviorPatterns[3].averageDuration} 分钟,峰值时间为 ${behaviorPatterns[3].peakTime}`,
|
||
|
|
`财务操作行为的频率为 ${behaviorPatterns[4].frequency} 次,呈 ${this.getTrendDescription(behaviorPatterns[4].trend)} 趋势`,
|
||
|
|
];
|
||
|
|
|
||
|
|
return {
|
||
|
|
merchantId,
|
||
|
|
timestamp,
|
||
|
|
behaviorPatterns,
|
||
|
|
insights,
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error analyzing merchant behavior:', error);
|
||
|
|
throw new Error('Failed to analyze merchant behavior');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 生成商户行为分析报告
|
||
|
|
* @param params 报告参数
|
||
|
|
* @param traceInfo 追踪信息
|
||
|
|
* @returns 分析报告
|
||
|
|
*/
|
||
|
|
public static async generateBehaviorAnalysisReport(
|
||
|
|
params: {
|
||
|
|
merchantId: string;
|
||
|
|
timeRange: { start: string; end: string };
|
||
|
|
reportType: 'detailed' | 'summary';
|
||
|
|
},
|
||
|
|
traceInfo: {
|
||
|
|
tenantId: string;
|
||
|
|
shopId: string;
|
||
|
|
taskId: string;
|
||
|
|
traceId: string;
|
||
|
|
businessType: 'TOC' | 'TOB';
|
||
|
|
}
|
||
|
|
): Promise<{
|
||
|
|
reportId: string;
|
||
|
|
merchantId: string;
|
||
|
|
reportType: string;
|
||
|
|
timeRange: { start: string; end: string };
|
||
|
|
timestamp: string;
|
||
|
|
summary: string;
|
||
|
|
behaviorPatterns: Array<{
|
||
|
|
behavior: string;
|
||
|
|
frequency: number;
|
||
|
|
averageDuration: number;
|
||
|
|
peakTime: string;
|
||
|
|
trend: 'increasing' | 'decreasing' | 'stable';
|
||
|
|
}>;
|
||
|
|
insights: string[];
|
||
|
|
recommendations: string[];
|
||
|
|
}> {
|
||
|
|
try {
|
||
|
|
const reportId = `BEHAVIOR-REPORT-${Date.now()}`;
|
||
|
|
const merchantId = params.merchantId;
|
||
|
|
const timestamp = new Date().toISOString();
|
||
|
|
|
||
|
|
// 分析商户行为
|
||
|
|
const analysis = await this.analyzeMerchantBehavior(params, traceInfo);
|
||
|
|
|
||
|
|
// 生成摘要
|
||
|
|
const summary = `商户 ${merchantId} 在 ${params.timeRange.start} 至 ${params.timeRange.end} 期间的行为分析报告`;
|
||
|
|
|
||
|
|
// 生成建议
|
||
|
|
const recommendations = [
|
||
|
|
'建议优化登录流程,提高商户使用体验',
|
||
|
|
'建议在峰值时间提供额外的系统资源,确保服务稳定性',
|
||
|
|
'建议简化产品管理操作,减少平均处理时间',
|
||
|
|
'建议优化订单处理流程,提高处理效率',
|
||
|
|
'建议提供库存管理自动化工具,减少手动操作',
|
||
|
|
'建议优化财务操作界面,提高操作便捷性',
|
||
|
|
];
|
||
|
|
|
||
|
|
return {
|
||
|
|
reportId,
|
||
|
|
merchantId,
|
||
|
|
reportType: params.reportType,
|
||
|
|
timeRange: params.timeRange,
|
||
|
|
timestamp,
|
||
|
|
summary,
|
||
|
|
behaviorPatterns: analysis.behaviorPatterns,
|
||
|
|
insights: analysis.insights,
|
||
|
|
recommendations,
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error generating behavior analysis report:', error);
|
||
|
|
throw new Error('Failed to generate behavior analysis report');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 预测商户行为趋势
|
||
|
|
* @param params 预测参数
|
||
|
|
* @param traceInfo 追踪信息
|
||
|
|
* @returns 预测结果
|
||
|
|
*/
|
||
|
|
public static async predictMerchantBehaviorTrend(
|
||
|
|
params: {
|
||
|
|
merchantId: string;
|
||
|
|
timeRange: { start: string; end: string };
|
||
|
|
predictionDays: number;
|
||
|
|
},
|
||
|
|
traceInfo: {
|
||
|
|
tenantId: string;
|
||
|
|
shopId: string;
|
||
|
|
taskId: string;
|
||
|
|
traceId: string;
|
||
|
|
businessType: 'TOC' | 'TOB';
|
||
|
|
}
|
||
|
|
): Promise<{
|
||
|
|
merchantId: string;
|
||
|
|
timestamp: string;
|
||
|
|
predictionDays: number;
|
||
|
|
predictions: Array<{
|
||
|
|
behavior: string;
|
||
|
|
currentFrequency: number;
|
||
|
|
predictedFrequency: number;
|
||
|
|
trend: 'increasing' | 'decreasing' | 'stable';
|
||
|
|
confidence: number;
|
||
|
|
}>;
|
||
|
|
}> {
|
||
|
|
try {
|
||
|
|
const merchantId = params.merchantId;
|
||
|
|
const timestamp = new Date().toISOString();
|
||
|
|
|
||
|
|
// 模拟预测数据
|
||
|
|
const predictions = [
|
||
|
|
{
|
||
|
|
behavior: 'login',
|
||
|
|
currentFrequency: Math.floor(Math.random() * 50) + 10,
|
||
|
|
predictedFrequency: Math.floor(Math.random() * 20) + 10,
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
confidence: Math.floor(Math.random() * 30) + 70,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
behavior: 'product_management',
|
||
|
|
currentFrequency: Math.floor(Math.random() * 30) + 5,
|
||
|
|
predictedFrequency: Math.floor(Math.random() * 15) + 5,
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
confidence: Math.floor(Math.random() * 30) + 70,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
behavior: 'order_processing',
|
||
|
|
currentFrequency: Math.floor(Math.random() * 40) + 8,
|
||
|
|
predictedFrequency: Math.floor(Math.random() * 20) + 8,
|
||
|
|
trend: ['increasing', 'decreasing', 'stable'][Math.floor(Math.random() * 3)] as 'increasing' | 'decreasing' | 'stable',
|
||
|
|
confidence: Math.floor(Math.random() * 30) + 70,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
return {
|
||
|
|
merchantId,
|
||
|
|
timestamp,
|
||
|
|
predictionDays: params.predictionDays,
|
||
|
|
predictions,
|
||
|
|
};
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error predicting merchant behavior trend:', error);
|
||
|
|
throw new Error('Failed to predict merchant behavior trend');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取趋势描述
|
||
|
|
* @param trend 趋势
|
||
|
|
* @returns 趋势描述
|
||
|
|
*/
|
||
|
|
private static getTrendDescription(trend: string): string {
|
||
|
|
const trendDescriptions = {
|
||
|
|
increasing: '上升',
|
||
|
|
decreasing: '下降',
|
||
|
|
stable: '稳定',
|
||
|
|
};
|
||
|
|
return trendDescriptions[trend as keyof typeof trendDescriptions] || '';
|
||
|
|
}
|
||
|
|
}
|