Homepage no longer waits on /api/onboarding for six starter questions. Natal answers show the spoken layer first; the Level 2 skeleton sits in a collapsed 完整分析 block. Wide tables scroll sideways on a phone. Form inputs are 16px so iOS does not zoom on focus.
73 lines
3.0 KiB
TypeScript
73 lines
3.0 KiB
TypeScript
type GreetingPeriod = "morning" | "noon" | "afternoon" | "evening" | "late-night";
|
|
|
|
type GreetingVariant = {
|
|
readonly salutation: (name: string) => string;
|
|
readonly question: string;
|
|
};
|
|
|
|
const greetingVariants: Record<GreetingPeriod, readonly GreetingVariant[]> = {
|
|
morning: [
|
|
{ salutation: (name) => `早上好,${name}。`, question: "今天最想先看什么?" },
|
|
{ salutation: (name) => `${name},早安。`, question: "今天最该关注哪件事?" },
|
|
{ salutation: (name) => `早上好,${name}。`, question: "想从哪个问题开始?" },
|
|
],
|
|
noon: [
|
|
{ salutation: (name) => `中午好,${name}。`, question: "现在最想理清哪件事?" },
|
|
{ salutation: (name) => `${name},中午好。`, question: "什么问题最需要方向?" },
|
|
{ salutation: (name) => `午间好,${name}。`, question: "事业、关系或选择,想先聊哪个?" },
|
|
],
|
|
afternoon: [
|
|
{ salutation: (name) => `${name},下午好。`, question: "现在最想推进哪件事?" },
|
|
{ salutation: (name) => `下午好,${name}。`, question: "今天想先理清什么?" },
|
|
{ salutation: (name) => `${name},下午好。`, question: "事业、关系或选择,想先聊哪个?" },
|
|
],
|
|
evening: [
|
|
{ salutation: (name) => `晚上好,${name}。`, question: "今天最挂心的是哪件事?" },
|
|
{ salutation: (name) => `${name},晚上好。`, question: "此刻最想聊哪件事?" },
|
|
{ salutation: (name) => `晚上好,${name}。`, question: "把心里的问题告诉我吧。" },
|
|
],
|
|
"late-night": [
|
|
{ salutation: (name) => `夜深了,${name}。`, question: "此刻最想问什么?" },
|
|
{ salutation: (name) => `${name},还没休息吗?`, question: "想从哪件事说起?" },
|
|
{ salutation: (name) => `这么晚还醒着,${name}。`, question: "直接说说最在意的问题吧。" },
|
|
],
|
|
};
|
|
|
|
export type StartGreetingParts = {
|
|
readonly salutation: string;
|
|
readonly question: string;
|
|
};
|
|
|
|
export function createStartGreetingParts(
|
|
name: string,
|
|
now = new Date(),
|
|
variantSelection = Math.random(),
|
|
): StartGreetingParts {
|
|
const displayName = name.trim() || "你好";
|
|
const hour = now.getHours();
|
|
const period: GreetingPeriod = hour >= 5 && hour < 11
|
|
? "morning"
|
|
: hour >= 11 && hour < 14
|
|
? "noon"
|
|
: hour >= 14 && hour < 18
|
|
? "afternoon"
|
|
: hour >= 18 && hour < 23 ? "evening" : "late-night";
|
|
const variants = greetingVariants[period];
|
|
const index = Math.min(Math.max(Math.floor(variantSelection * variants.length), 0), variants.length - 1);
|
|
const variant = variants[index]!;
|
|
return { salutation: variant.salutation(displayName), question: variant.question };
|
|
}
|
|
|
|
export function createStartGreeting(
|
|
name: string,
|
|
now = new Date(),
|
|
variantSelection = Math.random(),
|
|
): string {
|
|
const parts = createStartGreetingParts(name, now, variantSelection);
|
|
return `${parts.salutation}${parts.question}`;
|
|
}
|
|
|
|
export function createOnboardingFallbackGreeting(name: string): string {
|
|
return `${name.trim()},从你此刻最关心的问题开始吧。`;
|
|
}
|