68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
import type { Revision } from '../types';
|
||
import { labelOf } from '../lib/fieldLabels';
|
||
import { Button } from './ui';
|
||
|
||
const STATUS_LABEL: Record<string, string> = {
|
||
pending: '待审核',
|
||
approved: '已通过',
|
||
rejected: '已驳回',
|
||
};
|
||
const STATUS_CLS: Record<string, string> = {
|
||
pending: 'tag tag-amber',
|
||
approved: 'tag tag-green',
|
||
rejected: 'tag tag-gray',
|
||
};
|
||
|
||
export function RevisionList({
|
||
revisions,
|
||
onApprove,
|
||
onReject,
|
||
}: {
|
||
revisions: Revision[];
|
||
onApprove?: (id: number) => void;
|
||
onReject?: (id: number) => void;
|
||
}) {
|
||
if (revisions.length === 0)
|
||
return <p className="muted">暂无修订记录。</p>;
|
||
return (
|
||
<ul className="rev-list">
|
||
{revisions.map((r) => (
|
||
<li key={r.id} className="rev-item">
|
||
<div className="rev-head">
|
||
<span className={STATUS_CLS[r.status]}>{STATUS_LABEL[r.status]}</span>
|
||
<span className="rev-author">{r.author_name}</span>
|
||
<span className="muted rev-date">
|
||
{new Date(r.created_at + 'Z').toLocaleString('zh-CN')}
|
||
</span>
|
||
</div>
|
||
{r.note && <p className="rev-note">{r.note}</p>}
|
||
<ul className="rev-changes">
|
||
{r.changes.map((c) => (
|
||
<li key={c.field}>
|
||
<b>{labelOf(c.field)}</b>:
|
||
<span className="old">{c.old_value || '—'}</span>
|
||
{' → '}
|
||
<span className="new">{c.new_value || '—'}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
{r.status === 'pending' && (onApprove || onReject) && (
|
||
<div className="rev-actions">
|
||
{onApprove && (
|
||
<Button variant="primary" size="sm" onClick={() => onApprove(r.id)}>
|
||
通过
|
||
</Button>
|
||
)}
|
||
{onReject && (
|
||
<Button variant="danger" size="sm" onClick={() => onReject(r.id)}>
|
||
驳回
|
||
</Button>
|
||
)}
|
||
</div>
|
||
)}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
);
|
||
}
|