feat: 接入运维真实数据与三角色权限链路

- 新增 model_deploy 与 model_operations 双库查询,支持模型列表、模型详情、单月监控结果和运维工作台真实接口。

- 关闭运维模块生产 Mock 数据,补充缺表/空数据降级、工作台空状态和首条纵向链路测试。

- 按业务团队、模型团队、管理员权限矩阵接入菜单、页面、操作按钮和后端接口权限校验,支持 business_team 角色。

- 更新工作台布局、深色欢迎卡片、全宽页面适配、顶部回退,以及权限分组展示。

- 新增架构实现基线、周目标完成情况和角色权限矩阵初始化 SQL 文档。
This commit is contained in:
郑龙捷
2026-09-02 15:02:47 +08:00
parent 6d044784ec
commit 74dd97428f
51 changed files with 2142 additions and 1062 deletions
+21 -2
View File
@@ -83,7 +83,7 @@ function NavRow({
}) {
const itemIcon = <item.icon />;
const childActivePath = (child: NavigationItem) =>
child.activePath ?? pathForPage(child.page);
child.activePath ?? (child.sub ? `${pathForPage(child.page)}/${child.sub}` : pathForPage(child.page));
const childIsActive = (child: NavigationItem) => {
const activePath = childActivePath(child);
return pathname === activePath || Boolean(child.sub && pathname.startsWith(`${activePath}/`));
@@ -208,6 +208,7 @@ function AuthenticatedLayout() {
const setWorkspaceMenuOpen = useUiStore((s) => s.setWorkspaceMenuOpen);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [operationsServiceOnline, setOperationsServiceOnline] = useState(false);
const bindingGeneration = useRef(0);
const can = usePermission;
@@ -245,6 +246,20 @@ function AuthenticatedLayout() {
// 心跳 / cleanup / 切页结束编辑 / 卸载前释放
useEditSessionLifecycle({ activePage });
useEffect(() => {
if (activePage !== "operations") return;
const controller = new AbortController();
void fetch("/api/v1/health", {
credentials: "same-origin",
signal: controller.signal,
})
.then((response) => setOperationsServiceOnline(response.ok))
.catch(() => {
if (!controller.signal.aborted) setOperationsServiceOnline(false);
});
return () => controller.abort();
}, [activePage]);
// 原 common/Sidebar 的编辑会话守卫上移到这里:切出 /scripts 时有活动编辑
// 会话先 endEditing,回工作台时清空选中脚本;再按当前激活页导航。
function guardedNavigate(targetPath: string) {
@@ -312,7 +327,7 @@ function AuthenticatedLayout() {
<SidebarInset className="h-screen min-w-0">
<Topbar
pageTitle={pageTitle}
apiOnline={apiOnline}
apiOnline={activePage === "operations" ? operationsServiceOnline : apiOnline}
user={user}
currentWorkspace={effectiveWorkspace}
workspaces={effectiveWorkspaces}
@@ -320,6 +335,10 @@ function AuthenticatedLayout() {
onSetWorkspaceMenuOpen={setWorkspaceMenuOpen}
onSetCurrentWorkspace={setCurrentWorkspace}
onLogout={logout}
onBack={() => {
if (window.history.length > 1) navigate(-1);
else navigate("/workbench");
}}
/>
<Outlet />