Files
FuelLog/AGENTS.md
T

11 KiB

AGENTS.md

一个轻量、精美、移动端优先的个人加油记录与车辆燃油成本分析工具。

中英别名: FuelLog / 加油记

项目目标

10 秒完成一笔加油记录,自动算出实际油价、百公里油耗、每公里成本;移动端 + PWA 优先;架构简单、不堆中间件,后续可扩展到充电、保养、停车、保险等车辆综合成本。

完整产品/技术决策见 FuelLog_PLAN.md,本文件是给 Agent 的工程操作手册。


仓库结构(单仓双工程,推荐)

仓库根 = 整个项目,内含前端与后端两个 Go module 风格的子工程:

FuelLog/
├── fuellog-web/        # Vue 3 + TS + Vite 前端
├── fuellog-api/        # Go + Gin + GORM 后端
├── deploy/             # docker-compose / Nginx / PWA manifest 等
├── docs/               # 设计稿、API 文档、截图
├── data/               # SQLite 文件(开发期;部署期挂 volume)
├── AGENTS.md           # 本文件
├── README.md
└── .gitignore

若 Agent 决定使用 frontend/ backend/ 之类的别名,在该子目录里再放一份本地 AGENTS.md 明确路径即可,根目录命令按本文件执行。


Setup commands

准备环境

  • Node.js ≥ 20,pnpm ≥ 9(优先 pnpm,无则 npm)
  • Go ≥ 1.22
  • Docker / Docker Compose(部署)
  • git、make(可选,make help 查看快捷命令)

后端

cd fuellog-api
go mod tidy
cp .env.example .env          # 本地 SQLite 默认 ./data/fuellog.db
go run ./cmd/server           # 监听 :8080
go test ./...                 # 核心计算单测
go vet ./...

前端

cd fuellog-web
pnpm install                  # 或 npm install
pnpm dev                      # 启动 Vite,默认 :5173,自动代理 /api -> :8080
pnpm build
pnpm preview                  # 预览构建产物
pnpm typecheck                # vue-tsc
pnpm lint                     # eslint + prettier

整体(开发期)

docker compose -f deploy/docker-compose.dev.yml up   # API + Web + 反代 一把起

部署

docker compose -f deploy/docker-compose.yml up -d

data/ 目录必须挂载 volume,SQLite 不可随容器删除。


技术栈(锁定,不要临时换)

Frontend

  • Vue 3 + TypeScript + Vite
  • Vue Router / Pinia
  • Tailwind CSS(主题通过 CSS Variables / Tailwind Theme,不在组件里写死颜色)
  • Naive UI(优先,不适合时退到 Element Plus)
  • ECharts(统计图表)
  • vite-plugin-pwa(PWA: manifest + service worker + 添加到主屏)

Backend

  • Go + Gin
  • GORM(默认;若团队更熟 sqlc 允许,需在 PR 写理由)
  • SQLite(默认,代码层用 GORM 抽象,后续能切 Postgres)
  • 金额:使用 decimal 库或按"分"为单位的整数,避免 float 累计误差

Infra

  • Docker / Docker Compose
  • Nginx / Nginx Proxy Manager 反代
  • 单一 SQLite 文件 + volume 持久化

MVP 禁止引入

Kubernetes / 微服务 / Kafka / Redis / RabbitMQ / Elasticsearch / GraphQL / Service Mesh / CQRS / Event Sourcing —— 出现真实需求前不要上。


项目布局

后端 fuellog-api/

fuellog-api/
├── cmd/server/                 # main.go
├── internal/
│   ├── handler/                # Gin handler,只做 HTTP
│   ├── service/                # 业务逻辑(油价/油耗/成本/统计)
│   ├── repository/             # 数据库访问
│   ├── model/                  # 实体
│   ├── dto/                    # 入参/出参
│   ├── middleware/             # 日志/错误/恢复
│   └── router/                 # 路由注册
├── migrations/                 # GORM AutoMigrate 或 goose 脚本
├── config/
├── pkg/                        # 通用工具(decimal 封装、错误码等)
├── go.mod
└── Dockerfile

硬性分层:Handler 不允许写业务逻辑。Service 持有 Repository 抽象,便于单测。

前端 fuellog-web/

fuellog-web/
├── src/
│   ├── api/                    # 类型化 API client(基于 openapi 后再生成)
│   ├── assets/
│   ├── components/
│   ├── layouts/                # 移动端 Bottom Nav + 桌面侧栏
│   ├── pages/
│   │   ├── dashboard/
│   │   ├── refuel/             # 列表 + 新增 + 编辑
│   │   ├── statistics/
│   │   └── vehicle/
│   ├── router/
│   ├── stores/                 # Pinia
│   ├── types/
│   ├── utils/                  # decimal 工具、单位转换
│   ├── App.vue
│   └── main.ts
├── public/                     # PWA manifest 图标
├── package.json
└── vite.config.ts

Code style

通用

  • 文件名、变量、commit 用英文;用户可见文案、注释、commit message 用简体中文。
  • Conventional Commits 强制:feat: fix: docs: refactor: style: test: chore: perf:。
  • 提交前 pnpm lint + go vet 必须 0 错 0 警。
  • 金额、加油量、里程统一用 decimal 或显式单位,严禁直接 == 比较 float。

前端

  • TypeScript strict: true;不写 any,能用 unknown / 联合类型收口。
  • Vue SFC <script setup lang="ts">;组合式 API 优先。
  • Tailwind + 主题 token,不写死颜色/间距/字号。
  • 移动端 360 / 390 / 430 三档断点优先验证,再适配桌面。
  • 任何页面必须有 Loading / Empty / Error 三态。

后端

  • gofmt + goimports 必跑。
  • 错误统一 pkg/apperror,返回 { "code": "INVALID_ARGUMENT", "message": "..." }。
  • 参数校验在 Handler 入参后立即完成,失败立即 abort。
  • 业务时间统一 UTC 存库,展示按本地时区格式化。

数据库 & Migration

  • MVP 使用 SQLite,文件路径从 env 读,默认 ./data/fuellog.db。
  • 任何表结构变更必须新增 migration 文件,不允许 AutoMigrate 覆盖生产数据。
  • 核心表:vehicle、refuel_record,字段定义严格按 FuelLog_PLAN.md §7。
  • 后续扩展(charging_record / maintenance_record / fuel_price_history)要预留命名空间,不要把字段塞进 refuel_record。

核心计算规则(必须有单测)

公式见 FuelLog_PLAN.md §6,这里只列硬要求:

  1. 实际油价 = 总金额 / 加油量 —— 服务端实时计算并落库,前端输入金额 + 升数后立刻展示。
  2. 行驶里程 = 本次里程 - 上一次有效里程(同一车辆按时间顺序)。
  3. 百公里油耗 仅在连续两次 is_full=true 的记录之间计算,半箱油记录不能进入标准油耗。
  4. 每公里燃油成本 = 本次燃油费用 / 行驶里程。
  5. 单测必须覆盖:
    • 油价计算(176.33 / 23.67 ≈ 7.45)
    • 油耗计算((10500-10000) / 40 * 100 = 8.0)
    • 半箱油不计入标准油耗
    • 删除/编辑记录后 Dashboard / 统计数据正确刷新

API 设计

Base path /api,见 FuelLog_PLAN.md §8。最低端点集:

GET/POST/PUT/DELETE   /api/vehicles[/...]
GET/POST/PUT/DELETE   /api/refuels[?...filters]
GET                   /api/dashboard
GET                   /api/statistics/overview
GET                   /api/statistics/fuel-consumption
GET                   /api/statistics/fuel-price
GET                   /api/statistics/monthly-cost
GET                   /api/statistics/cost-per-km
  • 查询参数:vehicle_id、start_date、end_date、fuel_type、station_name、page、page_size。
  • 错误统一格式见上文 apperror。
  • 必须在 docs/api.md 或 Swagger 同步端点;前端类型与 DTO 保持一致。

UI / UX 硬性要求

  • Mobile first,卡片式 Dashboard,大字号主指标(本月花费最大,平均油价/平均油耗次之)。
  • 10 秒录入 新增加油:加油时间 → 里程 → 加油量 → 总金额 → 油品 → 加油站 → 是否加满 → 备注,保存按钮固定在移动端底部。
  • Light / Dark Mode 必须支持,可跟随系统;通过 CSS Variables 切换,不在组件里堆 if-else。
  • 空数据 / 加载中 / 错误 状态统一,不能一片白。
  • 删除 任何记录/车辆都要二次确认。
  • 移动端文案要短(加油量 23.67 L、金额 176.33 元),实际油价 ¥7.45/L 实时显示。

PWA

MVP 必须包含:

  • manifest.webmanifest、app icon(192 / 512 / maskable)
  • service worker(由 vite-plugin-pwa 生成)
  • 添加到主屏可用
  • 离线时能打开基础 UI(空数据也 OK)
  • 真正的离线数据同步放后续版本

数据导入导出

Phase 7 必做,放在 MVP 后期,不要拖到最后:

  • 导出 JSON:含 vehicles + refuel_records 全量
  • 导入 JSON:覆盖或合并,UI 给出明确选项
  • 导出 CSV:加油记录(给 Excel 看)
  • 目的:用户数据任何时候可迁出,不被项目绑死

安全 & 数据完整性

  • 金额 ≥ 0,加油量 > 0,里程 ≥ 0,加油时间为合法日期 —— 后端强校验。
  • vehicle_id 必须存在,跨车辆引用全部拒绝。
  • 删除操作必须显式确认。
  • .env 入 .gitignore,不提交密钥;生产敏感配置走环境变量。
  • 容器内 API 默认只监听内网,由 Nginx 反代对外。

Testing

  • 后端:go test ./...,重点覆盖 internal/service(计算 + 统计)。
  • 前端:Vitest 覆盖 utils/ 与关键组件;Playwright 跑核心流程(创建车 → 加油 → 看到 Dashboard 更新)。
  • 每完成一个 Phase,跑一次 docker compose up -d,确认整体可起。
  • CI 至少跑:go vet + go test + pnpm typecheck + pnpm build。

Definition of Done

一个功能完成必须同时满足:

  • 功能可用(API + 前后端闭环)
  • 移动端正常(360 / 390 / 430 三档目视)
  • 桌面端正常
  • 数据库 migration 同步
  • 错误处理完整(统一 apperror 格式)
  • Loading / Empty / Error 状态完整
  • 核心逻辑有单测
  • docker compose up 能起
  • README / docs/api.md 同步更新
  • commit message 走 Conventional Commits

Agent 执行顺序(每步先验证,再下一步)

严格按 FuelLog_PLAN.md §27 推进。禁止跳步、禁止一次性生成全部代码:

  1. 初始化项目骨架(本文件落盘后,创建 fuellog-web/ + fuellog-api/ + deploy/ + docker-compose.dev.yml)
  2. 后端 Model / Repository / Service / Handler + SQLite + migration
  3. 核心计算单测
  4. 后端 API(车辆 / 加油 / Dashboard / 统计)
  5. 前端骨架(Vue Router + Pinia + Tailwind + Naive UI + 主题)
  6. Dashboard 页面
  7. 新增加油页面
  8. 加油记录列表
  9. 车辆管理
  10. 统计图表(ECharts)
  11. UI 精修 / 暗色模式 / Loading / Empty / Error
  12. PWA
  13. 导入导出
  14. Docker 完整部署测试
  15. README + 截图

每完成一步,回到 Definition of Done 自查,再开下一步。


注意事项

  • 不要提前加复杂设施:MVP 不需要 Redis、不需要 K8s、不需要微服务。需要时再讨论。
  • 不要堆业务逻辑在 Handler:所有计算走 Service,便于单测。
  • 不要写死颜色/间距/字号:统一从 Tailwind theme / CSS Variables 读。
  • 不要为"显得高级"加没有实际价值的技术。
  • 任何与本文件冲突的需求,先改本文件再改代码,保持文档先行。