feat(frontend/admin): M10 后台管理面板(/admin hash 路由 + 15 大模块 + RBAC(owner/admin/viewer) + 审计 + Miuix);Docs/api-client.md v0.3 契约补全;tsc+vite build 通过
This commit is contained in:
1 parent
4c48e94659
commit
f43eb17030
26 files changed
+2253
-4
No files matched your search
@@ -0,0 +1,72 @@
|
||||
import { useState } from "react";
|
||||
import { useAsyncData } from "../../lib/useAsyncData";
|
||||
import { adminListMemories } from "../../lib/api";
|
||||
import type { MemoryRecord } from "../../lib/types";
|
||||
import { useAutoReload } from "../hooks";
|
||||
import { useAuditStore } from "../audit";
|
||||
import { AdminTable, Notice, PageHeader, type AdminColumn } from "../components";
|
||||
import { Button, Surface, Tag } from "../../components/primitives";
|
||||
|
||||
const scopeTone: Record<string, "ok" | "warn" | "accent" | "neutral"> = {
|
||||
user: "accent",
|
||||
habitual: "ok",
|
||||
project: "warn",
|
||||
};
|
||||
|
||||
const columns: AdminColumn<MemoryRecord>[] = [
|
||||
{ key: "scope", title: "作用域", render: (m) => <Tag tone={scopeTone[m.scope] ?? "neutral"}>{m.scope}</Tag> },
|
||||
{ key: "text", title: "内容", render: (m) => <span className="block max-w-md truncate">{m.text}</span> },
|
||||
{ key: "id", title: "ID", render: (m) => <span className="font-mono text-xs text-[var(--mu-text-lo)]">{m.id}</span> },
|
||||
];
|
||||
|
||||
export function MemoriesModule(): React.ReactNode {
|
||||
const { data, loading, error, reload } = useAsyncData(adminListMemories, []);
|
||||
useAutoReload(reload, 15000);
|
||||
const [query, setQuery] = useState("");
|
||||
const log = useAuditStore((s) => s.log);
|
||||
|
||||
const filtered = (data ?? []).filter((m) => {
|
||||
if (!query.trim()) return true;
|
||||
const q = query.toLowerCase();
|
||||
return m.text.toLowerCase().includes(q) || m.scope.toLowerCase().includes(q) || m.id.toLowerCase().includes(q);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<PageHeader
|
||||
title="记忆管理"
|
||||
subtitle="GET /api/v1/admin/memories · 用户习惯(全局)/角色日常(只读)/项目(读写) 作用域隔离"
|
||||
actions={
|
||||
<Button
|
||||
variant="soft"
|
||||
onClick={() => {
|
||||
log("memory.vectorTest", "ok");
|
||||
alert("向量检索测试(占位):后端 M10+ 提供语义/向量路径。");
|
||||
}}
|
||||
>
|
||||
向量测试
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
<Surface className="space-y-3">
|
||||
<input
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="按内容 / 作用域 / ID 检索…"
|
||||
className="w-full rounded-[var(--mu-radius)] bg-[var(--mu-surface-2)] px-3 py-2 text-sm outline-none focus:ring-1 focus:ring-[var(--mu-accent)]"
|
||||
/>
|
||||
<AdminTable
|
||||
columns={columns}
|
||||
rows={loading ? null : filtered}
|
||||
loading={loading}
|
||||
error={error}
|
||||
emptyTitle="无记忆数据"
|
||||
rowKey={(m) => m.id}
|
||||
/>
|
||||
</Surface>
|
||||
|
||||
<Notice>编辑 / 删除 / 衰减 / 溯源为后端 M10+ 提供,当前只读。群聊 / 陌生人会话查记忆时只读不写、不入主会话上下文、不泄露主人敏感信息。</Notice>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user