refactor(web): 前端单页收敛修正——导航式侧边栏 + 去输入模式 chip,mode 由后端自切
按设计/01 §3 + 主人要求:行为模式切换由后端/agent 自切(热切换),前端不再提供 手动切换的行为模式按钮列表。 - 侧边栏改为导航式(连接状态 / 设置 / 管理面板 / 主题),不再列行为模式按钮; App.tsx 还原 <Sidebar/> 布局。 - ChatInput 去掉行为模式 chip 切换条(模式不由用户手选)。 - useChat.send/chatStream 不再传 mode;消息 mode 由后端在回复时决定, MessageBubble 仍按 message.mode 渲染。 - ChatShell onVoice 为占位(语音处理在 agent)。
This commit is contained in:
1 parent
4aab0f501a
commit
77f75b0d99
6 files changed
+105
-129
No files matched your search
@@ -1,25 +1,14 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Button } from "./primitives";
|
||||
import { Icon, type IconName } from "./Icon";
|
||||
import { useModeStore } from "../store/useModeStore";
|
||||
import type { Mode } from "../lib/types";
|
||||
import { Icon } from "./Icon";
|
||||
|
||||
export interface ChatInputProps {
|
||||
onSend: (text: string, mode: Mode) => void;
|
||||
onSend: (text: string) => void;
|
||||
sending: boolean;
|
||||
onVoice: () => void;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const INPUT_MODES: ReadonlyArray<{ mode: Mode; label: string; icon: IconName }> = [
|
||||
{ mode: "chat", label: "对话", icon: "chat" },
|
||||
{ mode: "code", label: "代码", icon: "terminal" },
|
||||
{ mode: "home", label: "家居", icon: "home" },
|
||||
{ mode: "work", label: "工作", icon: "folder" },
|
||||
{ mode: "docs", label: "知识库", icon: "docs" },
|
||||
{ mode: "vision", label: "视觉", icon: "vision" },
|
||||
];
|
||||
|
||||
export function ChatInput({
|
||||
onSend,
|
||||
sending,
|
||||
@@ -28,8 +17,6 @@ export function ChatInput({
|
||||
}: ChatInputProps): React.ReactNode {
|
||||
const [value, setValue] = useState("");
|
||||
const taRef = useRef<HTMLTextAreaElement>(null);
|
||||
const mode = useModeStore((s) => s.mode);
|
||||
const setMode = useModeStore((s) => s.setMode);
|
||||
|
||||
// auto-grow the textarea up to a max height
|
||||
useEffect(() => {
|
||||
@@ -42,31 +29,12 @@ export function ChatInput({
|
||||
const submit = () => {
|
||||
const t = value.trim();
|
||||
if (!t || sending) return;
|
||||
onSend(t, mode);
|
||||
onSend(t);
|
||||
setValue("");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="glass sticky bottom-0 border-t border-[var(--mu-glass-border)] p-3 md:p-4">
|
||||
{/* input-mode switcher: sets the mode for the NEXT message (design/07 §1). */}
|
||||
<div className="mx-auto mb-2 flex max-w-2xl items-center gap-1 overflow-x-auto pb-0.5">
|
||||
<span className="mr-1 shrink-0 text-[10px] text-[var(--mu-text-lo)]">行为模式</span>
|
||||
{INPUT_MODES.map(({ mode: m, label, icon }) => (
|
||||
<button
|
||||
key={m}
|
||||
onClick={() => setMode(m)}
|
||||
className={`inline-flex shrink-0 items-center gap-1 rounded-[var(--mu-radius-pill)] px-2.5 py-1 text-xs transition-all duration-200 ease-[var(--mu-spring)] active:scale-95 ${
|
||||
mode === m
|
||||
? "bg-[var(--mu-accent)]/15 text-[var(--mu-accent-hi)]"
|
||||
: "bg-[var(--mu-surface-4)] text-[var(--mu-text-mid)] hover:bg-[var(--mu-surface-5)]"
|
||||
}`}
|
||||
>
|
||||
<Icon name={icon} size={13} />
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="mx-auto flex max-w-2xl items-end gap-2 rounded-[var(--mu-radius-lg)] bg-[var(--mu-surface-2)] p-2 shadow-[var(--mu-shadow-1)]">
|
||||
<textarea
|
||||
ref={taRef}
|
||||
|
||||
Reference in new issue
Block a user