liujie
2026-04-28 b7ace278c8486eb6299f6668f8d092fb859352ca
p0功能 小程序
2个文件已添加
10个文件已修改
200 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUser.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TExchangeCodeUseRecord.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/ExchangeCodeUseRecordQuery.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OtherFallbackFactory.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OtherClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TAppUserMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/KsolarUtils.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TExchangeCodePackageController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TExchangeCodePackageService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TExchangeCodePackageServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/20260427_balance_exchange.sql 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TAppUser.java
@@ -82,6 +82,10 @@
    @ApiModelProperty(value = "积分")
    @TableField("points")
    private Integer points;
    @ApiModelProperty(value = "余额")
    @TableField("balance")
    private BigDecimal balance;
    @ApiModelProperty(value = "积分")
    @TableField("first_add")
    private Integer firstAdd;
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TExchangeCodeUseRecord.java
@@ -11,6 +11,7 @@
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = false)
@@ -37,4 +38,25 @@
    @TableField("used_amount")
    @ApiModelProperty("本次使用金额")
    private BigDecimal usedAmount;
    @TableField(exist = false)
    private String uid;
    @TableField(exist = false)
    private String code;
    @TableField(exist = false)
    private String orderCode;
    @TableField(exist = false)
    private Integer changeType;
    @TableField(exist = false)
    private BigDecimal changeAmount;
    @TableField(exist = false)
    private BigDecimal currentBalance;
    @TableField(exist = false)
    private LocalDateTime dateTime;
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/dto/ExchangeCodeUseRecordQuery.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.other.api.dto;
import com.ruoyi.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("兑换码使用流水查询DTO")
public class ExchangeCodeUseRecordQuery extends BasePage {
    @ApiModelProperty("用户ID")
    private Long userId;
    @ApiModelProperty("变动类型:1=兑换,2=充电")
    private Integer changeType;
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OtherFallbackFactory.java
@@ -5,6 +5,7 @@
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.dto.ExchangeCodeBindDTO;
import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
import com.ruoyi.other.api.dto.ExchangeCodeUseRecordQuery;
import com.ruoyi.other.api.dto.TagListQueryDto;
import com.ruoyi.other.api.dto.UnitListQueryDto;
import com.ruoyi.other.api.feignClient.OtherClient;
@@ -160,6 +161,15 @@
            public R<ExchangeCodeConsumeResultVO> consumeExchangeCodeBalance(ExchangeCodeConsumeDTO dto) {
                return R.fail("扣减兑换码余额失败:" + throwable.getMessage());
            }
            @Override
            public R<Page<TExchangeCodeUseRecord>> exchangeCodeUseRecordPage(ExchangeCodeUseRecordQuery query) {
                return R.fail("查询兑换码流水失败:" + throwable.getMessage());
            }
            @Override
            public R<TExchangeCodeUseRecord> exchangeCodeUseRecordDetail(Long id, Long userId) {
                return R.fail("查询兑换码流水详情失败:" + throwable.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OtherClient.java
@@ -6,12 +6,15 @@
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.dto.ExchangeCodeBindDTO;
import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
import com.ruoyi.other.api.dto.ExchangeCodeUseRecordQuery;
import com.ruoyi.other.api.dto.TagListQueryDto;
import com.ruoyi.other.api.dto.UnitListQueryDto;
import com.ruoyi.other.api.factory.OtherFallbackFactory;
import com.ruoyi.other.api.vo.CouponListVOVO;
import com.ruoyi.other.api.vo.ExchangeCodeBindResultVO;
import com.ruoyi.other.api.vo.ExchangeCodeConsumeResultVO;
import com.ruoyi.other.api.domain.TExchangeCodeUseRecord;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@@ -111,4 +114,11 @@
    @PostMapping(value = "/exchange-code-package/consumeBalance")
    R<ExchangeCodeConsumeResultVO> consumeExchangeCodeBalance(@RequestBody ExchangeCodeConsumeDTO dto);
    @PostMapping(value = "/exchange-code-package/useRecord/page")
    R<Page<TExchangeCodeUseRecord>> exchangeCodeUseRecordPage(@RequestBody ExchangeCodeUseRecordQuery query);
    @GetMapping(value = "/exchange-code-package/useRecord/detail")
    R<TExchangeCodeUseRecord> exchangeCodeUseRecordDetail(@RequestParam("id") Long id,
                                                           @RequestParam("userId") Long userId);
}
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
@@ -44,9 +44,13 @@
import com.ruoyi.other.api.domain.*;
import com.ruoyi.other.api.domain.TCoupon;
import com.ruoyi.other.api.domain.TVip;
import com.ruoyi.other.api.dto.ExchangeCodeBindDTO;
import com.ruoyi.other.api.dto.ExchangeCodeUseRecordQuery;
import com.ruoyi.other.api.dto.UnitListQueryDto;
import com.ruoyi.other.api.feignClient.IntegralRuleClient;
import com.ruoyi.other.api.feignClient.OtherClient;
import com.ruoyi.other.api.vo.ExchangeCodeBindResultVO;
import com.ruoyi.other.api.domain.TExchangeCodeUseRecord;
import com.ruoyi.other.api.feignClient.VipClient;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.model.LoginUserApplet;
@@ -728,6 +732,45 @@
        
        return R.ok(page);
        
    }
    @ApiOperation(value = "余额明细", tags = {"小程序-个人中心"})
    @PostMapping(value = "/user/balance/page1")
    public R<Page<TExchangeCodeUseRecord>> balanceDetail(@RequestBody ExchangeCodeUseRecordQuery queryDto) {
        if (queryDto.getUserId() == null) {
            queryDto.setUserId(tokenService.getLoginUserApplet().getUserId());
        }
        return otherClient.exchangeCodeUseRecordPage(queryDto);
    }
    @ApiOperation(value = "余额明细详情", tags = {"小程序-个人中心"})
    @GetMapping(value = "/user/balance/detail")
    public R<TExchangeCodeUseRecord> balanceDetail(@RequestParam("id") Long id) {
        Long userId = tokenService.getLoginUserApplet().getUserId();
        return otherClient.exchangeCodeUseRecordDetail(id, userId);
    }
    @ApiOperation(value = "兑换余额", tags = {"小程序-个人中心"})
    @PostMapping(value = "/user/balance/exchange")
    public R<BigDecimal> exchangeBalance(@RequestBody ExchangeCodeBindDTO dto) {
        LoginUserApplet loginUser = tokenService.getLoginUserApplet();
        TAppUser appUser = appUserService.getById(loginUser.getUserId());
        R<ExchangeCodeBindResultVO> bindResult = otherClient.bindExchangeCode(dto, appUser.getId(), appUser.getPhone());
        if (bindResult.getData() == null) {
            return R.fail(bindResult.getMsg());
        }
        Map<Long, BigDecimal> balanceMap = otherClient.getExchangeCodeBalanceMap(Collections.singletonList(appUser.getId())).getData();
        BigDecimal totalExchangeBalance = balanceMap == null ? BigDecimal.ZERO : balanceMap.getOrDefault(appUser.getId(), BigDecimal.ZERO);
        BigDecimal oldBalance = defaultBalance(appUser.getBalance());
        BigDecimal exchangeAmount = totalExchangeBalance.subtract(oldBalance);
        if (exchangeAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return R.fail("兑换金额异常");
        }
        BigDecimal newBalance = oldBalance.add(exchangeAmount);
        appUser.setBalance(newBalance);
        appUserService.updateById(appUser);
        return R.ok(exchangeAmount);
    }
    
    @ApiOperation(value = "积分详情", tags = {"小程序-个人中心"})
@@ -1480,4 +1523,8 @@
        return R.ok();
    }
    
    private BigDecimal defaultBalance(BigDecimal balance) {
        return balance == null ? BigDecimal.ZERO : balance;
    }
}
ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TAppUserMapper.xml
@@ -16,6 +16,7 @@
        <result column="wx_openid" property="wxOpenid" />
        <result column="ali_openid" property="aliOpenid" />
        <result column="points" property="points" />
        <result column="balance" property="balance" />
        <result column="province" property="province" />
        <result column="province_code" property="provinceCode" />
        <result column="city" property="city" />
@@ -29,7 +30,7 @@
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, phone, avatar, vip_id, vip_end_time, company_id, id_card, auth_status, wx_openid, ali_openid, points, province, province_code, city, city_code, status, create_time, del_flag, last_login_time,invite_user_id
        id, name, phone, avatar, vip_id, vip_end_time, company_id, id_card, auth_status, wx_openid, ali_openid, points, balance, province, province_code, city, city_code, status, create_time, del_flag, last_login_time,invite_user_id
    </sql>
</mapper>
ruoyi-service/ruoyi-jianguan/src/main/java/com/ruoyi/jianguan/util/KsolarUtils.java
@@ -225,8 +225,8 @@
    }
    public static void main(String[] args) throws Exception {
        String electricity = getElectricity();
        System.out.println(electricity);
        Double allEnergy = getAllEnergy(LocalDate.now().toString());
        System.out.println(allEnergy);
    }
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TExchangeCodePackageController.java
@@ -15,6 +15,8 @@
import com.ruoyi.other.api.dto.ExchangeCodeBindDTO;
import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
import com.ruoyi.other.api.dto.ExchangeCodePackageSaveDTO;
import com.ruoyi.other.api.dto.ExchangeCodeUseRecordQuery;
import com.ruoyi.other.api.domain.TExchangeCodeUseRecord;
import com.ruoyi.other.api.vo.ExchangeCodeBindResultVO;
import com.ruoyi.other.api.vo.ExchangeCodeConsumeResultVO;
import com.ruoyi.other.api.vo.ExchangeCodePackageDetailVO;
@@ -41,6 +43,7 @@
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@RestController
@RequestMapping("/exchange-code-package")
@@ -184,6 +187,19 @@
        return R.ok(exchangeCodePackageService.consumeBalance(dto));
    }
    @PostMapping("/useRecord/page")
    @ApiOperation(value = "兑换码余额流水分页", tags = {"小程序-兑换码"})
    public R<Page<TExchangeCodeUseRecord>> useRecordPage(@RequestBody ExchangeCodeUseRecordQuery query) {
        return R.ok(exchangeCodePackageService.useRecordPage(query));
    }
    @GetMapping("/useRecord/detail")
    @ApiOperation(value = "兑换码余额流水详情", tags = {"小程序-兑换码"})
    public R<TExchangeCodeUseRecord> useRecordDetail(@RequestParam("id") Long id,
                                                      @RequestParam("userId") Long userId) {
        return R.ok(exchangeCodePackageService.useRecordDetail(id, userId));
    }
    private String buildQrPayload(ExchangeCodeDetailVO detail) {
        return "code=" + detail.getCode() + "&password=" + detail.getPassword();
    }
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TExchangeCodePackageService.java
@@ -6,6 +6,8 @@
import com.ruoyi.other.api.dto.ExchangeCodeBindDTO;
import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
import com.ruoyi.other.api.dto.ExchangeCodePackageSaveDTO;
import com.ruoyi.other.api.dto.ExchangeCodeUseRecordQuery;
import com.ruoyi.other.api.domain.TExchangeCodeUseRecord;
import com.ruoyi.other.api.vo.ExchangeCodeBindResultVO;
import com.ruoyi.other.api.vo.ExchangeCodeConsumeResultVO;
import com.ruoyi.other.api.vo.ExchangeCodePackageDetailVO;
@@ -17,6 +19,7 @@
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
public interface TExchangeCodePackageService extends IService<TExchangeCodePackage> {
@@ -45,4 +48,8 @@
    Map<Long, java.math.BigDecimal> getUserExchangeCodeBalanceMap(List<Long> userIds);
    ExchangeCodeConsumeResultVO consumeBalance(ExchangeCodeConsumeDTO dto);
    Page<TExchangeCodeUseRecord> useRecordPage(ExchangeCodeUseRecordQuery query);
    TExchangeCodeUseRecord useRecordDetail(Long id, Long userId);
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TExchangeCodePackageServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
@@ -13,6 +14,7 @@
import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
import com.ruoyi.other.api.dto.ExchangeCodePackageSaveDTO;
import com.ruoyi.other.api.dto.ExchangeCodePackageSpecDTO;
import com.ruoyi.other.api.dto.ExchangeCodeUseRecordQuery;
import com.ruoyi.other.api.vo.ExchangeCodeBindResultVO;
import com.ruoyi.other.api.vo.ExchangeCodeConsumeResultVO;
import com.ruoyi.other.api.vo.ExchangeCodePackageDetailVO;
@@ -276,6 +278,13 @@
        detail.setBindPhone(bindPhone);
        detail.setBindTime(LocalDateTime.now());
        codeDetailMapper.updateById(detail);
        BigDecimal amount = getDetailRemainAmount(detail);
        TExchangeCodeUseRecord record = new TExchangeCodeUseRecord();
        record.setDetailId(detail.getId());
        record.setOrderId(0L);
        record.setUserId(userId);
        record.setUsedAmount(amount);
        useRecordMapper.insert(record);
        refreshPackageStats(exchangePackage.getId());
        ExchangeCodeBindResultVO resultVO = new ExchangeCodeBindResultVO();
        resultVO.setDetailId(detail.getId());
@@ -283,6 +292,28 @@
        resultVO.setPackageName(exchangePackage.getPackageName());
        resultVO.setBindPhone(bindPhone);
        return resultVO;
    }
    @Override
    public Page<TExchangeCodeUseRecord> useRecordPage(ExchangeCodeUseRecordQuery query) {
        Page<TExchangeCodeUseRecord> page = useRecordMapper.selectPage(Page.of(query.getPageCurr(), query.getPageSize()),
                new QueryWrapper<TExchangeCodeUseRecord>()
                        .eq("user_id", query.getUserId())
                        .eq(Objects.equals(query.getChangeType(), 1), "IFNULL(order_id, 0)", 0)
                        .gt(Objects.equals(query.getChangeType(), 2), "order_id", 0)
                        .orderByDesc("create_time"));
        page.getRecords().forEach(this::fillUseRecordView);
        return page;
    }
    @Override
    public TExchangeCodeUseRecord useRecordDetail(Long id, Long userId) {
        TExchangeCodeUseRecord record = useRecordMapper.selectOne(new QueryWrapper<TExchangeCodeUseRecord>()
                .eq("id", id)
                .eq("user_id", userId)
                .last("limit 1"));
        fillUseRecordView(record);
        return record;
    }
    @Override
@@ -318,6 +349,7 @@
        }
        List<TExchangeCodeUseRecord> existingRecords = useRecordMapper.selectList(new QueryWrapper<TExchangeCodeUseRecord>()
                .eq("order_id", dto.getOrderId())
                .gt("order_id", 0)
                .eq("del_flag", 0));
        if (!existingRecords.isEmpty()) {
            BigDecimal deducted = existingRecords.stream()
@@ -530,6 +562,26 @@
        return UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase();
    }
    private void fillUseRecordView(TExchangeCodeUseRecord record) {
        if (record == null) {
            return;
        }
        record.setUid(String.valueOf(record.getId()));
        record.setDateTime(record.getCreateTime());
        record.setChangeAmount(defaultMoney(record.getUsedAmount()));
        record.setCurrentBalance(defaultMoney(record.getUsedAmount()));
        record.setChangeType(record.getOrderId() == null || record.getOrderId() == 0 ? 1 : 2);
        if (record.getDetailId() != null) {
            TExchangeCodeDetail detail = codeDetailMapper.selectById(record.getDetailId());
            if (detail != null) {
                record.setCode(detail.getCode());
            }
        }
        if (record.getOrderId() != null && record.getOrderId() > 0) {
            record.setOrderCode(String.valueOf(record.getOrderId()));
        }
    }
    private BigDecimal defaultMoney(BigDecimal amount) {
        return amount == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
                : amount.setScale(2, RoundingMode.HALF_UP);
sql/20260427_balance_exchange.sql
New file
@@ -0,0 +1,8 @@
ALTER TABLE `t_app_user`
    ADD COLUMN `balance` decimal(10, 2) NOT NULL DEFAULT 0.00 COMMENT '余额' AFTER `points`;
ALTER TABLE `t_exchange_code_use_record`
    MODIFY COLUMN `order_id` bigint NULL DEFAULT 0 COMMENT '订单ID,0表示兑换入账';
CREATE INDEX `idx_exchange_code_use_record_user_time`
    ON `t_exchange_code_use_record` (`user_id`, `create_time`);