platform-assistant/docs/本地开发工作流.md
Sisyphus afac18e843 feat(F002): W26 + W29.x + W30 + W31 平台助手全部改动首次 commit
- W26: NestJS API + Next.js Web + Prisma + SQLite scaffold
- W26: Lead 模型 + Crawler + 询价发布助手 (线索池 + 一键发布)
- W29.x: MCP 集成 (Integration 模型 + connectMcp + publish_rfq 5 工具端到端跑通)
- W30: 3 字段补充 (notes / quotationType / quotationDemand)
- W31 P1: 自动填 enterpriseId / userId (Prisma companyUserId 字段 + get_app_identity tool + lead.service.ts publishArgs)
- W31: detail 详情页 + admin UI 集成管理 (OpenAppListView + AuditLogListView)

关联: ~/Documents/02-平台开发/产品开发/F002-W31-交接文档.md
GIT-AUDIT-REPORT-2026-06-24.md
2026-06-24 11:07:11 +08:00

131 lines
10 KiB
Markdown
Raw 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.

# 本地开发工作流(暂停部署)
**生效时间**: 2026-06-22 起
**原因**: 进入密集调试修改阶段,所有改动只在本地验证,等批次完成后再统一发到生产
---
## 🚦 红灯规则
| 行为 | 是否允许 |
|------|----------|
| 修改本地代码(apps/api、apps/web、scripts 等)| ✅ |
| 修改 prisma schema(本地 dev.db)| ✅ |
| nest watch 热重载 | ✅ 自动 |
| next dev 热重载 | ✅ 自动 |
| **rsync 代码到生产** | ❌ 暂停 |
| **重启生产 PM2 进程** | ❌ 暂停 |
| **生产 prisma db push** | ❌ 暂停 |
| **生产数据库迁移 / SQL** | ❌ 暂停 |
| **生产证书 / Nginx 修改** | ❌ 暂停 |
| **生产服务器手工操作** | ❌ 暂停(仅读查询例外)|
例外:本地只读查询到生产是允许的(如 `ssh ... ls/cat/tail/grep/curl/sshpass` 只读命令)
---
## ✅ 本地修改流程
1. 修改代码 → nest watch / next dev 自动重载
2. 用本地 DB 验证:`http://localhost:3001` + `localhost:4000/api`
3. 类型检查(必要时):
```bash
cd /Users/zou/Documents/02-平台开发/平台助手/apps/api
npx tsc --noEmit
cd /Users/zou/Documents/02-平台开发/平台助手/apps/web
npx tsc --noEmit
```
4. 在浏览器测试 UI 效果
---
## 📦 批次打包流程(等所有调试完成后)
打包前确认清单:
- [ ] 所有本地修改的源代码已稳定运行 ≥24 小时
- [ ] 本地数据库 schema 与 prisma/schema.prisma 一致
- [ ] 类型检查 0 错误
- [ ] 关键功能回归测试通过
打包命令:
```bash
# 1. 本地构建
cd /Users/zou/Documents/02-平台开发/平台助手
npm run build -w apps/api
npm run build -w apps/web # 如果失败,先绕过 next build lockfile patch
# 2. rsync 源码到生产(不传 node_modules、.next)
rsync -avz --delete \
--exclude='node_modules' \
--exclude='.next/cache' \
--exclude='prisma/dev.db*' \
--exclude='public/uploads' \
--rsh="sshpass -e ssh -o StrictHostKeyChecking=no" \
./ ubuntu@172.81.241.109:/opt/pingtai/
# 3. 生产环境:重新构建 + 同步 DB schema
sshpass -p 'Jubianshuzi@2026' ssh ubuntu@172.81.241.109 "
cd /opt/pingtai/apps/api
npm run build
npx prisma db push # 注意:会修改生产 DB schema
cd /opt/pingtai
npm install # 如果有依赖变更
pm2 restart pingtai-api pingtai-web --update-env
"
# 4. 验证
curl -s -o /dev/null -w 'API: %{http_code}\n' http://172.81.241.109:4000/api/health
curl -s -o /dev/null -w 'Web: %{http_code}\n' https://zoupeng.cloud
```
---
## 📝 调试变更追踪
每次修改请记录到这里,方便后续打包时知道改了哪些。
| 日期 | 修改内容 | 文件 |
|------|---------|------|
| 2026-06-22 | 加 publishTime 字段;publish 默认值改"未发布" | apps/api/prisma/schema.prisma |
| 2026-06-22 | crawler.upsert 写入 publishTime | apps/api/src/crawler/crawler.service.ts |
| 2026-06-22 | 表格加"发布时间"列;发布状态列字体统一 | apps/web/src/components/InquiryPage.tsx |
| 2026-06-22 | **MCP 集成密钥轮换**:本地数据库写入新 appSecret,集成状态 error → active。密钥轮换脚本 `scripts/rotate-mcp-key.sh`(拿到新密钥后 `NEW_APP_ID=xxx NEW_APP_SECRET=yyy bash scripts/rotate-mcp-key.sh` 一键执行)| scripts/rotate-mcp-key.sh(新文件)|
| 2026-06-22 | **修复 publish_rfq 返回 rfqId=null bug**:MCP tool 返回结构是 `{code, msg, data: {orderId, rfqId, status}}`,B2B 业务对象嵌在外层 `data.data`。原代码 `data.rfqId` 拿到 undefined。修复为 `payload = data.data \|\| data; payload.rfqId \|\| ...`。**修复后端到端验证通过**:远程订单号 `RFQ20260622161118531`、rfqId `2068970068244123649`、direvUrl 带真 rfqId | apps/api/src/lead/lead.service.ts |
| 2026-06-22 | **MCP 适配新 schema(移除了 category_id/unit/deadline)**:原 publishToDirev 传 `category_id:1 / unit:件 / deadline` 但 MCP server 重启后 schema 简化了。改为只传 schema 接受的字段:`title / description / qty / attachments`。attachments 优先用 `lead.attachments`(JSON 字符串),fallback 到 `lead.detailUrl` | apps/api/src/lead/lead.service.ts |
| 2026-06-22 | **Lead 模型加 4 个新字段**:quantity(整数)、unit(单位)、regionDetail(详细收货地址)、attachments(JSON 数组字符串)。db push 已同步本地 dev.db | apps/api/prisma/schema.prisma |
| 2026-06-22 | **前端 Lead 类型扩展**:InquiryPage / LeadDetailPage 的 Lead 接口加 regionDetail / quantity / unit / attachments 字段;表格加"数量"列(colSpan 从 10 改 11);详情页加"询价数量/收货地址/附件"三栏;抽屉加"询价数量/收货地址/公告日期";附件字段支持 JSON 数组渲染多链接 | apps/web/src/components/InquiryPage.tsx, apps/web/src/components/LeadDetailPage.tsx |
| 2026-06-22 | **devbox F002 升级需求文档**:`docs/devbox-requirements/MCP-publish_rfq-字段升级需求.md`。需求:在 devbox 的 `publish_rfq` zod schema + `InquiryServiceImpl.publish()` 补 deadline/deliveryDate/shippingAddress/contactName/contactPhone/freightFlag/paymentMethod/invoiceType/procurementType/inquiryParty 共 10 个商务字段。**当前 devbox 还没改,平台助手先按现有 schema 实现** | docs/devbox-requirements/MCP-publish_rfq-字段升级需求.md(新文件)|
| 2026-06-22 | **devbox F002 升级完成 + 平台助手二次适配**:devbox 已把 publish_rfq schema 升级(W29.7, 补 11 商务字段),Java 后端 `InquiryServiceImpl.publish()` 也补全字段映射。平台助手这边把新参数加进 `publishToDirev` 的 `publishArgs`:deadline(直接传 Lead.deadline YYYY-MM-DD)、deliveryDate(自动 deadline+30 天)、shippingAddress(优先 Lead.regionDetail, fallback region)、contactName/Phone(从 Lead.contact/phone)、inquiryParty("郑州巨变")、freightFlag("含运费")、procurementType("定量采购")、invoiceType("增值税专票")、paymentMethod("货到付款") | apps/api/src/lead/lead.service.ts |
| 2026-06-22 | **devbox 升级导致密钥重置**:`app_9dd07cb4e0e24fccbecd` 的 appSecret 被重置(MySQL 里 hash 前缀从 `$2a$10$iR3Rl` 变 `$2a$10$m3hRN`)。用 `POST /sys/openapi/app/reset-secret/{id}` 端点自助重置拿到新密钥 `d02dc00c6fbe4a34a5bf013134146c3f2759148c61a341d2`,本地集成密钥已轮换 | scripts/rotate-mcp-key.sh |
| 2026-06-22 | **端到端验证新字段入库**:rfqId=2068990783236042754,orderId=RFQ20260622173337369,MySQL 里 11 个商务字段都正确填充(purchase_quantity=50, inquiry_valid_date=2026-08-31, deliver_date=2026-09-30, shipping_address, contact_name="郑钊", contact_phone=15532027557, inquiry_party="郑州巨变", freight_flag=1, invoice_type=2, procurement_type=1, urls)。**唯一未入库:`payment_method` 字段为 NULL**,原因:devbox 按企业 ID + 名称查 `tb_supplier_pay_type` 表,没找到 "货到付款" 这个字典项就会抛错但不影响 publish 成功(注意日志可能有 `付款方式查询失败: ...` 警告)| — |
| 2026-06-23 | **密钥再次重置 + 司库系统重发**:devbox 傍晚又把密钥重置(hash 前缀 `m3hRN → diPRva`,update_date 18:18:22)。用 `reset-secret` 端点再次自助重置拿到新密钥 `fcb53684845648e2a7fc1082f5245180cfa4eea1f5404176`。**用户反馈现象**:选了 `司库系统升级完善项目` 点一键发布,本地显示"发布成功"但 B2B 后台查不到。**根因**:MCP 鉴权失败后代码降级为本地假订单号(X+时间戳),让用户误以为成功。 | scripts/rotate-mcp-key.sh |
| 2026-06-23 | **彻底移除降级本地模式 + MCP 失败弹警告**:(1) 后端 `publishToDirev` 不再写本地假 `inquiryNo=X...`;MCP 鉴权/调用失败时抛 `ServiceUnavailableException` 返回 503 + 详细错误信息;Lead 状态完全不动。(2) 前端 `doPublish` 收集每条失败原因(fetch `res.json().message`),失败时弹新 Modal(红框 + 错误列表 + 「去 MCP 配置」/「我知道了」按钮)。**端到端验证**:把密钥改成 `invalid_test_key_for_qa` → publish 返回 HTTP 503 + JSON 含 `appSecret 校验失败` + 引导文案;Lead 表 publish/inquiryNo/followLogs 全部不变。 | apps/api/src/lead/lead.service.ts, apps/web/src/components/InquiryPage.tsx |
| 2026-06-22 | **devbox F002 升级完成 + 平台助手二次适配**:devbox 已把 publish_rfq schema 升级(W29.7, 补 11 商务字段),Java 后端 `InquiryServiceImpl.publish()` 也补全字段映射。平台助手这边把新参数加进 `publishToDirev` 的 `publishArgs`:deadline(直接传 Lead.deadline YYYY-MM-DD)、deliveryDate(自动 deadline+30 天)、shippingAddress(优先 Lead.regionDetail, fallback region)、contactName/Phone(从 Lead.contact/phone)、inquiryParty("郑州巨变")、freightFlag("含运费")、procurementType("定量采购")、invoiceType("增值税专票")、paymentMethod("货到付款") | apps/api/src/lead/lead.service.ts |
| 2026-06-22 | **devbox 升级导致密钥重置**:`app_9dd07cb4e0e24fccbecd` 的 appSecret 被重置(MySQL 里 hash 前缀从 `$2a$10$iR3Rl` 变 `$2a$10$m3hRN`)。用 `POST /sys/openapi/app/reset-secret/{id}` 端点自助重置拿到新密钥 `d02dc00c6fbe4a34a5bf013134146c3f2759148c61a341d2`,本地集成密钥已轮换 | scripts/rotate-mcp-key.sh |
| 2026-06-22 | **端到端验证新字段入库**:rfqId=2068990783236042754,orderId=RFQ20260622173337369,MySQL 里 11 个商务字段都正确填充(purchase_quantity=50, inquiry_valid_date=2026-08-31, deliver_date=2026-09-30, shipping_address, contact_name="郑钊", contact_phone=15532027557, inquiry_party="郑州巨变", freight_flag=1, invoice_type=2, procurement_type=1, urls)。**唯一未入库:`payment_method` 字段为 NULL**,原因:devbox 按企业 ID + 名称查 `tb_supplier_pay_type` 表,没找到 "货到付款" 这个字典项就会抛错但不影响 publish 成功(注意日志可能有 `付款方式查询失败: ...` 警告)| — |
---
## ⚠️ 常见陷阱
1. **数据库结构**:本地 dev.db 和生产 dev.db 是分开的,本地任何 schema 变更不会自动同步到生产
2. **依赖升级**:如果加了新依赖(如 npm install xxx),生产需要单独跑 npm install
3. **next build**:生产 next build lockfile patch 经常失败,使用 dev mode 跑 web 即可,不强制 build
4. **Prisma generate**:每次改 schema 都要跑 `npx prisma generate`,否则 API 拿不到新字段
---
## 🔍 当前本地服务状态
```bash
# Web: http://localhost:3001 (PID 66990, next dev)
# API: http://localhost:4000/api (PID 17721 + 20451, nest watch)
# DB: apps/api/prisma/dev.db (本地 SQLite)
```
**账号**: admin / admin123