feat(frontend): M9 模态 UI(mode 系统+共享 store+WS 客户端 + chat(思维链/工具回显/情绪徽标)/code/Agent 监控/后台思考页 + Miuix 设计 token + PWA);tsc+vite build 通过
This commit is contained in:
1 parent
b3ffd51736
commit
4c48e94659
40 files changed
+5321
No files matched your search
@@ -0,0 +1,82 @@
|
||||
import { useRef, useState } from "react";
|
||||
import { Button, Surface, EmptyState, Tag } from "../components/primitives";
|
||||
|
||||
export function VisionMode(): React.ReactNode {
|
||||
const [preview, setPreview] = useState<string | null>(null);
|
||||
const [analyzing, setAnalyzing] = useState(false);
|
||||
const [tags, setTags] = useState<string[]>([]);
|
||||
const fileRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const onFile = (file: File | undefined) => {
|
||||
if (!file) return;
|
||||
setPreview(URL.createObjectURL(file));
|
||||
setTags([]);
|
||||
};
|
||||
|
||||
const analyze = () => {
|
||||
if (!preview) return;
|
||||
setAnalyzing(true);
|
||||
// 占位分析:真实实现会调用视觉模型,此处演示加载态并给出结果。
|
||||
window.setTimeout(() => {
|
||||
setAnalyzing(false);
|
||||
setTags(["图像", "占位分析", "视觉模型待接入"]);
|
||||
}, 900);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-3xl space-y-5 p-4">
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold">视觉</h2>
|
||||
<p className="text-sm text-[var(--mu-text-lo)]">图像分析</p>
|
||||
</div>
|
||||
|
||||
<input
|
||||
ref={fileRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
className="hidden"
|
||||
onChange={(e) => onFile(e.target.files?.[0])}
|
||||
/>
|
||||
|
||||
<button
|
||||
onClick={() => fileRef.current?.click()}
|
||||
className="flex min-h-[16rem] w-full flex-col items-center justify-center gap-3 rounded-[var(--mu-radius-lg)] border border-dashed border-[var(--mu-glass-border)] bg-[var(--mu-surface-2)]/40 p-4"
|
||||
>
|
||||
{preview ? (
|
||||
<img src={preview} alt="预览" className="max-h-64 rounded-[var(--mu-radius)] object-contain" />
|
||||
) : (
|
||||
<EmptyState icon="👁" title="点击上传图片" hint="支持拖拽/点选,占位实现,视觉模型待接入" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="primary" onClick={analyze} disabled={!preview || analyzing}>
|
||||
{analyzing ? "分析中…" : "开始分析"}
|
||||
</Button>
|
||||
{preview ? (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
if (preview) URL.revokeObjectURL(preview);
|
||||
setPreview(null);
|
||||
setTags([]);
|
||||
}}
|
||||
>
|
||||
清除
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{tags.length > 0 ? (
|
||||
<Surface className="flex flex-wrap items-center gap-2">
|
||||
<span className="text-xs text-[var(--mu-text-lo)]">识别结果</span>
|
||||
{tags.map((t) => (
|
||||
<Tag key={t} tone="accent">
|
||||
{t}
|
||||
</Tag>
|
||||
))}
|
||||
</Surface>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user