261 lines
7.0 KiB
TypeScript
261 lines
7.0 KiB
TypeScript
/**
|
||
* 下一步行动建议生成逻辑
|
||
*/
|
||
|
||
import type {
|
||
ActionContext,
|
||
ActionRule,
|
||
NextAction,
|
||
} from "@/types/next-action";
|
||
|
||
// 行动定义类型(与 ActionRule 中的 action 类型一致)
|
||
type ActionDefinition = Omit<NextAction, "id" | "priority" | "href">;
|
||
|
||
// 生成唯一ID
|
||
function generateActionId(): string {
|
||
return `action_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||
}
|
||
|
||
// 创建行动项
|
||
function createAction(
|
||
base: ActionDefinition,
|
||
priority: NextAction["priority"],
|
||
): NextAction {
|
||
return {
|
||
...base,
|
||
href: base.actionUrl, // href 与 actionUrl 保持一致
|
||
id: generateActionId(),
|
||
priority,
|
||
};
|
||
}
|
||
|
||
// 默认行动规则 - 新用户无数据
|
||
const newUserRules: ActionRule[] = [
|
||
{
|
||
condition: (ctx) => !ctx.hasBrands || ctx.brandCount === 0,
|
||
primaryAction: {
|
||
title: "创建第一个品牌",
|
||
description:
|
||
"开始您的品牌分析之旅,创建第一个品牌后即可获得详细的AI认知度评分。",
|
||
actionText: "创建品牌",
|
||
actionUrl: "/brands",
|
||
icon: "🎯",
|
||
},
|
||
secondaryAction: null,
|
||
optionalAction: {
|
||
title: "了解GEO",
|
||
description: "了解GEO平台如何帮助您监控品牌在AI平台的表现。",
|
||
actionText: "了解更多",
|
||
actionUrl: "/dashboard/reports",
|
||
icon: "📚",
|
||
},
|
||
},
|
||
];
|
||
|
||
// 有数据但评分低的规则
|
||
const lowScoreRules: ActionRule[] = [
|
||
{
|
||
condition: (ctx) =>
|
||
ctx.hasData &&
|
||
ctx.overallScore > 0 &&
|
||
ctx.overallScore < 60 &&
|
||
ctx.competitorCount > 0,
|
||
primaryAction: {
|
||
title: "查看差距分析",
|
||
description: "您的品牌在多个平台落后于竞品,点击查看详细差距分析。",
|
||
actionText: "查看差距分析",
|
||
actionUrl: "/compare",
|
||
icon: "📊",
|
||
},
|
||
secondaryAction: {
|
||
title: "添加更多竞品",
|
||
description: "添加更多竞品可以获得更完整的对比分析。",
|
||
actionText: "添加竞品",
|
||
actionUrl: "/brands",
|
||
icon: "👥",
|
||
},
|
||
optionalAction: {
|
||
title: "设置预警",
|
||
description: "设置竞品超越预警,第一时间获知竞争对手的动态变化。",
|
||
actionText: "立即设置",
|
||
actionUrl: "/dashboard/settings",
|
||
icon: "🔔",
|
||
},
|
||
},
|
||
];
|
||
|
||
// 评分高但无增长的规则
|
||
const highScoreNoGrowthRules: ActionRule[] = [
|
||
{
|
||
condition: (ctx) =>
|
||
ctx.hasData && ctx.overallScore >= 60 && ctx.scoreChange <= 0,
|
||
primaryAction: {
|
||
title: "设置涨粉预警",
|
||
description: "您的品牌评分较高但增长停滞,设置预警监控潜在风险。",
|
||
actionText: "设置预警",
|
||
actionUrl: "/dashboard/settings",
|
||
icon: "📈",
|
||
},
|
||
secondaryAction: {
|
||
title: "对比历史趋势",
|
||
description: "查看品牌评分的历史变化趋势,分析增长机会。",
|
||
actionText: "查看趋势",
|
||
actionUrl: "/dashboard/reports",
|
||
icon: "📉",
|
||
},
|
||
optionalAction: {
|
||
title: "导出报告",
|
||
description: "导出详细的分析报告,用于内部汇报或战略制定。",
|
||
actionText: "导出报告",
|
||
actionUrl: "/dashboard/reports",
|
||
icon: "📄",
|
||
},
|
||
},
|
||
];
|
||
|
||
// 竞品威胁规则
|
||
const competitorThreatRules: ActionRule[] = [
|
||
{
|
||
condition: (ctx) => ctx.competitorCount > 0 && ctx.hasData,
|
||
primaryAction: {
|
||
title: "查看差距分析",
|
||
description:
|
||
"竞品正在逼近或超越您的品牌,点击查看详细分析并制定应对策略。",
|
||
actionText: "查看差距分析",
|
||
actionUrl: "/compare",
|
||
icon: "⚠️",
|
||
},
|
||
secondaryAction: {
|
||
title: "设置预警",
|
||
description: "设置竞品超越预警,第一时间获知竞争对手的动态变化。",
|
||
actionText: "设置预警",
|
||
actionUrl: "/dashboard/settings",
|
||
icon: "🔔",
|
||
},
|
||
optionalAction: {
|
||
title: "添加查询词",
|
||
description: "添加更多查询词以获得更完整的品牌分析。",
|
||
actionText: "添加查询词",
|
||
actionUrl: "/dashboard/queries",
|
||
icon: "🔍",
|
||
},
|
||
},
|
||
];
|
||
|
||
// 正常数据状态规则
|
||
const normalDataRules: ActionRule[] = [
|
||
{
|
||
condition: (ctx) => ctx.hasData && ctx.hasQueryHistory,
|
||
primaryAction: {
|
||
title: "继续优化",
|
||
description: "您的品牌表现良好,继续保持并关注最新动态。",
|
||
actionText: "查看详情",
|
||
actionUrl: "/dashboard",
|
||
icon: "✨",
|
||
},
|
||
secondaryAction: {
|
||
title: "对比分析",
|
||
description: "与竞品进行对比分析,发现更多优化机会。",
|
||
actionText: "查看对比",
|
||
actionUrl: "/compare",
|
||
icon: "📊",
|
||
},
|
||
optionalAction: {
|
||
title: "导出报告",
|
||
description: "导出分析报告用于内部汇报。",
|
||
actionText: "导出报告",
|
||
actionUrl: "/dashboard/reports",
|
||
icon: "📄",
|
||
},
|
||
},
|
||
];
|
||
|
||
// 所有规则按优先级排序
|
||
const allRules: ActionRule[] = [
|
||
...newUserRules,
|
||
...lowScoreRules,
|
||
...highScoreNoGrowthRules,
|
||
...competitorThreatRules,
|
||
...normalDataRules,
|
||
];
|
||
|
||
/**
|
||
* 根据上下文生成行动建议
|
||
*/
|
||
export function generateNextActions(context: ActionContext): NextAction[] {
|
||
const actions: NextAction[] = [];
|
||
|
||
// 遍历规则,找到第一个匹配的
|
||
for (const rule of allRules) {
|
||
if (rule.condition(context)) {
|
||
// 添加主要行动
|
||
actions.push(createAction(rule.primaryAction, "primary"));
|
||
|
||
// 添加次要行动
|
||
if (rule.secondaryAction) {
|
||
actions.push(createAction(rule.secondaryAction, "secondary"));
|
||
}
|
||
|
||
// 添加可选行动
|
||
if (rule.optionalAction) {
|
||
actions.push(createAction(rule.optionalAction, "optional"));
|
||
}
|
||
|
||
break; // 找到第一个匹配规则后停止
|
||
}
|
||
}
|
||
|
||
// 如果没有任何规则匹配,返回默认行动
|
||
if (actions.length === 0) {
|
||
actions.push(
|
||
createAction(
|
||
{
|
||
title: "开始分析",
|
||
description: "创建您的第一个品牌,开始GEO品牌健康分析。",
|
||
actionText: "立即创建",
|
||
actionUrl: "/brands",
|
||
icon: "🚀",
|
||
},
|
||
"primary",
|
||
),
|
||
);
|
||
actions.push(
|
||
createAction(
|
||
{
|
||
title: "查看教程",
|
||
description: "了解如何使用GEO平台监控您的品牌。",
|
||
actionText: "查看教程",
|
||
actionUrl: "/dashboard/reports",
|
||
icon: "📚",
|
||
},
|
||
"secondary",
|
||
),
|
||
);
|
||
}
|
||
|
||
return actions;
|
||
}
|
||
|
||
/**
|
||
* 获取行动建议的缓存key
|
||
*/
|
||
export function getCacheKey(context: ActionContext): string {
|
||
return `next_actions_${context.currentPage}_${context.brandId || "global"}_${context.overallScore}`;
|
||
}
|
||
|
||
/**
|
||
* 判断是否可以使用缓存
|
||
*/
|
||
export function canUseCache(
|
||
cachedActions: NextAction[] | undefined,
|
||
_context: ActionContext,
|
||
): boolean {
|
||
if (!cachedActions || cachedActions.length === 0) {
|
||
return false;
|
||
}
|
||
|
||
// 简单缓存策略:1分钟内不需要重新生成
|
||
// 这里可以通过localStorage存储时间戳来更精确控制
|
||
return true;
|
||
}
|