跳转至

DIP1-01 · 架构设计

文档编号:DOC-D00-D1-01 / DIP1-01(ARC) 版本:V2.0 创建日期:2026-08-09 最近更新:2026-08-09 维护人:TL / DT 决策审批人:TL + SPO 关联文档TND-E V1.1 §5.3、DIP1-00 READMEQMDCPT-DMDS-D

V2.0 重大变更:前端从 Next.js PWA 升级为 React Native 原生 App(师傅端 + 客户端);运营后台保留 Next.js Web;跳过阶段1 飞书对接,直接实施阶段2。详见 ADR-002 / ADR-006 / ADR-007。


一、设计原则(五条铁律,违反须提交变更申请)

# 原则 含义 实践落地
P1 DDD 四层分离 领域层必须是纯 Python,不依赖 FastAPI/SQLAlchemy 等任何框架 Code Review 检查 domain/ 模块 import,禁止引入 fastapi / sqlalchemy
P2 依赖倒置 领域层定义 Repository 端口(ABC 抽象基类),基础设施层实现,应用层依赖端口不依赖实现 domain/*/ports.py 定义接口,infrastructure/db/repositories.py 实现
P3 模块化单体优先,服务化按需 阶段 1-2 单体部署,不拆微服务;信号触发拆分(TND-E §6.3.2) 代码层模块边界清晰,接口通信仅通过 Application Service;禁止跨模块 DB Join
P4 配置外置,业务参数一律进 DB 报价系数、派单阈值、结算规则不得硬编码代码 mds_params_config 配置表 + OPR 后台配置页面 + 缓存 Redis
P5 字段命名兼容 MVP-FS 所有 snake_case 字段名与飞书多维表格保持完全一致,CSV→DB 零改名 DIP1-02 §字段映射表

二、系统分层架构(C4 容器视角)

flowchart TD
    subgraph USER["用户层(3 类核心 + 2 类扩展)"]
        U1["OPR 运营后台用户<br/>(成文·黄·洪·司徒)"]
        U2["WKR 师傅<br/>(香港安装师傅)"]
        U3["CST 客户<br/>(香港终端消费者)"]
        U4["DLV 配送(扩展)"]
        U5["PRT 合作方(扩展)"]
    end

    subgraph FE["前端容器层(Web + RN 双引擎)"]
        FE1["OPR 运营后台<br/>Next.js 14 SSR<br/>apps/opr-admin<br/>(PC Web 保留)"]
        FE2["WKR 师傅 App<br/>React Native + Expo<br/>apps/wkr-app<br/>(iOS+Android 原生)"]
        FE3["CST 客户 App<br/>React Native + Expo<br/>apps/cst-app<br/>(iOS+Android 原生)"]
    end

    subgraph API_GW["接口层(FastAPI)"]
        GW1["REST API 路由<br/>interfaces/api/*_router.py"]
        GW2["Webhook 回调<br/>interfaces/webhooks/*.py"]
        AUTH["JWT + RBAC 鉴权中间件"]
        RATE["限流 + 日志 + Trace 中间件"]
    end

    subgraph APP_LAYER["应用层(Application Use Case)"]
        APP1["报价用例<br/>QuoteApplicationService"]
        APP2["跟踪用例<br/>OrderApplicationService"]
        APP3["主数据用例<br/>MasterDataApplicationService"]
        APP4["派单用例<br/>DispatchApplicationService"]
        APP5["结算用例<br/>SettlementApplicationService"]
        APP6["AI 融合用例<br/>AIIntegrationService"]
    end

    subgraph DOMAIN_LAYER["领域层(Domain,纯 Python)"]
        D1["QSV 报价上下文<br/>实体 + 值对象 + 报价策略接口"]
        D2["CPT 跟踪上下文<br/>实体 + 8 阶段状态机 + 采集物约束"]
        D3["MDS 主数据上下文<br/>Worker/Customer/Category/Building 实体"]
        D4["DSP 派单上下文<br/>匹配算法接口 + 派单规则"]
        D5["PAY 结算上下文<br/>对账规则 + 发票实体"]
        D6["共享内核<br/>Money/DateTimeRange/Address VO + 领域事件"]
    end

    subgraph INFRA_LAYER["基础设施层(实现 Domain 端口)"]
        INF1["PostgreSQL 16<br/>SQLAlchemy 2.0 ORM + Alembic"]
        INF2["Redis 7<br/>缓存 + 异步任务队列 + 分布式锁"]
        INF3["Cloudflare R2<br/>照片/附件对象存储(S3 兼容)"]
        INF4["飞书开放平台 SDK<br/>Bitable API + IM 机器人"]
        INF5["LLM API<br/>听写助手/报价建议/师傅推荐/照片质检"]
        INF6["日志 + 监控 + 告警<br/>Logfire/Sentry/Prometheus"]
    end

    USER --> FE
    FE -->|"HTTPS + JSON"| API_GW
    API_GW --> APP_LAYER
    APP_LAYER -->|"调用端口接口"| DOMAIN_LAYER
    INFRA_LAYER -->|"实现端口接口"| DOMAIN_LAYER

    style USER fill:#D4AF78,stroke:#004046,color:#004046
    style FE fill:#457b9d,stroke:#004046,color:#fff
    style API_GW fill:#004046,stroke:#004046,color:#fff
    style APP_LAYER fill:#2a9d8f,stroke:#004046,color:#fff
    style DOMAIN_LAYER fill:#2a9d8f,stroke:#004046,color:#fff
    style INFRA_LAYER fill:#555,stroke:#004046,color:#fff

2.1 各层职责

职责 允许做 禁止做
Interfaces 接口层 对外暴露 REST API/Webhook、参数校验(Pydantic)、鉴权、异常映射 HTTP 状态码 路由定义、依赖注入 Application Service、DTO ↔ 领域对象转换 写任何业务逻辑(如"阶段 3 是否可跳阶段 4"这类判断必须下沉到领域层)
Application 应用层 用例编排、事务边界、DTO 组装、调用多个领域服务/仓储 调用领域服务 + 仓储端口、发送领域事件、跨上下文协调 写业务规则;不得跨模块直接查表;不得 import SQLAlchemy/FastAPI
Domain 领域层 核心业务规则、实体状态不变量、领域服务、仓储端口定义 定义 Entity/VO/Aggregate/Domain Service/Repository Port/Domain Event 引用任何框架(FastAPI/SQLAlchemy/Redis);访问外部资源;不做 ORM Mapping
Infrastructure 基础设施层 实现仓储端口、对接飞书/AI/R2 外部系统、ORM 映射、消息队列、缓存 SQLAlchemy Model 定义、飞书 SDK 封装、S3 Client、Celery Task 写业务规则;实现逻辑必须通过 Domain 定义的端口回归

三、限界上下文映射(Context Mapping)

上下文 简称 上游/下游 关系模式 交互方式
报价 QSV 核心独立上下文 报价计算独立,不依赖其他上下文状态
跟踪 CPT 下游(消费 QSV 报价结果;消费 MDS 师傅/客户信息;消费 DSP 派单结果) Customer-Supplier + ACL(防腐层) QSV 生成 Quote 后,CPT 持有 quote_id 引用;师傅/客户信息通过 Application Service 查 MDS
主数据 MDS 上游(为 QSV/CPT/DSP/PAY 提供师傅/品类/楼宇/客户档案 ID) Published Language(统一 ID 规范) 所有引用一律用 worker_id / customer_id / category_code / building_id,禁止冗余复制字段
派单 DSP 下游(消费 WKR 画像)→ 上游(发布派单结果给 CPT) Customer-Supplier DSP 生成 assignment_id → CPT 阶段 L2 写入
结算 PAY 下游(消费 CPT 完工数据 + WKR 费率 + QSV 报价) Conformist(严格跟随 QSV/CPT 模型) 统一 order_id 对账
flowchart LR
    MDS["MDS 主数据<br/>[上游 Published Language]"] -->|worker_id/category_code| QSV["QSV 报价"]
    MDS -->|worker_id/customer_id/building_id| DSP["DSP 派单"]
    QSV -->|quote_id + final_amount| CPT["CPT 跟踪"]
    DSP -->|assignment_id| CPT
    CPT -->|order_id + stage_data + worker_id| PAY["PAY 结算"]
    MDS -->|worker_rate_level| PAY

    style MDS fill:#fbf1dc,stroke:#D4AF78,color:#8B6F3E
    style PAY fill:#457b9d,stroke:#004046,color:#fff
    style CPT fill:#2a9d8f,stroke:#004046,color:#fff

反腐层(ACL):CPT 调用 QSV/MDS 时必须通过 Application Service 的防腐接口,禁止直接引入 QSV 的 SQLAlchemy Model 或其他上下文内部类。


四、物理部署架构(阶段 1 → 阶段 2 演进)

4.1 阶段 2:Cloudflare + VPS + App Store(直接阶段2,跳过飞书)

flowchart LR
    DNS["DNS<br/>hk2026.com.hk(Cloudflare)"]
    CF["Cloudflare CDN + WAF + 缓存"]

    subgraph PAGES["Cloudflare Pages(OPR Web)"]
        FE_O["OPR 后台<br/>opr.hk2026.com.hk<br/>Next.js SSR"]
    end

    subgraph APP_STORE["应用商店(RN 双端)"]
        APP_IOS["App Store<br/>WKR App + CST App<br/>iOS 14+"]
        APP_AND["Google Play<br/>WKR App + CST App<br/>Android 9+"]
    end

    subgraph EXPO["Expo 云服务"]
        EAS["EAS Build + Submit<br/>云端构建+自动提审"]
        OTA["Expo Updates<br/>JS Bundle 热更新"]
        PUSH["Expo Notifications<br/>APNs + FCM 统一推送"]
    end

    subgraph HK_VPS["香港 VPS(阿里云/腾讯云轻量,4C8G 起步)"]
        DOCKER["Docker Engine"]
        BE["Backend API<br/>api.hk2026.com.hk<br/>FastAPI + Uvicorn 单容器"]
        PG["PostgreSQL 16<br/>Container + 定期备份到 R2"]
        RD["Redis 7<br/>Container"]
        PUSH_SVC["Push Service<br/>Expo Push + 模板渲染"]
    end

    R2["Cloudflare R2<br/>附件存储 assets.hk2026.com.hk"]
    LLM["LLM API<br/>OpenAI/国产大模型"]

    DNS --> CF
    CF --> PAGES
    CF -->|"/api/* 反代"| BE
    PAGES -->|"数据请求"| BE
    APP_IOS -->|"HTTPS + JWT"| BE
    APP_AND -->|"HTTPS + JWT"| BE
    APP_IOS --> OTA
    APP_AND --> OTA
    BE --> PUSH
    PUSH --> APP_IOS
    PUSH --> APP_AND
    EAS --> APP_IOS
    EAS --> APP_AND
    BE --> PG
    BE --> RD
    BE --> R2
    BE --> LLM
    BE --> PUSH_SVC

成本预估(阶段 2):香港 VPS ≈ 300-600 HKD/月 + Cloudflare 免费档 + Expo 免费档(EAS Build 30 次/月足够)+ Apple Developer $99/年 + Google Play $25 一次性 + 域名 ≈ 100 HKD/年。

4.2 未来扩展:高可用 + 服务化(按需拆分)

  • 数据库:PostgreSQL 一主一从(只读副本,OPR 查询报表走从库)
  • 后端:拆分为 2-3 个服务(AI 服务 + PAY 结算优先独立),容器编排用 Docker Compose 或最小化 K3s
  • 前端:新增 DLV/PRT 端,继续 RN 复用组件
  • 消息队列:新增 Kafka 或 RabbitMQ(订单事件异步解耦)
  • 阶段0 飞书对接:若 MVP-FS 飞书方案实际运行后需要数据沉淀,按 DIP1-P1 文档启动飞书 SDK 对接(本文档保留供未来使用)

五、非功能需求(NFR)

维度 阶段 2 目标(直接阶段2) 度量方法
性能 QSV 报价 P95 < 200ms;CPT 列表查询 P95 < 500ms Locust 压测 + Logfire
可用性 SLA ≥ 99.9%(每月 ≤ 43 分钟不可用) Uptime Kuma 监控
并发 支撑 500-1000 并发用户(OPR 10 + WKR 100 + CST 800+) Locust + 实际业务压测
数据安全 PDPO 合规审计通过;客户/师傅手机号 AES-256 加密;RBAC + RLS 行级权限;R2 签名 URL;AI 调用脱敏 渗透测试 + PDPO 自查表
可维护性 单元测试覆盖率 ≥ 80%;架构守护测试(防止领域层依赖框架);CI 全绿才能合并 SonarQube + CI Gate
可观测性 全链路 Trace(OpenTelemetry)+ 移动端崩溃监控(Sentry RN SDK)+ 业务指标 Logfire + Grafana + Sentry
国际化 繁/简/英三语切换(i18n 框架 + 词典) Next-intl + i18next
移动端兼容性 WKR/CST App 兼容 iOS 14+ / Android 9+(React Native 原生) BrowserStack + 真机抽样
移动端离线 WKR 师傅端 L6 拍照离线缓存 ≥ 24h;弱网自动重试上传 离线场景测试
推送送达率 APNs + FCM 推送送达率 ≥ 95%;点击率 ≥ 30% Expo Notifications Dashboard
App 启动性能 冷启动 ≤ 2s;热启动 ≤ 0.5s Flipper 性能 profiling
OPR 后台兼容 Chrome 90+ / Safari 14+ / Edge 90+ BrowserStack

六、架构演进信号与决策树(什么情况下从单体拆服务)

flowchart TD
    A["模块化单体运行<br/>阶段 1 稳定 2 个月"] --> B{触发信号?}
    B -->|"单模块部署冲突 ≥ 3 次/月<br/>(康威定律)"| C["按团队边界拆服务"]
    B -->|"单一模块 CPU/内存<br/>使用率持续 > 70%"| D["单模块独立扩容<br/>(优先 PAY/AI 服务)"]
    B -->|"某模块数据库连接<br/>占总连接 > 60%"| E["拆独立服务+独立 DB Schema<br/>(优先 MDS/QSV 读多)"]
    B -->|"上线新端 CST/DLV/PRT<br/>接口请求量翻倍"| F["引入 BFF 层,按端定制 API<br/>(TND-E §6.3.1)"]
    B -->|"无强信号"| Z["维持单体<br/>不拆 = 省钱省复杂度"]

    style Z fill:#2a9d8f,stroke:#004046,color:#fff

架构底线:任何拆分决策必须由 TL 书面发起、SPO 审批;拆分前先完成「单体内部优化」(SQL 慢查询、缓存命中率、异步队列消峰)——可单体优化的一律不拆服务。


七、技术风险与对策

风险 概率 影响 对策
RN 原生模块冲突(第三方库版本不兼容) Expo managed workflow 统一版本;冲突时降级 bare workflow;每周依赖审计
App Store / Google Play 审核被拒 提前遵守审核指南(PDPO 隐私政策、苹果登录选项、安卓目标 API 级别);首次提审预留 2 周缓冲
Expo 限制(部分原生能力需 bare workflow) managed 优先;必要时 eject 到 bare;保留原生扩展能力
师傅端 L6 拍照离线场景复杂(弱网/无网/电量) AsyncStorage 本地队列 + NetInfo 网络监听 + 指数退避重试;照片压缩 WebP 减少体积
BE/FE 核心开发招聘不到位 Code Agent 全栈实施 + DT AI 协同;司徒兜底关键模块;前端 RN 部分可分阶段交付
推送送达率不达标(iOS 静默推送限制) Expo Notifications 统一通道;关键通知走高优先级;送达率监控告警
师傅照片/视频存储成本爆炸(每日 100 单 × 每单 20 张) Cloudflare R2 零出口费;前端 WebP 压缩;超过 90 天自动降冷
数据库 DDL 变更回滚风险 Alembic 双脚本(upgrade + downgrade);CI dry-run;上线前全站备份;重大变更凌晨窗口

八、决策记录(Architecture Decision Records,ADR)

关键架构决策须记录,便于未来回溯为什么"这么选"。

ADR # 决策 日期 决策人 理由
ADR-001 选 Python FastAPI 而非 Go/Node 后端 2026-08-09 TL + SPO ① AI 生态最成熟(Pandas/LLM 工具链);② 司徒 Python 熟练度最高;③ 报价/派单算法代码可读性强
ADR-002 选 React Native + Expo 而非 Next.js PWA(V2.0 重写) 2026-08-09 TL + SPO ① 原生体验远超 PWA(动画/手势/启动速度);② 深度集成相机/推送/离线/生物识别;③ 香港师傅 Android 为主,PWA 留存率低;④ Expo 一站式 OTA/构建/推送;⑤ 运营后台保留 Next.js(PC Web 场景更佳)
ADR-003 PostgreSQL 而非 MySQL 2026-08-09 TL ① JSONB 原生存储采集物和灵活字段;② 窗口函数(派单匹配算法)更强;③ 未来 GIS 扩展(PostGIS)
ADR-004 模块化单体先行,不直接微服务 2026-08-09 TL + SPO ① 团队 < 10 人,微服务复杂度 > 收益;② 业务规则未稳定,拆分边界可能错误
ADR-005 香港 VPS + Cloudflare,不上 AWS/GCP 2026-08-09 TL + BO ① 成本低一个数量级;② 香港 VPS 访问延迟更低;③ GCP/AWS 香港区域价格贵
ADR-006 选 Expo managed workflow 而非纯 RN CLI 2026-08-09 TL ① EAS Build 云端构建免本地 Xcode/Android Studio;② Expo Updates OTA 热更新 JS Bundle;③ Expo Notifications 统一 APNs+FCM;④ Expo SDK 统一依赖版本减少冲突
ADR-007 客户端 CST 纳入阶段2 范围(原 Out of Scope) 2026-08-09 TL + SPO ① 全干系方平台目标需要客户端参与;② RN 复用师傅端组件成本低;③ 客户端是口碑营销与推荐闭环的关键触点;④ 询价→下单→评价全流程数字化
ADR-008 跳过阶段1 飞书对接,直接实施阶段2 2026-08-09 TL + SPO ① 飞书方案(阶段0)实际运行情况待观察;② 直接做原生 App 避免飞书 SDK 投入打水漂;③ 飞书对接文档 DIP1-P1 保留,未来按需启动;④ Code Agent 全栈聚焦阶段2 目标

修订记录

版本 日期 修订人 修订内容
V1.0 2026-08-09 DT 初始化:DDD 四层分层 + 限界上下文映射 + 阶段 1/2 部署架构 + 7 条 NFR + 5 条 ADR
V2.0 2026-08-09 DT 前端架构升级为 React Native:C4 容器图前端层改为 3 端(opr-admin Web + wkr-app RN + cst-app RN);部署架构新增 App Store/Google Play + Expo EAS/OTA/Notifications;NFR 新增移动端离线/推送/启动性能/兼容性 4 项;技术风险新增 RN/审核/离线/推送 4 项;ADR-002 重写(RN 替代 Next.js PWA)+ 新增 ADR-006(Expo)/ADR-007(客户端纳入)/ADR-008(跳过飞书)

本文件为 DIP1 架构设计(DOC-D00-D1-01 V2.0),前端采用 React Native + Expo(师傅端+客户端原生)+ Next.js(运营后台 Web)双引擎架构。