feat(teacher-portal): 完整实现 teacher-portal 微前端

包含 settings/students/api、graphql、mocks、ui-tokens 设计令牌等
This commit is contained in:
SpecialX
2026-07-10 19:10:20 +08:00
parent 14d836beb0
commit 1eacd1ed87
48 changed files with 3897 additions and 1056 deletions

View File

@@ -51,6 +51,12 @@ export type { UseToastReturn } from "./use-toast.js";
export { useTraceId } from "./use-trace-id.js";
export type { UseTraceIdReturn } from "./use-trace-id.js";
export {
useGraphQLClient,
GraphQLClientContext,
} from "./use-graphql-client.js";
export type { UseGraphQLClientReturn } from "./use-graphql-client.js";
// 共享类型
export type {
UserSession,

View File

@@ -18,10 +18,11 @@ export interface UserSession {
}
/**
* 数据范围(对齐 iam DataScope 6 级)
* 数据范围(对齐 ARB-001 §1.2 schema DataScope enum)
* 与 apps/teacher-portal/src/lib/graphql.ts DataScope 保持一致
*/
export type DataScope =
"ALL" | "SCHOOL" | "GRADE" | "CLASS" | "SUBJECT" | "SELF";
"SELF" | "CLASS" | "GRADE" | "SCHOOL" | "DISTRICT" | "ALL";
/**
* 权限点检查结果

View File

@@ -0,0 +1,53 @@
import { useContext, useMemo } from "react";
import type { Client } from "urql";
/**
* useGraphQLClient - 获取 urql client 单例
*
* 用途:从 Shell 注入的 GraphQLProvider Context 中获取 urql client。
* 总裁裁决 §2.17 方案 A:Shell(teacher-portal)暴露 GraphQLProvider,
* Remote(student/parent/admin)复用同一 client 单例,避免多实例 + 缓存不一致。
*
* 注意:本 hook 必须在 GraphQLProvider 内部调用,否则抛出错误。
*
* @example
* const client = useGraphQLClient();
* const [result] = useQuery({ query: DashboardQuery });
*
* MF 暴露:ARB-002 §2.2 exposes './useGraphQLClient'
*/
// GraphQLClientContext 由 Shell(apps/teacher-portal/src/app/providers.tsx)创建并注入。
// 此处通过 createContext 占位,Shell 在初始化时通过 Provider value 覆盖。
// 为避免 hooks 包直接依赖 urql(peerDependency),Context 值类型用 Client(urql 类型)。
// urql 在 apps/* 的 dependencies 中,通过 peerDependencies 声明。
import { createContext } from "react";
/**
* GraphQL Client Context
*
* Shell(teacher-portal)通过 <Context.Provider value={client}> 注入。
* Remote(student/parent/admin-portal)通过 MF shared 复用同一 Context 实例。
*/
export const GraphQLClientContext = createContext<Client | null>(null);
GraphQLClientContext.displayName = "GraphQLClientContext";
export interface UseGraphQLClientReturn {
/** urql client 单例 */
client: Client;
}
export function useGraphQLClient(): UseGraphQLClientReturn {
const client = useContext(GraphQLClientContext);
if (!client) {
throw new Error(
"useGraphQLClient 必须在 GraphQLProvider 内部调用。" +
"请确保组件树被 <GraphQLProvider> 包裹(apps/teacher-portal/src/app/providers.tsx)。",
);
}
return useMemo(() => ({ client }), [client]);
}