@@ -0,0 +1,45 @@
|
||||
# 2026-08-12 工作记录
|
||||
|
||||
## 杜康好客 · 三项功能需求落地(dev_jacy 分支)
|
||||
|
||||
### 需求1:管理端用户列表增加好客权益金额列
|
||||
- 后端 `server/dukang-api/src/modules/ops/admin-users.service.ts`:
|
||||
- 新增常量 `BENEFIT_STAT_STATUSES = ['ACTIVE','USED_UP']`、`UserBenefitStat` 类型、`EMPTY_BENEFIT_STAT`、`toAmount()`。
|
||||
- `list()` / `detail()` 均调用新增私有方法 `loadBenefitStats(userIds)`,用 `benefitCoupon.groupBy({ by:['userId'], where:{status:{in:[...BENEFIT_STAT_STATUSES]}}, _sum:{totalAmount,usedAmount,balance} })` 批量聚合,避免 N+1。
|
||||
- `mapAdminUserRow` 增加 `benefit` 参数并展开到返回对象。统计口径与 C 端 `listCoupons` 一致(排除 VOID)。
|
||||
- 前端 `apps/admin-web/src/lib/api.ts`:`AdminUserRow` 增加 `benefitTotalAmount?/benefitUsedAmount?/benefitBalance?: number`。
|
||||
- 前端 `apps/admin-web/src/pages/UsersPage.tsx`:新增「剩余权益/已用权益/累计权益」三列(右对齐、可排序,scroll x 改为 1830),详情抽屉 Descriptions 增加「好客权益」项。
|
||||
|
||||
### 需求2:管理端门店入驻合同支持多图上传
|
||||
- 新建共享工具 `server/dukang-api/src/common/store-media/contract-urls.util.ts`:`MAX_CONTRACT_FILES=20`、`normalizeContractUrls(urls?, legacy?)`、`contractMediaType(url)`(.pdf→FILE 否则 IMAGE)。
|
||||
- 后端 `admin-stores.service.ts`:import 上述工具;create(645 行)/ update(451 行)路径由单条 `contractUrl` 改为遍历建立多条 `bizType:'CONTRACT'` 记录(`sortOrder:i`、`mediaType` 按扩展名判定)。
|
||||
- DTO `admin-mutate.dto.ts`:`contractUrl?:string` 标记 `@deprecated`,新增 `contractUrls?:string[]`(`@IsArray @IsString({each:true}) @ArrayMaxSize(20)`)。
|
||||
- 前端 `apps/admin-web/src/lib/storeCreate.ts`:`StoreCreateForm.contractUrl?:string` → `contractUrls?:string[]`。
|
||||
- `MultiImageUpload.tsx`:新增 `isPdf()`、`FilePdfOutlined`、PDF 缩略图卡片、`buttonText` prop。
|
||||
- `StoresPage.tsx`:编辑抽屉 + 创建 step1 表单均改用 `MultiImageUpload`(name=contractUrls, maxCount=20, accept=image/*,.pdf, buttonText="批量上传合同"),回显/保存 payload 改为 `contractUrls:string[]`。
|
||||
|
||||
### 需求3:合伙人 H5 门店入驻合同支持多图上传
|
||||
|
||||
## 发布流水线(同一会话,22:45 后)
|
||||
|
||||
完整跑通 dukang-release 标准流程:`dev_jacy` → push → merge `dev` → merge `main` → 发生产。
|
||||
- 提交 `8805335` feat(ops,store,partner): 用户权益列 + 门店合同多图上传(13 文件,356+/59-)
|
||||
- `dev_jacy` push → `origin/dev_jacy`(8805335)
|
||||
- merge `dev_jacy`→`dev` → `491f03e`,push `origin/dev`
|
||||
- merge `dev`→`main` → `4a0e184`,push `origin/main`
|
||||
- `deploy/deploy-prod.sh -- --skip-db`(无 Prisma schema 变更,故 --skip-db)→ `DEPLOY_EXIT=0`,`==> 发版完成 (production)`
|
||||
- 生产 PM2 全 online:`dukang-api`(8090) / admin-web / h5-partner / h5-shop / h5-user;健康检查 `api:200` `mini-user(h5):200`;版本记录 commit=4a0e184
|
||||
|
||||
### 踩坑/注意
|
||||
- `git checkout main` 时本机工作树出现 `server/dukang-api` 大量 `D`(误删)假象:实为 sandbox 下 checkout 未刷新工作树,非仓库损坏。用 `git checkout -f main` 重新填充即恢复;`origin/main` 始终正确(ls-remote 核对 4a0e184)。
|
||||
- 提交/合并后 `git status` 报 "ahead of origin by N" 为本地 tracking ref 陈旧,非真实分歧(ls-remote 已核对远程三分支均含本次提交)。
|
||||
- 仅提交 13 个需求文件 + 新建 `server/dukang-api/src/common/store-media/`,已排除 `.workbuddy/` 与 `fix_acl.ps1`。
|
||||
- 发布命令在 sandbox 下直接运行 SSH 部署成功(未强制禁用沙箱)。
|
||||
- `apps/h5-partner/src/lib/storeDraft.ts`:`StoreDraftForm.contractUrl:string` → `contractUrls:string[]`;`defaultStoreForm` 改为 `contractUrls:[]`;新增 `MAX_CONTRACT_COUNT=20`;`normalizeStoreDraftForm` 新增 `contractUrls` 计算(兼容旧 `contractUrl` 迁移为数组,去重限 20);`validateStoreStep2` 参数/校验改为 `contractUrls`,不足 1 张返回「请上传签约合同」。
|
||||
- `MultiOssUploadField.tsx`:新增 `accept?`、`unit?` props,`isPdf()`,PDF 缩略图卡片。
|
||||
- `StoreCreatePage.tsx`:签约合同区块 `OssUploadField` → `MultiOssUploadField`(value=`form.contractUrls ?? []`, maxCount=MAX_CONTRACT_COUNT, unit="个", accept="image/*,.pdf");提交体 `contractUrl` → `contractUrls`,新增 `const contractUrls = Array.from(new Set(...)).slice(0, MAX_CONTRACT_COUNT)`;envPhotoUrls slice 上限由 3 改为 20。修正了渲染块误用未定义变量 `contractUrls`(已改为从 form 读取)。
|
||||
|
||||
### 验证
|
||||
- 后端 `npx tsc --noEmit`(server/dukang-api)通过,exit 0。
|
||||
- admin-web / h5-partner 使用 `git stash` 基线对比法:本次改动**未引入任何新类型错误**(现存错误均为预存在基线问题:css module 声明、`import.meta.env`、过期 config 类型、TabLayout `end`、staff `staffRole` 等)。
|
||||
- 向后兼容:旧 `contractUrl` 字段保留并标记 deprecated,H5 草稿旧数据自动迁移;避免破坏现有 API 客户端。
|
||||
@@ -0,0 +1,43 @@
|
||||
# 2026-08-16
|
||||
|
||||
## 新增:线上库同步本地 CLI 工具
|
||||
- 文件:`deploy/sync-prod-db-to-local.sh`(新建,未提交)
|
||||
- 用途:将生产库 `dukang_prod`(阿里云 RDS `rm-bp139andp1aa385i9.mysql.rds.aliyuncs.com:3306`,用户 `dukangadmin`)同步到本地 Docker MySQL `dukang_haoke`(localhost:6016 / 容器内 `dukang-v1-mysql`,root/root)。
|
||||
- 原理:SSH 隧道借道 `dukang-server`(`-L 6018:rds:3306`)→ 本地无 mysql 客户端,故在 `dukang-v1-mysql` 容器内跑 mysqldump/mysql,经 `host.docker.internal:TUNNEL_PORT` 连隧道;管道直导,不落临时文件。
|
||||
- 安全:默认先 `docker exec mysqldump` 备份本地到 `deploy/backups/`;需 `--yes` 跳过交互确认;`--dry-run` 只读远端 DATABASE_URL 并打印计划。
|
||||
- 远端凭据从 `/opt/dukang/server/dukang-api/.env.production` 的 DATABASE_URL 运行时解析(密码经 `MYSQL_PWD` 环境变量传入,避免命令行暴露)。
|
||||
- 已知限制:不支持密码含 `@`;prod DB 名与本地不同(dukang_prod→dukang_haoke)靠 mysqldump 不带 `--databases` 实现库名映射。
|
||||
- 状态:仅跑通 `--dry-run`,未执行真实同步(待用户确认,因会覆盖本地库并拉取生产数据)。
|
||||
|
||||
## 修复:首次同步失败的根因
|
||||
- 失败现象:`mysqldump` 退出码 2,提示 `本地库可能处于不一致状态`(工具自身的失败兜底提示)。
|
||||
- 真实根因有两条:
|
||||
1. **密码解析错误**:生产 DB 密码含 `@` 字符(`passHasAt=true`)。原 bash 解析用「第一个 @」切分 userinfo/host,把密码里 `@` 之后的部分截断,导致 Access denied。
|
||||
修复:改为在服务端用 `new URL()` 解析,base64 回传各字段(user/host/port/db/password),本地 `base64 -d` 还原,彻底免疫 `@`/`:`/`$` 等特殊字符。服务端 auth 测试 `authTestStatus=0` 验证密码正确。
|
||||
2. **权限不足**:`dukangadmin`(应用库用户)无 `RELOAD`/`FLUSH_TABLES` 权限。`--single-transaction` 仍会触发全局 `FLUSH TABLES` → Access denied。
|
||||
修复:`mysqldump` 改用 `--lock-tables=0`(不发起 FTWRL)+ `--set-gtid-purged=OFF`(RDS 启用 GTID,否则本地恢复会报 GTID_PURGED 错误),并保留 `--skip-routines --skip-events --column-statistics=0 --no-tablespaces --add-drop-table --skip-triggers --no-create-db`。
|
||||
- 验证:结构导出(--no-data)在 4 组 flag 中仅 `--lock-tables=0` / `--skip-lock-tables`(不含 --single-transaction)退出 0。
|
||||
- 现工具已修正并实际执行同步(--yes,先自动备份本地到 deploy/backups/)。
|
||||
- 注意:`--lock-tables=0` 无事务一致性快照;生产库在线写入期间导出可能有极小不一致,但恢复时 mysqldump 自带 `FOREIGN_KEY_CHECKS=0`,_dev 库可接受。若需完全一致快照,可给 dukangadmin 授 RELOAD 后用 --single-transaction。
|
||||
|
||||
## 修改:套餐审核导航样式恢复一致
|
||||
- 文件:`apps/admin-web/src/layouts/AdminLayout.tsx` 的 `attachPackageAuditBadge`(`/store-package-audits` 项)。
|
||||
- 诉求演变:用户先要求「文字恒为白色」→ 后改为「不要单独处理,保持与子菜单一致,只是多一个待审徽章图标」。
|
||||
- 最终实现:label 改为 `<span style={{display:'inline-flex',gap:6}}>套餐审核{pendingCount>0 && <Badge count size="small"/>}</span>`。文字无强制颜色,随菜单主题继承 normal/hover/selected 颜色;徽章仅 pendingCount>0 时作为图标提示,不参与着色。
|
||||
|
||||
## 发布流水线(本次收尾,含之前未上线的 8+1 文件)
|
||||
- 背景:此前「联系电话脱敏+套餐多行输入+同步工具」等 9 文件 commit `8de4179` 已 push dev_jacy/dev/main,但**生产发布失败**(deploy.env 丢失导致 `未配置 DEPLOY_HOST`)。
|
||||
- 修复发布:`deploy.env` 是 gitignore 的本地密钥文件,已丢失不可找回;改用 SSH 别名 `dukang-server`(~/.ssh/config:HostName 47.110.129.57 / User root / IdentityFile pem)覆盖:`bash deploy/deploy-prod.sh --host dukang-server -- --skip-db`。
|
||||
- 关键排查:`origin/*` 本地缓存 ref 多次陈旧(误报 ahead/behind),必须以 `git ls-remote` 为准。本次真实远端:dev_jacy=8de4179、dev=c05cd0e、main=bac5c7a,与本地一致,无丢失。
|
||||
- 本次提交:`bafb342` fix(admin) 套餐审核样式 → push dev_jacy → merge dev(`0bfc19b`) → merge main(`029fd69`) → push。
|
||||
- 发布结果:`DEPLOY_EXIT=0`,`==> 发版完成 (production)`,健康检查 api:200 / mini-user(h5):200,系统版本记录 commit `029fd69`。
|
||||
- 提示:以后若想恢复标准 `bash deploy/deploy-prod.sh`(不带 --host),需重建 `deploy/deploy.env`(从 `deploy.env.example` 复制,填入 DEPLOY_HOST=47.110.129.57 等;该文件 gitignore,勿提交)。
|
||||
|
||||
## 排查:h5-partner 本地 /login 调 /partner/me 报 401
|
||||
- 现象:`http://localhost:5176/login` 启动后控制台报 `GET /api/v1/partner/me 401 (Unauthorized)`。
|
||||
- 结论:**不是 bug,是登录页的「过期 token 探测」**。链路:Vite 代理 `/api`→`localhost:3010`(正常);后端返回 `{"code":401,"message":"Missing token"}`(说明后端在线、代理通)。`ensureSession()`(api.ts:244)只在 localStorage 有 token 时才打 `/partner/me`;无 token 直接返回未登录。所以 401 来自之前测试残留的失效 token → 前端静默清除并展示登录表单,不崩、不弹错。刷新页面(token 已清)即不再出现。
|
||||
- 本地登录方式(关键,README 已过期):
|
||||
- `MOCK_SMS=true`(.env),短信走 mock,不连运营商;固定码 `MOCK_SMS_FIXED_CODE` 默认 `999888`(README 写的 123456 已不准)。
|
||||
- README 的测试号 `13700000001` **不在本地同步库**;本地 `partner_account` 共 9 个,可用真实号如 `18049821889`(Jacy) / `13073729990`(queen)(均 ACTIVE)。
|
||||
- 流程:填真实合伙人手机号 → 获取验证码 → **验证码打印在 `pnpm dev:api` 后端终端**(`Mock SMS → 180****8889 code=XXXXXX`)→ 填码登录。
|
||||
- 注意 h5-partner 默认 5175,本次因 5175 被占自动落到 5176,代理是路径匹配不受影响。
|
||||
Reference in New Issue
Block a user