feat(diagnostic): refactor services with monitor and context providers

- Update default-diagnostic-service.ts

- Update diagnostic-monitor-context.tsx

- Update diagnostic-service-context.tsx

- Update monitored-diagnostic-service.ts

- Update teacher diagnostic page
This commit is contained in:
SpecialX
2026-07-04 10:22:48 +08:00
parent eee0145274
commit b63d116b6c
5 changed files with 42 additions and 23 deletions

View File

@@ -1,5 +1,3 @@
"use client"
import type { ActionState } from "@/shared/types/action-state"
import {

View File

@@ -10,13 +10,22 @@
* 默认值为 noopDiagnosticMonitor不发送任何事件
* 确保未注入 Provider 时业务流程不受影响。
*
* 注意monitor prop 为可选Server Component 不应传递含函数的对象。
* 若需注入真实监控实现,请在 Client Component 内部使用。
*
* 用法:
* ```tsx
* <DiagnosticMonitorProvider monitor={postHogMonitor}>
* <DiagnosticServiceProvider service={defaultDiagnosticService}>
* // Server Component不传 monitor
* <DiagnosticMonitorProvider>
* <DiagnosticServiceProvider>
* <ReportList />
* </DiagnosticServiceProvider>
* </DiagnosticMonitorProvider>
*
* // Client Component可注入真实实现
* <DiagnosticMonitorProvider monitor={postHogMonitor}>
* ...
* </DiagnosticMonitorProvider>
* ```
*/
@@ -32,8 +41,12 @@ const DiagnosticMonitorContext = createContext<DiagnosticMonitor>(
)
interface DiagnosticMonitorProviderProps {
/** 监控实现(默认使用 noop生产环境注入真实实现 */
monitor: DiagnosticMonitor
/**
* 监控实现(可选)。
* 未传时使用 noopDiagnosticMonitor。
* Server Component 不要传此 prop含函数无法跨边界传递
*/
monitor?: DiagnosticMonitor
children: ReactNode
}
@@ -41,8 +54,9 @@ export function DiagnosticMonitorProvider({
monitor,
children,
}: DiagnosticMonitorProviderProps): ReactNode {
const value = monitor ?? noopDiagnosticMonitor
return (
<DiagnosticMonitorContext.Provider value={monitor}>
<DiagnosticMonitorContext.Provider value={value}>
{children}
</DiagnosticMonitorContext.Provider>
)

View File

@@ -1,8 +1,12 @@
"use client"
import { createContext, useContext, type ReactNode } from "react"
import { createContext, useContext, useMemo, type ReactNode } from "react"
import type { DiagnosticService } from "./diagnostic-service"
import { defaultDiagnosticService } from "./default-diagnostic-service"
import { createMonitoredDiagnosticService } from "./monitored-diagnostic-service"
import { noopDiagnosticMonitor } from "./diagnostic-monitor"
import { useDiagnosticMonitor } from "./diagnostic-monitor-context"
/**
* v2-P1-4: 诊断模块服务 Context。
@@ -10,13 +14,14 @@ import type { DiagnosticService } from "./diagnostic-service"
* 组件通过 useDiagnosticService() 获取服务实现,
* 而非直接 import actions实现依赖反转。
*
* 默认由 DefaultDiagnosticServiceProvider 注入真实实现(调用 Server Actions
* 默认由 DiagnosticServiceProvider 在客户端组装默认实现(调用 Server Actions
* 测试时可注入 mock 实现以隔离组件测试。
*/
const DiagnosticServiceContext = createContext<DiagnosticService | null>(null)
interface DiagnosticServiceProviderProps {
service: DiagnosticService
/** 可选自定义服务实现,未传则使用 defaultDiagnosticService + 监控包装 */
service?: DiagnosticService
children: ReactNode
}
@@ -24,8 +29,18 @@ export function DiagnosticServiceProvider({
service,
children,
}: DiagnosticServiceProviderProps): ReactNode {
const monitor = useDiagnosticMonitor()
const value = useMemo<DiagnosticService>(() => {
if (service) return service
// 客户端组装:默认 service + 监控埋点包装
return createMonitoredDiagnosticService(
defaultDiagnosticService,
monitor ?? noopDiagnosticMonitor,
)
}, [service, monitor])
return (
<DiagnosticServiceContext.Provider value={service}>
<DiagnosticServiceContext.Provider value={value}>
{children}
</DiagnosticServiceContext.Provider>
)

View File

@@ -1,5 +1,3 @@
"use client"
/**
* v2-P2-7: 带监控埋点的诊断服务工厂。
*