feat: improve app ui and project metadata

This commit is contained in:
Yaojia Wang
2026-06-28 07:31:20 +02:00
parent 3bd464d400
commit 90a66437d7
86 changed files with 4892 additions and 1108 deletions

View File

@@ -1,10 +1,14 @@
"use client";
import Link from "next/link";
import { ArrowRight, CheckCircle2, ListTree } from "lucide-react";
import { Button } from "@/components/ui/Button";
import { StatusNote } from "@/components/ui/StatusNote";
import type { AcceptResponse } from "@/lib/api/types";
import { buildAcceptPreview } from "@/lib/review/accept-preview";
import { ThinkingIndicator } from "@/components/ThinkingIndicator";
import { buttonClass } from "@/lib/ui/variants";
interface AcceptPanelProps {
projectId: string;
@@ -42,40 +46,50 @@ export function AcceptPanel({
if (result) {
return (
<div className="rounded border border-pass/50 bg-panel p-4">
<h3 className="mb-2 text-sm font-semibold text-pass"></h3>
<ul className="space-y-1 text-xs text-ink-soft">
<li>
<span className="font-mono text-ink">v{result.accepted_version}</span>
</li>
<li>
{result.digest_added ? "已新增一行" : "未变更"}
</li>
<li>
<span className="font-mono text-ink">
<StatusNote variant="success" title="本章已验收">
<p className="text-sm leading-6">
稿
</p>
</StatusNote>
<dl className="mt-3 grid grid-cols-3 gap-2 text-center">
<div className="rounded border border-line bg-bg/60 p-2">
<dt className="text-[11px] text-ink-soft"></dt>
<dd className="mt-1 font-mono text-sm text-ink">
v{result.accepted_version}
</dd>
</div>
<div className="rounded border border-line bg-bg/60 p-2">
<dt className="text-[11px] text-ink-soft"></dt>
<dd className="mt-1 text-sm text-ink">
{result.digest_added ? "已新增" : "未变更"}
</dd>
</div>
<div className="rounded border border-line bg-bg/60 p-2">
<dt className="text-[11px] text-ink-soft"></dt>
<dd className="mt-1 font-mono text-sm text-ink">
{result.decisions_recorded}
</span>{" "}
</li>
{result.review_id ? (
<li className="truncate">
<span className="font-mono">{result.review_id}</span>
</li>
) : null}
</ul>
</dd>
</div>
</dl>
{result.review_id ? (
<p className="mt-2 truncate text-[11px] text-ink-soft">
<span className="font-mono">{result.review_id}</span>
</p>
) : null}
{/* 验收闭环 → 写下一章入口(修「验收后无路可走」的断点)。 */}
<div className="mt-3 flex flex-wrap items-center gap-2">
<Link
href={`/projects/${projectId}/write?chapter=${chapterNo + 1}`}
className="rounded bg-cinnabar px-4 py-2 text-sm text-panel hover:opacity-90"
className={buttonClass({ variant: "primary" })}
>
{chapterNo + 1}
<ArrowRight className="h-4 w-4" aria-hidden="true" />
{chapterNo + 1}
</Link>
<Link
href={`/projects/${projectId}/outline`}
className="rounded border border-line px-4 py-2 text-sm text-ink hover:border-cinnabar hover:text-cinnabar"
className={buttonClass({ variant: "secondary" })}
>
<ListTree className="h-4 w-4" aria-hidden="true" />
</Link>
</div>
@@ -84,20 +98,24 @@ export function AcceptPanel({
}
return (
<div className="rounded border border-line bg-panel p-4">
<div
className={`rounded border bg-panel p-4 ${
blocked ? "border-conflict/35" : "border-line"
}`}
>
{blocked ? (
<p className="mb-2 text-xs text-conflict" role="status">
<StatusNote className="mb-3" variant="danger" role="status">
{unresolvedCount}
</p>
</StatusNote>
) : (
<>
<p className="mb-2 text-xs text-ink-soft">
<StatusNote className="mb-3" variant={reviewed ? "success" : "info"}>
{conflictCount === 0
? reviewed
? "无冲突,可直接验收。"
: "尚未审稿——建议先点「重新审稿」确认本章无冲突,再验收。"
: "全部冲突已裁决,可验收本章。"}
</p>
</StatusNote>
{/* R3验收前「本次将更新」清单预期落库口径以验收回执为准。 */}
<div className="mb-3 rounded border border-line/70 bg-bg/50 p-3">
<h4 className="mb-1.5 text-xs font-semibold text-ink">
@@ -122,19 +140,22 @@ export function AcceptPanel({
</div>
</>
)}
<button
type="button"
<Button
onClick={onAccept}
disabled={blocked || accepting}
aria-disabled={blocked || accepting}
className="w-full rounded bg-cinnabar px-4 py-2 text-sm text-panel hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40"
variant="primary"
className="w-full"
>
{accepting ? (
<ThinkingIndicator label="验收中" className="justify-center" />
) : (
"全部处理完 → 验收本章"
<>
<CheckCircle2 className="h-4 w-4" aria-hidden="true" />
</>
)}
</button>
</Button>
</div>
);
}