- 证据接口与 CSV/XLSX 导出去掉 NUMERIC(44,24) 存储尺度尾零(无损精度) - KPI 大金额折行截断:字号收紧 + nowrap + 省略号兜底 - 贡献分解/走势图表轴标签重叠与 Y 轴裁剪:hideOverlap + 万/亿缩写 - 表格隐藏全不可用指标列,空态改为条件渲染(修复空表覆盖层残留) - 数据质量与字段字典/导入确认的中文标签映射(不再暴露内部键名) - 证据弹窗重复点击当前期间停在加载中(F03);证据表格最小宽度 - Playwright 覆盖 F03 重复点击与期间切换场景
165 lines
3.5 KiB
TypeScript
165 lines
3.5 KiB
TypeScript
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<Metric, string> = {
|
|
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 const roleLabels: Record<string, string> = {
|
|
period: "期间",
|
|
year: "年份",
|
|
month: "月份",
|
|
dimension: "维度",
|
|
customer: "客户标识",
|
|
quantity: "数量",
|
|
revenue: "实际收入",
|
|
cost: "成本",
|
|
gross: "毛利贡献",
|
|
list_amount: "应收金额",
|
|
discount: "折扣金额",
|
|
ignore: "未使用",
|
|
};
|
|
export interface Mapping {
|
|
sheet: string;
|
|
header: number;
|
|
columns: Column[];
|
|
margin_rates: Record<string, number>;
|
|
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<string, number>;
|
|
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<string, string>;
|
|
group: string;
|
|
metric: Metric;
|
|
}
|
|
export interface Value {
|
|
current: Numeric;
|
|
baseline: Numeric;
|
|
delta: Numeric;
|
|
change: Numeric;
|
|
}
|
|
export interface Row {
|
|
label: string;
|
|
values: Record<Metric, Value>;
|
|
rows: number;
|
|
baseline_rows: number;
|
|
anomaly: boolean;
|
|
impact: Numeric;
|
|
contribution: Numeric;
|
|
filters: Record<string, string>;
|
|
}
|
|
export interface Analysis {
|
|
context: Context & {
|
|
missing: string[];
|
|
current: string[];
|
|
baseline: string[];
|
|
};
|
|
summary: Record<string, Value>;
|
|
rows: Row[];
|
|
trend: ({ period: string } & Record<string, Numeric>)[];
|
|
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 });
|