feat(web): 生成器 ThinkingIndicator/空结果态/数量校验 + 文风页 PageHeader + Codex 分段控件 + RefineView role 修正

This commit is contained in:
Yaojia Wang
2026-06-30 08:56:23 +02:00
parent 68606b84dc
commit 9d67f237a2
7 changed files with 126 additions and 46 deletions

View File

@@ -3,6 +3,7 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import { Database, Sparkles } from "lucide-react";
import { ThinkingIndicator } from "@/components/ThinkingIndicator";
import { Button } from "@/components/ui/Button";
import { Field } from "@/components/ui/Field";
import { SectionHeader } from "@/components/ui/SectionHeader";
@@ -10,6 +11,7 @@ import { StatusNote } from "@/components/ui/StatusNote";
import { TextInput } from "@/components/ui/TextInput";
import type { CharacterCardView } from "@/lib/api/types";
import {
clampCharacterCount,
MAX_CHARACTER_COUNT,
MIN_CHARACTER_COUNT,
updateCard,
@@ -95,13 +97,19 @@ export function CharacterGenerator({
/>
</Field>
<div className="flex flex-wrap items-end gap-3">
<Field label="数量" className="w-24">
<Field
label="数量"
className="w-28"
help={`${MIN_CHARACTER_COUNT}${MAX_CHARACTER_COUNT}`}
>
<TextInput
type="number"
min={MIN_CHARACTER_COUNT}
max={MAX_CHARACTER_COUNT}
value={count}
onChange={(e) => setCount(Number(e.target.value))}
onChange={(e) =>
setCount(clampCharacterCount(Number(e.target.value)))
}
/>
</Field>
<Field label="定位(可选)" className="min-w-[12rem] flex-1">
@@ -113,7 +121,12 @@ export function CharacterGenerator({
</Field>
<Button
onClick={() => void onGenerate()}
disabled={generating || brief.trim().length === 0}
disabled={
generating ||
brief.trim().length === 0 ||
count < MIN_CHARACTER_COUNT ||
count > MAX_CHARACTER_COUNT
}
variant="primary"
>
<Sparkles className="h-4 w-4" aria-hidden="true" />
@@ -122,6 +135,12 @@ export function CharacterGenerator({
</div>
</div>
{generating ? (
<div className="rounded border border-line bg-panel/50 p-4 text-cinnabar">
<ThinkingIndicator label="生成中" />
</div>
) : null}
{gen.genStatus === "preview" && drafts.length > 0 ? (
<div className="flex flex-col gap-3">
<p className="text-xs text-ink-soft">