feat(portal-shell): extract domain API layer and migrate 31 widgets

Task 4-10 of portal-shell data abstraction plan (M1-M2).

Add 7 domain API modules under src/lib/api/ (parent/admin/teacher/
student/universal/sidebar/topbar), each exposing semantic hooks that
wrap useWidgetQuery/useWidgetMutation and return flattened domain
models. Widget code now imports from @/lib/api instead of inlining
gql literals.

- 31 widgets migrated (gql literal count in widgets: 0)
- 7 test files (85 cases, all passing)
- topbar.useNotifications renamed to useNotificationBell to avoid
  barrel export collision with universal.useNotifications
- typecheck + lint (0 errors) + test (85/85) verified
This commit is contained in:
SpecialX
2026-07-17 13:07:24 +08:00
parent f623dcf4a7
commit 2910a90271
73 changed files with 8206 additions and 87 deletions

View File

@@ -0,0 +1,40 @@
/**
* invitation-codes 插件清单admin
*
* 邀请码管理,插入 main slot。生成/查看/撤销邀请码。
* 查询/变更经 apollo-router → iam 子图 invitationCodes。
*
* 关联portal-shell spec §3 admin 分类、§5.6 统一 Hook
*/
import type { PluginManifest } from "@/lib/types";
export const manifestMeta: Omit<PluginManifest, "Component"> = {
pluginId: "invitation-codes",
version: "0.1.0",
requiredShellVersion: "^1.0.0",
metadata: {
displayName: "邀请码",
description: "生成并管理用户注册邀请码,支持角色/有效期/次数配置",
category: "admin",
requiredRoles: ["admin"],
defaultSlot: "main",
defaultSize: { colSpan: 2, rowSpan: 1 },
defaultProps: {
defaultMaxUses: 1,
defaultTtlHours: 72,
},
propsSchema: {
type: "object",
properties: {
defaultMaxUses: {
type: "number",
description: "默认最大使用次数1=一次性,>1=批量)",
},
defaultTtlHours: {
type: "number",
description: "默认有效期(小时)",
},
},
},
},
};