# Changelog > 记录本项目每次改动。新条目追加到顶部。格式:`日期 — 改动概述`,正文按 `新增 / 变更 / 修复 / 移除` 分类。链接 PR / commit / 相关文档(如有)。 ## 2026-06-25 ### 新增 - **远程开发准备**:新增 `.gitattributes`(文本统一 LF,避免 Windows CRLF 污染 Linux 服务器)与 `infra/setup.sh`(Debian/Ubuntu 一键装 Node20/pnpm/Python3.11 + 依赖 + 启动说明)。首个 git commit 落地(此前仅 `git init`,0 提交)。 ### 变更 - **默认周期改为「单日(昨日)」**(`apps/web` `period.ts`):`DEFAULT_PERIOD` `last_7d` → `day`,首屏即看昨日的拼团漏斗(数据 T+1,昨日为最大可查日);测试同步更新。 - **品牌字 `HS-Data` → `HS Data`**(空格替代连字符):顶栏品牌、`index.html` 标题、`document.title` 一并更新。 ### 修复 - **时间选择选中态彻底重做**(`apps/web`):此前 近7/近30 用 shadcn Tabs、单日用 Button variant,选中高亮依赖 `data-active`/默认白底,在浅色页**几乎不可见**——用户感知不到"当前在哪个周期"。 - 合并 `DateField` + `PeriodSelect` → 单一 **`TimePeriodSelect`** segmented 控件(单日/近7天/近30天三选一);**选中 = mint 实色 + 白字,由 React 状态直接驱动**(不依赖任何 shadcn 变体),100% 可见、三段反馈统一。 - 删除 `DateField.tsx` / `PeriodSelect.tsx` 及孤儿导出(`PERIOD_OPTIONS`/`ROLLING_PERIOD_OPTIONS`/`periodLabel`);测试 role `tab` → `button`。Vitest 37 passed、build clean。`docs/04` §5 同步。 ## 2026-06-24 ### 新增 - **品牌与 favicon**(`apps/web`):新增 `public/favicon.svg`(mint 圆角方块 + 漏斗三阶 glyph),`index.html` 接入 favicon + `theme-color` + 标题改 `HS-Data · 数据服务平台`。顶栏品牌重做:mint 方块 mark(漏斗 glyph,与 favicon 一致)+ `HS-Data`(-Data mint)+ 竖线 + 灰色副标题「数据服务平台」,替换原全小写平排文字。 - **顶栏/页面体验五件套**(`apps/web`): - **面包屑**(`Breadcrumb` + `nav-utils.findTrail`):内容区顶部显示「行为分析 / 漏斗分析 / 拼团漏斗」,末项高亮——深层导航定位。 - **动态页面标题**:`document.title` 随路由变为「<当前页> · HS-Data」。 - **ECharts 懒加载**:`FunnelChart` 改 `React.lazy` + `Suspense`,拆出独立 chunk —— 主包 **1.56MB → 510KB**(echarts 1.05MB 按需加载,非漏斗页不加载)。 - **暗色模式开关**(`ThemeToggle`):顶栏 Sun/Moon 切换,偏好存 `localStorage`,`main.tsx` 首屏前应用避免闪烁。 - 品牌图标由 lucide `Target` 换为自绘漏斗 glyph(与 favicon 统一)。 - Vitest **37 passed**、build clean(FunnelResult 图表断言改 `findByTestId` 适配懒加载)。 ### 变更 - **加回「指标体系」L1 + 导航展开/折叠改为主流交互**(`docs/01`/`docs/02`/`docs/04` + `apps/web`): - L1 由 4 → **5**,加回 **指标体系**(指标目录/指标大盘/指标监控):主流数据产品核心(统一指标口径),只取消费面、不做治理后台。 - **导航展开/折叠对齐主流后台**(VS Code/AntD Pro/神策):点 L1/L2 分组手动展开/折叠(不跳转)、**多个可同时展开**(非手风琴)、进入某页自动展开其所在分支且不折叠其它分支、当前分支可手动折叠。`NavTree.tsx` 改为受控 open 集合;父节点为 toggle 按钮,叶子才跳转。 - 同步 `docs/01` §2(5 L1 + §2.3 导航交互)/§3/§7/§8、`docs/02` §9、`docs/04` §3。Vitest **37 passed**(+折叠/多开两条)、build clean。 - **IA 精简为内部工具版(四字对齐,多实体画像)**(`docs/01`/`docs/02`/`docs/04` + `apps/web`): - L1 由 7 砍到 **4**:行为分析 / 画像体系 / 数据看板 / 营销触达(模块名统一四字)。依据:内部工具非 SaaS——**不设独立"实时"域**(实时大盘并入数据看板)、**画像改多实体体系**(用户/商家/产品画像,标签作底层不单列)、**砍掉数据管理/工作台/指标平台**门面。 - 导航视觉强化层级:L1 加粗 + 图标 + 展开箭头 ▸/▾;L2/L3 左侧竖引导线 + 缩进 + mint pill 激活。 - 同步 `docs/01` §2(4 L1 表 + L2/L3 + 取舍说明)、§3/§5/§7/§8;`docs/02` §9;`docs/04` §3;`NAV` 树 + `NavTree.tsx`。Vitest **35 passed**、build clean。 - **前端导航对齐三级 IA**(`apps/web`,落地 `docs/01` §2):左侧导航由 5 个扁平能力域改为多级 L1 能力域 + 三级导航树(L1 能力域 → L2 分析模块 → L3 报表)。 - 新增 `routes/domains.ts` 的 `NAV` 树 + `layout/NavTree.tsx`(递归渲染、仅展开当前分支、按深度缩进);`App.tsx` 由树**自动生成路由**(父节点重定向到首个叶子,可用叶子 → 页面,余 → 占位)。 - 拼团漏斗落点 `/behavior/funnel/group`(= 行为分析 > 漏斗分析 > 拼团漏斗);`/` 重定向至此。其余 L1/L2 出"待开发"占位。 - `AppLayout` 抽出导航为 `NavTree`,保留既定主题/三段式布局/抗抖滚动模型;`docs/04` §3 导航说明同步更新。 - Vitest **35 passed**、`vite build` clean(本机实跑)。 - **PRD 信息架构重构**(`docs/01` v2.0):由 5 个扁平能力域升级为主流数据平台通用的**三级 IA**(L1 能力域 → L2 分析模块 → L3 报表/实例),参考神策 + 网易有数/阿里 OneData/Aloudata 指标平台/CDP。 - 平台定位改为**多形态一站式数据平台门户**;明确数据现实约束(T+1 预聚合宽表 → 只做固定报表,自助分析需事件级数据列远期)。 - 7 个 L1 能力域:看板 / 行为分析 / 用户画像与标签 / 指标平台 / 实时 / 营销触达 / 数据管理(+工作台首页);**标签体系、指标体系**各立为独立 L1 预留。 - MVP 落点明确:`行为分析 > 漏斗分析 > 拼团漏斗(固定)` 端到端,余 L1/L2 进导航出"待开发"占位。 - 漏斗详规对齐已上线实况(拼团固定 5 步、单日/近7天/近30天、单日历史回溯、T+1、不补零),替换旧"任意步骤/自定义15天/bitmap"描述;演进路线、明确不做、验收标准同步更新。 - 同步:`docs/02` §9 路由对齐 7 个 L1 + 漏斗下 L2/L3;`docs/05` 补"导航 IA 以 docs/01 为准、视觉以 docs/04 为准"。 - 导航代码改造(`apps/web` 左侧导航 5→7 域 + L2 子菜单)列为后续任务,本次仅文档。 ### 新增 - **`docs/04-设计规范`**:前端视觉/交互**定稿**并锁定(神策风 mint 主题色板、三段式布局、漏斗图 mint 渐变、单日日历常驻 + 滚动 Tabs 控件、快照/截至文案、抗抖滚动模型)。`docs/02` §1 加指针。设计决策以本文为唯一权威来源。 ### 变更 - **前端视觉定稿(神策风)**(`apps/web`,在 shadcn 迁移基础上): - 主题色板取自 sensorsdata.cn 实际 CSS:主色 mint `#04CB94`、文本 `#1F2D3D`、底 `#F9FAFC`(非纯白)、弱化 `#99A9BF`、淡 mint `#DEFFF6`、错误 `#EF4444`;默认亮色(`.dark` 备而不用)。 - 布局三段式:白顶栏(底线 + mint logo + mint dot/MVP)+ 浅 slate-100 侧栏(active 项淡 mint 底 + mint-700 字)+ 微蓝白主区 + 白卡轻投影。否决过的方案:全白(太平)、深 navy 侧栏(对比太狠 / 顶左同色)。 - 漏斗图改 mint 单色渐变 `#064E3B→#04CB94`,块宽按真实 UV 比例。 - 控件改版:**单日日历常驻**(`DateField` 自带「单日」标签 + 高亮 active 态)替代「单日」Tab;Tabs 仅留近 7/30 天。 - **修复加载抖动**(`AppLayout`):根容器 `min-h-screen` → `h-screen overflow-hidden`,令 `
` 为唯一滚动区 + `scrollbar-gutter:stable`,横向不再因滚动条出现/消失而抖;骨架高度对齐内容,竖向不跳。 - **前端漏斗对齐拼团契约 v3 + 单日历史日期选择器**(`apps/web`): - 周期模型:`yesterday|last_7d|last_30d` → `day|last_7d|last_30d`,Tab 文案 `单日 / 近 7 天 / 近 30 天`,默认仍 `last_7d`。固定漏斗第 3 步「详情」→「拼团详情」;副标题改「拼团漏斗:启动 → 曝光 → 拼团详情 → 下单 → 成功」。 - 类型(`api/types.ts`):请求加可选 `snapshot_dt?`(仅 `day` 发送),响应 `snapshot_dt` 可为 `null`。 - 新增 `DateField`(shadcn `calendar` + `popover`,基于 react-day-picker v10):仅 `period==='day'` 渲染;默认昨日;`disabled={{ after: 昨日 }}` 禁今天/未来(T+1),历史不设下限;选日即以该 `snapshot_dt` 重查。切到 7/30 天时隐藏。 - 快照说明两态:`day` → 「数据快照日:YYYY-MM-DD」;`last_7d/30d` → 「数据截至 YYYY-MM-DD(近 7 天/近 30 天)」,点明滚动窗口 as-of 日不含今天。 - 请求形态:`day` 发 `{period, snapshot_dt}`;7/30 天发 `{period}`(api fn 与页面双重保证省略)。mock 支持 `day` 历史(按日期做确定性 ±8% 抖动,不同 `snapshot_dt` 取不同数)、`missing` 时 `snapshot_dt: null`、保留 `?missing=1`、`VITE_USE_MOCK` 默认开。 - 新增依赖 `react-day-picker@10` + `date-fns@4`,新增 `components/ui/{calendar,popover}.tsx`。保留既定 mint 主题、AppLayout、漏斗渐变、抗抖骨架不动。 - Vitest **33 passed**、`vite build` **clean**(本机实跑)。 - **后端 MVP 漏斗升级为「拼团漏斗 + 两张真实表」(契约 v3)**(`apps/api`): - 数据源由单表 `ads_trd_group_funnel` 拆为两表(`docs/03` §11):`ads_trd_group_funnel_daily`(单日、留全历史)+ `ads_trd_group_funnel_rolling`(近 7/30 天、覆盖式 1 行)。 - 请求契约:`period` 枚举由 `yesterday|last_7d|last_30d` 改为 `day|last_7d|last_30d`;新增可选 `snapshot_dt`(ISO `YYYY-MM-DD`,仅 `day` 有效,7/30 天忽略)。响应 `snapshot_dt` 回显实际取数行的 `dt`(yyyyMMdd)。 - 路由:`day` → daily 表(给 `snapshot_dt` 走 `WHERE dt=:dt`,否则最新 `dt`,列 `uv_start/show/detail/order/paid`);`last_7d`/`last_30d` → rolling 唯一行,取 `uv_*_7d` / `uv_*_30d`。 - 校验:`day` 的 `snapshot_dt` 上限昨日(T+1),今天/未来 → 422;非存在 `dt` → `missing`。第 3 步展示名由「详情」改为「拼团详情」。`data_status` 仍 `ready|missing`,不补零。 - `FakeFunnelRepository`(`USE_FAKE_DATA` 默认开)兜底:造约 10 天递减历史 daily 行(截至昨日,支持日期选择器回溯、不同 `snapshot_dt` 取不同数据)+ 1 行 as-of 昨日 rolling;无 DB 即可起。seed 脚本同步改插 10 daily + 1 rolling。 - 重写 Alembic 迁移(建两表,删旧单表迁移);改 `models.py`(两 ORM 模型)、`repository.py`/`funnel.py`/`schemas.py`/`api/funnels.py`;更新 `README.md`、`.env.example`。 - pytest **47 passed**(本机实跑);重出 `openapi.json`(Period=day/last_7d/last_30d、请求含 `snapshot_dt`)。 - **前端 UI 栈从 Ant Design 5 全量迁移到 shadcn/ui + Tailwind CSS v4**(B 方案): - `docs/02` §1 已改:`React + Vite + TS + Tailwind v4 + shadcn/ui(radix-nova/neutral)+ ECharts + TanStack Query`,Ant Design 退出技术栈。 - 装 Tailwind v4(`@tailwindcss/vite` 插件)、路径别名 `@/* → ./src/*`(tsconfig + vite.config)、`src/index.css` 用 v4 + neutral OKLCH 主题(light + dark)、`html/body` 默认 `class="dark"`。 - 跑 `shadcn@latest init`(CLI v4.11.0,style `radix-nova`,base color `neutral`,iconLibrary `lucide`)生成 `components.json` 和 `src/components/ui/`;`add` 了 button/card/tabs/table/badge/alert/skeleton/separator/scroll-area/sheet/sonner。 - 移除 `antd` / `@ant-design/icons` / `dayjs`(grep 0 命中)。重写 `AppLayout`(Tailwind 壳 + lucide-icon 侧栏)、`PeriodSelect`(shadcn Tabs)、`FunnelResult`(Card + Alert + Skeleton + lucide Inbox)、`ResultTable`(shadcn Table)、`Placeholder`(Card + Construction 图标)。保留 ECharts 漏斗图、新契约、5 域导航、mock 行为不变。 - Vitest **26/26 passed**、`vite build` **clean**(本机实跑)。dev server 起在 `:5173`。 ### 已知未完成 - **shadcn 官方 Skill 未装到 `apps/web/.claude/skills/shadcn/`**。两层阻断:① 网络上 `git clone https://github.com/shadcn/ui.git`(`pnpm dlx skills add shadcn/ui` 调用的)被防火墙 RST(`raw.githubusercontent.com` 也超时,api.github.com / codeload 通);② harness 拒绝代理脚本写入 `.claude/skills/`(self-modification 防护)。需要在本地终端跑 `pnpm dlx skills add shadcn/ui`,或改走 shadcn MCP(`.mcp.json` 配置)。 (前一条 v2 漏斗转向条目原文保留:) - **MVP 漏斗转向"固定漏斗 + 真实预聚合宽表"**(真实表 `ads_trd_group_funnel` 到位,替代原 bitmap 泛用漏斗方案): - 契约 v2(`docs/02` §5/§6、`docs/03` §11):请求 `{period: yesterday|last_7d|last_30d}`;响应 `{period, snapshot_dt, results×5(event_key), data_status: ready|missing}`;固定 5 步 启动→曝光→详情→下单→成功。 - 后端 `apps/api`:改查 `ads_trd_group_funnel` 最新 `dt` 行选 `*_1d/7d/30d` 列;`USE_FAKE_DATA`(默认开)假数据兜底,无 DB 也能起;移除 pyroaring/bitmap 两表/OR 逻辑;Alembic 改建宽表;seed 改插快照行;pytest **25 passed**(本机实跑);重出 `openapi.json`。 - 前端 `apps/web`:去掉任意步骤配置 + 自定义范围 + 15天/今天校验;改 3 周期按钮(默认近7天)+ 固定 5 步;接新契约;mock 默认开;Vitest **26 passed**、构建通过(本机实跑)。 - `packages/api-types`:`pnpm gen:api-types` 跑通,由 `openapi.json` 生成 `schema.ts`(Period/DataStatus/event_key/snapshot_dt)。 - 端到端联通(本机实跑):后端 `uvicorn`(假数据)`POST /api/funnels/query {period:last_7d}` 返回契约正确;前端 dev server 起于 `:5173`。 ### 移除 - bitmap 相关:`app/services/bitmap.py`、`daily/period_event_bitmap` 两表与迁移、pyroaring 依赖、相关测试/seed(挪到后续"泛用漏斗"阶段)。 - 前端:`StepConfig`、自定义 `TimeRangePicker`、15天/今天校验工具及其测试。 ### 环境 - 安装 **Python 3.11.9**(用户作用域),`apps/api/.venv` 装齐依赖,后端测试本机可跑。否决"降级到 Python 2.7.5"(FastAPI/Pydantic v2 不支持)。Docker 仍未用(非管理员装不了),本地以 `USE_FAKE_DATA` 假数据替代。 ## 2026-06-23 ### 新增 - **MVP 全栈脚手架落地**(按 `docs/01/02/03` 与计划阶段 0–4): - 阶段 0 — Monorepo 脚手架:`git init`(main)、根 `package.json` + `pnpm-workspace.yaml`、`.gitignore`/`.nvmrc`/`.editorconfig`;根脚本 `dev:web`/`build:web`/`test:web`/`gen:api-types`。 - infra — `infra/docker-compose.yml` 起 PostgreSQL 16。 - 阶段 1+2 — 后端 `apps/api`(FastAPI + Pydantic v2 + SQLAlchemy async + pyroaring):`POST /api/funnels/query` 严格按 `docs/02` §5;Alembic 建 `daily_event_bitmap` / `period_event_bitmap` 两表;周期优先 / 自定义 daily OR 取数;第 1 层转化率 `null`、`data_status` 四态不补零;bitmap 计算走线程池不阻塞 event loop;seed 脚本(含缺失/损坏样本)、`export_openapi.py`、pytest 测试集(覆盖 `docs/02` §8)。 - 阶段 3 — 前端 `apps/web`(React 19 + Vite + TS + AntD 5 + ECharts + TanStack Query):平台壳 + 五域导航;漏斗页四区 + 校验(≤15 天、今天不可选/不可提交);其余四域共用 `Placeholder`;按 `data_status` 显式渲染、`null` 转化率显示 “—” 不补零;mock 模式(`VITE_USE_MOCK`);Vitest 37 项测试通过。 - 阶段 4 — `packages/api-types`:接好 `openapi-typescript` 生成链(`pnpm gen:api-types` 读 `apps/api/openapi.json`),含占位 `schema.ts`。 - `CLAUDE.md`:项目协作守则(思考优先、简单优先、外科手术式改动、目标驱动、变更入 changelog)。 - `CHANGELOG.md`:本文件。 ### 待办(环境受限,未在本机执行) - 后端运行/测试与端到端联调需 **Python 3.11+** 与 **Docker**(本机仅 Python 3.8、无 Docker):`apps/api` 代码与测试按 3.11 编写但未执行。 - `gen:api-types` 待后端用 `python -m scripts.export_openapi` 导出 `apps/api/openapi.json` 后运行;在此之前前端用 `apps/web/src/api/types.ts`(契约一致)。