diff --git a/db/20260914_add_wallet_code_use_index.sql b/db/20260914_add_wallet_code_use_index.sql new file mode 100644 index 000000000..0f9e090c7 --- /dev/null +++ b/db/20260914_add_wallet_code_use_index.sql @@ -0,0 +1,21 @@ +-- wallet_code_use 补二级索引(饭点卡顿波次 2026-09-14 诊断配套,PolarDB 分布式版 MySQL8 兼容模式) +-- 背景:该表此前仅有主键,慢日志实测 UPDATE 全表扫描并锁定全部扫描行: +-- UPDATE wallet_code_use SET del_flag = '1' +-- WHERE del_flag = '0' AND user_id = ? AND biz_type = '5' AND biz_id = ? +-- 扫描 14,653 行、单次耗时最长达 11 秒(波次期间),锁面放大拥堵。 +-- 索引设计说明:biz_type 为 tinytext 无法进入普通二级索引;user_id + biz_id 组合 +-- 已可把扫描范围缩到该用户名下几行,biz_type 在索引外过滤,无需进索引。 +-- idx_wcu_biz 单列索引服务 WalletCodeUseServiceImpl.getInfoByShortCode 按 biz_id 查询。 +-- 执行前请确认同名索引不存在:SHOW INDEX FROM pjcloudx_wallet.wallet_code_use; +-- 表仅约 1.5 万行,Online DDL 秒级完成,无锁风险;本文件只包含索引 DDL。 + +ALTER TABLE pjcloudx_wallet.wallet_code_use + ADD INDEX idx_wcu_user_biz (user_id, biz_id), + ADD INDEX idx_wcu_biz (biz_id); + +-- 说明: +-- 1) 全量建库脚本 db/800pjcloudx_wallet.sql 已同步补上这两个索引,新建环境无需再执行本文件。 +-- 2) 两条索引合并在一条 ALTER 中执行,只做一次表重建;如需拆开单独执行(参考 +-- hard_order verification_time 加列时的生产执行惯例),可改为两条独立的 CREATE INDEX 语句: +-- CREATE INDEX idx_wcu_user_biz ON pjcloudx_wallet.wallet_code_use (user_id, biz_id); +-- CREATE INDEX idx_wcu_biz ON pjcloudx_wallet.wallet_code_use (biz_id); diff --git a/db/800pjcloudx_wallet.sql b/db/800pjcloudx_wallet.sql index f5e6b8a6a..da68e5e89 100644 --- a/db/800pjcloudx_wallet.sql +++ b/db/800pjcloudx_wallet.sql @@ -540,7 +540,9 @@ CREATE TABLE wallet_code_use update_time datetime DEFAULT NULL COMMENT '修改时间', del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记', tenant_id bigint DEFAULT NULL COMMENT '租户ID', - PRIMARY KEY (id) + PRIMARY KEY (id), + INDEX idx_wcu_user_biz (user_id, biz_id), + INDEX idx_wcu_biz (biz_id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='二维码使用表'; diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java index f89d0b4ec..712fcdf3e 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/hard/HardApiController.java @@ -149,7 +149,7 @@ public class HardApiController { @PostMapping("/create-order") @Operation(summary = "创建订单") - @Idempotent(expireTime = 10, info = "正在创建订单中,请勿重复操作") + @Idempotent(expireTime = 60, delKey = true, info = "正在创建订单中,请勿重复操作") public R createOrder(@Valid @RequestBody HardCreateOrderDto dto) { // 处理商品类型 if (ObjectUtil.isNotEmpty(dto.getList())) { @@ -167,7 +167,7 @@ public class HardApiController { @PostMapping("/create-hard-qr-code-order") @Operation(summary = "创建设备二维码扫一扫订单") - @Idempotent(expireTime = 10, info = "正在创建订单中,请勿重复操作") + @Idempotent(expireTime = 60, delKey = true, info = "正在创建订单中,请勿重复操作") public R createHardQrCodeScanOrder(@Valid @RequestBody HardCreateOrderDto dto) { // 处理商品类型 if (ObjectUtil.isNotEmpty(dto.getList())) { @@ -186,7 +186,7 @@ public class HardApiController { @PostMapping("/done-hard-qr-code-order") @Operation(summary = "用户确认设备二维码扫一扫订单") - @Idempotent(expireTime = 10, info = "订单支付中,请勿重复操作") + @Idempotent(expireTime = 60, delKey = true, info = "订单支付中,请勿重复操作") public R doneHardQrCodeScanOrder(@Validated @RequestBody HardDoneHardQrCodeScanOrderDto body) { PjcloudUser user = SecurityUtils.getUser(); hardwareOrderService.doneHardQrCodeScanOrder(body, user); diff --git a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java index b37225222..927fcd752 100644 --- a/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java +++ b/pjcloud-hardware/pjcloud-hardware-biz/src/main/java/com/bsd/pjcloud/hard/controller/order/HardOrderController.java @@ -225,7 +225,7 @@ public class HardOrderController { @Operation(summary = "app创建订单扫一扫", description = "app创建订单扫一扫") @PostMapping("/app/create-order-scan-qrcode") - @Idempotent(expireTime = 5, info = "正在创建订单中,请勿重复操作") + @Idempotent(expireTime = 60, delKey = true, info = "正在创建订单中,请勿重复操作") public R appCreateOrderScancode(@Validated @RequestBody HardAppCreateOrderScancode body) { PjcloudUser user = SecurityUtils.getUser(); HardAppCreateOrderDto dto = HardAppCreateOrderDto.builder() diff --git a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserFaceServiceImpl.java b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserFaceServiceImpl.java index e777f0b58..42f622e7b 100644 --- a/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserFaceServiceImpl.java +++ b/pjcloud-upms/pjcloud-upms-biz/src/main/java/com/bsd/pjcloud/admin/service/impl/SysUserFaceServiceImpl.java @@ -147,15 +147,33 @@ public class SysUserFaceServiceImpl extends ServiceImpl() + .set(SysUserFaceEntity::getFaceImg, sysUserFace.getFaceImg()) + .set(SysUserFaceEntity::getUpdateTime, LocalDateTime.now()) + .set(SysUserFaceEntity::getQualityScore, null) + .set(SysUserFaceEntity::getQualityStatus, null) + .set(SysUserFaceEntity::getQualityCheckedAt, null) + .set(SysUserFaceEntity::getQualityErrorCode, null) + .set(SysUserFaceEntity::getQualityDeviceId, null) + .eq(SysUserFaceEntity::getId, userFace.getId())); + if (updatedRows <= 0) { + throw new RuntimeException("人脸样本修改失败,请刷新后重试"); + } // 发送mq - sendFaceMq(List.of(sysUserFace.getUserId()), null); + sendFaceMq(List.of(userFace.getUserId()), null); } @Override diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/mch/MchManageController.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/mch/MchManageController.java index ce2eada5b..3cc9afe73 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/mch/MchManageController.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/controller/mch/MchManageController.java @@ -158,7 +158,8 @@ public class MchManageController { @Operation(summary = "app查询合作商家的分店", description = "app查询合作商家的分店") @GetMapping("/app/children-page-join") - @Inner(value = false) + // 不再 @Inner(value = false) 匿名放行:未登录/token 过期时返回 424, + // 与 page-join 行为一致,避免匿名上下文下静默查空导致前端显示"暂无分店" public R> appParentPageJoin(@ParameterObject Page page, @ParameterObject MchManageDto dto) { dto.setVisibleMobile(YesNoEnum.YES.getCode()); dto.setTypes(MerchantTypeEnum.SUPERMARKET.getType()); diff --git a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/mch/MchManageServiceImpl.java b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/mch/MchManageServiceImpl.java index 5f76ec807..52de9aa35 100644 --- a/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/mch/MchManageServiceImpl.java +++ b/pjcloud-wallet/pjcloud-wallet-biz/src/main/java/com/bsd/pjcloud/wallet/service/impl/mch/MchManageServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bsd.pjcloud.admin.api.dto.UserInfo; @@ -16,6 +17,7 @@ import com.bsd.pjcloud.admin.api.feign.RemoteUserService; import com.bsd.pjcloud.admin.api.utils.DataUtil; import com.bsd.pjcloud.common.core.constant.CacheConstants; import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum; +import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum; import com.bsd.pjcloud.common.core.util.BeanUtils; import com.bsd.pjcloud.common.core.util.CollectionUtils; import com.bsd.pjcloud.common.core.util.QRCodeImageGenerator; @@ -59,8 +61,10 @@ import org.springframework.web.multipart.MultipartFile; import java.io.ByteArrayInputStream; import java.io.Serializable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; /** @@ -202,10 +206,33 @@ public class MchManageServiceImpl extends ServiceImpl records) { + List ids = records.stream().map(MchManageVo::getId).filter(Objects::nonNull).toList(); + if (ObjectUtil.isEmpty(ids)) return; + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("parent_id", "count(*) as cnt") + .in("parent_id", ids) + .eq("visible_mobile", YesNoEnum.YES.getCode()) + .groupBy("parent_id"); + Map countMap = new HashMap<>(); + for (Map row : baseMapper.selectMaps(wrapper)) { + countMap.put(Long.valueOf(String.valueOf(row.get("parent_id"))), Long.valueOf(String.valueOf(row.get("cnt")))); + } + records.forEach(v -> v.setMchCount(countMap.getOrDefault(v.getId(), 0L))); + } + /** * 分页级联 */