fix: restore polished account experience and align AI with Lark design

This commit is contained in:
yuxuanhui
2026-09-07 23:31:23 +08:00
parent 3f3d417296
commit 7dcf46836f
23 changed files with 1669 additions and 807 deletions
+56 -26
View File
@@ -188,7 +188,12 @@ export function ChatPanel({
useEffect(() => {
if (!open) return;
previousFocus.current = document.activeElement as HTMLElement;
input.current?.querySelector("textarea")?.focus();
const textarea = input.current?.querySelector("textarea");
if (textarea && !textarea.disabled) textarea.focus();
else
root.current
?.querySelector<HTMLButtonElement>('button[aria-label="收起研究助手"]')
?.focus();
return () => {
requestAnimationFrame(() => {
if (
@@ -265,6 +270,7 @@ export function ChatPanel({
ref={root}
hidden={!open}
className="ai-chat"
id="research-assistant"
aria-label="AI 研究助手"
onKeyDown={(event) => {
if (event.key === "Escape") {
@@ -314,11 +320,13 @@ export function ChatPanel({
}}
/>
<header className="ai-header">
<div>
<strong>AI 研究助手</strong>
<span>与你一起查看、分析和记录</span>
</div>
<Button aria-label="收起研究助手" theme="borderless" onClick={onClose}>
<h2>AI 研究助手</h2>
<Button
type="tertiary"
aria-label="收起研究助手"
theme="borderless"
onClick={onClose}
>
收起
</Button>
</header>
@@ -337,7 +345,11 @@ export function ChatPanel({
}}
disabled={loading}
/>
<Button onClick={() => void createConversation()} disabled={loading}>
<Button
type="tertiary"
onClick={() => void createConversation()}
disabled={loading}
>
新会话
</Button>
</div>
@@ -359,10 +371,11 @@ export function ChatPanel({
{loading && <Spin />}
{!chat.messages.length && (
<div className="ai-empty">
<strong>从当前研究出发</strong>
<h3>从当前研究出发</h3>
<p>可以让我筛选 Alpha、解释已有指标,或提出研究记录修改。</p>
{!conversationId && (
<Button
type="tertiary"
onClick={() => void createConversation()}
disabled={loading}
>
@@ -451,7 +464,9 @@ export function ChatPanel({
<div className="ai-send">
<small>Enter 发送 · Shift + Enter 换行</small>
{activeRun ? (
<Button onClick={() => void stop()}>停止生成</Button>
<Button type="tertiary" onClick={() => void stop()}>
停止生成
</Button>
) : (
<Button
theme="solid"
@@ -513,7 +528,7 @@ function BusinessCard({
const openAlpha = (id: string) =>
onAction({ type: "open_alpha", alpha_id: id, nonce: Date.now() });
return (
<section className="ai-tool-card">
<section className="ai-tool-card" data-status={call.status}>
<div className="ai-card-title">
<strong>{toolLabels[call.name] ?? "业务操作"}</strong>
<Tag
@@ -546,8 +561,14 @@ function BusinessCard({
}[key]
}
</strong>
<del>{researchValue(key, target.before[key])}</del>
<ins>{researchValue(key, target.after[key])}</ins>
<del>
<span>修改前</span>
{researchValue(key, target.before[key])}
</del>
<ins>
<span>修改后</span>
{researchValue(key, target.after[key])}
</ins>
</div>
))}
</details>
@@ -569,20 +590,29 @@ function BusinessCard({
</p>
)}
{pending && (
<div className="inline-actions">
<Button
theme="solid"
disabled={disabled}
onClick={() => void onDecision(call.id, true)}
>
确认执行
</Button>
<Button
disabled={disabled}
onClick={() => void onDecision(call.id, false)}
>
拒绝
</Button>
<div className="ai-approval">
<p className="muted">
{call.preview.targets?.length
? `将修改 ${call.preview.targets.length} 条研究记录。`
: "将执行以上任务操作。"}
确认后执行。
</p>
<div className="inline-actions">
<Button
theme="solid"
disabled={disabled}
onClick={() => void onDecision(call.id, true)}
>
确认执行
</Button>
<Button
type="tertiary"
disabled={disabled}
onClick={() => void onDecision(call.id, false)}
>
拒绝
</Button>
</div>
</div>
)}
{typeof result.error === "string" && (