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`)。