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

@@ -0,0 +1,53 @@
import { useContext, useMemo } from "react";
import type { Client } from "urql";
/**
* useGraphQLClient - 获取 urql client 单例
*
* 用途:从 Shell 注入的 GraphQLProvider Context 中获取 urql client。
* 总裁裁决 §2.17 方案 AShellteacher-portal暴露 GraphQLProvider
* Remotestudent/parent/admin复用同一 client 单例,避免多实例 + 缓存不一致。
*
* 注意:本 hook 必须在 GraphQLProvider 内部调用,否则抛出错误。
*
* @example
* const client = useGraphQLClient();
* const [result] = useQuery({ query: DashboardQuery });
*
* MF 暴露ARB-002 §2.2 exposes './useGraphQLClient'
*/
// GraphQLClientContext 由 Shellapps/teacher-portal/src/app/providers.tsx创建并注入。
// 此处通过 createContext 占位Shell 在初始化时通过 Provider value 覆盖。
// 为避免 hooks 包直接依赖 urqlpeerDependencyContext 值类型用 Clienturql 类型)。
// urql 在 apps/* 的 dependencies 中,通过 peerDependencies 声明。
import { createContext } from "react";
/**
* GraphQL Client Context
*
* Shellteacher-portal通过 <Context.Provider value={client}> 注入。
* Remotestudent/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]);
}