- shadcn/ui 标准化:废弃纸感令牌,统一 bg-background/text-foreground 等 - Tailwind v4 + @theme inline,移除 tailwind.config.js - React 19 use() + Suspense 流式渲染,首屏骨架秒出 - 三级错误边界:Route → Section → Widget 层层兜底 - 错误上报:useErrorReport → sendBeacon → /api/log mock 端点 - 三层安全边界:L1 角色门禁 / L2 权限点门禁 / L3 数据范围 - 权限位图 base36 压缩:67 权限点 → ~14 字符,JWT 体积减少 ≥ 99% - notify 统一 Toast 封装,禁止业务直接 import sonner - PluginBoundary 替代 PluginLoader(错误边界 + Suspense + Skeleton 三件套) 验证:typecheck 0 错误 / lint 0 错误 / build 6 路由生成成功
66 lines
1.6 KiB
TypeScript
66 lines
1.6 KiB
TypeScript
import { useMemo } from "react";
|
||
import type { Viewport } from "./types";
|
||
|
||
/**
|
||
* useViewports - 视口列表查询
|
||
*
|
||
* 用途:按 scope 过滤当前用户的可用视口(iam 4 层视口模型)。
|
||
* 视口数据由调用方注入(apps/* 从 iam /iam/viewports 获取后传入)。
|
||
*
|
||
* iam 视口 4 层:admin / teacher / student / parent
|
||
*
|
||
* @example
|
||
* const { viewports, getByType, hasViewport } = useViewports({ viewports });
|
||
* const teacherViewports = getByType("teacher");
|
||
*/
|
||
|
||
export interface UseViewportsProps {
|
||
/** 当前用户的视口列表(从 iam 获取) */
|
||
viewports: Viewport[] | null;
|
||
}
|
||
|
||
export interface UseViewportsReturn {
|
||
/** 全部视口 */
|
||
viewports: Viewport[];
|
||
/** 按类型过滤 */
|
||
getByType: (type: Viewport["type"]) => Viewport[];
|
||
/** 检查是否拥有指定类型视口 */
|
||
hasViewport: (type: Viewport["type"]) => boolean;
|
||
/** 按 ID 查找 */
|
||
getById: (id: string) => Viewport | undefined;
|
||
}
|
||
|
||
export function useViewports({
|
||
viewports: input,
|
||
}: UseViewportsProps): UseViewportsReturn {
|
||
const viewports = useMemo(() => input ?? [], [input]);
|
||
|
||
const getByType = useMemo(
|
||
() =>
|
||
(type: Viewport["type"]): Viewport[] =>
|
||
viewports.filter((v) => v.type === type),
|
||
[viewports],
|
||
);
|
||
|
||
const hasViewport = useMemo(
|
||
() =>
|
||
(type: Viewport["type"]): boolean =>
|
||
viewports.some((v) => v.type === type),
|
||
[viewports],
|
||
);
|
||
|
||
const getById = useMemo(
|
||
() =>
|
||
(id: string): Viewport | undefined =>
|
||
viewports.find((v) => v.id === id),
|
||
[viewports],
|
||
);
|
||
|
||
return {
|
||
viewports,
|
||
getByType,
|
||
hasViewport,
|
||
getById,
|
||
};
|
||
}
|