50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useMemo } from 'react';
|
|
import { formatDateTime } from '@/lib/format';
|
|
import type { WorkActivitySourceType } from '@/lib/work-activity';
|
|
import { getEntityActivityLogEntries, type EntityActivityLogEntry } from '@/lib/entity-activity-log';
|
|
import { useWorkActivityStore } from '@/stores/useWorkActivityStore';
|
|
|
|
interface Props {
|
|
sourceType: WorkActivitySourceType;
|
|
sourceId: string;
|
|
legacyEntries?: EntityActivityLogEntry[];
|
|
title?: string;
|
|
}
|
|
|
|
export function ActivityLogPanel({ sourceType, sourceId, legacyEntries = [], title = '操作日志' }: Props) {
|
|
const { activities, fetchActivities } = useWorkActivityStore();
|
|
|
|
useEffect(() => {
|
|
fetchActivities();
|
|
}, [fetchActivities]);
|
|
|
|
const entries = useMemo(
|
|
() => getEntityActivityLogEntries(activities, sourceType, sourceId, legacyEntries),
|
|
[activities, sourceType, sourceId, legacyEntries],
|
|
);
|
|
|
|
return (
|
|
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
|
|
<div className="mb-3 text-[10px] uppercase tracking-wide text-[var(--ink-muted)]">{title}</div>
|
|
{entries.length === 0 ? (
|
|
<p className="text-[12px] text-[var(--ink-muted)]">暂无操作日志</p>
|
|
) : (
|
|
<div className="space-y-2.5">
|
|
{entries.map((entry) => (
|
|
<div key={entry.id} className="flex gap-2.5 text-[11px]">
|
|
<span className="w-[110px] shrink-0 tabular-nums text-[var(--ink-muted)]">{formatDateTime(entry.occurredAt)}</span>
|
|
<div className="min-w-0 flex-1">
|
|
<span className="font-medium text-[var(--ink)]">{entry.actorId || '系统'}</span>
|
|
<span className="text-[var(--ink-soft)]"> {entry.label}</span>
|
|
<div className="mt-0.5 truncate text-[var(--ink-muted)]">{entry.summary}</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|