haixunMaster/lib/types/style-profile.ts

90 lines
2.4 KiB
TypeScript
Raw Normal View History

2026-06-21 12:50:31 +00:00
export const STYLE_8D_KEYS = [
"d1Tone",
"d2Structure",
"d3Interaction",
"d4Topics",
"d5Rhythm",
"d6Visual",
"d7Conversion",
"d8Risk",
] as const;
export type Style8DKey = (typeof STYLE_8D_KEYS)[number];
export const STYLE_8D_LABELS: Record<Style8DKey, string> = {
d1Tone: "D1 語氣人格",
d2Structure: "D2 結構模板",
d3Interaction: "D3 互動方式",
d4Topics: "D4 主題分布",
d5Rhythm: "D5 發文節奏",
d6Visual: "D6 視覺語法",
d7Conversion: "D7 轉換方式",
d8Risk: "D8 風險紅線",
};
export interface StoredStyle8DProfile {
username: string;
analyzedAt: string;
postCount: number;
engagement: {
measuredPosts: number;
medianInteractions: number;
averageInteractions: number;
postsAboveThreshold: number;
threshold: number;
verdict: "strong" | "usable" | "unknown";
};
analysis: Record<Style8DKey, { summary: string; evidence: string[] }>;
personaDraft: string;
}
export function createEmptyStyle8DProfile(username = ""): StoredStyle8DProfile {
const emptyDimension = () => ({ summary: "", evidence: [] as string[] });
return {
username,
analyzedAt: "",
postCount: 0,
engagement: {
measuredPosts: 0,
medianInteractions: 0,
averageInteractions: 0,
postsAboveThreshold: 0,
threshold: 10,
verdict: "unknown",
},
analysis: {
d1Tone: emptyDimension(),
d2Structure: emptyDimension(),
d3Interaction: emptyDimension(),
d4Topics: emptyDimension(),
d5Rhythm: emptyDimension(),
d6Visual: emptyDimension(),
d7Conversion: emptyDimension(),
d8Risk: emptyDimension(),
},
personaDraft: "",
};
}
export function parseStyle8DProfile(raw?: string | null): StoredStyle8DProfile | null {
if (!raw?.trim()) return null;
try {
const value = JSON.parse(raw) as StoredStyle8DProfile;
if (!value?.analysis) return null;
return value;
} catch {
return null;
}
}
export function buildStyle8DPromptBlock(raw?: string | null): string | null {
const profile = parseStyle8DProfile(raw);
if (!profile) return null;
const dimensions = STYLE_8D_KEYS.map((key) => {
const summary = profile.analysis[key]?.summary?.trim();
return summary ? `${STYLE_8D_LABELS[key]}${summary}` : null;
}).filter(Boolean);
if (dimensions.length === 0) return null;
return `【8D 風格策略】\n產文與回覆都必須遵守\n${dimensions.join("\n")}`;
}