export type Numeric = string | number | null; export type Metric = | "revenue" | "cost" | "gross" | "roi" | "customers" | "basket" | "margin" | "discount_rate" | "self_revenue" | "upgrade_rate" | "list_basket"; export const labels: Record = { revenue: "实际收入", cost: "成本", gross: "毛利贡献", roi: "ROI", customers: "消费人数", basket: "客单价", margin: "毛利率", discount_rate: "产品扣率", self_revenue: "自营收入", upgrade_rate: "升单率", list_basket: "原价客单价", }; export interface Column { index: number; name: string; description: string; role: string; key: string; confidence: number; } export interface Mapping { sheet: string; header: number; columns: Column[]; margin_rates: Record; self_operated_products?: string[]; roi_formula: string; description: string; } export interface Preferences { entry: "overview" | "anomalies"; comparison: "yoy" | "mom"; hierarchy: string[]; metric: Metric; threshold: number; min_impact: number; min_samples: number; show_heatmap: boolean; show_queue: boolean; show_copilot: boolean; alerts: boolean; } export interface Dataset { id: string; name: string; status: string; version: string; row_count: number | null; periods: string[]; error: string; quality: Record; dimensions: { key: string; name: string; description: string }[]; profile?: { sheets: { name: string; rows: number; columns: number; preview: string[][]; }[]; }; mapping: Mapping; preferences: Preferences; revision: number; } export interface Context { start: string; end: string; comparison: string; baseline_end?: string; filters: Record; group: string; metric: Metric; } export interface Value { current: Numeric; baseline: Numeric; delta: Numeric; change: Numeric; } export interface Row { label: string; values: Record; rows: number; baseline_rows: number; anomaly: boolean; impact: Numeric; contribution: Numeric; filters: Record; } export interface Analysis { context: Context & { missing: string[]; current: string[]; baseline: string[]; }; summary: Record; rows: Row[]; trend: ({ period: string } & Record)[]; row_count: number; anomaly_count: number; comparable: boolean; notice: string; version: string; } export interface AIConfig { enabled: boolean; provider: "openai" | "local"; base_url: string; model: string; api_key_set: boolean; updated_at: string | null; } export interface Session { csrf: string; user: { id: number; name: string; role: string; organization: string; departments: string[]; } | null; ai_enabled: boolean; } export const format = (v: Numeric | undefined, metric?: string) => v == null ? "不可用" : [ "roi", "margin", "discount_rate", "upgrade_rate", "change", "contribution", ].includes(metric || "") ? `${(Number(v) * 100).toFixed(1)}%` : Number(v).toLocaleString("zh-CN", { maximumFractionDigits: 2 });