feat(asset-ai): simplify count answers and refine mobile conversation layout
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
shishengliang
2026-09-23 18:35:31 +08:00
parent fd514177c6
commit 5be6240bbf
13 changed files with 251 additions and 58 deletions
+20 -10
View File
@@ -1,7 +1,7 @@
// Adapted from Beautiful UI's MIT-licensed ThinkingState (Steps).
// Uses real server progress rather than the reference's timed demo sequence.
import { useEffect, useState } from "react";
import { Check, ChevronDown, LoaderCircle, Sparkles } from "lucide-react";
import { useEffect, useId, useState } from "react";
import { Check, ChevronDown, CircleAlert, LoaderCircle, Pause, Sparkles } from "lucide-react";
export function ThinkingState({
steps,
@@ -18,27 +18,30 @@ export function ThinkingState({
stopped?: boolean;
outcome?: string;
}) {
const traceId = useId();
const [manualExpanded, setExpanded] = useState<boolean | null>(null);
const [elapsed, setElapsed] = useState(0);
useEffect(() => {
if (!working) return;
const update = () => setElapsed((Date.now() - started) / 1000);
update();
const timer = window.setInterval(update, 100);
const timer = window.setInterval(update, 1000);
return () => window.clearInterval(timer);
}, [working, started]);
const expanded = manualExpanded ?? false;
const expanded = manualExpanded ?? working;
const StatusIcon = working ? LoaderCircle : stopped ? Pause : failed ? CircleAlert : Sparkles;
return (
<div className="aq-thinking">
<div className={`aq-thinking${working ? " aq-thinking-working" : ""}`} data-state={working ? "working" : stopped ? "stopped" : failed ? "failed" : "complete"}>
<button
type="button"
aria-expanded={expanded}
aria-controls={traceId}
onClick={() => setExpanded(!expanded)}
>
<Sparkles size={15} aria-hidden="true" />
<span className={working ? "aq-shimmer" : ""}>
<StatusIcon size={16} className={working ? "aq-spin" : ""} aria-hidden="true" />
<span className={`aq-thinking-title${working ? " aq-shimmer" : ""}`}>
{working
? steps.at(-1) || "正在分析"
? "正在分析"
: stopped
? "已由用户停止"
: failed
@@ -55,7 +58,10 @@ export function ThinkingState({
? "已回答"
: "分析完成"}
</span>
{elapsed > 0 && <span className="aq-time">{elapsed.toFixed(1)}s</span>}
<span className="aq-thinking-meta">
{steps.length > 0 && <span>{steps.length} 个步骤</span>}
{elapsed > 0 && <span className="aq-time">{Math.floor(elapsed)} 秒</span>}
</span>
<ChevronDown
size={14}
className={expanded ? "aq-rotated" : ""}
@@ -63,6 +69,7 @@ export function ThinkingState({
/>
</button>
<div
id={traceId}
className="aq-trace-collapse"
aria-hidden={!expanded}
style={{
@@ -72,14 +79,17 @@ export function ThinkingState({
>
<div className="aq-trace-clip">
<ol className="aq-trace">
{!steps.length && <li><span>{working ? "正在连接分析服务…" : "暂无执行步骤"}</span></li>}
{steps.map((step, index) => (
<li key={`${index}-${step}`}>
<li key={`${index}-${step}`} data-current={index === steps.length - 1}>
{working && index === steps.length - 1 ? (
<LoaderCircle
className="aq-spin"
size={14}
aria-hidden="true"
/>
) : index === steps.length - 1 && (failed || stopped) ? (
<StatusIcon size={14} aria-hidden="true" />
) : (
<Check size={14} aria-hidden="true" />
)}