diff --git a/apps/h5-shop/src/pages/HomePage.tsx b/apps/h5-shop/src/pages/HomePage.tsx index b0cd14d..d6cf65a 100644 --- a/apps/h5-shop/src/pages/HomePage.tsx +++ b/apps/h5-shop/src/pages/HomePage.tsx @@ -112,6 +112,10 @@ export default function HomePage() { const [authError, setAuthError] = useState(''); + const [showOpenModal, setShowOpenModal] = useState(false); + + const [opening, setOpening] = useState(false); + const pendingScanStartedRef = useRef(false); @@ -309,6 +313,12 @@ export default function HomePage() { setScanMsg(''); + // 门店临时闭店/休息中(非营业状态)时,点击扫码直接提示,不进入扫码流程 + if (status !== 'OPEN') { + setShowOpenModal(true); + return; + } + if (!isWechatEnv()) { setScanMsg('请在微信内打开门店端进行扫码核销'); @@ -349,6 +359,25 @@ export default function HomePage() { + async function openStoreAndContinue() { + if (opening) return; + setOpening(true); + try { + await request('SHOP_H5', '/shop/store/status', { + method: 'PUT', + body: JSON.stringify({ status: 'OPEN' }), + }); + setShowOpenModal(false); + setScanMsg(''); + void loadDashboard(); // 刷新门店状态为营业中,扫码按钮可再次使用 + } catch (e) { + setShowOpenModal(false); + setScanMsg(e instanceof Error ? e.message : '开启营业失败'); + } finally { + setOpening(false); + } + } + async function startWechatAuth() { setAuthLoading(true); @@ -615,6 +644,33 @@ export default function HomePage() { /> + {showOpenModal && ( +
+
+

门店休息中

+

门店目前休息中无法核销,是否开启营业?

+
+ + +
+
+
+ )} + ); diff --git a/杜康好客-v3.4.18-门店体验与登录态优化.md b/杜康好客-v3.4.18-门店体验与登录态优化.md index a9b9dc4..fecc2ca 100644 --- a/杜康好客-v3.4.18-门店体验与登录态优化.md +++ b/杜康好客-v3.4.18-门店体验与登录态优化.md @@ -11,7 +11,7 @@ | B. mini-user 套餐详情图 1/5 + 自动轮播 | `ProductCarousel` detail 变体 autoplay + 右下角 `1/5` 计数 | | C. 合伙人账号暂停禁止登录 | 非 `ACTIVE` → 登录/发码均拒,提示「该账号已暂停使用,请联系客服人员」 | | D. 门店端 申请提现 / 筛选栏留白对齐 | `WithdrawPage` 左右内边距统一 `--space-page` | -| E. 门店端 休息中核销 → 是否开启营业 | 核销页拦截时弹「是否开启营业?」,确认即开张后继续核销 | +| E. 门店端 门店休息中 → 是否开启营业 | 门店 PAUSED 时点击首页「扫码核销」即弹「是否开启营业?」,不进入扫码流程 | | F. mini-user 门店套餐图片自适应完整显示 | `ProductCarousel` 新增 `imageFit="adaptive"`(widthFix + 动态高度),门店套餐详情不再裁剪 | ## A. mini-user 门店座机电话脱敏(中间四位隐藏) @@ -62,11 +62,12 @@ 现状:`PhoneRedeemPage.tsx` / `RedeemConfirmPage.tsx` 拉取 `GET /shop/store`,`status !== 'OPEN'` 时 `storeClosed=true`,核销前拦截并报「门店未营业,无法核销」(服务端 `server/.../modules/redeem/redeem.service.ts` 的 `loadOpenStoreAccount` ~L117 亦硬校验「门店未营业」)。 -- 新交互:当 `storeClosed`(门店 PAUSED / 休息中)且用户尝试核销时,**不再仅提示无法核销**,而是弹确认框「是否开启营业?」: - - 确认 → 调用 `PUT /shop/store/status { status: 'OPEN' }`(复用 `StatusPage.tsx` 的 `requestToggle`/`confirmToggle` 调用方式),成功后 `setStoreClosed(false)`,放开核销、继续原流程(重新拉取或直接使用已输入金额 / 券码)。 - - 取消 → 维持 `storeClosed`,不放开。 +- **前置拦截(主路径 · 门店端首页 `HomePage`)**:门店状态非 `OPEN`(PAUSED 临时闭店 / 休息中)时,用户点击首页「扫码核销」按钮**立即**弹确认框「门店目前休息中无法核销,是否开启营业?」,**不进入扫码流程**: + - 确认 → 调用 `PUT /shop/store/status { status: 'OPEN' }`,成功后关闭弹窗并 `loadDashboard()` 刷新门店状态为营业中,用户可再次点击扫码。 + - 取消 → 关闭弹窗,维持拦截。 +- **确认页兜底(次路径 · `RedeemConfirmPage`)**:若直接带核销码进入确认页且门店仍非 `OPEN`,点击「确认核销」时同样弹「是否开启营业?」,开张后重新拉取预览并继续核销(`doConfirm`)。 - 边界:门店 `auditStatus !== 'APPROVED'` 时 `updateShopStatus` 会拒绝开张(抛「门店尚在总部审核中 / 审核未通过」),前端需捕获并提示该错误,不进入误开启。 -- 适用页:`PhoneRedeemPage`(手机号核销)、`RedeemConfirmPage`(扫码核销确认);`HomePage` 扫码入口本身不判状态,保持现状。 +- 适用页:`HomePage`(门店端首页扫码入口,PAUSED 时点击即弹窗)、`RedeemConfirmPage`(扫码核销确认页兜底)、`PhoneRedeemPage`(手机号核销)。 - 后端无需改动(开张接口与硬校验已存在)。 ## 关键接口 / 文件 @@ -103,7 +104,7 @@ - [ ] 套餐详情图多张时右下角显示 `1/5` 分页计数,并自动轮播(约 3.5s 切换);单图不计数、不轮播;点击仍可预览。 - [ ] 合伙人账号处于非 ACTIVE(暂停 / 停用)时:短信登录与微信登录均被拦截,提示「该账号已暂停使用,请联系客服人员」,无法进入。 - [ ] 门店管理(结算提现)页:申请提现按钮与筛选栏左右留白与其他区块一致(统一 `--space-page`),不再贴边。 -- [ ] 门店休息中时进入核销:弹「是否开启营业?」;确认开张后可继续核销;取消则维持拦截;未过审门店开张被拒时给出对应提示。 +- [ ] 门店休息中(PAUSED)时:点击门店端首页「扫码核销」按钮**立即**弹「门店目前休息中无法核销,是否开启营业?」,**不进入扫码流程**;确认开启后门店状态刷新、可再次扫码;取消则维持拦截;未过审门店开张被拒时给出对应提示。 - [ ] 门店套餐详情图片按真实比例完整显示、不再被裁切(轮播高度随图自适应);自动轮播与 `1/5` 计数仍正常。 - [ ] A 仅 `maskPhone` 规则、C/D/E 仅前端样式 / 交互;均无需 Prisma 迁移(C 复用 `DISABLED`)。