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:
@@ -8,12 +8,9 @@ import { ReportList } from "@/modules/diagnostic/components/report-list"
|
||||
import {
|
||||
DiagnosticServiceProvider,
|
||||
} from "@/modules/diagnostic/services/diagnostic-service-context"
|
||||
import { defaultDiagnosticService } from "@/modules/diagnostic/services/default-diagnostic-service"
|
||||
import { createMonitoredDiagnosticService } from "@/modules/diagnostic/services/monitored-diagnostic-service"
|
||||
import {
|
||||
DiagnosticMonitorProvider,
|
||||
} from "@/modules/diagnostic/services/diagnostic-monitor-context"
|
||||
import { noopDiagnosticMonitor } from "@/modules/diagnostic/services/diagnostic-monitor"
|
||||
import type { DiagnosticReportType, DiagnosticReportStatus } from "@/modules/diagnostic/types"
|
||||
|
||||
export const dynamic = "force-dynamic"
|
||||
@@ -64,11 +61,8 @@ export default async function TeacherDiagnosticPage({
|
||||
// v2-P2-2: 移除客户端 filter,DataScope 过滤已在 data-access 层完成
|
||||
// class_members scope 的学生已通过 filters.studentId 在 data-access 层过滤
|
||||
|
||||
// v2-P2-7: 包装默认服务以添加监控埋点(默认 no-op,生产环境可注入真实实现)
|
||||
const monitoredService = createMonitoredDiagnosticService(
|
||||
defaultDiagnosticService,
|
||||
noopDiagnosticMonitor,
|
||||
)
|
||||
// v2-P2-7: service 组装移至 DiagnosticServiceProvider(客户端),
|
||||
// 避免 server component 创建含函数的对象传给 client component。
|
||||
|
||||
return (
|
||||
<div className="h-full flex-1 flex-col space-y-8 p-8 md:flex">
|
||||
@@ -78,8 +72,8 @@ export default async function TeacherDiagnosticPage({
|
||||
{t("title.teacherReportListDesc")}
|
||||
</p>
|
||||
</div>
|
||||
<DiagnosticMonitorProvider monitor={noopDiagnosticMonitor}>
|
||||
<DiagnosticServiceProvider service={monitoredService}>
|
||||
<DiagnosticMonitorProvider>
|
||||
<DiagnosticServiceProvider>
|
||||
<ReportList reports={reports.reports} />
|
||||
</DiagnosticServiceProvider>
|
||||
</DiagnosticMonitorProvider>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client"
|
||||
|
||||
import type { ActionState } from "@/shared/types/action-state"
|
||||
|
||||
import {
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
"use client"
|
||||
|
||||
/**
|
||||
* v2-P2-7: 带监控埋点的诊断服务工厂。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user