1个文件已添加
84个文件已修改
1270 ■■■■■ 已修改文件
cloud-server-account/src/main/java/com/dsh/account/controller/CityController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/model/RefereeList.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/model/ReturnModel.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/GoodsExchangeVo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/resources/mapper/RefereeMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminController.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/controller/THuiminCardController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/model/CouponListVo.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/service/impl/UserCouponServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-competition/src/main/resources/mapper/ParticipantMapper.xml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-course/src/main/resources/mapper/CoursePackagePaymentConfigMapper.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/course/feignClient/account/model/RefereeList.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/audit/ManagementAuditWriter.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/DataStatisticsController.java 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TFinanceController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/THuiminCardController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TShopController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TSiteTypeController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/BallController.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/LoginController.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/SensitiveDataController.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/IncomeVO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/UserListVO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/CoursePackageService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/CourseServiceImpl.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/TSiteServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/DeptMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/DictMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/GateMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/MenuMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/OpenCityBusinessMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/OpenCityMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/PhoneMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/PushOrderMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/RoleMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/ServerCarModelMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/SysIntegralMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/TEvaluationMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/TNoticesMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/TOperatorMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/TOperatorUserMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/TStoreMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/UserMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/resources/mapper/VipMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/common/_container.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/ball/yuyue.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/dataStatistics/operatorIncome.html 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/dataStatistics/platformIncome.html 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/dataStatistics/storeIncome.html 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/finance/Income.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/finance/RegistrationOrder.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/operator/Operator.html 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/referee/referee.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/tCoach/TCoach.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/tIntegral/TIntegral.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/tPayHuimin/tPayHuimin.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/tShopEvaluation/TShop.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/userAudit/userAudit.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/vipDetail/vip_detail.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/vipPayment/vip_payment.html 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/js/common/sensitive-info.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/ball/yuyue.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/finance/RegistrationOrder.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/finance/income.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/operator/operator.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/referee/referee.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/tCoach/tCoach.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/tIntegral/tIntegral.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/tPayHuimin/tPayHuimin.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/tShopEvaluation/tShop.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/user/user.js 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/userAudit/userAudit.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/vipDetail/vipDetail.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/vipPayment/vipPayment.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/controller/BallController.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/controller/StoreConfigController.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-other/src/main/resources/mapper/GameMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/controller/CityController.java
@@ -57,6 +57,7 @@
            if (ToolUtil.isNotEmpty(listQuery.getPhone())) {
                tCityManagerLambdaQueryWrapper.like(TCityManager::getPhone, listQuery.getPhone());
            }
            tCityManagerLambdaQueryWrapper.orderByDesc(TCityManager::getId);
            Page<TCityManager> page1 = cityService.page(page, tCityManagerLambdaQueryWrapper);
            return page1;
        } catch (Exception e) {
cloud-server-account/src/main/java/com/dsh/account/model/RefereeList.java
@@ -8,6 +8,8 @@
 */
@Data
public class RefereeList {
    /** 裁判 ID,敏感信息查询时用于精确定位单条记录。 */
    private Integer id;
    /**
     * 姓名
     */
cloud-server-account/src/main/java/com/dsh/account/model/ReturnModel.java
@@ -8,5 +8,9 @@
    private Long returnId;
    /**
     * 是否已完成支付:true 表示无需继续拉起第三方支付,false 表示仍需使用返回的支付参数完成支付。
     */
    private Boolean paySuccess;
}
cloud-server-account/src/main/java/com/dsh/account/model/vo/userBenefitDetail/GoodsExchangeVo.java
@@ -36,4 +36,7 @@
    @ApiModelProperty(value = "用户优惠券领取记录id;仅购买门票且现金支付时可传", required = false)
    Long couponId;
    @ApiModelProperty(value = "用户优惠券领取记录id(兼容旧参数,建议改用couponId)", required = false)
    Long chooseCouponId;
}
cloud-server-account/src/main/java/com/dsh/account/service/impl/TAppUserServiceImpl.java
@@ -1481,6 +1481,10 @@
    @Override
    @Transactional
    public synchronized ResultUtil productRedemptionOperation(Integer userIdFormRedis, GoodsExchangeVo exchangeType) {
        // 兼容前端历史参数 chooseCouponId,内部统一使用 couponId。
        if (exchangeType.getCouponId() == null && exchangeType.getChooseCouponId() != null) {
            exchangeType.setCouponId(exchangeType.getChooseCouponId());
        }
        ReturnModel returnModel = new ReturnModel();
        Long returnId = null;
        //如果是兑换优惠卷
@@ -1575,6 +1579,8 @@
            }
            BigDecimal cashAmount = merchandise.getCash() == null ? BigDecimal.ZERO : merchandise.getCash();
            // 门票优惠后的订单现金应付总额;支付参数必须使用该金额,不能再使用商品原价。
            BigDecimal ticketPayableCashAmount = null;
            UserCoupon usedCoupon = null;
            if (exchangeType.getGoodsType() == 3 && exchangeType.getCouponId() != null && exchangeType.getCouponId() != 0) {
                if (exchangeType.getExchangeType() == 1) {
@@ -1605,10 +1611,12 @@
                            .divide(BigDecimal.valueOf(exchangeType.getNums() == null ? 1 : exchangeType.getNums()), 2, java.math.RoundingMode.HALF_UP);
                } else if (Integer.valueOf(2).equals(coupon.getType())) {
                    BigDecimal deduction = rule.getBigDecimal("conditionalAmount");
                    if (deduction == null) {
                    if (deduction == null || deduction.compareTo(BigDecimal.ZERO) <= 0) {
                        return ResultUtil.error("该优惠券无法使用");
                    }
                    cashAmount = orderCash.subtract(deduction).max(BigDecimal.ZERO)
                    // 代金券可覆盖全部订单金额,超出订单金额的部分不找零。
                    ticketPayableCashAmount = orderCash.subtract(deduction).max(BigDecimal.ZERO);
                    cashAmount = ticketPayableCashAmount
                            .divide(BigDecimal.valueOf(exchangeType.getNums() == null ? 1 : exchangeType.getNums()), 2, java.math.RoundingMode.HALF_UP);
                } else {
                    return ResultUtil.error("该优惠券不支持购买门票");
@@ -1639,6 +1647,9 @@
            } else {
                goodsNums = exchangeType.getNums();
            }
            BigDecimal cashPaymentAmount = ticketPayableCashAmount == null
                    ? cashAmount.multiply(BigDecimal.valueOf(goodsNums))
                    : ticketPayableCashAmount;
            TAppUser user = appUserService.getById(userIdFormRedis);
            if (merchandise.getIntegral() != null) {
@@ -1675,6 +1686,10 @@
            if (exchangeType.getExchangeType() == 1) {
                pointsMerchandise.setPayStatus(2);
                pointsMerchandise.setPaymentTime(new Date());
            } else if (cashPaymentAmount.compareTo(BigDecimal.ZERO) == 0) {
                // 优惠券将现金部分完全抵扣时,不能向第三方支付发起 0 元或原价支付。
                pointsMerchandise.setPayStatus(2);
                pointsMerchandise.setPaymentTime(new Date());
            } else {
                pointsMerchandise.setPayStatus(1);
            }
@@ -1694,7 +1709,7 @@
                pointsMerchandise.setIntegral(merchandise.getIntegral() * goodsNums);
            }
            if (exchangeType.getExchangeType() == 2 || exchangeType.getExchangeType() == 3) {
                pointsMerchandise.setCash(cashAmount);
                pointsMerchandise.setCash(exchangeType.getGoodsType() == 3 ? cashPaymentAmount : cashAmount);
                pointsMerchandise.setCashPayType(exchangeType.getPayType());
            }
@@ -1716,6 +1731,10 @@
                    BeanUtils.copyProperties(pointsMerchandise, userPointsMerchandise);
                    // 一笔订单只能关联一次优惠券,避免拆分门票后重复计入优惠金额。
                    userPointsMerchandise.setUserCouponId(null);
                    if (exchangeType.getGoodsType() == 3) {
                        // 门票拆单后仅首条保留订单总实付金额,避免支付/收入统计重复累加。
                        userPointsMerchandise.setCash(BigDecimal.ZERO);
                    }
                    userPointsMerchandises.add(userPointsMerchandise);
                }
                System.err.println("新增额外购买记录"+userPointsMerchandises);
@@ -1727,8 +1746,16 @@
                }
            }
            if ((m * goodsNums) == 0 && pointsMerchandise.getPayStatus() == 2) {
            if (pointsMerchandise.getPayStatus() == 2 && exchangeType.getExchangeType() != 1
                    && cashPaymentAmount.compareTo(BigDecimal.ZERO) == 0) {
                // 积分+现金商品被优惠券抵扣为零元时,仍需扣除积分;不等待支付回调。
                if (exchangeType.getExchangeType() == 2 && merchandise.getIntegral() != null
                        && merchandise.getIntegral() > 0
                        && !dealAppUserIntegral(userIdFormRedis, tAppUser, merchandise.getIntegral() * goodsNums)) {
                    return ResultUtil.error("用户积分不足!");
                }
                returnModel.setReturnId(returnId);
                returnModel.setPaySuccess(true);
                return ResultUtil.success(returnModel);
            }
@@ -1830,7 +1857,7 @@
                                } else if (merchandise.getType() == 1) {
                                    return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                                } else if (merchandise.getType() == 3) {
                                    return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                                    return WechatPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                                }
                            } catch (Exception e) {
                                return ResultUtil.runErr();
@@ -1838,6 +1865,8 @@
                        case 2:
                            if (merchandise.getType() == 2) {
                                return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(exchangeType.getStuIds().size())), code, merchandise.getId());
                            } else if (merchandise.getType() == 3) {
                                return AlipayPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                            } else {
                                return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                            }
@@ -1851,6 +1880,8 @@
                            try {
                                if (merchandise.getType() == 2) {
                                    return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(exchangeType.getStuIds().size())), code, merchandise.getId());
                                } else if (merchandise.getType() == 3) {
                                    return WechatPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                                } else {
                                    return WechatPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                                }
@@ -1860,6 +1891,8 @@
                        case 2:
                            if (merchandise.getType() == 2) {
                                return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(exchangeType.getStuIds().size())), code, merchandise.getId());
                            } else if (merchandise.getType() == 3) {
                                return AlipayPayment(merchandise.getType(), cashPaymentAmount, code, merchandise.getId());
                            } else {
                                return AlipayPayment(merchandise.getType(), cashAmount.multiply(new BigDecimal(goodsNums)), code, merchandise.getId());
                            }
@@ -1872,6 +1905,7 @@
            }
            returnModel.setReturnId(returnId);
            returnModel.setPaySuccess(pointsMerchandise.getPayStatus() == 2);
            return ResultUtil.success(returnModel);
        } catch (Exception e) {
            e.printStackTrace();
@@ -2226,7 +2260,20 @@
                }
            }).start();
        }
        return alipay;
        return appendPaySuccess(alipay);
    }
    /**
     * 支付宝、微信的成功响应仅表示已生成支付单,客户端仍需拉起第三方支付。
     */
    private ResultUtil appendPaySuccess(ResultUtil paymentResult) {
        JSONObject data = paymentResult.getData() == null ? new JSONObject()
                : JSON.parseObject(JSON.toJSONString(paymentResult.getData()));
        if (data == null) {
            data = new JSONObject();
        }
        data.put("paySuccess", false);
        return ResultUtil.getResult(paymentResult.getCode(), paymentResult.getMsg(), data);
    }
@@ -2248,7 +2295,7 @@
                        // 平台门票
                        ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                                "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
                        return weixinpay;
                        return appendPaySuccess(weixinpay);
                    } else {
                        String s2 = storeClient.getmerchantNumberByOperatorId(store1.getOperatorId());
                        System.err.println("微信商户号" + s2);
@@ -2259,7 +2306,7 @@
                        ResultUtil weixinpay = payMoneyUtil.weixinpayV3(s2, name, code,
                                "/base/pointMer/exchangeGoodPaymentWeChatCallback1",
                                cash.toString());
                        return weixinpay;
                        return appendPaySuccess(weixinpay);
                    }
                }
                break;
@@ -2271,7 +2318,7 @@
                    // 平台课包
                    ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                            "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
                    return weixinpay;
                    return appendPaySuccess(weixinpay);
                } else {
                    String s2 = storeClient.getmerchantNumberByOperatorId(store.getOperatorId());
                    System.err.println("微信商户号" + s2);
@@ -2282,7 +2329,7 @@
                    ResultUtil weixinpay = payMoneyUtil.weixinpayV3(s2, name, code,
                            "/base/pointMer/exchangeGoodPaymentWeChatCallback1",
                            cash.toString());
                    return weixinpay;
                    return appendPaySuccess(weixinpay);
                }
            case 3:
                if (!integers.isEmpty()) {
@@ -2291,7 +2338,7 @@
                        // 平台门票
                        ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                                "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
                        return weixinpay;
                        return appendPaySuccess(weixinpay);
                    } else {
                        String s2 = storeClient.getmerchantNumberByOperatorId(store1.getOperatorId());
                        System.err.println("微信商户号" + s2);
@@ -2302,13 +2349,13 @@
                        ResultUtil weixinpay = payMoneyUtil.weixinpayV3(s2, name, code,
                                "/base/pointMer/exchangeGoodPaymentWeChatCallback1",
                                cash.toString());
                        return weixinpay;
                        return appendPaySuccess(weixinpay);
                    }
                } else {
                    // 平台门票
                    ResultUtil weixinpay = payMoneyUtil.weixinpay(name, "", code, cash.toString(),
                            "/base/pointMer/exchangeGoodPaymentWeChatCallback", "APP", "");
                    return weixinpay;
                    return appendPaySuccess(weixinpay);
                }
        }
cloud-server-account/src/main/resources/mapper/RefereeMapper.xml
@@ -12,6 +12,9 @@
        CONCAT(province, city) as province,
        state
        from t_referee where state != 3
        <if test="null != item.id">
            and id = #{item.id}
        </if>
        <if test="null != item.name and '' != item.name">
            and name like CONCAT('%', #{item.name}, '%')
        </if>
@@ -32,6 +35,9 @@
        select
        count(*)
        from t_referee where state != 3
        <if test="null != item.id">
            and id = #{item.id}
        </if>
        <if test="null != item.name and '' != item.name">
            and name like CONCAT('%', #{item.name}, '%')
        </if>
@@ -45,4 +51,4 @@
            and cityCode = #{item.cityCode}
        </if>
    </select>
</mapper>
</mapper>
cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminController.java
@@ -106,7 +106,7 @@
            @ApiImplicitParam(value = "用户优惠券领取记录id;不使用时不传", name = "couponId", dataType = "long", required = false),
            @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
    })
    public ResultUtil<THuiminCard> payHuiminCard(Integer id, Integer payType, String studentIds, Long couponId) {
    public ResultUtil<?> payHuiminCard(Integer id, Integer payType, String studentIds, Long couponId) {
        try {
            Integer uid = tokenUtil.getUserIdFormRedis();
            if (null == uid) {
@@ -207,8 +207,17 @@
            System.err.println("支付数据" + tPayHuimin);
            payHuiminService.save(tPayHuimin);
            if (userCoupon != null) {
                userCoupon.setStatus(2);
                userCouponService.updateById(userCoupon);
                // t_user_coupon 以 userId 分片;updateById 会把 userId 放入 SET,
                // ShardingSphere 会拒绝更新分片键。只更新状态,并在 WHERE 中带上 userId。
                boolean couponUpdated = userCouponService.lambdaUpdate()
                        .set(UserCoupon::getStatus, 2)
                        .eq(UserCoupon::getId, userCoupon.getId())
                        .eq(UserCoupon::getUserId, uid)
                        .eq(UserCoupon::getStatus, 1)
                        .update();
                if (!couponUpdated) {
                    return ResultUtil.error("优惠券已被使用");
                }
            }
            BigDecimal bigDecimal = new BigDecimal(studentIds.split(",").length);
            if (tPayHuimin.getSalesMoney().compareTo(BigDecimal.ZERO)==0){
@@ -216,19 +225,21 @@
                tPayHuimin.setStatus(2);
                tPayHuimin.setPaymentTime(new Date());
                payHuiminService.updateById(tPayHuimin);
                return ResultUtil.success();
                JSONObject data = new JSONObject();
                data.put("paySuccess", true);
                return ResultUtil.success(data);
            }
            switch (payType) {
                case 1:
                    // todo 惠民卡收入属于平台商户 定死
                    return payMoneyUtil.weixinpay("购买玩湃惠民卡", "", tPayHuimin.getCode(), tPayHuimin.getSalesMoney().toString(),
                            "/base/huimin/callBack/weixinPayHuiminCallback", "APP", "");
                    return appendPaySuccess(payMoneyUtil.weixinpay("购买玩湃惠民卡", "", tPayHuimin.getCode(), tPayHuimin.getSalesMoney().toString(),
                            "/base/huimin/callBack/weixinPayHuiminCallback", "APP", ""));
//                return payMoneyUtil.weixinpayV3("1720719391","购买玩湃惠民卡",tPayHuimin.getCode(),
//                        "/base/huimin/callBack/weixinPayHuiminCallback1",tPayHuimin.getSalesMoney().toString());
                case 2:
                    String string = tPayHuimin.getSalesMoney().toString();
                    return payMoneyUtil.alipay(smid, "购买玩湃惠民卡", "购买玩湃惠民卡", "", tPayHuimin.getCode(), string,
                            "/base/huimin/callBack/aliPayHuiminCallback");
                    return appendPaySuccess(payMoneyUtil.alipay(smid, "购买玩湃惠民卡", "购买玩湃惠民卡", "", tPayHuimin.getCode(), string,
                            "/base/huimin/callBack/aliPayHuiminCallback"));
            }
        } catch (Exception e) {
@@ -238,6 +249,19 @@
        return ResultUtil.success();
    }
    /**
     * 支付参数生成成功不代表实际支付成功,前端仍需拉起第三方支付。
     */
    private ResultUtil<?> appendPaySuccess(ResultUtil<?> paymentResult) {
        JSONObject data = paymentResult.getData() == null ? new JSONObject()
                : JSON.parseObject(JSON.toJSONString(paymentResult.getData()));
        if (data == null) {
            data = new JSONObject();
        }
        data.put("paySuccess", false);
        return ResultUtil.getResult(paymentResult.getCode(), paymentResult.getMsg(), data);
    }
    /**
     * 查看玩湃惠民卡详情
cloud-server-activity/src/main/java/com/dsh/activity/controller/THuiminCardController.java
@@ -71,6 +71,7 @@
        if (tHuiminCard.getStatus() != null){
            queryWrapper.eq("status",tHuiminCard.getStatus());
        }
        queryWrapper.orderByDesc("sort").orderByDesc("id");
        Page<THuiminCard> page = new Page<>();
        page.setCurrent(tHuiminCard.getCurrent());
        page.setSize(tHuiminCard.getSize());
cloud-server-activity/src/main/java/com/dsh/activity/model/CouponListVo.java
@@ -4,6 +4,8 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author zhibing.pu
 * @date 2023/6/24 11:33
@@ -23,4 +25,8 @@
    private String favorable;
    @ApiModelProperty("有效时间")
    private String effectiveTime;
    @ApiModelProperty("本订单可抵扣金额")
    private BigDecimal discountAmount;
    @ApiModelProperty("本订单使用该券后的应付金额")
    private BigDecimal payableAmount;
}
cloud-server-activity/src/main/java/com/dsh/activity/service/impl/UserCouponServiceImpl.java
@@ -232,6 +232,7 @@
            couponListVo.setType(type);
            couponListVo.setEffectiveTime(userCoupon.get("endTime").toString());
            String content = userCoupon.get("content").toString();
            BigDecimal orderAmount = BigDecimal.valueOf(price == null ? 0D : price).max(BigDecimal.ZERO);
            if (type == 1) {//满减{"num1":1,"num2":1}
                JSONObject jsonObject = JSON.parseObject(content);
                Double num1 = jsonObject.getDouble("conditionalAmount");
@@ -240,6 +241,10 @@
                }
                couponListVo.setUseCondition("满" + num1 + "元可用");
                couponListVo.setFavorable(jsonObject.getString("deductionAmount"));
                BigDecimal discount = BigDecimal.valueOf(jsonObject.getDouble("deductionAmount"))
                        .min(orderAmount);
                couponListVo.setDiscountAmount(discount);
                couponListVo.setPayableAmount(orderAmount.subtract(discount));
            }
            if (type == 2) {//代金券{"num1":1}
                JSONObject jsonObject = JSON.parseObject(content);
@@ -247,11 +252,12 @@
                if (num1 == null) {
                    num1 = 0d;
                }
                if (price.compareTo(num1) < 0) {
                    continue;
                }
                // 代金券可全额抵扣,面额超过订单金额时按订单金额抵扣,不应从列表中剔除。
                couponListVo.setUseCondition("");
                couponListVo.setFavorable(num1 + "");
                BigDecimal discount = BigDecimal.valueOf(num1).max(BigDecimal.ZERO).min(orderAmount);
                couponListVo.setDiscountAmount(discount);
                couponListVo.setPayableAmount(orderAmount.subtract(discount));
            }
            if (type == 3) {//体验券{"num1":1}
                JSONObject jsonObject = JSON.parseObject(content);
cloud-server-competition/src/main/resources/mapper/ParticipantMapper.xml
@@ -51,6 +51,7 @@
        <if test="state !=null and state !='' and state ==3">
            and t3.payStatus =3
        </if>
        order by t1.insertTime desc, t1.id desc
    </select>
</mapper>
cloud-server-course/src/main/java/com/dsh/config/Sharding_jdbc/ShardingConfig.java
@@ -188,7 +188,8 @@
     * @return
     */
    private ShardingTableRuleConfiguration getCoursePackageOrderTableRuleConfiguration() {
        ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_course_package_order", "m_$->{0}.t_course_package_order$->{1..5}");//30
        // 兼容分表前写入基础表的历史购课记录;新订单仍按 appUserId 路由至后缀分表。
        ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_course_package_order", "m_$->{0}.t_course_package_order,m_$->{0}.t_course_package_order$->{1..5}");//30
        result.setTableShardingStrategy(new StandardShardingStrategyConfiguration("appUserId", "t_course_package_order-inline"));
        result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("id", "t_course_package_order-snowflake"));
        return result;
cloud-server-course/src/main/java/com/dsh/course/controller/CourseController.java
@@ -32,6 +32,7 @@
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
@@ -602,56 +603,42 @@
    public HashMap<String, Object> queryFee(@RequestBody QueryDataFee queryDataFee) {
        HashMap<String, Object> map = new HashMap<>();
        String data = queryDataFee.getData();
        List<Integer> ids = queryDataFee.getIds();
        if (ids.size() == 0) {
            ids.add(-1);
        }else{
            List<TCoursePackage> list = coursePackageService.list(new QueryWrapper<TCoursePackage>().in("storeId", ids)
                    .ne("status", 4).eq("auditStatus", 2).eq("state", 1));
            ids = list.stream().map(TCoursePackage::getId).collect(Collectors.toList());
            if(ids.size() == 0){
                ids.add(-1);
            }
        List<Integer> storeIds = queryDataFee.getIds() == null
                ? new ArrayList<>() : new ArrayList<>(queryDataFee.getIds());
        if (storeIds.isEmpty()) {
            storeIds.add(-1);
        }
        LambdaQueryWrapper<CoursePackageOrder> wrapper = new LambdaQueryWrapper<>();
        // 购课记录页使用分表 union 查询。统计也必须使用同一数据源,否则落在
        // t_course_package_order1~5 的订单(例如测试的 0.01 元订单)不会被统计到。
        CoursePackagePaymentQuery paymentQuery = new CoursePackagePaymentQuery();
        paymentQuery.setStoreIds(storeIds);
        paymentQuery.setPayStatus(2);
        List<CoursePackagePaymentVO> list = coursePackagePaymentService.listAll(paymentQuery);
        Date startTime = null;
        Date endTime = null;
        if (ToolUtil.isNotEmpty(data)) {
            String stime = data.split(" - ")[0] + " 00:00:00";
            String etime = data.split(" - ")[1] + " 23:59:59";
            // 课程订单没有单独 payTime 字段;已支付订单以创建时间作为支付入账时间。
            wrapper.between(CoursePackageOrder::getInsertTime, stime, etime);
            try {
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                startTime = formatter.parse(data.split(" - ")[0] + " 00:00:00");
                endTime = formatter.parse(data.split(" - ")[1] + " 23:59:59");
            } catch (Exception ignored) {
                // 与旧实现一致:页面时间格式异常时不额外限制时间范围。
            }
        }
        wrapper.in(CoursePackageOrder::getCoursePackageId, ids);
        wrapper.eq(CoursePackageOrder::getPayStatus, 2);
        wrapper.eq(CoursePackageOrder::getState, 1);
        wrapper.eq(CoursePackageOrder::getStatus, 1);
        ArrayList<Integer> objects = new ArrayList<>();
        objects.add(1);
        objects.add(2);
        objects.add(5);
        objects.add(6);
        wrapper.in(CoursePackageOrder::getPayType, objects);
        List<CoursePackageOrder> list = coursePackageOrderService.list(wrapper);
        double v = list.stream().map(CoursePackageOrder::getCashPayment).reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
        List<Integer> collect = list.stream().map(CoursePackageOrder::getCoursePackageId).collect(Collectors.toList());
        if (collect.size() == 0) {
            collect.add(-1);
        }
        //
        List<TCoursePackage> list2 = coursePackageService.list(new LambdaQueryWrapper<TCoursePackage>()
                .in(TCoursePackage::getId, collect)
                .ne(TCoursePackage::getState, 3));
        final Date queryStartTime = startTime;
        final Date queryEndTime = endTime;
        list = list.stream()
                .filter(payment -> payment.getCashPayment() != null)
                .filter(payment -> queryStartTime == null || payment.getInsertTime() == null
                        || (!payment.getInsertTime().before(queryStartTime)
                        && !payment.getInsertTime().after(queryEndTime)))
                .collect(Collectors.toList());
        double v = list.stream().map(CoursePackagePaymentVO::getCashPayment)
                .reduce(BigDecimal.ZERO, BigDecimal::add).doubleValue();
        // 课类型
        List<TCoursePackageType> list1 = coursePackageTypeService.list(
                new LambdaQueryWrapper<TCoursePackageType>().ne(TCoursePackageType::getState, 3));
        for (CoursePackageOrder tCoursePackagePayment : list) {
            for (TCoursePackage tCoursePackage : list2) {
                if (tCoursePackagePayment.getCoursePackageId().equals(tCoursePackage.getId())) {
                    tCoursePackagePayment.setType(tCoursePackage.getCoursePackageTypeId());
                }
            }
        }
        ArrayList<HashMap<String, Object>> hashMaps = new ArrayList<>();
@@ -659,9 +646,9 @@
            HashMap<String, Object> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("name", tCoursePackageType.getName());
            double a = 0;
            for (CoursePackageOrder tCoursePackagePayment : list) {
                if (tCoursePackagePayment.getType().equals(tCoursePackageType.getId())) {
                    a += tCoursePackagePayment.getCashPayment().doubleValue();
            for (CoursePackagePaymentVO payment : list) {
                if (tCoursePackageType.getId().equals(payment.getCoursePackageTypeId())) {
                    a += payment.getCashPayment().doubleValue();
                }
            }
            objectObjectHashMap.put("value", a);
cloud-server-course/src/main/java/com/dsh/course/controller/CoursePackagePaymentController.java
@@ -355,13 +355,19 @@
            }
            Store store = storeClient.queryStoreById(re.getStoreId());
            TAppUser appUser = appUserClient.queryAppUser1(re.getAppUserId());
            String studentId = re.getStudentId();
            String[] split = studentId.split(";");
            StringBuilder stringBuilder = new StringBuilder("");
            for (String s : split) {
                Student student = studentClient.queryStudentById(Integer.valueOf(s));
                stringBuilder.append(student.getName()+",");
            String studentId = re.getStudentId();
            if (studentId != null && !studentId.trim().isEmpty()) {
                String[] split = studentId.split(";");
                for (String s : split) {
                    if (s == null || s.trim().isEmpty()) {
                        continue;
                    }
                    Student student = studentClient.queryStudentById(Integer.valueOf(s));
                    if (student != null) {
                        stringBuilder.append(student.getName()).append(",");
                    }
                }
            }
            String string = stringBuilder.toString();
            if (string.length() > 0) {
cloud-server-course/src/main/resources/mapper/CoursePackagePaymentConfigMapper.xml
@@ -28,7 +28,13 @@
        t1.payUserName as buyTypeName, t1.classHours as classHours,t1.insertTime as insertTime,t1.coursePackageId as coursePackageId,
        CONCAT(t2.province,t2.city) as provinceAndCity,t2.coursePackageTypeId,t2.storeId,t2.name as coursePackage,
        t3.name as coursePackageType,t1.orderNumber
        from t_course_package_order t1
        from (
            select * from t_course_package_order1
            union all select * from t_course_package_order2
            union all select * from t_course_package_order3
            union all select * from t_course_package_order4
            union all select * from t_course_package_order5
        ) t1
        left join t_course_package t2 on t1.coursePackageId = t2.id
        left join t_course_package_type t3 on t2.coursePackageTypeId = t3.id
        <where>
@@ -119,4 +125,4 @@
        order by t1.insertTime desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/java/com/dsh/course/feignClient/account/model/RefereeList.java
@@ -8,6 +8,8 @@
 */
@Data
public class RefereeList {
    /** 裁判 ID,敏感信息查询时用于精确定位单条记录。 */
    private Integer id;
    /**
     * 姓名
     */
cloud-server-management/src/main/java/com/dsh/guns/modular/system/audit/ManagementAuditWriter.java
@@ -8,6 +8,7 @@
import javax.annotation.Resource;
import java.io.OutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
@@ -23,7 +24,10 @@
    public void append(Map<String, Object> audit) {
        try {
            List<ServiceInstance> instances = discoveryClient.getInstances("mb-cloud-other");
            if (instances == null || instances.isEmpty()) return;
            if (instances == null || instances.isEmpty()) {
                log.warn("管理端审计写入失败:未发现审计服务 mb-cloud-other");
                return;
            }
            URL url = new URL(instances.get(0).getUri().toString() + "/internal/audit-logs");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(1000);
@@ -33,10 +37,25 @@
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            byte[] body = JSON.toJSONString(audit).getBytes(StandardCharsets.UTF_8);
            try (OutputStream output = connection.getOutputStream()) { output.write(body); }
            connection.getResponseCode();
            int status = connection.getResponseCode();
            if (status < HttpURLConnection.HTTP_OK || status >= HttpURLConnection.HTTP_MULT_CHOICE) {
                log.warn("管理端审计写入失败,响应状态: {}, 响应内容: {}", status,
                        readResponse(connection.getErrorStream()));
            }
            connection.disconnect();
        } catch (Exception e) {
            log.warn("管理端审计写入失败", e);
        }
    }
    private String readResponse(InputStream input) {
        if (input == null) return "";
        try (InputStream stream = input) {
            byte[] buffer = new byte[1024];
            int length = stream.read(buffer);
            return length <= 0 ? "" : new String(buffer, 0, length, StandardCharsets.UTF_8);
        } catch (Exception ignored) {
            return "";
        }
    }
}
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/AppGuideManagementController.java
@@ -55,7 +55,7 @@
    public Map<String, Object> data() {
        Map<String, Object> r = new HashMap<>();
        r.put("config", appGuideConfigMapper.selectOne(new QueryWrapper<AppGuideConfig>().orderByDesc("id").last("limit 1")));
        r.put("banners", appGuideBannerMapper.selectList(new QueryWrapper<AppGuideBanner>().orderByAsc("sort").orderByDesc("id")));
        r.put("banners", appGuideBannerMapper.selectList(new QueryWrapper<AppGuideBanner>().orderByDesc("sort").orderByDesc("id")));
        List<QrLink> links = qrLinkMapper.selectList(new QueryWrapper<QrLink>().eq("type", "SITE_BOOKING").orderByDesc("id"));
        List<Map<String, Object>> linkData = new ArrayList<>();
        for (QrLink link : links) {
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/DataStatisticsController.java
@@ -82,8 +82,29 @@
    }
    /**
     * 运营商统计的门店范围:平台(0)统计平台门店,其他值统计对应运营商门店。
     * 将门店统计目标限制在当前账号可见范围内。门店账号固定统计自身;运营商账号
     * 只能统计归属自己的门店,避免其它门店的数据混入其统计结果。
     */
    private Integer resolveStatisticsStoreId(Integer storeId) {
        Integer objectType = UserExt.getUser().getObjectType();
        if (Integer.valueOf(3).equals(objectType)) {
            return UserExt.getUser().getObjectId();
        }
        if (storeId == null) {
            return null;
        }
        TStore store = storeService.getById(storeId);
        if (store == null || Integer.valueOf(3).equals(store.getState())) {
            return null;
        }
        if (Integer.valueOf(2).equals(objectType)
                && !UserExt.getUser().getObjectId().equals(store.getOperatorId())) {
            return null;
        }
        return storeId;
    }
    /** 平台(0)或运营商统计均以门店的 operatorId 作为唯一归属依据。 */
    private List<TStore> listStatisticsStores(Integer operatorId, boolean enabledOnly) {
        LambdaQueryWrapper<TStore> wrapper = new LambdaQueryWrapper<>();
        if (enabledOnly) {
@@ -91,12 +112,19 @@
        } else {
            wrapper.ne(TStore::getState, 3);
        }
        if (Integer.valueOf(0).equals(operatorId)) {
            wrapper.eq(TStore::getType, 1);
        if (operatorId == null) {
            // 平台统计:所有门店总和,不按门店所属运营商过滤。
        } else {
            wrapper.eq(TStore::getType, 2).eq(TStore::getOperatorId, operatorId);
            wrapper.eq(TStore::getOperatorId, operatorId);
        }
        return storeService.list(wrapper);
    }
    /** 空门店范围必须显式传递无匹配值,不能让下游 SQL 因空集合而省略 IN 条件。 */
    private List<Integer> listStatisticsStoreIds(Integer operatorId, boolean enabledOnly) {
        List<Integer> storeIds = listStatisticsStores(operatorId, enabledOnly).stream()
                .map(TStore::getId).collect(Collectors.toList());
        return storeIds.isEmpty() ? Collections.singletonList(-1) : storeIds;
    }
    /** 获取统计范围门店发生课程、订场或赛事消费的用户。 */
@@ -116,6 +144,30 @@
                .stream().map(SiteBooking::getAppUserId).filter(Objects::nonNull)
                .collect(Collectors.toList()));
        List<Integer> competitionUserIds = competitionClient.queryAppUserId(storeIds);
        if (competitionUserIds != null) {
            userIds.addAll(competitionUserIds);
        }
        List<Integer> validUserIds = userIds.stream().filter(Objects::nonNull).distinct()
                .collect(Collectors.toList());
        return validUserIds.isEmpty() ? Collections.singletonList(-1) : validUserIds;
    }
    private List<Integer> listStatisticsAppUserIdsForStore(Integer storeId) {
        if (storeId == null) {
            return Collections.singletonList(-1);
        }
        List<Integer> userIds = new ArrayList<>();
        List<Integer> courseUserIds = coursePackagePaymentClient.queryPaymentCoursePackage(
                Collections.singletonList(storeId));
        if (courseUserIds != null) {
            userIds.addAll(courseUserIds);
        }
        userIds.addAll(siteBookingService.list(new QueryWrapper<SiteBooking>()
                        .eq("storeId", storeId).eq("state", 1))
                .stream().map(SiteBooking::getAppUserId).filter(Objects::nonNull)
                .collect(Collectors.toList()));
        List<Integer> competitionUserIds = competitionClient.queryAppUserId(
                Collections.singletonList(storeId));
        if (competitionUserIds != null) {
            userIds.addAll(competitionUserIds);
        }
@@ -240,6 +292,23 @@
            storeId = resolveStoreId(storeId);
        }
        // 下游多处查询会在门店集合为空时忽略门店过滤。运营商没有任何门店时,
        // 直接返回完整的零值结构,避免被误统计为全平台数据。
        if (operatorId != null && storeId == null
                && storeService.count(new LambdaQueryWrapper<TStore>()
                        .eq(TStore::getOperatorId, operatorId)
                        .ne(TStore::getState, 3)) == 0) {
            Map<String, Object> emptyIncomeData = buildIncomeStatistics(Collections.emptyList());
            emptyIncomeData.put("incomeTypeNet", buildIncomeTypeNet(Collections.emptyList(), null));
            Map<String, Object> emptyTicketIncome = new HashMap<>();
            emptyTicketIncome.put("day", BigDecimal.ZERO);
            emptyTicketIncome.put("month", BigDecimal.ZERO);
            emptyTicketIncome.put("quarter", BigDecimal.ZERO);
            emptyTicketIncome.put("year", BigDecimal.ZERO);
            emptyIncomeData.put("ticketIncome", emptyTicketIncome);
            return emptyIncomeData;
        }
        // 参数代表当前统计目标,而非当前登录人的角色;平台账号查看运营商/门店页时,
        // 会员、充值也必须跟随被查看的运营商/门店归属。
        Integer statisticsScopeType = Integer.valueOf(3).equals(roleType) || storeId != null ? 3
@@ -247,10 +316,12 @@
        Integer statisticsScopeObjectId = statisticsScopeType == 3 ? storeId
                : (statisticsScopeType == 2 ? operatorId : null);
        List<Integer> cityManagerId= new ArrayList<>();
        // 积分商品收入接口按门店 ID 过滤;空集合会被其 SQL 视为“不过滤”,
        // 因此运营商统计必须传入该运营商名下的全部门店,不能传空集合。
        List<Integer> cityManagerId = new ArrayList<>();
        if (Integer.valueOf(2).equals(statisticsScopeType) && statisticsScopeObjectId != null) {
            cityManagerId = storeService.list(new QueryWrapper<TStore>()
                            .eq("cityManagerId", statisticsScopeObjectId).ne("state", 3))
                            .eq("operatorId", statisticsScopeObjectId).ne("state", 3))
                    .stream().map(TStore::getId).collect(Collectors.toList());
        } else if (Integer.valueOf(3).equals(statisticsScopeType) && statisticsScopeObjectId != null) {
            cityManagerId.add(statisticsScopeObjectId);
@@ -518,20 +589,24 @@
        // 门票饼图需要日/月/季/年卡拆分;此前该数据只在 type1 内部返回,
        // 现随统一营收接口返回,供平台页直接使用。
        monthlyData.put("ticketIncome", getTicketIncome(time, operatorId, storeId));
        // 平台收入类型饼图还需要课程、订场分类明细。此前页面只能读取 type1
        // 的模板数据,筛选后 getIncomeData 缺少该字段,导致课程图显示为空。
        if (operatorId == null && storeId == null) {
            Map<String, Object> platformTypeData = (Map<String, Object>) type1(time);
            monthlyData.put("courseData", platformTypeData.get("courseData"));
            monthlyData.put("siteData", platformTypeData.get("siteData"));
        }
        return monthlyData;
    }
    private Map<String, Object> getTicketIncome(String time, Integer operatorId, Integer storeId) {
        List<Integer> userIds;
        if (storeId != null) {
            userIds = appUserClient.getUserStore(storeId);
            userIds = listStatisticsAppUserIdsForStore(storeId);
        } else if (operatorId != null) {
            userIds = appUserClient.getUserYYs(operatorId);
            userIds = listStatisticsAppUserIds(operatorId);
        } else {
            List<Integer> platformUserIds = sysUserService.list(new LambdaQueryWrapper<User>()
                            .eq(User::getObjectType, 1))
                    .stream().map(User::getId).collect(Collectors.toList());
            userIds = appUserClient.getUserPt(platformUserIds);
            userIds = listStatisticsAppUserIds(null);
        }
        if (userIds == null) {
            userIds = new ArrayList<>();
@@ -902,10 +977,7 @@
    @ResponseBody
    public Object backPt(Integer type) {
        HashMap<String, Object> map = new HashMap<>();
        List<Integer> userPt = appUserClient.getUserPt(Arrays.asList(1));
        if(userPt.size()==0){
            userPt.add(-1);
        }
        List<Integer> userPt = listStatisticsAppUserIds(null);
        ArrayList<Object> integers = new ArrayList<>();
        int year = DateUtil.year(new Date());
        List<TBackRecord> thisYear = backRecordService.list(new LambdaQueryWrapper<TBackRecord>().like(TBackRecord::getTime, year).in(TBackRecord::getUserId,userPt));
@@ -1108,7 +1180,8 @@
    @RequestMapping(value = "/backStore")
    @ResponseBody
    public Object backStore(Integer id) {
        List<Integer> collect1 = Arrays.asList(id);
        id = resolveStatisticsStoreId(id);
        List<Integer> collect1 = Collections.singletonList(id == null ? -1 : id);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1227,15 +1300,16 @@
    @RequestMapping(value = "/userAndVipPt")
    @ResponseBody
    public Object userAndVipPt(Integer type) {
        type=1;
        HashMap<String, Object> map = appUserClient.userAndVipPt(type);
        // 平台用户统计按用户归属全量统计,不能以“已有消费记录”筛选,
        // 否则会遗漏尚未在门店消费的新注册用户。
        HashMap<String, Object> map = appUserClient.userAndVipPt(1);
        return map;
    }
    @RequestMapping(value = "/stuPt")
    @ResponseBody
    public Object stuPt() {
        HashMap<String, Object> map = appUserClient.stuPt();
        HashMap<String, Object> map = appUserClient.stuYys(listStatisticsAppUserIds(null));
        return map;
    }
    @RequestMapping(value = "/stuYys")
@@ -1269,7 +1343,8 @@
    @RequestMapping(value = "/stuStores")
    @ResponseBody
    public Object stuStores(Integer id) {
        List<Integer> collect1 = Arrays.asList(id);
        id = resolveStatisticsStoreId(id);
        List<Integer> collect1 = Collections.singletonList(id == null ? -1 : id);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1289,7 +1364,7 @@
    @RequestMapping(value = "/coursePt")
    @ResponseBody
    public Object coursePt() {
        List<Integer> userPt = appUserClient.getUserPt(Arrays.asList(1));
        List<Integer> userPt = listStatisticsAppUserIds(null);
        HashMap<String, Object> map = coursePackagePaymentClient.coursePt(userPt);
        return map;
    }
@@ -1306,7 +1381,8 @@
    @RequestMapping(value = "/courseStore")
    @ResponseBody
    public Object courseStore(Integer id) {
        List<Integer> userPt = appUserClient.getUserPt(Arrays.asList(id));
        id = resolveStatisticsStoreId(id);
        List<Integer> userPt = listStatisticsAppUserIdsForStore(id);
        HashMap<String, Object> map = coursePackagePaymentClient.coursePt(userPt);
        return map;
    }
@@ -1315,8 +1391,7 @@
    @ResponseBody
    public Object userAndVipYys(Integer id) {
        id = resolveOperatorId(id);
        List<TStore> list4 = listStatisticsStores(id, true);
        List<Integer> collect1 = list4.stream().map(TStore::getId).collect(Collectors.toList());
        List<Integer> collect1 = listStatisticsStoreIds(id, true);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1334,7 +1409,8 @@
    @RequestMapping(value = "/userAndVipStore")
    @ResponseBody
    public Object userAndVipStore(Integer id) {
        List<Integer> collect1 = Arrays.asList(id);
        id = resolveStatisticsStoreId(id);
        List<Integer> collect1 = Collections.singletonList(id == null ? -1 : id);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1352,10 +1428,10 @@
    @RequestMapping(value = "/actPt")
    @ResponseBody
    public Object actPt(Integer type) {
        List<Integer> userPt = appUserClient.getUserPt(Arrays.asList(1));
        List<Integer> userPt = listStatisticsAppUserIds(null);
        HashMap<String, Object> map = competitionClient.actPt(userPt);
        List<TStore> list = storeService.list(new LambdaQueryWrapper<TStore>().eq(TStore::getOperatorId, 0).ne(TStore::getState, 3));
        List<TStore> list = listStatisticsStores(null, false);
        long l1=0;
        for (TStore tStore : list) {
            l1 += getStoreOperatingHours(tStore, new Date());
@@ -1368,8 +1444,7 @@
    public Object actYys(Integer id) {
        id = resolveOperatorId(id);
        CompetionVO competionVO = new CompetionVO();
        List<TStore> list4 = listStatisticsStores(id, true);
        List<Integer> collect1 = list4.stream().map(TStore::getId).collect(Collectors.toList());
        List<Integer> collect1 = listStatisticsStoreIds(id, true);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1448,8 +1523,7 @@
//        List<User> list = sysUserService.list(new LambdaQueryWrapper<User>().eq(User::getObjectType, 2));
//        List<Integer> ids = list.stream().map(User::getId).collect(Collectors.toList());
//        List<Integer> userIds = appUserClient.getUserYYs(id);
        List<TStore> list4 = listStatisticsStores(id, true);
        List<Integer> collect1 = list4.stream().map(TStore::getId).collect(Collectors.toList());
        List<Integer> collect1 = listStatisticsStoreIds(id, true);
        QueryDataFee queryDataFee = new QueryDataFee(time, collect1);
        // 课程收入
        HashMap<String, Object> map3 = courseClient.queryFee(queryDataFee);
@@ -1469,7 +1543,7 @@
        }else{
            List<TSite> list = siteService.list(new QueryWrapper<TSite>().in("storeId", collect1).eq("state", 1));
            ids = list.stream().map(TSite::getId).collect(Collectors.toList());
            if(collect1.size()==0){
            if(ids.isEmpty()){
                ids.add(-1);
            }
        }
@@ -1485,9 +1559,29 @@
        objects.add(1);
        objects.add(2);
        vipPaymentLambdaQueryWrapper.in(SiteBooking::getPayType,objects);
        List<SiteBooking> list1 = siteBookingService.list(vipPaymentLambdaQueryWrapper);
        List<SiteBooking> list1 = new ArrayList<>(siteBookingService.list(vipPaymentLambdaQueryWrapper));
        double sum = list1.stream().mapToDouble(SiteBooking::getPayMoney).sum();
        map.put("fee5",sum);
        // 智慧球场支付记录的场地可能只保存在 t_game.siteId。ballClient 已补齐该值,
        // 将其转换为订场明细后可与普通订场一起按场地类型统计。
        GameDataQuery gameDataQuery = new GameDataQuery();
        gameDataQuery.setObjectId(id);
        if (ToolUtil.isNotEmpty(time)) {
            gameDataQuery.setStartTime(time.split(" - ")[0] + " 00:00:00");
            gameDataQuery.setEndTime(time.split(" - ")[1] + " 23:59:59");
        }
        double gameIncome = 0D;
        for (TGameRecord gameRecord : ballClient.getData(gameDataQuery)) {
            if (gameRecord.getSiteId() == null || gameRecord.getMoney() == null || !ids.contains(gameRecord.getSiteId())) {
                continue;
            }
            SiteBooking gameBooking = new SiteBooking();
            gameBooking.setSiteId(gameRecord.getSiteId());
            gameBooking.setPayMoney(gameRecord.getMoney().doubleValue());
            list1.add(gameBooking);
            gameIncome += gameRecord.getMoney().doubleValue();
        }
        map.put("fee5", sum + gameIncome);
        List<Integer> collect = list1.stream().map(SiteBooking::getSiteId).collect(Collectors.toList());
@@ -1549,8 +1643,9 @@
    @ResponseBody
    @RequestMapping("/selectStore")
    public Object selectStore(Integer id,String time) {
        id = resolveStatisticsStoreId(id);
        HashMap<String, Object> map = new HashMap<>();
        List<Integer> collect1 = Arrays.asList(id);
        List<Integer> collect1 = Collections.singletonList(id == null ? -1 : id);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1699,10 +1794,8 @@
    @ResponseBody
    public Object type1(String time) {
        HashMap<String, Object> map = new HashMap<>();
        // 找出平台的用户
        List<User> list = sysUserService.list(new LambdaQueryWrapper<User>().eq(User::getObjectType, 1));
        List<Integer> ids = list.stream().map(User::getId).collect(Collectors.toList());
        List<Integer> userIds = appUserClient.getUserPt(ids);
        // 平台统计是所有门店总和,用户范围同样来自所有门店的消费用户。
        List<Integer> userIds = listStatisticsAppUserIds(null);
        QueryDataFee queryDataFee = new QueryDataFee(time, userIds);
        // 课程和赛事接口的 ids 参数表示门店 ID;不能把平台用户 ID 传入。
        List<Integer> platformStoreIds = storeService.list(new LambdaQueryWrapper<TStore>()
@@ -1749,8 +1842,20 @@
        }
        // 平台智慧球场
        List<TGameRecord> data1 = ballClient.getData(gameDataQuery);
        // 将游戏支付转换为场地收入明细参与后续 siteId -> siteTypeId 分类。
        // fee5 仍由普通订场金额与游戏金额分别相加,避免重复计入总额。
        for (TGameRecord gameRecord : data1) {
            if (gameRecord.getSiteId() == null || gameRecord.getMoney() == null) {
                continue;
            }
            SiteBooking gameBooking = new SiteBooking();
            gameBooking.setSiteId(gameRecord.getSiteId());
            gameBooking.setPayMoney(gameRecord.getMoney().doubleValue());
            list1.add(gameBooking);
        }
        double sum1 = data1.stream()
                .map(TGameRecord::getMoney) // 获取每个 TGameRecord 对象的 money 字段
                .filter(Objects::nonNull)
                .mapToDouble(BigDecimal::doubleValue) // 将 BigDecimal 转换为 double
                .sum();
        map.put("fee5",sum+sum1);
@@ -1807,9 +1912,7 @@
    @RequestMapping("/stuCourseData")
    @ResponseBody
    public Object stuCourseData() {
        ArrayList<Integer> objects = new ArrayList<>();
        objects.add(1);
        List<Integer> userIds = appUserClient.getUserPt(objects);
        List<Integer> userIds = listStatisticsAppUserIds(null);
        List<Map<String,Object>> list = coursePackagePaymentClient.queryCourseData(userIds);
        ArrayList<Object> objects2 = new ArrayList<>();
        ArrayList<Object> objects3 = new ArrayList<>();
@@ -1827,8 +1930,7 @@
    @RequestMapping("/stuUserData")
    @ResponseBody
    public Object stuUserData() {
        ArrayList<Integer> objects = new ArrayList<>();
        objects.add(1);
        // 平台地域/年龄统计按平台注册用户全量口径,不能仅取已有消费记录的用户。
        HashMap<String, Object> map = appUserClient.queryUserAge1();
        return map;
@@ -1837,8 +1939,7 @@
    @ResponseBody
    public Object stuUserDataYys(Integer id) {
        id = resolveOperatorId(id);
        List<TStore> list4 = listStatisticsStores(id, true);
        List<Integer> collect1 = list4.stream().map(TStore::getId).collect(Collectors.toList());
        List<Integer> collect1 = listStatisticsStoreIds(id, true);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1855,8 +1956,8 @@
    @RequestMapping("/stuUserDataStore")
    @ResponseBody
    public Object stuUserDataStore(Integer id) {
        List<Integer> collect1 = Arrays.asList(id);
        id = resolveStatisticsStoreId(id);
        List<Integer> collect1 = Collections.singletonList(id == null ? -1 : id);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1876,8 +1977,7 @@
    @ResponseBody
    public Object selectYysJx(Integer id) {
        id = resolveOperatorId(id);
        List<TStore> list4 = listStatisticsStores(id, true);
        List<Integer> collect1 = list4.stream().map(TStore::getId).collect(Collectors.toList());
        List<Integer> collect1 = listStatisticsStoreIds(id, true);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
@@ -1909,7 +2009,8 @@
    @RequestMapping("/selectStoreJx")
    @ResponseBody
    public Object selectStoreJx(Integer id) {
        List<Integer> collect1 = Arrays.asList(id);
        id = resolveStatisticsStoreId(id);
        List<Integer> collect1 = Collections.singletonList(id == null ? -1 : id);
        //课程
        List<Integer> list = coursePackagePaymentClient.queryPaymentCoursePackage(collect1);
        //场地
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TFinanceController.java
@@ -340,6 +340,7 @@
                    TAppUser tAppUser = appUserClient.queryById(vipPayment.getAppUserId());
                    IncomeVO temp = new IncomeVO();
                    temp.setId(vipPayment.getId().toString());
                    temp.setAppUserId(vipPayment.getAppUserId());
                    if (tAppUser!=null){
                        if (tAppUser.getProvince()!=null){
                            temp.setProvince(tAppUser.getProvince());
@@ -371,6 +372,7 @@
                    TAppUser tAppUser = appUserClient.queryById(rechargeRecordsVO.getAppUserId());
                    IncomeVO temp = new IncomeVO();
                    temp.setId(rechargeRecordsVO.getId().toString());
                    temp.setAppUserId(rechargeRecordsVO.getAppUserId());
                    if (tAppUser!=null){
                        if (tAppUser.getProvince()!=null){
                            temp.setProvince(tAppUser.getProvince());
@@ -402,6 +404,7 @@
                    TAppUser tAppUser = appUserClient.queryById(registerOrderVO.getAppUserId());
                    IncomeVO temp = new IncomeVO();
                    temp.setId(registerOrderVO.getId().toString());
                    temp.setAppUserId(registerOrderVO.getAppUserId());
                    if (tAppUser!=null){
                        if (tAppUser.getProvince()!=null){
                            temp.setProvince(tAppUser.getProvince());
@@ -458,6 +461,7 @@
                            temp.setStoreName(substring);
                        }
                        temp.setId(competition.getId().toString());
                        temp.setAppUserId(competition.getAppUserId());
                        if (tAppUser!=null){
                            if (tAppUser.getProvince()!=null){
                                temp.setProvince(tAppUser.getProvince());
@@ -492,6 +496,7 @@
                    Store store = storeClient.getStoreById(siteBooking.getStoreId());
                    temp.setId(siteBooking.getId().toString());
                    temp.setAppUserId(siteBooking.getAppUserId());
                    temp.setProvince(siteBooking.getProvince());
                    temp.setCity(siteBooking.getCity());
                    temp.setStoreName(store.getName());
@@ -916,4 +921,3 @@
}
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/THuiminCardController.java
@@ -168,7 +168,19 @@
        tHuiminCard.setObjectType(objectType);
        Integer objectId = user.getObjectId();
        tHuiminCard.setObjectId(objectId);
        return super.packForBT(huiminCardClient.queryPage(tHuiminCard));
        Page<THuiminCard> page = huiminCardClient.queryPage(tHuiminCard);
        page.getRecords().sort(Comparator
                .comparing((THuiminCard card) -> parseSort(card.getSort()), Comparator.nullsLast(Comparator.reverseOrder()))
                .thenComparing(THuiminCard::getId, Comparator.nullsLast(Comparator.reverseOrder())));
        return super.packForBT(page);
    }
    private Long parseSort(String sort) {
        try {
            return sort == null ? null : Long.valueOf(sort);
        } catch (NumberFormatException ignored) {
            return null;
        }
    }
    /**
@@ -254,6 +266,7 @@
                        .eq(!StringUtils.isEmpty(query.getProvinceCode()), TSite::getProvinceCode, query.getProvinceCode())
                        .eq(operatorId != null, TSite::getOperatorId, operatorId)
                        .ne(TSite::getState,3)
                        .orderByDesc(TSite::getId)
                        .eq(TSite::getSign,0)
                        .eq(!StringUtils.isEmpty(query.getCityCode()), TSite::getCityCode, query.getCityCode())
                        .in(!storeIds.isEmpty(), TSite::getStoreId, storeIds));
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TShopController.java
@@ -503,7 +503,7 @@
    @ResponseBody
    public Object listTwo1(Integer id) {
        Page<TStoreOtherConfigTrue> page = new PageFactory<TStoreOtherConfigTrue>().defaultPage();
        List<TStoreOtherConfigTrue> list = tStoreOtherConfigTrueService.page(page,new LambdaQueryWrapper<TStoreOtherConfigTrue>().eq(TStoreOtherConfigTrue::getPid, id).eq(TStoreOtherConfigTrue::getState,1)).getRecords();
        List<TStoreOtherConfigTrue> list = tStoreOtherConfigTrueService.page(page,new LambdaQueryWrapper<TStoreOtherConfigTrue>().eq(TStoreOtherConfigTrue::getPid, id).eq(TStoreOtherConfigTrue::getState,1).orderByDesc(TStoreOtherConfigTrue::getId)).getRecords();
        page.setRecords(list);
        return  super.packForBT(page);
    }
@@ -698,10 +698,17 @@
                        }
                    }
                }else {
                    TCity one = cityService.getOne(new LambdaQueryWrapper<TCity>().eq(TCity::getId, tStore.getProvinceCode()));
                    // 编辑页提交的是行政区划编码;按 id 查询会导致查不到省、市,随后访问名称时抛出 NPE。
                    TCity one = cityService.getOne(new LambdaQueryWrapper<TCity>().eq(TCity::getCode, tStore.getProvinceCode()));
                    if (one == null) {
                        return ERROR;
                    }
                    tStore.setProvince(one.getName());
                    tStore.setProvinceCode(one.getCode());
                    TCity one1 = cityService.getOne(new LambdaQueryWrapper<TCity>().eq(TCity::getId, tStore.getCityCode()));
                    TCity one1 = cityService.getOne(new LambdaQueryWrapper<TCity>().eq(TCity::getCode, tStore.getCityCode()));
                    if (one1 == null) {
                        return ERROR;
                    }
                    tStore.setCity(one1.getName());
                    tStore.setCityCode(one1.getCode());
                }
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TSiteTypeController.java
@@ -166,7 +166,7 @@
    @ResponseBody
    public Object list() {
        Page<TSiteType> page = new PageFactory<TSiteType>().defaultPage();
        Page<TSiteType> page1 = siteTypeService.page(page, new LambdaQueryWrapper<TSiteType>().ne(TSiteType::getState,3));
        Page<TSiteType> page1 = siteTypeService.page(page, new LambdaQueryWrapper<TSiteType>().ne(TSiteType::getState,3).orderByDesc(TSiteType::getId));
        return  super.packForBT(page1);
    }
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TicketController.java
@@ -410,26 +410,26 @@
    @RequestMapping("/writeOff")
    @ResponseBody
    public Object writeOff(String id, Integer goType) {
        if (!Integer.valueOf(1).equals(goType) && !Integer.valueOf(2).equals(goType)) {
            return ResultUtil.error("入园方式参数不正确");
        }
        Long aLong = Long.valueOf(id);
        WriteOffDTO dto = new WriteOffDTO();
        // 核销人员ID与所属门店由登录上下文确定,不能由前端传入。
        Integer objectId = UserExt.getUser().getId();
        if (UserExt.getUser().getObjectType() == 1){
            dto.setVerifiStoreId(null);
        }else if (UserExt.getUser().getObjectType() == 2){
            TStore store = storeService.getOne(new QueryWrapper<TStore>().eq("cityManagerId", objectId));
            dto.setVerifiStoreId(store == null ? null : store.getId());
        }else{
            TStoreStaff storeByStoreStaffId = storeStaffClient.getStoreByStoreStaffId(objectId);
            dto.setVerifiStoreId(storeByStoreStaffId.getStoreId());
        }
        dto.setId(aLong);
        dto.setGoType(goType);
        dto.setVerificationUserId(objectId);
        try {
            if (!Integer.valueOf(1).equals(goType) && !Integer.valueOf(2).equals(goType)) {
                appendTicketWriteOffAudit(dto, "FAIL", "入园方式参数不正确");
                return ResultUtil.error("入园方式参数不正确");
            }
            dto.setId(Long.valueOf(id));
            // 核销人员ID与所属门店由登录上下文确定,不能由前端传入。
            Integer objectId = UserExt.getUser().getId();
            if (UserExt.getUser().getObjectType() == 1){
                dto.setVerifiStoreId(null);
            }else if (UserExt.getUser().getObjectType() == 2){
                TStore store = storeService.getOne(new QueryWrapper<TStore>().eq("cityManagerId", objectId));
                dto.setVerifiStoreId(store == null ? null : store.getId());
            }else{
                TStoreStaff storeByStoreStaffId = storeStaffClient.getStoreByStoreStaffId(objectId);
                dto.setVerifiStoreId(storeByStoreStaffId.getStoreId());
            }
            dto.setVerificationUserId(objectId);
            pointMercharsClient.writeOff(dto);
            appendTicketWriteOffAudit(dto, "SUCCESS", null);
            return new SuccessTip<>();
@@ -449,7 +449,7 @@
            Map<String, Object> afterData = new HashMap<>(beforeData);
            afterData.put("status", "已核销");
            afterData.put("goType", dto.getGoType());
            afterData.put("goTypeName", dto.getGoType() == 1 ? "手环" : "门票核销");
            afterData.put("goTypeName", Integer.valueOf(1).equals(dto.getGoType()) ? "手环" : "门票核销");
            afterData.put("verificationUserId", dto.getVerificationUserId());
            afterData.put("verifiStoreId", dto.getVerifiStoreId());
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/BallController.java
@@ -292,7 +292,9 @@
        User user = UserExt.getUser();
        ballQueryDto.setType(user.getObjectType());
        ballQueryDto.setId(user.getObjectId());
        return ballClient.list(ballQueryDto);
        List<Game> games = ballClient.list(ballQueryDto);
        games.sort(Comparator.comparing(Game::getId, Comparator.nullsLast(Comparator.reverseOrder())));
        return games;
    }
    @ResponseBody
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/LoginController.java
@@ -175,16 +175,30 @@
        if(null == user){
            return "/login.html";
        }
        List<String> roleList = Arrays.asList(user.getRoleid().split(","));
        if (roleList == null || roleList.size() == 0) {
            model.addAttribute("tips", "该用户没有角色,无法登陆");
        List<String> roleList = new ArrayList<>();
        if (user.getRoleid() != null) {
            for (String roleId : user.getRoleid().split(",")) {
                String trimmedRoleId = roleId.trim();
                if (trimmedRoleId.matches("\\d+")) {
                    try {
                        Integer.valueOf(trimmedRoleId);
                        roleList.add(trimmedRoleId);
                    } catch (NumberFormatException ignored) {
                        // 跳过超出 Integer 范围的脏角色数据。
                    }
                }
            }
        }
        if (roleList.isEmpty()) {
            model.addAttribute("tips", "该用户没有有效角色,无法登录");
            return "/login.html";
        }
        Integer language = UserExt.getLanguage();
        List<MenuNode> menus = menuService.getMenusByRoleIds(roleList);
        List<MenuNode> titles = MenuNode.buildTitle(menus);
        List<String> resUrlsByRoleId = menuService.getResUrlsByRoleId(Integer.valueOf(roleList.get(0)));
        Integer primaryRoleId = Integer.valueOf(roleList.get(0));
        List<String> resUrlsByRoleId = menuService.getResUrlsByRoleId(primaryRoleId);
        CacheUtil.menus.put(user.getAccount(), resUrlsByRoleId);
        if (SinataUtil.isEmpty(user)){
@@ -197,7 +211,11 @@
        model.addAttribute("titles", titles);
        Role role = roleService.getBaseMapper().selectById(roleList.get(0));
        Role role = roleService.getBaseMapper().selectById(primaryRoleId);
        if (role == null) {
            model.addAttribute("tips", "该用户角色不存在,无法登录");
            return "/login.html";
        }
        User byId = userService.getById(user.getId());
        //获取用户头像 Obtain user profile
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/SensitiveDataController.java
@@ -1,10 +1,19 @@
package com.dsh.guns.modular.system.controller.system;
import com.dsh.course.feignClient.account.AppUserClient;
import com.dsh.course.feignClient.account.CoachClient;
import com.dsh.course.feignClient.account.RefereeClient;
import com.dsh.course.feignClient.account.model.CoachSerchVO;
import com.dsh.course.feignClient.account.model.RefereeList;
import com.dsh.guns.config.UserExt;
import com.dsh.guns.core.common.exception.BizExceptionEnum;
import com.dsh.guns.core.exception.GunsException;
import com.dsh.guns.modular.system.audit.ManagementAuditWriter;
import com.dsh.guns.modular.system.model.SiteBooking;
import com.dsh.guns.modular.system.model.TOperator;
import com.dsh.guns.modular.system.model.CoachQuery;
import com.dsh.guns.modular.system.service.ISiteBookingService;
import com.dsh.guns.modular.system.service.TOperatorService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -15,6 +24,7 @@
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -25,6 +35,10 @@
    @Resource private AppUserClient appUserClient;
    @Resource private ManagementAuditWriter auditWriter;
    @Resource private IUserService userService;
    @Resource private ISiteBookingService siteBookingService;
    @Resource private CoachClient coachClient;
    @Resource private RefereeClient refereeClient;
    @Resource private TOperatorService operatorService;
    @GetMapping("/app-user/{id}")
    public Map<String, Object> appUser(@PathVariable Integer id) {
@@ -58,6 +72,87 @@
        return result;
    }
    /**
     * 预约管理查看关联预约人的敏感信息。
     *
     * <p>仅通过预约记录定位用户,避免前端以任意用户 ID 查询;该接口保留在
     * /system/sensitive 路径下,以使用全局的脱敏豁免和网关放行策略。</p>
     */
    @GetMapping("/booking/{bookingId}")
    public Map<String, Object> booking(@PathVariable Integer bookingId) {
        assertAdmin();
        SiteBooking booking = siteBookingService.getById(bookingId);
        if (booking == null || booking.getAppUserId() == null) {
            writeBookingAudit(bookingId, booking, null, "NOT_FOUND");
            return null;
        }
        Map<String, Object> result = appUserClient.sensitiveAppUser(booking.getAppUserId());
        writeBookingAudit(bookingId, booking, result, result == null ? "NOT_FOUND" : "SUCCESS");
        return result;
    }
    @GetMapping("/coach/{id}")
    public Map<String, Object> coach(@PathVariable Integer id) {
        assertAdmin();
        // 与教练管理页 /tCoach/list 使用同一个查询入口,确保返回字段和数据权限一致。
        CoachQuery query = new CoachQuery();
        query.setId(id);
        List<CoachSerchVO> coaches = coachClient.listAll(query);
        CoachSerchVO coach = coaches == null || coaches.isEmpty() ? null : coaches.get(0);
        Map<String, Object> result = null;
        if (coach != null) {
            result = new HashMap<String, Object>();
            result.put("id", coach.getId());
            result.put("name", coach.getName());
            result.put("phone", coach.getPhone());
            result.put("idCard", coach.getIdcard());
        }
        writeAudit("coach", id, coach == null ? null : coach.getName(), result == null ? "NOT_FOUND" : "SUCCESS");
        return result;
    }
    @GetMapping("/referee/{id}")
    public Map<String, Object> referee(@PathVariable Integer id) {
        assertAdmin();
        // 使用裁判管理页 /referee/listAll 对应的列表查询接口精确查询该裁判。
        RefereeList query = new RefereeList();
        query.setId(id);
        query.setOffset(0);
        query.setLimit(1);
        Map<String, Object> listResult = refereeClient.getRefereeList(query);
        List<Map<String, Object>> referees = listResult == null ? null
                : (List<Map<String, Object>>) listResult.get("rows");
        Map<String, Object> referee = referees == null || referees.isEmpty() ? null : referees.get(0);
        Map<String, Object> result = null;
        if (referee != null) {
            result = new HashMap<String, Object>();
            result.put("id", referee.get("id"));
            result.put("name", referee.get("name"));
            result.put("phone", referee.get("phone"));
        }
        writeAudit("referee", id, referee == null ? null : String.valueOf(referee.get("name")),
                result == null ? "NOT_FOUND" : "SUCCESS");
        return result;
    }
    @GetMapping("/operator/{id}")
    public Map<String, Object> operator(@PathVariable Integer id) {
        assertAdmin();
        TOperator operator = operatorService.getById(id);
        User employee = operator == null ? null : userService.getById(operator.getUserId());
        Map<String, Object> result = null;
        if (employee != null) {
            result = new HashMap<String, Object>();
            result.put("id", employee.getId());
            result.put("name", employee.getName());
            result.put("phone", employee.getPhone());
            result.put("idCard", employee.getIdCard());
        }
        writeAudit("operator", id, operator == null ? null : operator.getName(), result == null ? "NOT_FOUND" : "SUCCESS");
        return result;
    }
    private void assertAdmin() {
        if (UserExt.getUser() == null || !"admin".equalsIgnoreCase(UserExt.getUser().getAccount())) {
            throw new GunsException(BizExceptionEnum.NO_PERMITION);
@@ -84,6 +179,28 @@
        auditWriter.append(audit);
    }
    private void writeBookingAudit(Integer bookingId, SiteBooking booking,
                                   Map<String, Object> user, String result) {
        Map<String, Object> audit = new HashMap<String, Object>();
        audit.put("traceId", UUID.randomUUID().toString().replace("-", ""));
        audit.put("sourceService", "mb-cloud-management");
        audit.put("sourceType", "HTTP");
        audit.put("operationType", "VIEW_SENSITIVE");
        audit.put("riskLevel", "SENSITIVE");
        audit.put("operationName", "超级管理员从预约管理查看敏感信息");
        audit.put("requestMethod", "GET");
        audit.put("requestUri", "/system/sensitive/booking/" + bookingId);
        // 审计记录只存预约、用户标识和查询结果,绝不写入手机号、身份证号等明文。
        audit.put("requestParams", "bookingId=" + bookingId + ", appUserId="
                + (booking == null || booking.getAppUserId() == null ? "-" : booking.getAppUserId())
                + ", targetUserName=" + (userName(user) == null ? "-" : userName(user)));
        audit.put("userId", UserExt.getUser().getId());
        audit.put("userAccount", "admin");
        audit.put("result", result);
        audit.put("createdAt", new Date());
        auditWriter.append(audit);
    }
    private String userName(Map<String, Object> user) {
        if (user == null || user.get("name") == null) return null;
        return String.valueOf(user.get("name"));
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/system/UserMgrController.java
@@ -175,6 +175,11 @@
        }
        roleLambdaQueryWrapper.eq(Role::getObjType,UserExt.getUser().getObjectType());
        List<Role> list = roleService.list(roleLambdaQueryWrapper);
        // 员工可能是由平台账号创建、后续归属到门店的,原角色不一定属于当前登录人的角色范围。
        // 编辑时仍需保留该角色作为可选项,避免下拉框无法回显。
        if (role != null && list.stream().noneMatch(item -> Objects.equals(item.getId(), role.getId()))) {
            list.add(role);
        }
        model.addAttribute("list",list);
        model.addAttribute("language",UserExt.getLanguage());
        // 部门列表
@@ -461,6 +466,11 @@
                oldUser.setObjectId(null);
            }
        }
        // 门店关联会维护员工归属信息,但不能覆盖编辑页明确选择的角色。
        // 必须在关联处理后写入,否则有门店的员工会被上面的兼容逻辑强制改回角色 3。
        if (!StringUtils.isEmpty(user.getRoleid())) {
            oldUser.setRoleid(user.getRoleid());
        }
        this.userService.updateById(oldUser);
        return SUCCESS_TIP;
    }
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/IncomeVO.java
@@ -23,6 +23,8 @@
          {title:  '状态', field: 'state', visible: true, align: 'center', valign: 'middle',formatter:function (data) {return{1:"已支付",2:"未支付"}[data]}}
     */
    private String id;
    /** 关联用户 ID,仅用于管理端受审计的敏感信息查询。 */
    private Integer appUserId;
    private String province;
    private String city;
    private String storeName;
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/UserListVO.java
@@ -27,6 +27,8 @@
    private String idCard;
    // 所在部门
    private String deptName;
    // 角色名称
    private String roleName;
    // 状态 1=正常 2=冻结
    private Integer status;
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/CoursePackageService.java
@@ -90,8 +90,8 @@
        HttpServletRequest request = HttpKit.getRequest();
        queryCoursePackageLists.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryCoursePackageLists.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryCoursePackageLists.setSort(request.getParameter("sort"));
        queryCoursePackageLists.setOrder(request.getParameter("order"));
        queryCoursePackageLists.setSort("id");
        queryCoursePackageLists.setOrder("desc");
        Page<Map<String, Object>> mapPage = coursePackageClient.queryCoursePackageLists(queryCoursePackageLists);
        List<Map<String, Object>> records = mapPage.getRecords();
        for (Map<String, Object> record : records) {
@@ -360,8 +360,8 @@
        HttpServletRequest request = HttpKit.getRequest();
        queryRegistrationRecord.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryRegistrationRecord.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryRegistrationRecord.setSort(request.getParameter("sort"));
        queryRegistrationRecord.setOrder(request.getParameter("order"));
        queryRegistrationRecord.setSort("id");
        queryRegistrationRecord.setOrder("desc");
        Page<Map<String, Object>> mapPage = coursePackagePaymentClient.queryRegistrationRecord(queryRegistrationRecord);
        return mapPage;
    }
@@ -379,8 +379,8 @@
        HttpServletRequest request = HttpKit.getRequest();
        queryClassRecord.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryClassRecord.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryClassRecord.setSort(request.getParameter("sort"));
        queryClassRecord.setOrder(request.getParameter("order"));
        queryClassRecord.setSort("id");
        queryClassRecord.setOrder("desc");
        Page<Map<String, Object>> mapPage = coursePackageSchedulingClient.queryCoursePackageSchedulingList(queryClassRecord);
        return mapPage;
    }
@@ -400,8 +400,8 @@
        HttpServletRequest request = HttpKit.getRequest();
        queryCoursePackageStudentList.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryCoursePackageStudentList.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryCoursePackageStudentList.setSort(request.getParameter("sort"));
        queryCoursePackageStudentList.setOrder(request.getParameter("order"));
        queryCoursePackageStudentList.setSort("id");
        queryCoursePackageStudentList.setOrder("desc");
        return coursePackageStudentClient.queryCoursePackageStudentList(queryCoursePackageStudentList);
    }
@@ -635,8 +635,8 @@
        HttpServletRequest request = HttpKit.getRequest();
        queryWalkInStudentList.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryWalkInStudentList.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryWalkInStudentList.setSort(request.getParameter("sort"));
        queryWalkInStudentList.setOrder(request.getParameter("order"));
        queryWalkInStudentList.setSort("id");
        queryWalkInStudentList.setOrder("desc");
        return coursePackagePaymentClient.queryWalkInStudentList(queryWalkInStudentList);
    }
@@ -755,8 +755,8 @@
        HttpServletRequest request = HttpKit.getRequest();
        queryExamineCoursePackageLists.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryExamineCoursePackageLists.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryExamineCoursePackageLists.setSort(request.getParameter("sort"));
        queryExamineCoursePackageLists.setOrder(request.getParameter("order"));
        queryExamineCoursePackageLists.setSort("id");
        queryExamineCoursePackageLists.setOrder("desc");
        Page<Map<String, Object>> mapPage = coursePackageClient.queryExamineCoursePackageLists(queryExamineCoursePackageLists);
        List<Map<String, Object>> records = mapPage.getRecords();
        for (Map<String, Object> record : records) {
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/CourseServiceImpl.java
@@ -45,8 +45,8 @@
        queryCourseList.setName(name);
        queryCourseList.setLimit(Integer.valueOf(request.getParameter("limit")));
        queryCourseList.setOffset(Integer.valueOf(request.getParameter("offset")));
        queryCourseList.setSort(request.getParameter("sort"));
        queryCourseList.setOrder(request.getParameter("order"));
        queryCourseList.setSort("id");
        queryCourseList.setOrder("desc");
        Page<Map<String, Object>> mapPage = courseClient.queryCourseLists(queryCourseList);
        return mapPage;
    }
cloud-server-management/src/main/java/com/dsh/guns/modular/system/service/impl/TSiteServiceImpl.java
@@ -101,7 +101,7 @@
        // 通过日期 确定周X 查询设置的可以约时间段和金额 封装基础时间段数据
        LambdaQueryWrapper<TSitePrice> tSitePriceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tSitePriceLambdaQueryWrapper.eq(TSitePrice::getSiteId, id);
        tSitePriceLambdaQueryWrapper.orderByAsc(TSitePrice::getStartTime);
        tSitePriceLambdaQueryWrapper.orderByDesc(TSitePrice::getStartTime);
        tSitePriceLambdaQueryWrapper.eq(TSitePrice::getTargetAudience, targetAudience);
        tSitePriceLambdaQueryWrapper.eq(TSitePrice::getDayOfWeek, dayOfWeek.getValue());
        if (StringUtils.isNotBlank(halfName)) {
cloud-server-management/src/main/resources/mapper/DeptMapper.xml
@@ -38,6 +38,7 @@
            </if>
            )
        </if>
        order by id desc
    </select>
    <select id="list" resultType="java.util.Map">
            select * from sys_dept where 1=1
@@ -60,7 +61,7 @@
            </if>
            order by num ASC
            order by num DESC
    </select>
cloud-server-management/src/main/resources/mapper/DictMapper.xml
@@ -27,7 +27,7 @@
        select
        <include refid="Base_Column_List"/>
        from sys_dict
        where pid in(select id  from sys_dict where code = #{code}) order by num asc
        where pid in(select id  from sys_dict where code = #{code}) order by num desc
    </select>
    <select id="list" resultType="map">
@@ -36,7 +36,7 @@
        <if test="condition != null and condition != ''">
            AND name like CONCAT('%',#{condition},'%')
        </if>
        order by id ASC
        order by id DESC
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/GateMapper.xml
@@ -28,5 +28,6 @@
                #{id}
            </foreach>
        </if>
        order by t1.id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/MenuMapper.xml
@@ -174,7 +174,7 @@
        ) m3 ON m1.id = m3.id
        where m1.ismenu = 1
        and m1.status = 1
        order by levels,num asc
        order by levels desc,num desc
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/OpenCityBusinessMapper.xml
@@ -41,7 +41,7 @@
        <if test="null != province">
            and b.areaName = #{province}
        </if>
        order by a.sort
        order by a.sort desc, a.id desc
    </select>
@@ -57,6 +57,6 @@
        updateTime as updateTime,
        updateUser as updateUser
        from t_open_city_business
        where flag != 3 and openCityId = #{id} order by sort
        where flag != 3 and openCityId = #{id} order by sort desc, id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/OpenCityMapper.xml
@@ -35,7 +35,7 @@
        cityName as cityName,
        provinceName as provinceName,
        flag as flag,
        from t_open_city where flag = 1
        from t_open_city where flag = 1 order by id desc
    </select>
@@ -54,7 +54,7 @@
        insertUser as insertUser,
        updateTime as updateTime,
        updateUser as updateUser
        from t_open_city where flag = 1 and code = #{code}
        from t_open_city where flag = 1 and code = #{code} order by id desc
    </select>
    <select id="selectList1" resultType="com.dsh.course.entity.OpenCity">
        select
@@ -74,7 +74,7 @@
            any_value( insertUser) as insertUser,
            any_value( updateTime) as updateTime,
            any_value( updateUser) as updateUser
         from t_open_city where flag != 3 group by areaId
         from t_open_city where flag != 3 group by areaId order by max(id) desc
    </select>
    <select id="selectListCity" resultType="com.dsh.course.entity.OpenCity">
        select t1.id,
@@ -112,7 +112,7 @@
        from t_open_city t1
        left join t_city t2 on (t1.areaId = t2.id)
        left join t_city t3 on (t1.cityId = t3.id)
        where flag != 3 group by t1.areaId
        where flag != 3 group by t1.areaId order by max(t1.id) desc
    </select>
    <select id="selectListCity1" resultType="com.dsh.course.entity.OpenCity">
        select t1.id,
@@ -150,6 +150,6 @@
        t1.insertTime,
        t1.insertUser,
        t1.updateTime,
        t1.updateUser from t_open_city t1 left join t_city t2 on (t1.areaId = t2.id)  left join t_city t3 on (t1.cityId = t3.id) where flag != 3 and t1.areaId =#{code}
        t1.updateUser from t_open_city t1 left join t_city t2 on (t1.areaId = t2.id)  left join t_city t3 on (t1.cityId = t3.id) where flag != 3 and t1.areaId =#{code} order by t1.id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/PhoneMapper.xml
@@ -32,6 +32,7 @@
            and areaCode = #{code}
        </if>
        )
        order by id desc
    </select>
@@ -63,6 +64,7 @@
            </if>
            )
        </if>
        order by id desc
    </select>
@@ -80,6 +82,7 @@
        <if test="null != companyId">
            and companyId = #{companyId}
        </if>
        order by id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/PushOrderMapper.xml
@@ -30,5 +30,6 @@
        <if test="null != pushType">
            and pushType = #{pushType}
        </if>
        order by id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/RoleMapper.xml
@@ -29,6 +29,7 @@
        <if test="objectType == 1">
            and rr.objType =1
        </if>
        order by rr.id desc
    </select>
    <delete id="deleteRolesById">
@@ -48,6 +49,7 @@
        <if test="type == 2">
            and version = #{creatorId}
        </if>
        order by id desc
    </select>
        <select id="roleTreeListByRoleId" resultType="com.dsh.course.model.node.ZTreeNode">
@@ -105,7 +107,7 @@
            </if>
        </where>
        ORDER BY
        pId,
        num ASC
        pId DESC,
        num DESC
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/ServerCarModelMapper.xml
@@ -16,6 +16,6 @@
    <select id="queryServerCarModel" resultType="com.dsh.course.entity.ServerCarModel">
        select * from t_server_carmodel where state = 1 and `type` = #{type}
        select * from t_server_carmodel where state = 1 and `type` = #{type} order by id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/SysIntegralMapper.xml
@@ -13,6 +13,6 @@
    <select id="query" resultType="com.dsh.course.entity.SysIntegral">
        select * from t_sys_integral where companyId = #{companyId}
        select * from t_sys_integral where companyId = #{companyId} order by id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/TEvaluationMapper.xml
@@ -25,9 +25,10 @@
                #{id}
            </foreach>
        </if>
        order by t1.id desc
    </select>
    <select id="info" resultType="com.dsh.guns.modular.system.model.TEvaluationListVo">
        select t1.id,t1.appUserId,t1.score,t1.insertTime time,t1.imgs,t1.content,t2.name shopName,t2.province pName,t2.city cName from t_store_evaluation t1 left join t_store t2 on t1.storeId =t2.id
        where t1.id =#{id}
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/TNoticesMapper.xml
@@ -46,6 +46,7 @@
        <if test="type == 1">
            and isShow = 1
        </if>
        order by id desc
    </select>
@@ -79,6 +80,6 @@
                and o.language =#{yy}
            </if>
        </where>
        order by o.sort asc,o.insertTime desc
        order by o.sort desc,o.insertTime desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/resources/mapper/TOperatorMapper.xml
@@ -28,8 +28,9 @@
        <if test="type != null and type != ''">
            and t1.type =  #{type}
        </if>
        order by t1.id desc
    </select>
    <select id="getBankList" resultType="com.dsh.guns.modular.system.model.Bank">
        select * from t_bank
        select * from t_bank order by id desc
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/TOperatorUserMapper.xml
@@ -48,7 +48,7 @@
        <if test="state !=null ">
            and t1.audit = #{state}
        </if>
        ORDER BY t1.id;
        ORDER BY t1.id DESC;
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/TStoreMapper.xml
@@ -58,6 +58,7 @@
        <if test="operatorId !=null and operatorId !=''">
            and t1.operatorId = #{operatorId}
        </if>
        order by t1.id desc
    </select>
    <select id="queryProvince" resultType="map">
        select * from (
@@ -119,21 +120,22 @@
        <if test="storeName != null and storeName != ''">
            and `name` like CONCAT('%',#{storeName},'%')
        </if>
        order by id desc
    </select>
    <select id="listOne" resultType="java.util.Map">
        select id,name,sort,state from t_store_other where storeId=#{id}
        select id,name,sort,state from t_store_other where storeId=#{id} order by id desc
    </select>
    <select id="typeChange" resultType="java.util.Map">
        select t1.id,t1.name from t_turn t1 left join  t_turn t2 on t1.pid = t2.id where t2.name  =#{name}
        select t1.id,t1.name from t_turn t1 left join  t_turn t2 on t1.pid = t2.id where t2.name  =#{name} order by t1.id desc
    </select>
    <select id="typeChangeOne" resultType="java.util.Map">
        select id,name from t_turn  where pid  =#{id}
        select id,name from t_turn  where pid  =#{id} order by id desc
    </select>
    <select id="getConfig" resultType="java.lang.String">
        select name from t_turn where id =#{page}
    </select>
    <select id="listTwo" resultType="java.util.Map">
        select id,url,name ,  page,sort from t_store_other_config
        select id,url,name ,  page,sort from t_store_other_config order by id desc
    </select>
    <select id="getPage" resultType="com.dsh.guns.modular.system.model.TTurn">
@@ -146,9 +148,10 @@
                </foreach>
            </if>
        </where>
        order by t_turn.id desc
    </select>
    <select id="pageList" resultType="com.dsh.guns.modular.system.model.TTurn">
        select * from t_turn where pid = 0
        select * from t_turn where pid = 0 order by id desc
    </select>
    <select id="get" resultType="com.dsh.course.dto.JsDto">
        select * from t_js where  id = #{id}
@@ -157,7 +160,7 @@
    <select id="getConfig1" resultType="com.dsh.guns.modular.system.model.TImgConfig">
        select * from t_img_config
        select * from t_img_config order by id desc
    </select>
@@ -167,6 +170,7 @@
        SELECT op.id , CONCAT(us.name,'-',us.`phone`) as value
        FROM t_operator op
            LEFT JOIN sys_user us on op.userId = us.id
        order by op.id desc
@@ -190,6 +194,7 @@
        <if test="shopName !=null and shopName !=''">
            and t1.name like concat("%",#{shopName},"%")
        </if>
        order by t1.id desc
    </select>
    <select id="querySiteListOfpage" resultType="java.util.Map">
        SELECT t1.id, t2.operatorId, t1.province, t1.city, t2.name,t1.ids,t1.name as siteName
@@ -212,6 +217,7 @@
        <if test="storeId != null">
            and t1.storeId = #{storeId}
        </if>
        order by t1.id desc
    </select>
    <select id="querySiteListOfpageOperator" resultType="java.util.Map">
        SELECT t1.id, t2.operatorId, t1.province, t1.city, t2.name,t1.ids,t1.name as siteName
@@ -235,7 +241,7 @@
                #{id}
            </foreach>
        </if>
        order by t1.id desc
    </select>
    <select id="listStoreAll" resultType="map">
@@ -261,6 +267,7 @@
        <if test="null != cityCode and '' != cityCode">
            and a.cityCode = #{cityCode}
        </if>
        order by a.id desc
    </select>
@@ -279,5 +286,6 @@
        <foreach collection="ids" item="item" index="index" open="(" separator="," close=")">
            #{item}
        </foreach>
        order by a.id desc
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/UserMapper.xml
@@ -53,6 +53,7 @@
        <if test="beginTime != null and beginTime != '' and endTime != null and endTime != ''">
            and (createTime between CONCAT(#{beginTime},' 00:00:00') and CONCAT(#{endTime},' 23:59:59'))
        </if>
        order by id desc
    </select>
    <update id="setStatus">
@@ -133,7 +134,8 @@
    </select>
    <select id="searchUsers" resultType="com.dsh.guns.modular.system.model.UserListVO">
        select t1.id,t1.name ,t1.phone ,t1.avatar,t1.birthday,t1.sex,t1.idCard,t1.status,t1.version
        ,t2.simplename as deptName from sys_user t1
        ,t2.simplename as deptName,
        (select group_concat(r.name separator ',') from sys_role r where find_in_set(r.id, t1.roleid)) as roleName from sys_user t1
        left join sys_dept t2 on t1.deptid = t2.id
        <where>
            <if test="query.name != null and query.name != ''">
@@ -160,6 +162,7 @@
            </if>
            and t1.status != 3
        </where>
        order by t1.id desc
    </select>
</mapper>
cloud-server-management/src/main/resources/mapper/VipMapper.xml
@@ -12,5 +12,6 @@
        <if test="status != null">
            and status = #{status}
        </if>
        order by id desc
    </select>
</mapper>
</mapper>
cloud-server-management/src/main/webapp/WEB-INF/view/common/_container.html
@@ -64,6 +64,7 @@
    <script src="${ctxPath}/js/common/web-upload-object.js"></script>
    <script src="${ctxPath}/js/common/ztree-object.js"></script>
    <script src="${ctxPath}/js/common/Feng.js"></script>
    <script src="${ctxPath}/js/common/sensitive-info.js"></script>
    <script src="${ctxPath}/js/plugins/sweetalert/sweetalert.min.js"></script>
    <script src="${ctxPath}/layui/layui.js"></script>
cloud-server-management/src/main/webapp/WEB-INF/view/system/ball/yuyue.html
@@ -106,6 +106,7 @@
                            <#button name="取消预约" icon="fa-edit" clickFun="TStudent.openTStudentDetail4()" space="true"/>
                            <#button name="手动支付" icon="fa-edit" clickFun="TStudent.openTStudentDetail6()" space="true"/>
                            <#button name="查看详情" icon="fa-edit" clickFun="TStudent.openTStudentDetail5()" space="true"/>
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="TStudent.viewSensitiveData()" space="true"/>
                            <#button name="导出" icon="fa-download" clickFun="TStudent.exportData()" space="true"/>
<!--                            <button id="exportButton">TTTTTTTTTT</button>-->
                        </div>
cloud-server-management/src/main/webapp/WEB-INF/view/system/dataStatistics/operatorIncome.html
@@ -304,6 +304,11 @@
<script src="${ctxPath}/modular/system/dataStatistics/tSite.js"></script>
<script src="${ctxPath}/static/js/plugins/switchery/switchery.js"></script>
<script>
    // 仅格式化前端展示,接口返回的原始数值不作改动。
    function formatStatisticNumber(value) {
        var number = Number(value);
        return isFinite(number) ? number.toFixed(2) : '0.00';
    }
    var weekX = ["1周","2周","3周","4周"];
    var monthX = ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"];
@@ -381,21 +386,21 @@
            var netIncomeAmount = document.getElementById("netIncomeAmount");
            var couponDeductionAmount = document.getElementById("couponDeductionAmount");
            var refundAmount = document.getElementById("refundAmount");
            t1.innerText = list[0] || 0;
            t2.innerText = "年度应收:"+list[1]+"         ";
            netIncomeAmount.innerText = resp.netIncomeAmount || 0;
            couponDeductionAmount.innerText = resp.couponDeductionAmount || 0;
            refundAmount.innerText = resp.refundAmount || 0;
            t1.innerText = formatStatisticNumber(list[0]);
            t2.innerText = "年度应收:" + formatStatisticNumber(list[1]) + "         ";
            netIncomeAmount.innerText = formatStatisticNumber(resp.netIncomeAmount);
            couponDeductionAmount.innerText = formatStatisticNumber(resp.couponDeductionAmount);
            refundAmount.innerText = formatStatisticNumber(resp.refundAmount);
            var incomeTypeNet = resp.incomeTypeNet || {};
            $("#fee1").text(incomeTypeNet[1] || 0);
            $("#fee2").text(incomeTypeNet[2] || 0);
            $("#fee3").text(incomeTypeNet[3] || 0);
            $("#fee4").text(incomeTypeNet[4] || 0);
            $("#fee5").text(incomeTypeNet[5] || 0);
            $("#fee7").text(incomeTypeNet[6] || 0);
            t3.innerText = "月度营收:"+list[2]+"         ";
            t4.innerText = "周度营收:"+list[3]+"         ";
            t5.innerText = "日度营收:"+list[4]+"         ";
            $("#fee1").text(formatStatisticNumber(incomeTypeNet[1]));
            $("#fee2").text(formatStatisticNumber(incomeTypeNet[2]));
            $("#fee3").text(formatStatisticNumber(incomeTypeNet[3]));
            $("#fee4").text(formatStatisticNumber(incomeTypeNet[4]));
            $("#fee5").text(formatStatisticNumber(incomeTypeNet[5]));
            $("#fee7").text(formatStatisticNumber(incomeTypeNet[6]));
            t3.innerText = "月度营收:" + formatStatisticNumber(list[2]) + "         ";
            t4.innerText = "周度营收:" + formatStatisticNumber(list[3]) + "         ";
            t5.innerText = "日度营收:" + formatStatisticNumber(list[4]) + "         ";
            var year =  resp.yearIncome;
            var month =  resp.monthIncome;
            var week =  resp.weekIncome;
@@ -1471,10 +1476,10 @@
            return;
        }
        var ajax3 = new $ax(Feng.ctxPath + "/data/backYys", function(data){
            $("#back1").text(data.thisYear);
            $("#back2").text(data.thisMonth);
            $("#back3").text(data.thisWeek);
            $("#back4").text(data.thisDay);
            $("#back1").text(formatStatisticNumber(data.thisYear));
            $("#back2").text(formatStatisticNumber(data.thisMonth));
            $("#back3").text(formatStatisticNumber(data.thisWeek));
            $("#back4").text(formatStatisticNumber(data.thisDay));
            option1 = {
                tooltip: {
                    trigger: 'axis'
@@ -1925,6 +1930,8 @@
    var yearX = [];
    var timeX = [];
    var dataX = [];
    // 仅允许接口真实数据渲染,禁止历史遗留的演示图表覆盖统计结果。
    var renderDemoStatistics = false;
    // 创建一个日期对象
    var currentDate = new Date();
    // 获取当前日期的号数
@@ -1961,6 +1968,9 @@
            jxtj()
            srtj()
            income()
        }
        if (!renderDemoStatistics) {
            return;
        }
        var chartDom = document.getElementById('cookieTicket');
        var myChart = echarts.init(chartDom);
@@ -2000,6 +2010,9 @@
    myChart.setOption(option);
    });
    $(function(){
        if (!renderDemoStatistics) {
            return;
        }
        var chartDom = document.getElementById('cookieCourse');
        var myChart = echarts.init(chartDom);
        var option;
@@ -2037,6 +2050,9 @@
        myChart.setOption(option);
    });
    $(function(){
        if (!renderDemoStatistics) {
            return;
        }
        var chartDom = document.getElementById('cookieBooking');
        var myChart = echarts.init(chartDom);
        var option;
@@ -2074,6 +2090,9 @@
        myChart.setOption(option);
    });
    $(function(){
        if (!renderDemoStatistics) {
            return;
        }
        var chartDom = document.getElementById('cookieAge');
        var myChart = echarts.init(chartDom);
        var option;
@@ -2110,6 +2129,9 @@
        myChart.setOption(option);
    });
    $(function(){
        if (!renderDemoStatistics) {
            return;
        }
        var chartDom = document.getElementById('cookieGender');
        var myChart = echarts.init(chartDom);
        var option;
@@ -2146,6 +2168,9 @@
        myChart.setOption(option);
    });
    $(function(){
        if (!renderDemoStatistics) {
            return;
        }
        var chartDom = document.getElementById('cookieTeachCourse');
        var myChart = echarts.init(chartDom);
        var option;
cloud-server-management/src/main/webapp/WEB-INF/view/system/dataStatistics/platformIncome.html
@@ -350,6 +350,17 @@
<script src="${ctxPath}/modular/system/dataStatistics/echarts.min.js"></script>
<script src="${ctxPath}/static/js/plugins/switchery/switchery.js"></script>
<script>
    // 仅格式化前端展示,接口返回的原始数值不作改动。
    function formatStatisticNumber(value) {
        var number = Number(value);
        return isFinite(number) ? number.toFixed(2) : '0.00';
    }
    // 首次进入页面时,收入类型来自服务端模板变量;同样按两位小数展示。
    $(function () {
        $('#fee1, #fee2, #fee3, #fee4, #fee5, #fee7').each(function () {
            $(this).text(formatStatisticNumber($(this).text()));
        });
    });
    laydate.render({
        elem: '#beginTime'
        , trigger: 'click'
@@ -359,18 +370,20 @@
        var time =  $("#beginTime").val();
        // 营收卡片与收入类型卡片使用同一接口、同一时间范围,避免筛选后口径不一致。
        var incomeAjax = new $ax(Feng.ctxPath + "/data/getIncomeData", function(resp){
            $("#totalIncome").text(resp.incomeStatistics.totalIncomeAmount || 0);
            $("#netIncomeAmount").text(resp.incomeStatistics.netIncomeAmount || 0);
            $("#couponDeductionAmount").text(resp.incomeStatistics.couponDeductionAmount || 0);
            $("#refundAmount").text(resp.incomeStatistics.refundAmount || 0);
            $("#totalIncome").text(formatStatisticNumber(resp.incomeStatistics.totalIncomeAmount));
            $("#netIncomeAmount").text(formatStatisticNumber(resp.incomeStatistics.netIncomeAmount));
            $("#couponDeductionAmount").text(formatStatisticNumber(resp.incomeStatistics.couponDeductionAmount));
            $("#refundAmount").text(formatStatisticNumber(resp.incomeStatistics.refundAmount));
            var incomeTypeNet = resp.incomeTypeNet || {};
            $("#fee1").text(incomeTypeNet[1] || 0);
            $("#fee2").text(incomeTypeNet[2] || 0);
            $("#fee3").text(incomeTypeNet[3] || 0);
            $("#fee4").text(incomeTypeNet[4] || 0);
            $("#fee5").text(incomeTypeNet[5] || 0);
            $("#fee7").text(incomeTypeNet[6] || 0);
            $("#fee1").text(formatStatisticNumber(incomeTypeNet[1]));
            $("#fee2").text(formatStatisticNumber(incomeTypeNet[2]));
            $("#fee3").text(formatStatisticNumber(incomeTypeNet[3]));
            $("#fee4").text(formatStatisticNumber(incomeTypeNet[4]));
            $("#fee5").text(formatStatisticNumber(incomeTypeNet[5]));
            $("#fee7").text(formatStatisticNumber(incomeTypeNet[6]));
            renderTicketIncomeChart(resp.ticketIncome || {});
            renderIncomeTypePieChart('cookieCourse', '课程收入', resp.courseData);
            renderIncomeTypePieChart('cookieBooking', '订场收入', resp.siteData);
        });
        incomeAjax.set("time", time);
        incomeAjax.start();
@@ -399,6 +412,17 @@
            }]
        }, true);
    }
    function renderIncomeTypePieChart(elementId, title, data) {
        var chartDom = document.getElementById(elementId);
        var chart = echarts.getInstanceByDom(chartDom) || echarts.init(chartDom);
        chart.setOption({
            title: {text: title, left: 'center'},
            tooltip: {trigger: 'item'},
            series: [{name: title, type: 'pie', radius: '50%', data: data || []}]
        }, true);
    }
    // 创建一个日期对象
    var currentDate = new Date();
    // 获取当前日期的号数
@@ -432,18 +456,18 @@
    function renderIncomeStatistics(elementId, periodName, statistics) {
        document.getElementById(elementId).innerText = periodName + "统计:总营收金额 "
            + statistics.totalIncomeAmount + ",净收入金额 " + statistics.netIncomeAmount
            + ",优惠券抵扣金额 " + statistics.couponDeductionAmount + ",退款金额 "
            + statistics.refundAmount;
            + formatStatisticNumber(statistics.totalIncomeAmount) + ",净收入金额 " + formatStatisticNumber(statistics.netIncomeAmount)
            + ",优惠券抵扣金额 " + formatStatisticNumber(statistics.couponDeductionAmount) + ",退款金额 "
            + formatStatisticNumber(statistics.refundAmount);
    }
    function renderIncomeStatisticsList(elementId, title, labels, statistics) {
        var records = labels.map(function (label, index) {
            var item = statistics[index];
            return '<div class="income-period-record"><strong>' + label + '</strong>:总营收金额 '
                + item.totalIncomeAmount + ',净收入金额 ' + item.netIncomeAmount
                + ',优惠券抵扣金额 ' + item.couponDeductionAmount
                + ',退款金额 ' + item.refundAmount + '</div>';
                + formatStatisticNumber(item.totalIncomeAmount) + ',净收入金额 ' + formatStatisticNumber(item.netIncomeAmount)
                + ',优惠券抵扣金额 ' + formatStatisticNumber(item.couponDeductionAmount)
                + ',退款金额 ' + formatStatisticNumber(item.refundAmount) + '</div>';
        }).join('');
        document.getElementById(elementId).innerHTML = '<div class="income-period-title">' + title
            + '</div><div class="income-period-records">' + records + '</div>';
@@ -458,10 +482,10 @@
                formatter: function (params) {
                    var item = params[0];
                    var detail = statistics[item.dataIndex];
                    return labels[item.dataIndex] + '<br/>总营收:' + detail.totalIncomeAmount
                        + '<br/>净收入:' + detail.netIncomeAmount
                        + '<br/>优惠券抵扣:' + detail.couponDeductionAmount
                        + '<br/>退款:' + detail.refundAmount;
                    return labels[item.dataIndex] + '<br/>总营收:' + formatStatisticNumber(detail.totalIncomeAmount)
                        + '<br/>净收入:' + formatStatisticNumber(detail.netIncomeAmount)
                        + '<br/>优惠券抵扣:' + formatStatisticNumber(detail.couponDeductionAmount)
                        + '<br/>退款:' + formatStatisticNumber(detail.refundAmount);
                }
            },
            grid: {left: '5%', right: '4%', bottom: '18%', containLabel: true},
@@ -539,10 +563,10 @@
            var netIncomeAmount = document.getElementById("netIncomeAmount");
            var couponDeductionAmount = document.getElementById("couponDeductionAmount");
            var refundAmount = document.getElementById("refundAmount");
            t1.innerText = list[0] || 0;
            netIncomeAmount.innerText = resp.incomeStatistics.netIncomeAmount || 0;
            couponDeductionAmount.innerText = resp.incomeStatistics.couponDeductionAmount || 0;
            refundAmount.innerText = resp.incomeStatistics.refundAmount || 0;
            t1.innerText = formatStatisticNumber(list[0]);
            netIncomeAmount.innerText = formatStatisticNumber(resp.incomeStatistics.netIncomeAmount);
            couponDeductionAmount.innerText = formatStatisticNumber(resp.incomeStatistics.couponDeductionAmount);
            refundAmount.innerText = formatStatisticNumber(resp.incomeStatistics.refundAmount);
            renderIncomeStatisticsList("yearIncomeStatistics", "历年营收明细", resp.yearLabels, resp.yearIncomeStatistics);
            renderIncomeStatisticsList("monthIncomeStatistics", "本年各月营收明细", resp.monthLabels, resp.monthIncomeStatistics);
            renderIncomeStatisticsList("weekIncomeStatistics", "近四周营收明细", resp.weekLabels, resp.weekIncomeStatistics);
@@ -551,11 +575,14 @@
            renderIncomeTrendChart("incomeMonthChart", "本年各月营收趋势", resp.monthLabels, resp.monthIncomeStatistics);
            renderIncomeTrendChart("incomeWeekChart", "近四周营收趋势", resp.weekLabels, resp.weekIncomeStatistics);
            renderIncomeTrendChart("incomeDayChart", "近七日营收趋势", resp.dayLabels, resp.dayIncomeStatistics);
            $("#back1").text(resp.yearIncomeStatistics[resp.yearIncomeStatistics.length - 1].refundAmount || 0);
            $("#back2").text(resp.monthIncomeStatistics[new Date().getMonth()].refundAmount || 0);
            $("#back3").text(resp.weekIncomeStatistics[resp.weekIncomeStatistics.length - 1].refundAmount || 0);
            $("#back4").text(resp.dayIncomeStatistics[resp.dayIncomeStatistics.length - 1].refundAmount || 0);
            $("#back1").text(formatStatisticNumber(resp.yearIncomeStatistics[resp.yearIncomeStatistics.length - 1].refundAmount));
            $("#back2").text(formatStatisticNumber(resp.monthIncomeStatistics[new Date().getMonth()].refundAmount));
            $("#back3").text(formatStatisticNumber(resp.weekIncomeStatistics[resp.weekIncomeStatistics.length - 1].refundAmount));
            $("#back4").text(formatStatisticNumber(resp.dayIncomeStatistics[resp.dayIncomeStatistics.length - 1].refundAmount));
            renderRefundChart(myChart1, resp);
            renderTicketIncomeChart(resp.ticketIncome || {});
            renderIncomeTypePieChart('cookieCourse', '课程收入', resp.courseData);
            renderIncomeTypePieChart('cookieBooking', '订场收入', resp.siteData);
        });
        ajax.set("type",1);
        ajax.start();
@@ -1476,15 +1503,16 @@
        courseData = courseData.split('},')
        var a=[];
        for (let j = 0; j <courseData.length; j++) {
            if(j<courseData.length-1){
                var d = courseData[j].replace("{","").replace("}","").split(",")
                    let obj ={
                        name:d[0].split("=")[1],
                        value:d[1].split("=")[1]
                    }
                    a.push(obj)
        for (let j = 0; j < courseData.length; j++) {
            var d = courseData[j].replace("{", "").replace("}", "").split(",");
            if (d.length < 2) {
                continue;
            }
            let obj = {
                name: d[0].split("=")[1],
                value: d[1].split("=")[1]
            };
            a.push(obj);
        }
        var chartDom = document.getElementById('cookieCourse');
        var myChart = echarts.init(chartDom)
@@ -1525,15 +1553,16 @@
        courseData = courseData.split('},')
        var a=[];
        for (let j = 0; j <courseData.length; j++) {
            if(j<courseData.length-1){
                var d = courseData[j].replace("{","").replace("}","").split(",")
                let obj ={
                    name:d[0].split("=")[1],
                    value:d[1].split("=")[1]
                }
                a.push(obj)
        for (let j = 0; j < courseData.length; j++) {
            var d = courseData[j].replace("{", "").replace("}", "").split(",");
            if (d.length < 2) {
                continue;
            }
            let obj = {
                name: d[0].split("=")[1],
                value: d[1].split("=")[1]
            };
            a.push(obj);
        }
        var chartDom = document.getElementById('cookieBooking');
        var myChart = echarts.init(chartDom);
cloud-server-management/src/main/webapp/WEB-INF/view/system/dataStatistics/storeIncome.html
@@ -280,6 +280,11 @@
<script src="${ctxPath}/modular/system/dataStatistics/tSite.js"></script>
<script src="${ctxPath}/static/js/plugins/switchery/switchery.js"></script>
<script>
    // 仅格式化前端展示,接口返回的原始数值不作改动。
    function formatStatisticNumber(value) {
        var number = Number(value);
        return isFinite(number) ? number.toFixed(2) : '0.00';
    }
    function search(){
@@ -306,9 +311,9 @@
        var records = labels.map(function (label, index) {
            var item = statistics[index];
            return '<div class="income-period-record"><strong>' + label + '</strong>:总营收金额 '
                + item.totalIncomeAmount + ',净收入金额 ' + item.netIncomeAmount
                + ',优惠券抵扣金额 ' + item.couponDeductionAmount + ',退款金额 '
                + item.refundAmount + '</div>';
                + formatStatisticNumber(item.totalIncomeAmount) + ',净收入金额 ' + formatStatisticNumber(item.netIncomeAmount)
                + ',优惠券抵扣金额 ' + formatStatisticNumber(item.couponDeductionAmount) + ',退款金额 '
                + formatStatisticNumber(item.refundAmount) + '</div>';
        }).join('');
        document.getElementById(elementId).innerHTML = '<div class="income-period-title">' + title
            + '</div><div class="income-period-records">' + records + '</div>';
@@ -320,9 +325,9 @@
            title: {text: title, left: 'center', textStyle: {fontSize: 15}},
            tooltip: {trigger: 'axis', formatter: function (params) {
                var detail = statistics[params[0].dataIndex];
                return labels[params[0].dataIndex] + '<br/>总营收:' + detail.totalIncomeAmount
                    + '<br/>净收入:' + detail.netIncomeAmount + '<br/>优惠券抵扣:'
                    + detail.couponDeductionAmount + '<br/>退款:' + detail.refundAmount;
                return labels[params[0].dataIndex] + '<br/>总营收:' + formatStatisticNumber(detail.totalIncomeAmount)
                    + '<br/>净收入:' + formatStatisticNumber(detail.netIncomeAmount) + '<br/>优惠券抵扣:'
                    + formatStatisticNumber(detail.couponDeductionAmount) + '<br/>退款:' + formatStatisticNumber(detail.refundAmount);
            }},
            grid: {left: '5%', right: '4%', bottom: '18%', containLabel: true},
            xAxis: {type: 'category', boundaryGap: false, data: labels, axisLabel: {rotate: labels.length > 7 ? 35 : 0, interval: 0}},
@@ -335,17 +340,17 @@
    function income(){
        var ajax = new $ax(Feng.ctxPath + "/data/getIncomeData", function(resp){
            yearX = resp.year;
            $("#totalIncome").text(resp.incomeStatistics.totalIncomeAmount || 0);
            $("#netIncomeAmount").text(resp.incomeStatistics.netIncomeAmount || 0);
            $("#couponDeductionAmount").text(resp.incomeStatistics.couponDeductionAmount || 0);
            $("#refundAmount").text(resp.incomeStatistics.refundAmount || 0);
            $("#totalIncome").text(formatStatisticNumber(resp.incomeStatistics.totalIncomeAmount));
            $("#netIncomeAmount").text(formatStatisticNumber(resp.incomeStatistics.netIncomeAmount));
            $("#couponDeductionAmount").text(formatStatisticNumber(resp.incomeStatistics.couponDeductionAmount));
            $("#refundAmount").text(formatStatisticNumber(resp.incomeStatistics.refundAmount));
            var incomeTypeNet = resp.incomeTypeNet || {};
            $("#fee1").text(incomeTypeNet[1] || 0);
            $("#fee2").text(incomeTypeNet[2] || 0);
            $("#fee3").text(incomeTypeNet[3] || 0);
            $("#fee4").text(incomeTypeNet[4] || 0);
            $("#fee5").text(incomeTypeNet[5] || 0);
            $("#fee7").text(incomeTypeNet[6] || 0);
            $("#fee1").text(formatStatisticNumber(incomeTypeNet[1]));
            $("#fee2").text(formatStatisticNumber(incomeTypeNet[2]));
            $("#fee3").text(formatStatisticNumber(incomeTypeNet[3]));
            $("#fee4").text(formatStatisticNumber(incomeTypeNet[4]));
            $("#fee5").text(formatStatisticNumber(incomeTypeNet[5]));
            $("#fee7").text(formatStatisticNumber(incomeTypeNet[6]));
            renderIncomeStatisticsList("yearIncomeStatistics", "历年营收明细", resp.yearLabels, resp.yearIncomeStatistics);
            renderIncomeStatisticsList("monthIncomeStatistics", "本年各月营收明细", resp.monthLabels, resp.monthIncomeStatistics);
            renderIncomeStatisticsList("weekIncomeStatistics", "近四周营收明细", resp.weekLabels, resp.weekIncomeStatistics);
cloud-server-management/src/main/webapp/WEB-INF/view/system/finance/Income.html
@@ -43,6 +43,9 @@
                                <#button name="重置" icon="fa-trash" clickFun="TCompetition.resetSearch()" space="true"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="TCompetitionTableToolbar" role="group">
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="TCompetition.viewSensitiveData()"/>
                        </div>
                            <div class="ibox-title" style="display: flex">
                                <h3 id ="totalMoney"></h3><h3>元</h3>
                            </div>
cloud-server-management/src/main/webapp/WEB-INF/view/system/finance/RegistrationOrder.html
@@ -83,6 +83,9 @@
                                <#button name="重置" icon="fa-trash" clickFun="TCompetition.resetSearch()" space="true"/>
                            </div>
                        </div>
                        <div class="hidden-xs" id="TCompetitionTableToolbar" role="group">
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="TCompetition.viewSensitiveData()"/>
                        </div>
                            <div class="ibox-title" style="display: flex">
                                <h3 id ="totalOrder"></h3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                <h3 id ="cashPayment"></h3><h3>元</h3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
cloud-server-management/src/main/webapp/WEB-INF/view/system/operator/Operator.html
@@ -41,6 +41,7 @@
                            <#button name="解冻" icon="fa-check" clickFun="TSite.onShelf()" space="true"/>
                            <#button name="重置密码" icon="fa-search" clickFun="TSite.reload()" space="true"/>
                            <#button name="绑定商户号" icon="fa-search" clickFun="TSite.bindWx()" space="true"/>
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="TSite.viewSensitiveData()" space="true"/>
                        </div>
                        <#table id="TSiteTable"/>
                    </div>
@@ -49,7 +50,7 @@
        </div>
    </div>
</div>
<script src="${ctxPath}/modular/system/operator/operator.js"></script>
<script src="${ctxPath}/modular/system/operator/operator.js?v=20260921-sensitive-view"></script>
<script>
    laydate.render({
        elem: '#createTime'
cloud-server-management/src/main/webapp/WEB-INF/view/system/referee/referee.html
@@ -59,6 +59,7 @@
              @}
              @if(shiro.hasPermission("/referee/onShelf")){
              <#button name="解冻" icon="fa-edit" clickFun="Referee.onShelf()" space="true"/>
              <#button name="查看敏感信息" icon="fa-eye" clickFun="Referee.viewSensitiveData()" space="true"/>
              @}
            </div>
            <#table id="RefereeTable"/>
cloud-server-management/src/main/webapp/WEB-INF/view/system/tCoach/TCoach.html
@@ -59,6 +59,7 @@
                    <#button name="解冻" icon="fa-check" clickFun="TSite.onShelf()" space="true"/>
                    <#button name="冻结" icon="fa-remove" clickFun="TSite.offShelf()" space="true"/>
                    <#button name="查看详情" icon="fa-search" clickFun="TSite.openInfo()" space="true"/>
                    <#button name="查看敏感信息" icon="fa-eye" clickFun="TSite.viewSensitiveData()" space="true"/>
                </div>
                <#table id="TSiteTable"/>
            </div>
cloud-server-management/src/main/webapp/WEB-INF/view/system/tIntegral/TIntegral.html
@@ -43,6 +43,7 @@
                </div>
                <div class="hidden-xs" id="TCompetitionTableToolbar" role="group">
                    <#button name="赠送积分" icon="fa-plus" clickFun="TSite.openAdd()"/>
                    <#button name="查看敏感信息" icon="fa-eye" clickFun="TSite.viewSensitiveData()" space="true"/>
                </div>
                <#table id="TSiteTable"/>
cloud-server-management/src/main/webapp/WEB-INF/view/system/tPayHuimin/tPayHuimin.html
@@ -76,6 +76,7 @@
                            @}
                            @if(shiro.hasPermission("/tPayHuimin/export")){
                                <#button name="导出" icon="fa-edit" clickFun="TPayHuimin.export()" space="true"/>
                                <#button name="查看敏感信息" icon="fa-eye" clickFun="TPayHuimin.viewSensitiveData()" space="true"/>
                            @}
                            <div class="form-group">
                                <label> 售卖总金额:¥</label>
cloud-server-management/src/main/webapp/WEB-INF/view/system/tShopEvaluation/TShop.html
@@ -55,6 +55,7 @@
                    <#button name="上架" icon="fa-plus" clickFun="TCompetition.updateState(1)"/>
                    <#button name="下架" icon="fa-edit" clickFun="TCompetition.updateState(2)" space="true"/>
                    <#button name="查看详情" icon="fa-remove" clickFun="TCompetition.info()" space="true"/>
                    <#button name="查看敏感信息" icon="fa-eye" clickFun="TCompetition.viewSensitiveData()" space="true"/>
                </div>
                <#table id="TCompetitionTable"/>
            </div>
cloud-server-management/src/main/webapp/WEB-INF/view/system/userAudit/userAudit.html
@@ -27,6 +27,7 @@
                        </div>
                        <div class="hidden-xs" id="DriverApplyRefundTableToolbar" role="group">
                            <#button name="批量审核" icon="fa-plus" clickFun="DriverApplyRefund.auditBatch()"/>
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="DriverApplyRefund.viewSensitiveData()" space="true"/>
                        </div>
                        <#table id="DriverApplyRefundTable"/>
                    </div>
cloud-server-management/src/main/webapp/WEB-INF/view/system/vipDetail/vip_detail.html
@@ -83,6 +83,7 @@
                        <div class="hidden-xs" id="TCompetitionTableToolbar" role="group">
                            @if(objectType==1){
                            <#button name="导出" icon="fa-plus" clickFun="TCompetition.export()"/>
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="TCompetition.viewSensitiveData()" space="true"/>
                            @}
                        </div>
                <#table id="TCompetitionTable"/>
cloud-server-management/src/main/webapp/WEB-INF/view/system/vipPayment/vip_payment.html
@@ -47,6 +47,7 @@
                </div>
                        <div class="hidden-xs" id="TCompetitionTableToolbar" role="group">
                            <#button name="导出" icon="fa-plus" clickFun="TCompetition.export()"/>
                            <#button name="查看敏感信息" icon="fa-eye" clickFun="TCompetition.viewSensitiveData()" space="true"/>
                        </div>
                <#table id="TCompetitionTable"/>
            </div>
cloud-server-management/src/main/webapp/static/js/common/sensitive-info.js
New file
@@ -0,0 +1,41 @@
/** Admin-only sensitive-information viewer. Every request is audited by the server. */
var SensitiveInfo = {
    view: function (url) {
        layer.confirm('查看完整敏感信息将记录操作日志,是否继续?', {
            icon: 3,
            title: '敏感信息查看'
        }, function (index) {
            $.ajax({
                url: Feng.ctxPath + url,
                type: 'GET',
                success: function (data) {
                    layer.close(index);
                    if (!data) {
                        Feng.info('未查询到敏感信息');
                        return;
                    }
                    // 弹窗只展示手机号;接口中的 id、name 等定位字段不应暴露给页面。
                    var phone = data.phone || data.mobile || data.telephone || data.tel || data.name;
                    if (!phone) {
                        Feng.info('未查询到手机号');
                        return;
                    }
                    var content = '<div class="form-horizontal" style="padding:20px"><div class="form-group">'
                        + '<label class="col-sm-4 control-label">手机号:</label><div class="col-sm-8">'
                        + '<p class="form-control-static">' + SensitiveInfo.escape(String(phone))
                        + '</p></div></div></div>';
                    layer.open({type: 1, title: '敏感信息', area: ['480px', 'auto'], content: content});
                },
                error: function (xhr) {
                    layer.close(index);
                    Feng.error(xhr.responseJSON && xhr.responseJSON.message ? xhr.responseJSON.message : '敏感信息查询失败');
                }
            });
        });
    },
    escape: function (value) {
        return value.replace(/[&<>'"]/g, function (char) {
            return {'&': '&amp;', '<': '&lt;', '>': '&gt;', "'": '&#39;', '"': '&quot;'}[char];
        });
    }
};
cloud-server-management/src/main/webapp/static/modular/system/ball/yuyue.js
@@ -123,6 +123,10 @@
    }
};
TStudent.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/booking/' + this.seItem.id);
};
/**
 * 点击添加
 */
cloud-server-management/src/main/webapp/static/modular/system/finance/RegistrationOrder.js
@@ -49,6 +49,10 @@
    }
};
TCompetition.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/app-user/' + this.seItem.appUserId);
};
@@ -148,4 +152,3 @@
    TCompetition.table = table.init();
    TCompetition.getData();
});
cloud-server-management/src/main/webapp/static/modular/system/finance/income.js
@@ -50,6 +50,12 @@
    }
};
TCompetition.viewSensitiveData = function () {
    if (!this.check()) return;
    if (!this.seItem.appUserId) { Feng.info('该收入记录未关联可查询用户'); return; }
    SensitiveInfo.view('/system/sensitive/app-user/' + this.seItem.appUserId);
};
@@ -147,4 +153,3 @@
    TCompetition.table = table.init();
    TCompetition.getData();
});
cloud-server-management/src/main/webapp/static/modular/system/operator/operator.js
@@ -51,6 +51,10 @@
        return true;
    }
};
TSite.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/operator/' + this.seItem.id);
};
/**
 * 商户号认证
 */
cloud-server-management/src/main/webapp/static/modular/system/referee/referee.js
@@ -45,6 +45,10 @@
        return true;
    }
};
Referee.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/referee/' + this.seItem.id);
};
/**
 * 商户号认证
 */
cloud-server-management/src/main/webapp/static/modular/system/tCoach/tCoach.js
@@ -61,6 +61,10 @@
        return true;
    }
};
TSite.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/coach/' + this.seItem.id);
};
/**
 * 上架
 */
cloud-server-management/src/main/webapp/static/modular/system/tIntegral/tIntegral.js
@@ -59,6 +59,13 @@
        return true;
    }
};
TSite.viewSensitiveData = function () {
    if (!this.check()) return;
    var userId = this.seItem.appUserId || this.seItem.userId;
    if (!userId) { Feng.info('该积分记录未关联用户'); return; }
    SensitiveInfo.view('/system/sensitive/app-user/' + userId);
};
TSite.oneChange = function (e) {
    var oneId=$(e).val();
    var ajax = new $ax(Feng.ctxPath + "/tCity/onChange", function(data){
cloud-server-management/src/main/webapp/static/modular/system/tPayHuimin/tPayHuimin.js
@@ -81,6 +81,10 @@
    }
};
TPayHuimin.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/app-user/' + this.seItem.appUserId);
};
/**
 * 点击添加玩湃惠民卡
 */
cloud-server-management/src/main/webapp/static/modular/system/tShopEvaluation/tShop.js
@@ -78,6 +78,13 @@
    }
};
TCompetition.viewSensitiveData = function () {
    if (!this.check()) return;
    var userId = this.seItem.appUserId || this.seItem.userId;
    if (!userId) { Feng.info('该评价未关联用户'); return; }
    SensitiveInfo.view('/system/sensitive/app-user/' + userId);
};
/**
 * 点击添加车辆管理
 */
@@ -430,4 +437,4 @@
    }else {
        Feng.confirm("Apakah Anda pasti akan mengekspor informasi kendaraan?", operation);
    }
}
}
cloud-server-management/src/main/webapp/static/modular/system/user/user.js
@@ -41,6 +41,7 @@
            }
        },
        {title:  '身份证号', field: 'idCard', align: 'center', valign: 'middle', sortable: true},
        {title:  '角色', field: 'roleName', align: 'center', valign: 'middle', sortable: true},
        {title:  '所在部门', field: 'deptName', align: 'center', valign: 'middle', sortable: true},
        {title:  '状态', field: 'status', align: 'center', valign: 'middle', sortable: true,
            formatter:function (data) {
cloud-server-management/src/main/webapp/static/modular/system/userAudit/userAudit.js
@@ -105,6 +105,10 @@
    return true;
};
DriverApplyRefund.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/app-user/' + this.seItem.userId);
};
/**
 * 打开编辑
cloud-server-management/src/main/webapp/static/modular/system/vipDetail/vipDetail.js
@@ -39,6 +39,17 @@
    ];
};
TCompetition.check = function () {
    var selected = $('#' + this.id).bootstrapTable('getSelections');
    if (selected.length === 0) { Feng.info('请先选中表格中的某一记录!'); return false; }
    TCompetition.seItem = selected[0];
    return true;
};
TCompetition.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/app-user/' + this.seItem.appUserId);
};
TCompetition.export = function (){
    var queryData = TCompetition.getQueryParam();
@@ -201,4 +212,4 @@
    }else {
        Feng.confirm("Apakah Anda pasti akan mengekspor informasi kendaraan?", operation);
    }
}
}
cloud-server-management/src/main/webapp/static/modular/system/vipPayment/vipPayment.js
@@ -56,6 +56,17 @@
    ];
};
TCompetition.check = function () {
    var selected = $('#' + this.id).bootstrapTable('getSelections');
    if (selected.length === 0) { Feng.info('请先选中表格中的某一记录!'); return false; }
    TCompetition.seItem = selected[0];
    return true;
};
TCompetition.viewSensitiveData = function () {
    if (this.check()) SensitiveInfo.view('/system/sensitive/app-user/' + this.seItem.appUserId);
};
TCompetition.export = function (){
    var queryData = TCompetition.getQueryParam();
    // 生成带参数的完整URL
@@ -289,4 +300,4 @@
    }else {
        Feng.confirm("Apakah Anda pasti akan mengekspor informasi kendaraan?", operation);
    }
}
}
cloud-server-other/src/main/java/com/dsh/other/controller/BallController.java
@@ -45,8 +45,8 @@
    public List<TGameRecord> getData(@RequestBody GameDataQuery query){
        if (query.getStoreId()==null){
            // 获取到游戏ids
            List<Integer> gameIds = gameService.list(new QueryWrapper<Game>().eq("operationId", query.getObjectId()))
                    .stream().map(Game::getId).collect(Collectors.toList());
            List<Game> games = gameService.list(new QueryWrapper<Game>().eq("operationId", query.getObjectId()));
            List<Integer> gameIds = games.stream().map(Game::getId).collect(Collectors.toList());
            // 运营商下没有智慧球场时,不能省略 gameId 条件后查询全部支付记录。
            if (gameIds.isEmpty()) {
                return new ArrayList<>();
@@ -60,10 +60,11 @@
            }
            wrapper.in("gameId", gameIds);
            List<TGameRecord> list = gameRecordService.list(wrapper);
            fillMissingSiteId(list, games);
            return list;
        }else{
            List<Integer> gameIds = gameService.list(new QueryWrapper<Game>().eq("storeId", query.getStoreId()))
                    .stream().map(Game::getId).collect(Collectors.toList());
            List<Game> games = gameService.list(new QueryWrapper<Game>().eq("storeId", query.getStoreId()));
            List<Integer> gameIds = games.stream().map(Game::getId).collect(Collectors.toList());
            // 门店下没有智慧球场时,不能省略 gameId 条件后查询全部支付记录。
            if (gameIds.isEmpty()) {
                return new ArrayList<>();
@@ -76,10 +77,26 @@
            }
            wrapper.in("gameId", gameIds);
            List<TGameRecord> list = gameRecordService.list(wrapper);
            fillMissingSiteId(list, games);
            return list;
        }
    }
    /**
     * 旧游戏支付记录可能没有写入 t_game_record.siteId,场地归属以 t_game.siteId 为准补齐,
     * 让调用方能够按场地类型做收入统计。
     */
    private void fillMissingSiteId(List<TGameRecord> records, List<Game> games) {
        Map<Integer, Integer> gameSiteIds = games.stream()
                .filter(game -> game.getId() != null && game.getSiteId() != null)
                .collect(Collectors.toMap(Game::getId, Game::getSiteId, (first, ignored) -> first));
        for (TGameRecord record : records) {
            if (record.getSiteId() == null) {
                record.setSiteId(gameSiteIds.get(record.getGameId()));
            }
        }
    }
    @ResponseBody
    @PostMapping("/student/webStudentList")
cloud-server-other/src/main/java/com/dsh/other/controller/StoreConfigController.java
@@ -138,14 +138,14 @@
            Collections.sort(listVo, new Comparator<StoreConfigVo>() {
                @Override
                public int compare(StoreConfigVo o1, StoreConfigVo o2) {
                    return o1.getSort().compareTo(o2.getSort());
                    return Comparator.nullsLast(Integer::compareTo).compare(o1.getSort(), o2.getSort());
                }
            });
            //排序
            Collections.sort(listVo, new Comparator<StoreConfigVo>() {
                @Override
                public int compare(StoreConfigVo o1, StoreConfigVo o2) {
                    return o1.getIsTop().compareTo(o2.getIsTop()) * -1;
                    return Comparator.nullsLast(Integer::compareTo).compare(o2.getIsTop(), o1.getIsTop());
                }
            });
            for (int i = 0; i < listVo.size(); i++) {
cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java
@@ -848,7 +848,7 @@
                if (userCoupon != null && coupon.getType() == 2) {//代金券
                    JSONObject jsonObject = JSON.parseObject(coupon.getContent());
                    Double num1 = jsonObject.getDouble("conditionalAmount");
                    if (money.compareTo(new BigDecimal(num1)) <= 0) {
                    if (num1 == null || num1 <= 0) {
                        return ResultUtil.error("该优惠券无法使用");
                    }
                    money = money.subtract(new BigDecimal(num1)).max(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_EVEN);
@@ -895,6 +895,7 @@
            siteBooking.setPayMoney(BigDecimal.ZERO.doubleValue());
            siteBooking.setPayTime(new Date());
            siteBookingService.updateById(siteBooking);
            consumeCouponAfterSuccessfulPayment(siteBooking);
            HashMap<String, String> map = new HashMap<>();
            map.put("siteBooking", siteBooking.getId().toString());
            return ResultUtil.success(map);
@@ -1043,9 +1044,25 @@
        siteBooking.setPayTime(new Date());
        siteBooking.setStatus(1);
        siteBookingService.updateById(siteBooking);
        consumeCouponAfterSuccessfulPayment(siteBooking);
        HashMap<String, String> map = new HashMap<>();
        map.put("siteBooking", siteBooking.getId().toString());
        return ResultUtil.success(map);
    }
    /**
     * 场地订单实际支付成功后才核销所选优惠券;避免仅创建待支付订单就提前消耗优惠券。
     */
    private void consumeCouponAfterSuccessfulPayment(SiteBooking siteBooking) {
        if (siteBooking.getUserCouponId() == null || siteBooking.getUserCouponId() == 0) {
            return;
        }
        UserCoupon userCoupon = userCouponClient.queryUserCouponById(
                new QueryUserCouponByIdAndUserId(siteBooking.getUserCouponId(), siteBooking.getAppUserId()));
        if (userCoupon != null && Integer.valueOf(1).equals(userCoupon.getStatus())) {
            userCoupon.setStatus(2);
            userCouponClient.updateUserCoupon(userCoupon);
        }
    }
@@ -1280,17 +1297,11 @@
            if (coupon.getType() == 2) {//代金券
                JSONObject jsonObject = JSON.parseObject(coupon.getContent());
                Double num1 = jsonObject.getDouble("conditionalAmount");
                money = money.subtract(new BigDecimal(num1)).setScale(2, RoundingMode.HALF_EVEN);
                money = money.subtract(new BigDecimal(num1)).max(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_EVEN);
            }
            userCoupon.setStatus(2);
            userCouponClient.updateUserCoupon(userCoupon);
        }
        if (null != couponId && payType == 3) {
            UserCoupon userCoupon = userCouponClient.queryUserCouponById(new QueryUserCouponByIdAndUserId(siteBooking.getUserCouponId(), appUser.getId()));
            userCoupon.setStatus(1);
            userCouponClient.updateUserCoupon(userCoupon);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        siteBooking.setOrderNo(sdf.format(new Date()) + UUIDUtil.getNumberRandom(3));
@@ -1299,9 +1310,6 @@
            siteBooking.setPayMoney(playCoin.doubleValue());
        } else {
            siteBooking.setPayMoney(money.doubleValue());
        }
        if (payType == 3) {
            siteBooking.setUserCouponId(null);
        }
        siteBookingService.updateById(siteBooking);
        if (payType == 1) {//微信支付
@@ -1368,7 +1376,7 @@
            if (coupon.getType() == 2) {//代金券
                JSONObject jsonObject = JSON.parseObject(coupon.getContent());
                Double num1 = jsonObject.getDouble("conditionalAmount");
                money = money.subtract(new BigDecimal(num1)).setScale(2, RoundingMode.HALF_EVEN);
                money = money.subtract(new BigDecimal(num1)).max(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_EVEN);
            }
        }
        switch (siteBooking.getPayType()) {
cloud-server-other/src/main/resources/mapper/GameMapper.xml
@@ -33,7 +33,7 @@
            and si.`name` like concat('%',#{query.site},'%')
        </if>
        order by ga.id desc
    </select>
    <select id="orderlist" resultType="map">