From 743d242d52eda18b463bebe7d3cb3c0eb819c735 Mon Sep 17 00:00:00 2001 From: jacy-dukang Date: Sat, 4 Jul 2026 20:36:26 +0800 Subject: [PATCH] =?UTF-8?q?v3=E8=AE=A1=E5=88=92=E5=86=85=E5=AE=B9=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/agents/backend-lead.md | 2 +- .cursor/agents/boundary-reviewer.md | 4 +- .cursor/agents/owner-d-shop-redeem.md | 2 +- .cursor/rules/dukang-core.mdc | 2 +- .cursor/rules/frontend-h5.mdc | 2 +- .cursor/rules/packages-shared.mdc | 4 +- .cursor/skills/dukang-coding/SKILL.md | 4 +- .../skills/dukang-coding/reference-backend.md | 8 +- .../dukang-coding/reference-frontend.md | 8 +- .cursor/skills/dukang-task-card/SKILL.md | 6 +- AGENTS.md | 14 +- agent.md | 4 +- apps/AGENTS.md | 8 +- apps/h5-partner/src/App.tsx | 1 + apps/h5-partner/src/pages/LoginPage.tsx | 48 ++++- conventions.md | 14 +- packages/domain/src/index.test.ts | 22 ++- packages/domain/src/index.ts | 7 +- packages/shared-types/src/enums.ts | 3 +- server/dukang-api/AGENTS.md | 4 +- .../src/modules/redeem/redeem.service.ts | 4 +- skills.md | 4 +- 杜康好客-v3编码手册.md | 169 ++++++++++++++++++ 23 files changed, 291 insertions(+), 53 deletions(-) create mode 100644 杜康好客-v3编码手册.md diff --git a/.cursor/agents/backend-lead.md b/.cursor/agents/backend-lead.md index 5166632..3d401ce 100644 --- a/.cursor/agents/backend-lead.md +++ b/.cursor/agents/backend-lead.md @@ -50,7 +50,7 @@ Never scatter `if (process.env.MOCK_PAY)` in trade/benefit services. 1. Align with V2 manual §五 2. Notify table owner: jacy-dukang 或 刘京尧(store/redeem 相关表) 3. `pnpm db:validate` + seed still works -4. PR: jacy-dukang Review;涉及 store/redeem 表时 @刘京尧 +4. PR: jacy-dukang Review;涉及 store/redeem 表时通知刘京尧 ## Forbidden diff --git a/.cursor/agents/boundary-reviewer.md b/.cursor/agents/boundary-reviewer.md index a3d5f75..65a4d81 100644 --- a/.cursor/agents/boundary-reviewer.md +++ b/.cursor/agents/boundary-reviewer.md @@ -25,8 +25,8 @@ Inspect the diff (or named files) for: | 逻辑域 | Git 账号 | Apps | Modules | |--------|----------|------|---------| -| 主责 | jacy-dukang | h5-user, admin-web | iam, trade, benefit, analytics, catalog, settlement, ops | -| 合伙人+门店 | 刘京尧 | h5-partner, h5-shop | store, redeem | +| 主责 | jacy-dukang | h5-user, admin-web, 门店 | iam, trade, benefit, analytics, catalog, settlement, ops | +| 合伙人 | 刘京尧 | h5-partner, h5-shop | store, redeem | | 横切 | jacy-dukang | — | packages, callbacks, jobs, common, integrations | 逻辑 A/B/C/D 边界仍有效;刘京尧 同时负责 B+D,但 **store 与 redeem 模块仍不可互写表**。 diff --git a/.cursor/agents/owner-d-shop-redeem.md b/.cursor/agents/owner-d-shop-redeem.md index 6a697ee..dbef3c1 100644 --- a/.cursor/agents/owner-d-shop-redeem.md +++ b/.cursor/agents/owner-d-shop-redeem.md @@ -36,7 +36,7 @@ User (Owner A) generates token → Shop scans/confirms (you) ## Hard rules - Redis token: `redeem:token:{token}` TTL 300s -- Amount: `0 < amount ≤ min(balance, 500)` +- Amount: direct redeem `0 < amount ≤ total ACTIVE benefit balance`; document redeem `0 < amount ≤ document balance` - Transaction + coupon `version` optimistic lock - **Never** `prisma.order.update` in redeem module diff --git a/.cursor/rules/dukang-core.mdc b/.cursor/rules/dukang-core.mdc index 070ea54..9f44df1 100644 --- a/.cursor/rules/dukang-core.mdc +++ b/.cursor/rules/dukang-core.mdc @@ -41,7 +41,7 @@ alwaysApply: true ## 核心业务常量 - 权益额 = `benefit_amount ?? price` -- 核销:0 < amount ≤ min(balance, **500**) +- 核销:直接核销 `0 < amount ≤ 全部 ACTIVE 权益总余额`;带单据核销 `0 < amount ≤ 该单据可用金额` - 订单 Tab:`all | pending_pay | pending_ship | pending_receive | completed` - API:`/api/v1`,响应 `{ code, message, data }` diff --git a/.cursor/rules/frontend-h5.mdc b/.cursor/rules/frontend-h5.mdc index 0415a19..5ddef82 100644 --- a/.cursor/rules/frontend-h5.mdc +++ b/.cursor/rules/frontend-h5.mdc @@ -24,7 +24,7 @@ src/ | App | 端口 | 负责人 | 样式 | X-Client-App | |-----|------|--------|------|--------------| | h5-user | 5173 | jacy-dukang | shared-ui tokens | USER_H5 | -| h5-shop | 5174 | 刘京尧 | shared-ui tokens | SHOP_H5 | +| h5-shop | 5174 | jacy-dukang | shared-ui tokens | SHOP_H5 | | h5-partner | 5175 | 刘京尧 | shared-ui tokens | PARTNER_H5 | | admin-web | 5175 | jacy-dukang | Ant Design 5 | HQ_WEB | diff --git a/.cursor/rules/packages-shared.mdc b/.cursor/rules/packages-shared.mdc index ab73ae1..b3f2557 100644 --- a/.cursor/rules/packages-shared.mdc +++ b/.cursor/rules/packages-shared.mdc @@ -24,13 +24,13 @@ alwaysApply: false ## domain - 纯函数,无 IO(无 Prisma/Redis/HTTP) -- 起购 2/6 瓶、权益 `benefitAmount ?? price`、核销 ¥500 上限在此实现 +- 起购 2/6 瓶、权益 `benefitAmount ?? price`、V3 两路径核销规则在此实现 - 变更必须有单元测试 ```typescript const benefitAmount = product.benefitAmount ?? product.price; // 同城起购 2 瓶 / 跨城 6 瓶 -// 核销上限 ¥500 +// 直接核销按全部 ACTIVE 权益总余额;带单据核销按该单据可用金额 ``` ## shared-ui diff --git a/.cursor/skills/dukang-coding/SKILL.md b/.cursor/skills/dukang-coding/SKILL.md index 691858a..c34ef10 100644 --- a/.cursor/skills/dukang-coding/SKILL.md +++ b/.cursor/skills/dukang-coding/SKILL.md @@ -81,14 +81,14 @@ await this.prisma.order.update({ ... }); ## 数据库变更 1. 改 `server/dukang-api/prisma/schema.prisma` 对齐手册 §五 -2. 迁移需 OWNER Review(store/redeem 表 → @刘京尧) +2. 迁移需 OWNER Review(store/redeem 表 → 刘景尧) 3. 初始化 SQL:`server/dukang-api/prisma/init_v3.sql` ## 核心业务(packages/domain) ```typescript const benefitAmount = product.benefitAmount ?? product.price; -// 核销:0 < amount ≤ min(balance, 500) +// 核销:直接核销按全部 ACTIVE 权益总余额;带单据核销按该单据可用金额 // 同城 min 2 瓶 / 跨城 min 6 瓶 // 支付成功 → log_third_party + user_order.pay_status=PAID diff --git a/.cursor/skills/dukang-coding/reference-backend.md b/.cursor/skills/dukang-coding/reference-backend.md index c9e5948..58e3836 100644 --- a/.cursor/skills/dukang-coding/reference-backend.md +++ b/.cursor/skills/dukang-coding/reference-backend.md @@ -36,8 +36,8 @@ Admin 路由在 `modules/ops/` 下,前缀 `/admin/*`。 | catalog | `/catalog`, `/admin/cities`, `/admin/products` | jacy-dukang | | trade | `/trade`, `/partner/orders`, `/admin/orders` | jacy-dukang | | benefit | `/benefit` | jacy-dukang | -| store | `/stores`, `/partner/stores`, `/admin/store-audits` | 刘京尧 | -| redeem | `/redeem`, `/shop/redeem` | 刘京尧 | +| store | `/stores`, `/partner/stores`, `/admin/store-audits` | 刘景尧 | +| redeem | `/redeem`, `/shop/redeem` | 刘景尧 | | settlement | `/settlement`, `/partner/settlement`, `/admin/settlement` | jacy-dukang | | ops | `/admin/dashboard`, `/admin/reports` | jacy-dukang | | analytics | `/analytics`, `/promo/touch` | jacy-dukang | @@ -48,8 +48,8 @@ Admin 路由在 `modules/ops/` 下,前缀 `/admin/*`。 | 前缀 | 示例表 | 负责人 | |------|--------|--------| | user_ | user_user, user_order, user_benefit_coupon | jacy-dukang | -| store_ | store_store, store_account, store_payout | 刘京尧 / jacy-dukang(settlement) | -| partner_ | partner_partner, partner_bill | 刘京尧 / jacy-dukang(settlement) | +| store_ | store_store, store_account, store_payout | 刘景尧 / jacy-dukang(settlement) | +| partner_ | partner_partner, partner_bill | 刘景尧 / jacy-dukang(settlement) | | hq_ | hq_account | jacy-dukang | | common_ | common_product_item, common_event, common_city | jacy-dukang | | log_ | log_third_party, log_user_analytics | 写入方 Module | diff --git a/.cursor/skills/dukang-coding/reference-frontend.md b/.cursor/skills/dukang-coding/reference-frontend.md index 4195ee8..4dcb79b 100644 --- a/.cursor/skills/dukang-coding/reference-frontend.md +++ b/.cursor/skills/dukang-coding/reference-frontend.md @@ -7,8 +7,8 @@ | App | 目录 | 端口 | 负责人 | X-Client-App | 原型 | |-----|------|------|--------|--------------|------| | h5-user | apps/h5-user | 5173 | jacy-dukang | USER_H5 | pages/user/ | -| h5-shop | apps/h5-shop | 5174 | 刘京尧 | SHOP_H5 | pages/shop/ | -| h5-partner | apps/h5-partner | 5175 | 刘京尧 | PARTNER_H5 | pages/partner/ | +| h5-shop | apps/h5-shop | 5174 | 刘景尧 | SHOP_H5 | pages/shop/ | +| h5-partner | apps/h5-partner | 5175 | 刘景尧 | PARTNER_H5 | pages/partner/ | | admin-web | apps/admin-web | 5175 | jacy-dukang | HQ_WEB | pages/hq/ | > **h5-partner 与 admin-web 端口同为 5175**,勿同时 `dev:partner` + `dev:admin`。 @@ -51,7 +51,7 @@ H5 三端引用 `@dukang/shared-ui`(`tokens.css`)。admin-web 使用 Ant Des all | pending_pay | pending_ship | pending_receive | completed ``` -## h5-shop 路由(刘京尧) +## h5-shop 路由(刘景尧) | 路由 | Page | 主要 API | |------|------|----------| @@ -63,7 +63,7 @@ all | pending_pay | pending_ship | pending_receive | completed | /status | StatusPage | /shop/store | | /mine | MinePage | /shop/store | -## h5-partner 路由(刘京尧) +## h5-partner 路由(刘景尧) | 路由 | Page | 主要 API | |------|------|----------| diff --git a/.cursor/skills/dukang-task-card/SKILL.md b/.cursor/skills/dukang-task-card/SKILL.md index 6deacb9..7ca7621 100644 --- a/.cursor/skills/dukang-task-card/SKILL.md +++ b/.cursor/skills/dukang-task-card/SKILL.md @@ -31,8 +31,8 @@ description: >- |------|--------|---------| | C 端 FE、h5-user、交易后端 | jacy-dukang | P1-M1-002, M2-* | | admin、catalog、settlement | jacy-dukang | M1-BE-CAT-* | -| 合伙人、store | 刘京尧 | P1-M4-001 | -| 门店核销、h5-shop | 刘京尧 | P1-M3-002 | +| 合伙人、store | 刘景尧 | P1-M4-001 | +| 门店核销、h5-shop | 刘景尧 | P1-M3-002 | | Monorepo/integrations | jacy-dukang | P1-M0-* | ## preV1 任务卡(精简) @@ -47,7 +47,7 @@ description: >- | P1-M2-001 | 起购校验 2/6 瓶 | | P1-M2-002 | Mock 支付发券 | | P1-M2-003 | 5 Tab 含 pending_ship | -| P1-M3-001 | 核销 ¥500 上限 | +| P1-M3-001 | V3 两路径核销金额限制 | | P1-M3-002 | 门店扫码核销 | | P1-M4-001 | 录店 AUTO_APPROVE → C 端可见 | | P1-M5-001 | 配送自动推进到 COMPLETED | diff --git a/AGENTS.md b/AGENTS.md index deddf75..43fb334 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,16 +54,16 @@ Mock 验证码:`123456`。测试账号见 [`README.md`](./README.md)。 | 负责人 | Git 账号 | 职责 | |--------|----------|------| | **Jacy**(管理员) | `jacy-dukang` | C 端、admin-web、后端主模块、packages、Prisma 迁移主 Review | -| **刘京尧** | `刘京尧` | 合伙人 H5、门店 H5、`store` / `redeem` 模块 | +| **刘景尧** | `刘景尧` | 合伙人 H5、门店 H5、`store` / `redeem` 模块 | 逻辑模块边界仍按 A/B/C/D 划分(便于 Agent 隔离),**人员合并**如下: | 逻辑 OWNER | 负责人 | 可改路径 | 后端 Module | |------------|--------|----------|-------------| | **A + C + Lead** | jacy-dukang | `apps/h5-user/`, `apps/admin-web/`, `packages/*`, `callbacks/`, `jobs/`, `common/`, `integrations/` | `iam`, `trade`, `benefit`, `analytics`, `catalog`, `settlement`, `ops` | -| **B + D** | 刘京尧 | `apps/h5-partner/`, `apps/h5-shop/` | `store`, `redeem` | +| **B + D** | 刘景尧 | `apps/h5-partner/`, `apps/h5-shop/` | `store`, `redeem` | -**Prisma 迁移**:jacy-dukang 主 Review;若改 `store_*` / 核销相关表,需 `@刘京尧` 共同 Review。 +**Prisma 迁移**:jacy-dukang 主 Review;若改 `store_*` / 核销相关表,需刘景尧共同 Review。 ### 跨模块规则(R1–R8 摘要) @@ -91,8 +91,8 @@ Mock 验证码:`123456`。测试账号见 [`README.md`](./README.md)。 | `owner-a-user-trade` | jacy-dukang | C 端 H5、订单、支付、权益、埋点 | | `owner-c-catalog-ops` | jacy-dukang | admin-web、开城商品、结算、运营 | | `backend-lead` | jacy-dukang | packages、callbacks、jobs、Prisma 横切 | -| `owner-b-partner-store` | 刘京尧 | 合伙人 H5、门店 CRUD/审核 | -| `owner-d-shop-redeem` | 刘京尧 | 门店 H5、核销 | +| `owner-b-partner-store` | 刘景尧 | 合伙人 H5、门店 CRUD/审核 | +| `owner-d-shop-redeem` | 刘景尧 | 门店 H5、核销 | | `boundary-reviewer` | — | PR 前只读审查跨模块违规 | ## Skills(按需 @) @@ -116,7 +116,7 @@ Mock 验证码:`123456`。测试账号见 [`README.md`](./README.md)。 ``` 权益额 = benefit_amount ?? price 同城起购 2 瓶 / 跨城 6 瓶 -核销:0 < amount ≤ min(balance, 500);Redis 码 5 分钟 +核销:直接核销 0 < amount ≤ 全部 ACTIVE 权益总余额;带单据核销 0 < amount ≤ 该单据可用金额;Redis 码 5 分钟 C 端门店仅 status=OPEN 订单 Tab:all | pending_pay | pending_ship | pending_receive | completed ``` @@ -124,7 +124,7 @@ C 端门店仅 status=OPEN ## 提交与 PR - Conventional Commits:`feat(trade):`、`fix(redeem):`;scope = 端或模块 -- 跨模块 PR → jacy-dukang + 刘京尧 共同 Review(若涉及双方模块) +- 跨模块 PR → jacy-dukang + 刘景尧 共同 Review(若涉及双方模块) - 改 API/表 → 同步 V2 手册 §五/§六 + `shared-types` - 不提交 `.env`、`dist/`、`node_modules/` diff --git a/agent.md b/agent.md index 6e85a58..ff0be89 100644 --- a/agent.md +++ b/agent.md @@ -81,7 +81,7 @@ | 负责人 | Git 账号 | App(preV1 → V2) | Module | |--------|----------|-------------------|--------| | Jacy | jacy-dukang | h5-user、admin-web → mini-user/mini-hq | iam, trade, benefit, analytics, catalog, settlement, ops | -| 刘京尧 | 刘京尧 | h5-partner、h5-shop → mini-partner | store, redeem | +| 刘景尧 | 刘景尧 | h5-partner、h5-shop → mini-partner | store, redeem | | Jacy(横切) | jacy-dukang | packages/*, callbacks/, jobs/, integrations/ | 基础设施 | **禁止**:Module A 直写 Module B 的 Prisma 表;apps import server 源码。 @@ -93,7 +93,7 @@ ```text 权益发放额 = common_product_item.benefit_amount ?? price 同城起购 2 瓶 / 跨城 6 瓶 -核销:0 < amount ≤ min(balance, 500) +核销:直接核销 0 < amount ≤ 全部 ACTIVE 权益总余额;带单据核销 0 < amount ≤ 该单据可用金额 C 端门店列表仅 status=OPEN 订单 Tab:all | pending_pay | pending_ship | pending_receive | completed 支付回调幂等 → 发券 → common_event(BENEFIT_LEDGER, GRANT) diff --git a/apps/AGENTS.md b/apps/AGENTS.md index 59250e4..68ed792 100644 --- a/apps/AGENTS.md +++ b/apps/AGENTS.md @@ -7,8 +7,8 @@ | App | 端口 | X-Client-App | 负责人 | 原型 | |-----|------|--------------|--------|------| | `h5-user` | 5173 | `USER_H5` | jacy-dukang | `pages/user/` | -| `h5-shop` | 5174 | `SHOP_H5` | 刘京尧 | `pages/shop/` | -| `h5-partner` | 5175 | `PARTNER_H5` | 刘京尧 | `pages/partner/` | +| `h5-shop` | 5174 | `SHOP_H5` | 刘景尧 | `pages/shop/` | +| `h5-partner` | 5175 | `PARTNER_H5` | 刘景尧 | `pages/partner/` | | `admin-web` | — | (Admin JWT) | jacy-dukang | preV1 内部 HQ 替代 | V2 目标:`mini-user` / `mini-partner` / `mini-hq` 替换对应 H5(除门店仍 H5)。 @@ -36,13 +36,13 @@ V2 目标:`mini-user` / `mini-partner` / `mini-hq` 替换对应 H5(除门店 **勿改**:门店核销确认 UI(属 h5-shop)、合伙人录店(属 h5-partner) -### h5-shop(刘京尧) +### h5-shop(刘景尧) 主链路:门店登录 → 首页 → 扫码/输入核销 → 确认 → 记录 → 营业状态 **勿改**:C 端出码页面(属 h5-user) -### h5-partner(刘京尧) +### h5-partner(刘景尧) 主链路:登录 → 工作台 → 录店 → 门店列表 → 辖区订单 → Mock 推进配送(preV1) diff --git a/apps/h5-partner/src/App.tsx b/apps/h5-partner/src/App.tsx index 9f4f4c7..a14e454 100644 --- a/apps/h5-partner/src/App.tsx +++ b/apps/h5-partner/src/App.tsx @@ -22,6 +22,7 @@ function WechatOAuthHandler() { useEffect(() => { if (!isWechatEnv() || !location.search.includes('code=')) return; + if (location.pathname === '/login') return; void handlePartnerWechatCallback() .then((result) => { if (!result || !savePartnerWechatAuth(result)) return; diff --git a/apps/h5-partner/src/pages/LoginPage.tsx b/apps/h5-partner/src/pages/LoginPage.tsx index f1641e4..2f306e8 100644 --- a/apps/h5-partner/src/pages/LoginPage.tsx +++ b/apps/h5-partner/src/pages/LoginPage.tsx @@ -1,6 +1,12 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import { request, saveAuth } from '../lib/api'; +import { + authorizePartnerWechat, + handlePartnerWechatCallback, + savePartnerWechatAuth, +} from '../lib/wechat-auth'; +import { isWechatEnv } from '../lib/weixin'; export default function LoginPage() { const navigate = useNavigate(); @@ -9,7 +15,21 @@ export default function LoginPage() { const [phone, setPhone] = useState('13700000001'); const [code, setCode] = useState('123456'); const [loading, setLoading] = useState(false); + const [wechatLoading, setWechatLoading] = useState(false); const [codeCooldown, setCodeCooldown] = useState(0); + const [msg, setMsg] = useState(''); + + useEffect(() => { + if (!isWechatEnv()) return; + void handlePartnerWechatCallback() + .then((result) => { + if (!result) return; + if (savePartnerWechatAuth(result)) { + navigate('/'); + } + }) + .catch((e) => setMsg(e instanceof Error ? e.message : '微信登录失败')); + }, [navigate]); async function login() { setLoading(true); @@ -29,6 +49,21 @@ export default function LoginPage() { } } + async function wechatLogin() { + setMsg(''); + if (!isWechatEnv()) { + setMsg('请在微信内打开以使用微信一键登录'); + return; + } + setWechatLoading(true); + try { + await authorizePartnerWechat(); + } catch (e) { + setMsg(e instanceof Error ? e.message : '微信登录失败'); + setWechatLoading(false); + } + } + function sendCode() { if (codeCooldown > 0) return; request('PARTNER_H5', '/partner/auth/sms/send', { @@ -122,10 +157,17 @@ export default function LoginPage() { {!loading && arrow_forward}
其他登录方式
- + {msg &&

{msg}

}