Files
oil-formula-calculator/doc/deploy.md
Hera Zhao ee8ec23dc7 Refactor frontend to Vue 3 + Vite + Pinia + Cypress E2E
- Replace single-file 8441-line HTML with Vue 3 SPA
- Pinia stores: auth, oils, recipes, diary, ui
- Composables: useApi, useDialog, useSmartPaste, useOilTranslation
- 6 shared components: RecipeCard, RecipeDetailOverlay, TagPicker, etc.
- 9 page views: RecipeSearch, RecipeManager, Inventory, OilReference, etc.
- 14 Cypress E2E test specs (113 tests), all passing
- Multi-stage Dockerfile (Node build + Python runtime)
- Demo video generation scripts (TTS + subtitles + screen recording)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:35:00 +00:00

195 lines
6.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 精油配方计算器 - 部署文档
## 架构
- **前端**: Vue 3 + Vite + Pinia + Vue Router构建为静态文件由 FastAPI serve
- **后端**: FastAPI + SQLite端口 8000
- **部署**: Kubernetes (k3s) on `oci.euphon.net`
- **域名**: https://oil.oci.euphon.net
- **TLS**: Traefik + Let's Encrypt (自动)
## 目录结构
```
├── backend/
│ ├── main.py # FastAPI 应用
│ ├── database.py # SQLite 数据库操作
│ ├── defaults.json # 默认精油和配方数据(首次启动时 seed
│ └── requirements.txt
├── frontend/ # Vue 3 + Vite 项目
│ ├── package.json
│ ├── vite.config.js
│ ├── index.html
│ ├── public/ # 静态资源favicon、PWA icons
│ └── src/
│ ├── main.js # 入口文件
│ ├── App.vue # 根组件
│ ├── router/ # Vue Router 路由配置
│ ├── stores/ # Pinia 状态管理
│ │ ├── auth.js # 认证/用户
│ │ ├── oils.js # 精油价格
│ │ ├── recipes.js # 配方/标签/收藏
│ │ ├── diary.js # 个人配方日记
│ │ └── ui.js # UI 状态
│ ├── composables/ # 组合式函数
│ │ ├── useApi.js # API 请求封装
│ │ ├── useDialog.js # 自定义对话框
│ │ ├── useSmartPaste.js # 智能粘贴解析
│ │ └── useOilTranslation.js # 精油中英翻译
│ ├── components/ # 共享组件
│ │ ├── RecipeCard.vue
│ │ ├── RecipeDetailOverlay.vue
│ │ ├── TagPicker.vue
│ │ ├── LoginModal.vue
│ │ ├── UserMenu.vue
│ │ └── CustomDialog.vue
│ ├── views/ # 页面组件
│ │ ├── RecipeSearch.vue # 配方查询
│ │ ├── RecipeManager.vue # 管理配方
│ │ ├── Inventory.vue # 个人库存
│ │ ├── OilReference.vue # 精油价目
│ │ ├── Projects.vue # 商业核算
│ │ ├── MyDiary.vue # 我的(日记/品牌/账号)
│ │ ├── AuditLog.vue # 操作日志
│ │ ├── BugTracker.vue # Bug 追踪
│ │ └── UserManagement.vue # 用户管<E688B7><E7AEA1>
│ └── assets/
│ └── styles.css # 全局样式
├── deploy/
│ ├── namespace.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── pvc.yaml # 1Gi 持久卷,存放 SQLite 数据库
│ ├── ingress.yaml
│ ├── setup-kubeconfig.sh
│ └── kubeconfig
├── Dockerfile # 多阶段构建Node → Python
└── doc/deploy.md
```
## 本地开发
```bash
# 前端开发(热更新)
cd frontend
npm install
npm run dev # 默认 http://localhost:5173自动代理 /api 到 :8000
# 后端开发
cd backend
pip install -r requirements.txt
uvicorn backend.main:app --reload --port 8000
```
## 构建
```bash
# 前端构建
cd frontend
npm run build # 输出到 frontend/dist/
# Docker 构建(多阶段:先构建前端,再打包后端)
docker build -t oil-calculator .
```
## 首次部署
已完成,以下为记录。
```bash
# 1. SSH 到服务器
ssh fam@oci.euphon.net
# 2. 上传项目
scp oil-calc.tar.gz fam@oci.euphon.net:/tmp/
ssh fam@oci.euphon.net "mkdir -p ~/oil-calculator && cd ~/oil-calculator && tar xzf /tmp/oil-calc.tar.gz"
# 3. 构建并推送镜像
cd ~/oil-calculator
docker build -t registry.oci.euphon.net/oil-calculator:latest .
docker push registry.oci.euphon.net/oil-calculator:latest
# 4. 部署 k8s 资源
cd deploy
kubectl apply -f namespace.yaml
kubectl apply -f pvc.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
# 5. 需要 regcred 才能拉取私有镜像(从已有 ns 复制)
kubectl get secret regcred -n guitar -o yaml | sed 's/namespace: guitar/namespace: oil-calculator/' | kubectl apply -f -
```
## 更新部署
```bash
# 在本地打包上传
cd /path/to/oil
tar czf /tmp/oil-calc.tar.gz Dockerfile backend/ frontend/ deploy/ --exclude='frontend/node_modules' --exclude='frontend/dist'
scp /tmp/oil-calc.tar.gz fam@oci.euphon.net:/tmp/
# SSH 到服务器构建并重启
ssh fam@oci.euphon.net
cd ~/oil-calculator && tar xzf /tmp/oil-calc.tar.gz
docker build -t registry.oci.euphon.net/oil-calculator:latest .
docker push registry.oci.euphon.net/oil-calculator:latest
kubectl rollout restart deploy/oil-calculator -n oil-calculator
```
或者使用受限 kubeconfig仅重启不含构建
```bash
KUBECONFIG=deploy/kubeconfig kubectl rollout restart deploy/oil-calculator
```
## 受限 Kubeconfig
文件位于 `deploy/kubeconfig`,权限范围:
- **Namespace**: `oil-calculator` only
- **ServiceAccount**: `oil-calculator-deployer`
- **权限**: pods, services, deployments, replicasets, ingresses, PVC, configmaps, secrets, pods/log 的完整 CRUD
- **无法**访问其他 namespace 或集群级资源
重新生成:`bash deploy/setup-kubeconfig.sh`
## K8s 配置要点
- **Ingress class**: `traefik`
- **TLS annotation**: `traefik.ingress.kubernetes.io/router.tls.certresolver: le`
- **镜像仓库**: `registry.oci.euphon.net`(需要 `regcred` secret
- **数据持久化**: PVC 挂载到 `/data`SQLite 数据库在 `/data/oil_calculator.db`
## API 端点
| Method | Path | 说明 |
|--------|------|------|
| GET | /api/oils | 所有精油列表 |
| POST | /api/oils | 添加/更新精油 |
| DELETE | /api/oils/{name} | 删除精油 |
| GET | /api/recipes | 所有配方列表 |
| POST | /api/recipes | 新增配方 |
| PUT | /api/recipes/{id} | 更新配方 |
| DELETE | /api/recipes/{id} | 删除配方 |
| GET | /api/tags | 所有标签 |
| POST | /api/tags | 新增标签 |
| DELETE | /api/tags/{name} | 删除标签 |
| GET | /api/me | 当前用户信息 |
| POST | /api/login | 登录 |
| POST | /api/register | 注册 |
| GET | /api/diary | 个人配方列表 |
| POST | /api/diary | 创建个人配方 |
| PUT | /api/diary/{id} | 更新个人配方 |
| DELETE | /api/diary/{id} | 删除个人配方 |
| GET | /api/favorites | 收藏列表 |
| POST | /api/favorites/{id} | 添加收藏 |
| DELETE | /api/favorites/{id} | 取消收藏 |
| GET | /api/inventory | 个人库存 |
| POST | /api/inventory | 更新库存 |
| GET | /api/projects | 商业项目列表 |
| GET | /api/audit-log | 操作日志 |
| GET | /api/users | 用户列表(管理员)|
| GET | /api/bug-reports | Bug 列表 |
| GET | /api/notifications | 通知列表 |
| GET | /api/version | 服务器版本 |