From ceed71eca40f4c1de818dc5a8433c34bca56b38d Mon Sep 17 00:00:00 2001 From: zdl <3489966805@qq.com> Date: Fri, 21 Nov 2025 18:11:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BA=20TypeScript=20?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/types/metrics.ts | 349 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 src/types/metrics.ts diff --git a/src/types/metrics.ts b/src/types/metrics.ts new file mode 100644 index 00000000..d15fb72d --- /dev/null +++ b/src/types/metrics.ts @@ -0,0 +1,349 @@ +/** + * 性能指标相关的 TypeScript 类型定义 + * @module types/metrics + */ + +// ============================================================ +// Web Vitals 指标 +// ============================================================ + +/** + * Web Vitals 评级 + */ +export type MetricRating = 'good' | 'needs-improvement' | 'poor'; + +/** + * 单个 Web Vitals 指标 + */ +export interface WebVitalMetric { + /** 指标名称 (如 'LCP', 'FCP') */ + name: string; + /** 指标值(毫秒或分数) */ + value: number; + /** 评级 (good/needs-improvement/poor) */ + rating: MetricRating; + /** 与上周对比的差值 */ + delta?: number; + /** 测量时间戳 */ + timestamp: number; +} + +/** + * 完整的 Web Vitals 指标集合 + */ +export interface WebVitalsMetrics { + /** Largest Contentful Paint - 最大内容绘制时间 */ + LCP: WebVitalMetric; + /** First Contentful Paint - 首次内容绘制时间 */ + FCP: WebVitalMetric; + /** Cumulative Layout Shift - 累积布局偏移 */ + CLS: WebVitalMetric; + /** First Input Delay - 首次输入延迟 */ + FID: WebVitalMetric; + /** Time to First Byte - 首字节时间 */ + TTFB: WebVitalMetric; +} + +// ============================================================ +// 资源加载指标 +// ============================================================ + +/** + * 资源类型 + */ +export type ResourceType = 'script' | 'stylesheet' | 'image' | 'font' | 'document' | 'other'; + +/** + * 单个资源加载指标 + */ +export interface ResourceTiming { + /** 资源名称 */ + name: string; + /** 资源类型 */ + type: ResourceType; + /** 资源大小(字节) */ + size: number; + /** 加载耗时(毫秒) */ + duration: number; + /** 开始时间 */ + startTime: number; + /** 是否来自缓存 */ + fromCache: boolean; +} + +/** + * 资源加载统计 + */ +export interface ResourceStats { + /** JS 文件总大小(字节) */ + totalJsSize: number; + /** CSS 文件总大小(字节) */ + totalCssSize: number; + /** 图片总大小(字节) */ + totalImageSize: number; + /** 字体总大小(字节) */ + totalFontSize: number; + /** 总加载时间(毫秒) */ + totalLoadTime: number; + /** 缓存命中率(0-1) */ + cacheHitRate: number; + /** 详细的资源列表 */ + resources: ResourceTiming[]; +} + +// ============================================================ +// 首屏指标 +// ============================================================ + +/** + * 首屏性能指标 + */ +export interface FirstScreenMetrics { + /** Web Vitals 指标 */ + webVitals: Partial; + /** 资源加载统计 */ + resourceStats: ResourceStats; + /** 首屏可交互时间(毫秒) */ + timeToInteractive: number; + /** 骨架屏展示时长(毫秒) */ + skeletonDisplayDuration: number; + /** API 请求统计 */ + apiStats: ApiRequestStats; + /** 测量时间戳 */ + measuredAt: number; +} + +/** + * API 请求统计 + */ +export interface ApiRequestStats { + /** 总请求数 */ + totalRequests: number; + /** 平均响应时间(毫秒) */ + avgResponseTime: number; + /** 最慢的请求耗时(毫秒) */ + slowestRequest: number; + /** 失败的请求数 */ + failedRequests: number; + /** 详细的请求列表 */ + requests: ApiRequestTiming[]; +} + +/** + * 单个 API 请求时序 + */ +export interface ApiRequestTiming { + /** 请求 URL */ + url: string; + /** 请求方法 */ + method: string; + /** 响应时间(毫秒) */ + duration: number; + /** HTTP 状态码 */ + status: number; + /** 是否成功 */ + success: boolean; + /** 开始时间 */ + startTime: number; +} + +// ============================================================ +// 业务指标 +// ============================================================ + +/** + * 功能卡片点击统计 + */ +export interface FeatureCardMetrics { + /** 卡片 ID */ + cardId: string; + /** 卡片标题 */ + cardTitle: string; + /** 点击次数 */ + clicks: number; + /** 点击率(CTR) */ + clickRate: number; + /** 平均点击时间(距离页面加载的毫秒数) */ + avgClickTime: number; +} + +/** + * 首页业务指标 + */ +export interface HomePageBusinessMetrics { + /** 页面浏览次数(PV) */ + pageViews: number; + /** 独立访客数(UV) */ + uniqueVisitors: number; + /** 平均停留时长(秒) */ + avgSessionDuration: number; + /** 跳出率(0-1) */ + bounceRate: number; + /** 登录转化率(0-1) */ + loginConversionRate: number; + /** 功能卡片点击统计 */ + featureCards: FeatureCardMetrics[]; +} + +// ============================================================ +// PostHog 事件属性 +// ============================================================ + +/** + * PostHog 性能事件通用属性 + */ +export interface PerformanceEventProperties { + /** 页面类型 */ + page_type: string; + /** 设备类型 */ + device_type?: string; + /** 网络类型 */ + network_type?: string; + /** 浏览器 */ + browser?: string; + /** 是否已登录 */ + is_authenticated?: boolean; + /** 测量时间戳 */ + measured_at: number; +} + +/** + * Web Vitals 事件属性 + */ +export interface WebVitalsEventProperties extends PerformanceEventProperties { + /** 指标名称 */ + metric_name: 'LCP' | 'FCP' | 'CLS' | 'FID' | 'TTFB'; + /** 指标值 */ + metric_value: number; + /** 评级 */ + metric_rating: MetricRating; + /** 与上周对比 */ + delta?: number; +} + +/** + * 资源加载事件属性 + */ +export interface ResourceLoadEventProperties extends PerformanceEventProperties { + /** JS 总大小(KB) */ + js_size_kb: number; + /** CSS 总大小(KB) */ + css_size_kb: number; + /** 图片总大小(KB) */ + image_size_kb: number; + /** 总加载时间(秒) */ + total_load_time_s: number; + /** 缓存命中率(百分比) */ + cache_hit_rate_percent: number; + /** 资源总数 */ + resource_count: number; +} + +/** + * 首屏可交互事件属性 + */ +export interface FirstScreenInteractiveEventProperties extends PerformanceEventProperties { + /** 可交互时间(秒) */ + tti_seconds: number; + /** 骨架屏展示时长(秒) */ + skeleton_duration_seconds: number; + /** API 请求数 */ + api_request_count: number; + /** API 平均响应时间(毫秒) */ + api_avg_response_time_ms: number; +} + +// ============================================================ +// Hook 配置 +// ============================================================ + +/** + * useFirstScreenMetrics Hook 配置选项 + */ +export interface UseFirstScreenMetricsOptions { + /** 页面类型(用于区分不同页面) */ + pageType: string; + /** 是否启用控制台日志 */ + enableConsoleLog?: boolean; + /** 是否自动上报到 PostHog */ + trackToPostHog?: boolean; + /** 自定义事件属性 */ + customProperties?: Record; +} + +/** + * useFirstScreenMetrics Hook 返回值 + */ +export interface UseFirstScreenMetricsResult { + /** 是否正在测量 */ + isLoading: boolean; + /** 首屏指标(测量完成后) */ + metrics: FirstScreenMetrics | null; + /** 手动触发重新测量 */ + remeasure: () => void; + /** 导出指标为 JSON */ + exportMetrics: () => string; +} + +// ============================================================ +// 性能阈值配置 +// ============================================================ + +/** + * 单个指标的阈值配置 + */ +export interface MetricThreshold { + /** good 阈值(小于此值为 good) */ + good: number; + /** needs-improvement 阈值(小于此值为 needs-improvement,否则 poor) */ + needsImprovement: number; +} + +/** + * 所有性能指标的阈值配置 + */ +export interface PerformanceThresholds { + LCP: MetricThreshold; + FCP: MetricThreshold; + CLS: MetricThreshold; + FID: MetricThreshold; + TTFB: MetricThreshold; + TTI: MetricThreshold; +} + +// ============================================================ +// 调试面板 +// ============================================================ + +/** + * 调试面板配置 + */ +export interface DebugPanelConfig { + /** 是否启用 */ + enabled: boolean; + /** 默认是否展开 */ + defaultExpanded?: boolean; + /** 刷新间隔(毫秒) */ + refreshInterval?: number; + /** 位置 */ + position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'; +} + +/** + * 调试面板数据 + */ +export interface DebugPanelData { + /** Web Vitals 指标 */ + webVitals: Partial; + /** 资源统计 */ + resources: ResourceStats; + /** API 统计 */ + api: ApiRequestStats; + /** 首屏时间 */ + firstScreen: { + tti: number; + skeletonDuration: number; + }; + /** 最后更新时间 */ + lastUpdated: number; +}