07-项目结构与模块.md 7.4 KB

项目结构与模块

给新接手者的"地图":目录层级、各模块职责、运行与部署流程。细节散落各专题文档,本文只做总览 + 指路。 关联:产品/IA docs/01、技术架构与契约 docs/02、数据契约 docs/03、设计规范 docs/04、接口 docs/06

1. 这是什么

hs-data 是内部一站式数据平台(monorepo)。当前 MVP 端到端做通一个 L3 报表——拼团漏斗(行为分析 > 漏斗分析 > 拼团漏斗),含两个视图:漏斗(固定 5 步快照)与趋势(按日折线)。其余能力域进导航、出"待开发"占位。

2. 顶层目录

hs-data/
├── apps/
│   ├── web/            # 前端 SPA(React 19 + Vite + Tailwind v4 + shadcn/ui + ECharts)
│   └── api/            # 后端只读查询服务(FastAPI + SQLAlchemy async + asyncpg)
├── packages/
│   └── api-types/      # 由后端 OpenAPI 生成的 TS 类型(契约同步用)
├── docs/               # 产品 / 技术 / 数据契约 / 设计 / 协作 / 接口 / 本文
├── infra/              # 部署与本地基础设施脚本(look.sh / serve*.sh / serve.py / docker-compose)
├── CLAUDE.md           # 开发硬约束(给 AI 与人)
└── CHANGELOG.md        # 改动留痕(按日期,顶部最新)

pnpm workspace(pnpm-workspace.yaml)管 apps/* + packages/*;pnpm 用 corepack 调用(corepack pnpm@10 …),无需全局装。

3. apps/web —— 前端

多模块单页应用:统一外壳(顶栏 + 左侧三级导航 + 内容区),业务模块挂内容区。当前只有漏斗模块是实模块,其余是占位。

apps/web/src/
├── main.tsx / App.tsx          # 入口 + 路由装配
├── routes/domains.ts           # L1/L2/L3 导航与路由数据(5 能力域,见 docs/01 §2)
├── layout/                     # 外壳:AppLayout / NavTree(可折叠导航)/ Breadcrumb / ThemeToggle
├── api/
│   ├── funnel.ts               # 查询客户端 + mock(queryFunnel / queryFunnelTrend);USE_MOCK 开关
│   ├── types.ts                # 前端契约类型(手维护,镜像后端;见 packages/api-types)
│   └── queryClient.ts          # TanStack Query 客户端
├── modules/
│   ├── funnel/                 # ★ 拼团漏斗(唯一实模块)
│   │   ├── FunnelPage.tsx      #   L3 页:漏斗 / 趋势 两视图 Tab(React 状态驱动)
│   │   ├── FunnelView.tsx      #   漏斗视图:单日(默认昨日)/ 近7 / 近30 快照
│   │   ├── TrendView.tsx       #   趋势视图:UV 折线 + 转换率折线,范围 近30天/自定义
│   │   ├── period.ts           #   固定 5 步定义、日期工具、范围/区间助手
│   │   ├── format.ts           #   UV / 比率格式化(null → "—",不补零)
│   │   └── components/         #   TimePeriodSelect / TrendRangeSelect / FunnelChart / TrendChart / FunnelResult / ResultTable
│   └── placeholder/            # "待开发"占位页(非可用模块统一复用)
└── components/ui/              # shadcn/ui 原语(button/card/calendar/tabs/popover/…)

要点:ECharts 图(FunnelChart/TrendChart)懒加载拆独立 chunk;数据状态三态显式渲染——ready 出图、missing 出「暂无数据」(不补零)、传输错误出 Alert。

4. apps/api —— 后端

只读查询服务。无写入、无 bitmap、无跨天聚合;数据源是预聚合的两张 ADS 表。详见 apps/api/README.md

apps/api/app/
├── main.py                 # FastAPI 入口;按 STATIC_DIR 可选同源托管 SPA(线上单进程)
├── config.py               # 设置(DATABASE_URL / DB_SCHEMA=ads / USE_FAKE_DATA)
├── schemas.py              # Pydantic 契约(FunnelQuery* / FunnelTrend*)
├── api/funnels.py          # 路由:POST /api/funnels/query、/api/funnels/trend
├── services/
│   ├── funnel.py           # 编排 + 转化口径 + 校验 + 趋势裁前导0;FunnelRepository 协议
│   └── repository.py       # SqlAlchemy 仓库(连真表)+ Fake 仓库(USE_FAKE_DATA)
└── db/
    ├── models.py           # ORM:ads_trd_group_funnel_daily / _rolling(无 schema,靠 search_path=ads)
    └── session.py          # async engine;真实连接挂 search_path=ads

scripts/:export_openapi.py(导 OpenAPI,无需 DB)、seed.py(本地假 PG 灌样例);alembic/(本地建表迁移)。线上真实数据由上游 ETL 写入,不经 seed/alembic。

5. packages/api-types

后端 GET /openapi.json → 生成前端 TS 类型,作为契约同步手段(corepack pnpm@10 gen:api-types)。当前前端实际用手维护的 apps/web/src/api/types.ts(刻意镜像契约,便于后续切换为生成类型)。

6. infra

文件 用途
look.sh 一键部署:web 测试+构建 → 推 feature(源码)+deploy(产物)→ 服务器拉取 → 上线(仅 /look 显式触发)
serve-hs-api.sh 服务器单进程启动器(uvicorn 同源托管 SPA+API,端口 8080,脱离会话存活)
serve.py 旧纯静态 SPA 服(已被 uvicorn 同源托管取代,保留备用)
serve-start.sh 静态服守护启动器(历史,未启用)
setup.sh 服务器装依赖(历史脚手架)
docker-compose.yml 本地起 PostgreSQL(本地接真库时用)

7. 运行流程

线上(单进程同源,见 docs/02 §10):

浏览器 ──HTTP──▶ 服务器 100.64.0.62:8080 (uvicorn, ~/miniconda3 的 Python 3.11)
                   ├── GET /、/assets/*  → 托管 ~/hs-data 的 SPA 产物(STATIC_DIR,实时读盘)
                   └── POST /api/funnels/* → 查 PostgreSQL 100.64.0.10:25432 (schema=ads)

前端相对 /api 同源调用 → 免 CORS、免反代;只有一个常驻进程。

本地开发:Vite dev(:5173)跑前端,默认 USE_MOCK 直接出假数据,无需后端;需要时另起 uvicorn(:8000),Vite 代理 /api 过去。

数据:T+1,最大可查日为昨日。单日可回溯历史;近7/30天为滚动窗口(rolling 表唯一行,只有最新 as-of)。口径见 docs/02 §5–6。

8. 构建与部署流程(/look)

本地(Windows)
  pnpm test + build(VITE_USE_MOCK=false)
       │  产物 apps/web/dist
       ▼
  git push:  feature(源码)  +  deploy(纯产物分支)   ──▶ GitLab(git.hobbystocks.cn)
                                                              │
服务器(CentOS 7)  git pull                                    ▼
  ~/hs-data  ← deploy 分支(SPA 产物,uvicorn 实时读盘,前端改动免重启)
  ~/hs-api   ← feature 分支(后端源码;仅当 apps/api 变更才重启 uvicorn)

CentOS 7 glibc 2.17 跑不了现代前端构建,故本地构建、git 送达、服务器只托管+跑后端;Python 3.11 用隔离 Miniconda,不动系统环境。细节见 docs/02 §10。

9. 本地怎么跑

corepack pnpm@10 install
corepack pnpm@10 --filter @hs-data/web dev     # 前端(mock)→ http://localhost:5173

# 后端(可选,默认假数据)
cd apps/api && python -m venv .venv && .venv/Scripts/python -m pip install -e ".[dev]"
.venv/Scripts/uvicorn app.main:app --reload --port 8000   # http://localhost:8000/docs

# 测试
corepack pnpm@10 --filter @hs-data/web test    # 前端 Vitest
cd apps/api && .venv/Scripts/pytest -q          # 后端 pytest