feat(版本详情): 完善流程日志与需求覆盖
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { X, Link2, ChevronRight, ArrowRightLeft } from 'lucide-react';
|
||||
import { BugStatusBadge } from './BugStatusBadge';
|
||||
import { ActivityLogPanel } from '@/components/ActivityLogPanel';
|
||||
import { useBugStore } from '@/stores/useBugStore';
|
||||
import { useTestCaseStore } from '@/stores/useTestCaseStore';
|
||||
import { useRequirementStore } from '@/stores/useRequirementStore';
|
||||
@@ -11,6 +12,7 @@ import { useAuthStore } from '@/stores/useAuthStore';
|
||||
import { BUG_ALLOWED_TRANSITIONS, BUG_STATUS_LABEL, BUG_SEVERITY_LABEL, BUG_SEVERITY_COLOR } from '@/lib/bug';
|
||||
import { formatDateTime } from '@/lib/format';
|
||||
import { isMemberReference, resolveMemberDisplayName } from '@/lib/member-system';
|
||||
import type { EntityActivityLogEntry } from '@/lib/entity-activity-log';
|
||||
import type { BugStatus } from '@/lib/bug';
|
||||
|
||||
const LOG_ACTION_LABEL: Record<string, string> = {
|
||||
@@ -53,6 +55,21 @@ export function BugDetailDrawer({ bugId, onClose, contextLabel }: Props) {
|
||||
const [transferTo, setTransferTo] = useState('');
|
||||
const [transferRemark, setTransferRemark] = useState('');
|
||||
const [lightboxSrc, setLightboxSrc] = useState<string | null>(null);
|
||||
const legacyLogEntries = useMemo<EntityActivityLogEntry[]>(() => {
|
||||
return (bug.logs || []).map((log) => {
|
||||
const from = log.fromValue ? resolveMemberDisplayName(log.fromValue, members) : '';
|
||||
const to = log.toValue ? resolveMemberDisplayName(log.toValue, members) : '';
|
||||
const change = from && to ? `${from} → ${to}` : '';
|
||||
const remark = log.remark ? `(${log.remark})` : '';
|
||||
return {
|
||||
id: `bug-log-${log.id}`,
|
||||
occurredAt: log.createdAt,
|
||||
actorId: resolveMemberDisplayName(log.operator, members),
|
||||
label: LOG_ACTION_LABEL[log.action] || log.action,
|
||||
summary: [change, remark].filter(Boolean).join(' ') || bug.title,
|
||||
};
|
||||
});
|
||||
}, [bug.logs, bug.title, members]);
|
||||
|
||||
const handleTransition = (to: BugStatus) => {
|
||||
if (to === 'fixed') { setShowResolutionInput(true); return; }
|
||||
@@ -201,27 +218,7 @@ export function BugDetailDrawer({ bugId, onClose, contextLabel }: Props) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 操作日志 */}
|
||||
{bug.logs && bug.logs.length > 0 && (
|
||||
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
|
||||
<div className="text-[10px] text-[var(--ink-muted)] uppercase tracking-wide mb-3">操作日志</div>
|
||||
<div className="space-y-2.5">
|
||||
{[...bug.logs].reverse().map((log) => (
|
||||
<div key={log.id} className="flex gap-2.5 text-[11px]">
|
||||
<span className="text-[var(--ink-muted)] tabular-nums shrink-0 w-[110px]">{formatDateTime(log.createdAt)}</span>
|
||||
<div className="flex-1">
|
||||
<span className="font-medium text-[var(--ink)]">{resolveMemberDisplayName(log.operator, members)}</span>
|
||||
<span className="text-[var(--ink-soft)]"> {LOG_ACTION_LABEL[log.action] || log.action}</span>
|
||||
{log.fromValue && log.toValue && (
|
||||
<span className="text-[var(--ink-muted)]"> {resolveMemberDisplayName(log.fromValue, members)} → {resolveMemberDisplayName(log.toValue, members)}</span>
|
||||
)}
|
||||
{log.remark && <span className="text-[var(--ink-muted)]"> ({log.remark})</span>}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ActivityLogPanel sourceType="bug" sourceId={bug.id} legacyEntries={legacyLogEntries} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user