feat: 思考过程展示优化 — 先展开再自动收拢

AiProcessBlock 改进:
- 超时从 2.6s 延至 6s,用户有充足时间阅读思考链路
- 新增 aiProcessPulse 脉冲高亮动画,强调'思考过程刚出炉'
- 展开时自动 scrollIntoView,确保不被正文遮挡
- 摘要文案改为'AI 思考 / 执行过程(N步 — 自动收拢中...)'

CSS 新增:
- .ai-process-fresh 脉冲动画 + summary 文字高亮
- @keyframes aiProcessPulse: 0→50%→100% 边框扩散+收拢
This commit is contained in:
QihuAI Design committed 2026-07-23 22:00:49 +08:00
1 parent 9d67b0544c
commit 2721da5d4c
2 files changed
+43 -5

No files matched your search

+24
View File
@@ -1574,6 +1574,30 @@ del {
border-color: color-mix(in srgb, var(--color-accent, #5B5FED) 35%, transparent); border-color: color-mix(in srgb, var(--color-accent, #5B5FED) 35%, transparent);
} }
/* 新鲜出炉的思考面板 — 脉冲高亮动画 */
.ai-process-fresh {
animation: aiProcessPulse 1.2s ease-out;
}
.ai-process-fresh .ai-process-summary {
color: var(--color-accent, #5B5FED);
font-weight: 700;
}
@keyframes aiProcessPulse {
0% {
box-shadow: 0 0 0 0 rgba(91, 95, 237, 0.4);
border-color: var(--color-accent, #5B5FED);
}
50% {
box-shadow: 0 0 0 6px rgba(91, 95, 237, 0.08);
border-color: color-mix(in srgb, var(--color-accent, #5B5FED) 60%, transparent);
}
100% {
box-shadow: 0 6px 22px rgba(91, 95, 237, 0.10);
border-color: color-mix(in srgb, var(--color-accent, #5B5FED) 35%, transparent);
}
}
.ai-process-summary { .ai-process-summary {
list-style: none; list-style: none;
cursor: pointer; cursor: pointer;
+19 -5
View File
@@ -478,22 +478,35 @@ const Dropdown: React.FC<DropdownProps> = ({ trigger, children, className = '',
// ===== AI 思考 / 执行过程面板(顶部展开 + 自动收拢) ===== // ===== AI 思考 / 执行过程面板(顶部展开 + 自动收拢) =====
// autoExpand=true 时(本轮刚产生的助手消息)首屏展开呈现思考链路, // autoExpand=true 时(本轮刚产生的助手消息)首屏展开呈现思考链路,
// 2.6s 后若用户未手动干预则自动收拢为一行摘要,避免与回复内容冲突。 // 6s 后若用户未手动干预则自动收拢为一行摘要,避免与回复内容冲突。
// 展开时自动滚动到视图内,带脉冲动画提示用户注意。
const AiProcessBlock: React.FC<{ steps: any[]; autoExpand: boolean }> = ({ steps, autoExpand }) => { const AiProcessBlock: React.FC<{ steps: any[]; autoExpand: boolean }> = ({ steps, autoExpand }) => {
const [open, setOpen] = useState(autoExpand); const [open, setOpen] = useState(autoExpand);
const [fresh, setFresh] = useState(autoExpand);
const timerRef = useRef<number | null>(null); const timerRef = useRef<number | null>(null);
const touchedRef = useRef(false); const touchedRef = useRef(false);
const blockRef = useRef<HTMLDetailsElement>(null);
useEffect(() => { useEffect(() => {
if (!autoExpand) { if (!autoExpand) {
setOpen(false); setOpen(false);
setFresh(false);
return; return;
} }
setOpen(true); setOpen(true);
setFresh(true);
touchedRef.current = false; touchedRef.current = false;
// 自动滚动到视图内(上方留 60px 避免被顶部遮挡)
if (blockRef.current) {
blockRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
timerRef.current = window.setTimeout(() => { timerRef.current = window.setTimeout(() => {
if (!touchedRef.current) setOpen(false); if (!touchedRef.current) {
}, 2600); setOpen(false);
// 收拢后短暂保留 fresh 样式再移除
setTimeout(() => setFresh(false), 500);
}
}, 6000);
return () => { return () => {
if (timerRef.current) window.clearTimeout(timerRef.current); if (timerRef.current) window.clearTimeout(timerRef.current);
}; };
@@ -503,6 +516,7 @@ const AiProcessBlock: React.FC<{ steps: any[]; autoExpand: boolean }> = ({ steps
const toggle = () => { const toggle = () => {
touchedRef.current = true; touchedRef.current = true;
setFresh(false);
if (timerRef.current) { if (timerRef.current) {
window.clearTimeout(timerRef.current); window.clearTimeout(timerRef.current);
timerRef.current = null; timerRef.current = null;
@@ -511,10 +525,10 @@ const AiProcessBlock: React.FC<{ steps: any[]; autoExpand: boolean }> = ({ steps
}; };
return ( return (
<details className="ai-process" open={open}> <details ref={blockRef} className={`ai-process${open ? '' : ''}${fresh ? ' ai-process-fresh' : ''}`} open={open}>
<summary className="ai-process-summary" onClick={(e) => { e.preventDefault(); toggle(); }}> <summary className="ai-process-summary" onClick={(e) => { e.preventDefault(); toggle(); }}>
<span className="ai-process-badge">🧠</span> <span className="ai-process-badge">🧠</span>
思考 / 执行过程({steps.length} 步,{open ? '点击收起' : '点击展开'}) AI 思考 / 执行过程({steps.length} 步 — {open ? '自动收拢中... 点击手动收起' : '点击展开查看'})
</summary> </summary>
<div className="ai-process-list"> <div className="ai-process-list">
{steps.map((s: any, i: number) => ( {steps.map((s: any, i: number) => (