feat(asset-ai): simplify count answers and refine mobile conversation layout
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -30,7 +30,6 @@ import {
|
||||
} from "../../../shared/assets/assistant";
|
||||
import { askAssetAssistant, AssistantRequestError } from "./client";
|
||||
import { fetchAuthenticated } from "../../../auth/api-client";
|
||||
import { DemandGaps } from "./DemandGaps";
|
||||
import { ThinkingState } from "./ThinkingState";
|
||||
import { CompoundResultView } from "./CompoundResultView";
|
||||
import { BUSINESS_QUESTIONS, conversationTitle, findConversationResult, replaceAnalysisResult } from "./conversation-presentation";
|
||||
@@ -90,6 +89,23 @@ export default function AssetAssistant({
|
||||
close: () => void;
|
||||
appearance: "light" | "dark";
|
||||
}) {
|
||||
const page = useRef<HTMLElement>(null);
|
||||
useLayoutEffect(() => {
|
||||
const viewport = window.visualViewport;
|
||||
const updateViewport = () => {
|
||||
page.current?.style.setProperty('--aq-viewport-height', `${viewport?.height ?? window.innerHeight}px`);
|
||||
page.current?.style.setProperty('--aq-viewport-top', `${viewport?.offsetTop ?? 0}px`);
|
||||
};
|
||||
updateViewport();
|
||||
viewport?.addEventListener('resize', updateViewport);
|
||||
viewport?.addEventListener('scroll', updateViewport);
|
||||
window.addEventListener('resize', updateViewport);
|
||||
return () => {
|
||||
viewport?.removeEventListener('resize', updateViewport);
|
||||
viewport?.removeEventListener('scroll', updateViewport);
|
||||
window.removeEventListener('resize', updateViewport);
|
||||
};
|
||||
}, []);
|
||||
const [theme, setTheme] = useState(appearance);
|
||||
const [turns, setTurns] = useState<Turn[]>([]);
|
||||
const turnsRef = useRef(turns);
|
||||
@@ -110,7 +126,6 @@ export default function AssetAssistant({
|
||||
const [activeResult, setActiveResult] = useState<AssistantResult>();
|
||||
const sessionRef = useRef<string | undefined>(undefined);
|
||||
const sessions = useRef(new Map<string, string | null>());
|
||||
const [showGaps, setShowGaps] = useState(false);
|
||||
const nextId = useRef(0);
|
||||
const composer = useRef<HTMLTextAreaElement>(null);
|
||||
const scroller = useRef<HTMLDivElement>(null);
|
||||
@@ -189,7 +204,6 @@ export default function AssetAssistant({
|
||||
return () => controller.abort();
|
||||
}, []);
|
||||
const revealTurn = (id: number) => {
|
||||
setShowGaps(false);
|
||||
setExpandedTurns((old) => new Set(old).add(id));
|
||||
autoFollow.current = null;
|
||||
setViewedTurn(id);
|
||||
@@ -232,7 +246,6 @@ export default function AssetAssistant({
|
||||
action?: AssistantAction,
|
||||
) => {
|
||||
if (!message.trim() || abortRef.current) return;
|
||||
setShowGaps(false);
|
||||
setIndependent(false);
|
||||
const inlineTurn = action && base?.resultId
|
||||
? turnsRef.current.find(turn => !!findConversationResult([turn], base.resultId!))
|
||||
@@ -344,7 +357,6 @@ export default function AssetAssistant({
|
||||
).catch(() => {});
|
||||
sessionRef.current = undefined;
|
||||
setActiveResult(undefined);
|
||||
setShowGaps(false);
|
||||
setTurns([]);
|
||||
setExpandedTurns(new Set());
|
||||
setDraft("");
|
||||
@@ -355,6 +367,7 @@ export default function AssetAssistant({
|
||||
}, [subject]);
|
||||
return (
|
||||
<section
|
||||
ref={page}
|
||||
className={`aq-shell aq-page aq-${theme}`}
|
||||
aria-label="资产 AI 问数"
|
||||
>
|
||||
@@ -388,10 +401,6 @@ export default function AssetAssistant({
|
||||
返回资产总览
|
||||
<ArrowUpRight size={14} />
|
||||
</button>
|
||||
<button className="aq-nav" onClick={() => setShowGaps(true)}>
|
||||
<CircleHelp size={16} />
|
||||
待完善需求
|
||||
</button>
|
||||
<div className="aq-side-label aq-history-label">
|
||||
本次对话<span>{turns.length.toString().padStart(2, "0")}</span>
|
||||
</div>
|
||||
@@ -438,13 +447,6 @@ export default function AssetAssistant({
|
||||
<span className="aq-header-subtitle">你的资产分析助手</span>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
className="aq-icon-button"
|
||||
onClick={() => setShowGaps(!showGaps)}
|
||||
aria-label="查看待完善需求"
|
||||
>
|
||||
<History size={17} />
|
||||
</button>
|
||||
<button
|
||||
className="aq-icon-button aq-mobile-new"
|
||||
onClick={reset}
|
||||
@@ -509,9 +511,7 @@ export default function AssetAssistant({
|
||||
onTouchMove={() => { autoFollow.current = null; readerRevision.current++; }}
|
||||
onPointerDown={() => { autoFollow.current = null; readerRevision.current++; }}
|
||||
onKeyDown={(event) => { if (["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", " "].includes(event.key)) { autoFollow.current = null; readerRevision.current++; } }}>
|
||||
{showGaps ? (
|
||||
<DemandGaps close={() => setShowGaps(false)} />
|
||||
) : !turns.length ? (
|
||||
{!turns.length ? (
|
||||
<div className="aq-welcome">
|
||||
<div className="aq-welcome-mark">
|
||||
<Sparkles size={30} strokeWidth={1.3} />
|
||||
@@ -519,15 +519,14 @@ export default function AssetAssistant({
|
||||
<h2>关于资产,你想了解什么?</h2>
|
||||
<p>
|
||||
用一句话,发现数据里的答案。
|
||||
<br className="aq-mobile-break" />{" "}
|
||||
从全局统计,一路看到每一台车。
|
||||
<span className="aq-welcome-detail"> 从全局统计,一路看到每一台车。</span>
|
||||
</p>
|
||||
<div className="aq-prompt-grid">
|
||||
{PROMPTS.map((p) => (
|
||||
<button key={p.title} onClick={() => void ask(p.text)}>
|
||||
<div>
|
||||
<p.icon size={18} />
|
||||
<ArrowUpRight size={14} />
|
||||
<p.icon size={18} aria-hidden="true" />
|
||||
<ArrowUpRight size={14} aria-hidden="true" />
|
||||
</div>
|
||||
<strong>{p.title}</strong>
|
||||
<span>{p.detail}</span>
|
||||
@@ -711,13 +710,7 @@ export default function AssetAssistant({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="aq-waiting">
|
||||
<span />
|
||||
<span />
|
||||
<span />
|
||||
</div>
|
||||
)}
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user