优化文案
This commit is contained in:
+136
-69
@@ -1,4 +1,5 @@
|
||||
import { PanelShell } from "@/components/panel-shell";
|
||||
import { ActivityChart } from "@/components/activity-chart";
|
||||
import { getCaregiverActivity } from "@/lib/caregiver-panel";
|
||||
import {
|
||||
formatDateTime,
|
||||
@@ -11,102 +12,168 @@ import { requireCaregiverSession } from "@/lib/page-auth";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
function aggregateByDate(items: { createdAt: Date | string }[]) {
|
||||
const counts: Record<string, number> = {};
|
||||
for (const item of items) {
|
||||
const date = new Date(item.createdAt);
|
||||
const key = `${date.getMonth() + 1}/${date.getDate()}`;
|
||||
counts[key] = (counts[key] || 0) + 1;
|
||||
}
|
||||
return Object.entries(counts)
|
||||
.map(([date, count]) => ({ date, count }))
|
||||
.reverse();
|
||||
}
|
||||
|
||||
export default async function ActivityPage() {
|
||||
const caregiver = await requireCaregiverSession("/activity");
|
||||
const { usageEvents, conversationTurns, toolCalls } = await getCaregiverActivity(
|
||||
caregiver.id,
|
||||
);
|
||||
|
||||
const usageChartData = aggregateByDate(usageEvents);
|
||||
const conversationChartData = aggregateByDate(conversationTurns);
|
||||
|
||||
return (
|
||||
<PanelShell
|
||||
currentPath="/activity"
|
||||
title="活动记录独立成页,回看陪伴过程更清楚。"
|
||||
description="这里专门收下老人端的使用事件、最近对话片段和工具调用,不再和留言流混排。"
|
||||
title="陪伴动态"
|
||||
description="了解长辈最近的使用情况、聊天内容和智能服务记录。"
|
||||
caregiverToken={caregiver.sessionToken}
|
||||
>
|
||||
{usageEvents.length === 0 && conversationTurns.length === 0 && toolCalls.length === 0 ? (
|
||||
<section className="rounded-[32px] border border-dashed border-[var(--line)] bg-white/72 px-6 py-10 text-center shadow-[0_20px_50px_rgba(115,76,42,0.10)]">
|
||||
<h2 className="font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
还没有活动记录
|
||||
暂时没有动态
|
||||
</h2>
|
||||
<p className="mx-auto mt-4 max-w-2xl text-base leading-8 text-[var(--muted)]">
|
||||
等老人端开始对话、切换镜头或触发桥接工具后,这里会自动累积活动时间线。
|
||||
长辈开始使用智能助理后,这里会自动记录使用情况和聊天内容,方便您随时了解。
|
||||
</p>
|
||||
</section>
|
||||
) : (
|
||||
<section className="grid gap-6 xl:grid-cols-3">
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
使用事件
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
老人端操作轨迹
|
||||
</h2>
|
||||
<div className="mt-5 space-y-3">
|
||||
{usageEvents.map((event) => (
|
||||
<div key={event.id} className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4">
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-[var(--muted)]">
|
||||
<span>{getDeviceName(event.elderDevice.displayName)}</span>
|
||||
<span>{formatDateTime(event.createdAt)}</span>
|
||||
</div>
|
||||
<p className="mt-2 text-sm leading-7 text-[var(--ink)]">
|
||||
{getUsageLabel(event.eventType)}
|
||||
<>
|
||||
{(usageChartData.length > 1 || conversationChartData.length > 1) && (
|
||||
<section className="grid gap-6 xl:grid-cols-2">
|
||||
{usageChartData.length > 1 && (
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
使用频率
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-2xl text-[var(--ink)]">
|
||||
最近使用趋势
|
||||
</h2>
|
||||
<div className="mt-4">
|
||||
<ActivityChart data={usageChartData} color="#c76733" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{conversationChartData.length > 1 && (
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
聊天频率
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-2xl text-[var(--ink)]">
|
||||
最近对话趋势
|
||||
</h2>
|
||||
<div className="mt-4">
|
||||
<ActivityChart data={conversationChartData} color="#76845e" />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
对话片段
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
最近说了什么
|
||||
</h2>
|
||||
<div className="mt-5 space-y-3">
|
||||
{conversationTurns.map((turn) => (
|
||||
<div key={turn.id} className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4">
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-[var(--muted)]">
|
||||
<span>{getConversationRoleLabel(turn.role)}</span>
|
||||
<span>{formatDateTime(turn.createdAt)}</span>
|
||||
</div>
|
||||
<p className="mt-2 text-xs text-[var(--muted)]">
|
||||
{getDeviceName(turn.elderDevice.displayName)}
|
||||
<section className="grid gap-6 xl:grid-cols-3">
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
使用记录
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
最近的操作
|
||||
</h2>
|
||||
<div className="mt-5 space-y-3">
|
||||
{usageEvents.length === 0 ? (
|
||||
<p className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4 text-sm leading-7 text-[var(--muted)]">
|
||||
暂时没有使用记录。
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-7 text-[var(--ink)]">
|
||||
{truncateText(turn.content, 132)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
) : (
|
||||
usageEvents.map((event) => (
|
||||
<div key={event.id} className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4">
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-[var(--muted)]">
|
||||
<span>{getDeviceName(event.elderDevice.displayName)}</span>
|
||||
<span>{formatDateTime(event.createdAt)}</span>
|
||||
</div>
|
||||
<p className="mt-2 text-sm leading-7 text-[var(--ink)]">
|
||||
{getUsageLabel(event.eventType)}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
工具调用
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
function calling 执行记录
|
||||
</h2>
|
||||
<div className="mt-5 space-y-3">
|
||||
{toolCalls.map((log) => (
|
||||
<div key={log.id} className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4">
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-[var(--muted)]">
|
||||
<span>{getDeviceName(log.elderDevice.displayName)}</span>
|
||||
<span>{formatDateTime(log.createdAt)}</span>
|
||||
</div>
|
||||
<p className="mt-2 text-sm font-semibold text-[var(--ink)]">
|
||||
{log.toolName}
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
聊天记录
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
最近的对话
|
||||
</h2>
|
||||
<div className="mt-5 space-y-3">
|
||||
{conversationTurns.length === 0 ? (
|
||||
<p className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4 text-sm leading-7 text-[var(--muted)]">
|
||||
暂时没有聊天记录。
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-7 text-[var(--muted)]">
|
||||
{truncateText(log.outputText || log.argumentsJson, 136)}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
) : (
|
||||
conversationTurns.map((turn) => (
|
||||
<div key={turn.id} className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4">
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-[var(--muted)]">
|
||||
<span>{getConversationRoleLabel(turn.role)}</span>
|
||||
<span>{formatDateTime(turn.createdAt)}</span>
|
||||
</div>
|
||||
<p className="mt-2 text-xs text-[var(--muted)]">
|
||||
{getDeviceName(turn.elderDevice.displayName)}
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-7 text-[var(--ink)]">
|
||||
{truncateText(turn.content, 132)}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="rounded-[32px] border border-white/75 bg-white/82 p-6 shadow-[0_26px_60px_rgba(115,76,42,0.12)]">
|
||||
<p className="text-sm font-medium tracking-[0.18em] text-[var(--copper)] uppercase">
|
||||
智能服务
|
||||
</p>
|
||||
<h2 className="mt-2 font-[family-name:var(--font-display)] text-3xl text-[var(--ink)]">
|
||||
助理做了什么
|
||||
</h2>
|
||||
<div className="mt-5 space-y-3">
|
||||
{toolCalls.length === 0 ? (
|
||||
<p className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4 text-sm leading-7 text-[var(--muted)]">
|
||||
暂时没有智能服务记录。
|
||||
</p>
|
||||
) : (
|
||||
toolCalls.map((log) => (
|
||||
<div key={log.id} className="rounded-[24px] bg-[var(--paper-soft)] px-5 py-4">
|
||||
<div className="flex items-center justify-between gap-3 text-xs text-[var(--muted)]">
|
||||
<span>{getDeviceName(log.elderDevice.displayName)}</span>
|
||||
<span>{formatDateTime(log.createdAt)}</span>
|
||||
</div>
|
||||
<p className="mt-2 text-sm font-semibold text-[var(--ink)]">
|
||||
{log.toolName}
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-7 text-[var(--muted)]">
|
||||
{truncateText(log.outputText || log.argumentsJson, 136)}
|
||||
</p>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
)}
|
||||
</PanelShell>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user