无关风月
2025-04-01 deb91eb570baecdae92aeeb105661209f59e06e2
Merge branch '2.0' of http://120.76.84.145:10101/gitblit/r/java/PlayPai into 2.0
17个文件已修改
5个文件已添加
1130 ■■■■■ 已修改文件
cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminAgreementController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/controller/PayHuiminController.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/entity/HuiminPayQuery.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/entity/THuiminAgreementSetting.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/entity/THuiminCard.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feignclient/account/AppUserClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feignclient/account/StudentClient.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/feignclient/other/OperatorClient.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/mapper/PayHuiminMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/model/response/SalesDetailVO.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/service/PayHuiminService.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/java/com/dsh/activity/service/impl/PayHuiminServiceImpl.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-activity/src/main/resources/mapper/PayHuiminMapper.xml 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/PayHuiminClient.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/model/HuiminPayQuery.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/model/THuiminCard.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TPayHuiminController.java 217 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/SalesDetailVO.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/tHuiminAgreement/tHuiminAgreement.html 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/WEB-INF/view/system/tPayHuimin/tPayHuimin.html 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-management/src/main/webapp/static/modular/system/tPayHuimin/tPayHuimin.js 123 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cloud-server-account/src/main/java/com/dsh/account/controller/AppUserController.java
@@ -1,17 +1,33 @@
package com.dsh.account.controller;
import com.alibaba.nacos.common.utils.Md5Utils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dsh.account.dto.BindDto;
import com.dsh.account.dto.IntroduceUserQuery;
import com.dsh.account.dto.SelectDto;
import com.dsh.account.dto.UpdateInfoDto;
import com.dsh.account.entity.*;
import com.dsh.account.model.*;
import com.dsh.account.entity.IntroduceUser;
import com.dsh.account.entity.TAppGift;
import com.dsh.account.entity.TAppUser;
import com.dsh.account.entity.TCourseInfoRecord;
import com.dsh.account.entity.TStudent;
import com.dsh.account.entity.UserIntegralChanges;
import com.dsh.account.model.AddAppUserVo;
import com.dsh.account.model.AdvertisementChangeStateDTO;
import com.dsh.account.model.AppUserByNameAndPhoneDTO;
import com.dsh.account.model.AppUserIdsByCityName;
import com.dsh.account.model.JoinPlayPaiVo;
import com.dsh.account.model.LoginSMSCodeVo;
import com.dsh.account.model.LoginWeChatVo;
import com.dsh.account.model.QueryByNamePhone;
import com.dsh.account.model.query.appUserQuery.QueryAppUser;
import com.dsh.account.model.vo.QueryAppUserVO;
import com.dsh.account.service.*;
import com.dsh.account.service.IVipPaymentService;
import com.dsh.account.service.TAppGiftService;
import com.dsh.account.service.TAppUserService;
import com.dsh.account.service.TCourseInfoRecordService;
import com.dsh.account.service.TStudentService;
import com.dsh.account.service.UserIntegralChangesService;
import com.dsh.account.util.PayMoneyUtil;
import com.dsh.account.util.ResultUtil;
import com.dsh.account.util.TokenUtil;
@@ -19,15 +35,22 @@
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -503,7 +526,17 @@
            return null;
        }
    }
    /**
     * 根据用户id获取用户信息
     *
     * @param appUserIdList
     * @return
     */
    @ResponseBody
    @PostMapping("/base/appUser/queryAppUserBatch")
    List<TAppUser> queryAppUserBatch(@RequestBody List<Integer> appUserIdList){
        return appUserService.listByIds(appUserIdList);
    }
    @Autowired
    private UserIntegralChangesService userIntegralChangesService;
cloud-server-activity/src/main/java/com/dsh/activity/controller/HuiminAgreementController.java
@@ -34,8 +34,7 @@
    /**
     * 根据当前用户类型查询惠民卡协议
     * @param objectType
     * @param operatorId
     * @param query
     * @return
     */
    @ResponseBody
cloud-server-activity/src/main/java/com/dsh/activity/controller/PayHuiminController.java
New file
@@ -0,0 +1,73 @@
package com.dsh.activity.controller;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsh.activity.entity.HuiminPayQuery;
import com.dsh.activity.model.response.SalesDetailVO;
import com.dsh.activity.service.PayHuiminService;
import com.dsh.activity.util.ResultUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
 * 惠民卡支付记录
 * @author mitao
 * @date 2025/3/31
 */
@RestController
@RequestMapping("")
public class PayHuiminController {
    @Resource
    private PayHuiminService payHuiminService;
    /**
     * 售卖明细分页列表
     * @param query
     * @return
     */
    @PostMapping("/base/huimin-record/list")
    public Page<SalesDetailVO> selectPage(@RequestBody HuiminPayQuery query){
        return payHuiminService.selectPage(query);
    }
    /**
     * 统计数据
     * @param query
     * @return
     */
    @PostMapping("/base/getStaticsData")
    public Map<String, BigDecimal> getStaticsData(@RequestBody HuiminPayQuery query){
        return payHuiminService.getStaticsData(query);
    }
    /**
     * 退款惠民卡
     * @param id
     */
    @GetMapping("/base/tPayHuimin/refund/{id}")
    public ResultUtil<?> refund(@PathVariable("id") Integer id){
        try {
            return payHuiminService.refund(id);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 导出数据
     * @param query
     * @return
     */
    @PostMapping("/base/tPayHuimin/export-data")
    public List<SalesDetailVO> exportData(@RequestBody HuiminPayQuery query){
        return payHuiminService.exportData(query);
    }
}
cloud-server-activity/src/main/java/com/dsh/activity/entity/HuiminPayQuery.java
New file
@@ -0,0 +1,39 @@
package com.dsh.activity.entity;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import java.util.List;
@Data
public class HuiminPayQuery {
    // 基础查询条件
    private String huiMinName;        // 惠民名称
    private String huiMinType;        // 惠民类型
    private Long operatorId;          // 运营商ID
    private Long useId;               // 使用记录ID
    // 用户信息
    private String userName;          // 用户名
    private String phone;             // 联系方式
    // 时间范围
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date paymentTimeStart; // 支付时间-开始
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date paymentTimeEnd; // 支付时间-结束
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTimeStart;     // 结束时间-开始
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTimeEnd;     // 结束时间-结束
    // 状态查询
    private Integer status;     // 使用状态
    //购买用户
    private List<Integer> appUserIds;
    private long current;
    private long size;
}
cloud-server-activity/src/main/java/com/dsh/activity/entity/THuiminAgreementSetting.java
@@ -33,8 +33,6 @@
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @TableField("agreementId")
    private Integer agreementId;
    /**
     * 协议名称
     */
cloud-server-activity/src/main/java/com/dsh/activity/entity/THuiminCard.java
@@ -164,6 +164,12 @@
    @TableField("storeId")
    private Integer storeId;
    /**
     *运营商id
     */
    @ApiModelProperty(value = "运营商id")
    @TableField("operatorId")
    private Integer operatorId;
    /**
     *状态 1已上架 2已下架 3已删除
     */
    @ApiModelProperty(value = "状态 1已上架 2已下架 3已删除 ")
cloud-server-activity/src/main/java/com/dsh/activity/feignclient/account/AppUserClient.java
@@ -6,7 +6,6 @@
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@@ -32,4 +31,13 @@
     */
    @PostMapping("/base/appUser/queryAppUserList")
    public List<TAppUser> queryAppUserList(@RequestBody AppUserByNameAndPhoneDTO dto);
    /**
     * 根据用户id获取用户信息
     *
     * @param appUserIdList
     * @return
     */
    @PostMapping("/base/appUser/queryAppUserBatch")
    List<AppUser> queryAppUserBatch(@RequestBody List<Integer> appUserIdList);
}
cloud-server-activity/src/main/java/com/dsh/activity/feignclient/account/StudentClient.java
@@ -1,12 +1,10 @@
package com.dsh.activity.feignclient.account;
import com.dsh.activity.entity.TStudent;
import com.dsh.activity.feignclient.account.model.Student;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
cloud-server-activity/src/main/java/com/dsh/activity/feignclient/other/OperatorClient.java
@@ -1,10 +1,9 @@
package com.dsh.activity.feignclient.other;
import com.dsh.activity.feignclient.other.model.Store;
import com.dsh.activity.feignclient.other.model.StoreDetailOfCourse;
import com.dsh.activity.feignclient.other.model.TOperatorCity;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
cloud-server-activity/src/main/java/com/dsh/activity/mapper/PayHuiminMapper.java
@@ -1,17 +1,39 @@
package com.dsh.activity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsh.activity.entity.THuiminCard;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsh.activity.entity.HuiminPayQuery;
import com.dsh.activity.entity.TPayHuimin;
import com.dsh.activity.model.response.HuiminCardVO;
import com.dsh.activity.model.response.SalesDetailVO;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
 * @author zhibing.pu
 * @date 2023/7/11 17:30
 */
public interface PayHuiminMapper extends BaseMapper<TPayHuimin> {
    /**
     * 售卖明细分页列表
     * @param query
     * @return
     */
    Page<SalesDetailVO> selectSalesDetailPage(Page<SalesDetailVO> page,@Param("query") HuiminPayQuery query);
    /**
     * 获取售卖明细统计数据
     * @param query
     * @return
     */
    Map<String, BigDecimal> getStaticsData(@Param("query") HuiminPayQuery query);
    /**
     * 导出数据
     * @param query
     * @return
     */
    List<SalesDetailVO> exportData(@Param("query") HuiminPayQuery query);
}
cloud-server-activity/src/main/java/com/dsh/activity/model/response/SalesDetailVO.java
New file
@@ -0,0 +1,37 @@
package com.dsh.activity.model.response;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class SalesDetailVO {
    // 基础信息
    private Long id;                    // 主键ID[8]
    private String huiMinName;          // 惠民卡名称
    private Integer huiMinType;          // 惠民卡类型(1:年度卡,2:年内卡)
    private BigDecimal salesMoney;      // 售卖金额(精确计算)
    // 关联信息
    private Integer operatorId;
    private String operatorName;        // 所属运营商
    private Integer storeId;
    private String storeName;           // 可用门店
    private Integer appUserId;           // 购买用户ID
    private String userName;            // 购买用户
    private String phone;               // 联系电话
    // 时间信息
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date paymentTime;  // 购买时间[1,8](@ref)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;      // 有效期
    // 使用信息
    private String studentName;         // 绑定人员
    private String studentId;          // 绑定人员ID
    private Integer useTimes;           // 已用次数
    private Integer status;             // 状态(1:使用中,2:已退款)
}
cloud-server-activity/src/main/java/com/dsh/activity/service/PayHuiminService.java
@@ -1,11 +1,16 @@
package com.dsh.activity.service;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsh.activity.entity.THuiminCard;
import com.dsh.activity.entity.HuiminPayQuery;
import com.dsh.activity.entity.TPayHuimin;
import com.dsh.activity.model.response.HuiminCardVO;
import com.dsh.activity.model.response.SalesDetailVO;
import com.dsh.activity.util.ResultUtil;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
 * <p>
@@ -16,5 +21,30 @@
 * @since 2023-07-06
 */
public interface PayHuiminService extends IService<TPayHuimin> {
    /**
     * 售卖明细分页列表
     * @param query
     * @return
     */
    Page<SalesDetailVO> selectPage(HuiminPayQuery query);
    /**
     * 获取统计数据
     * @param query
     * @return
     */
    Map<String, BigDecimal> getStaticsData(HuiminPayQuery query);
    /**
     * 退款惠民卡
     * @param id
     */
    ResultUtil<?> refund(Integer id) throws AlipayApiException;
    /**
     * 获取导出数据
     * @param query
     * @return
     */
    List<SalesDetailVO> exportData(HuiminPayQuery query);
}
cloud-server-activity/src/main/java/com/dsh/activity/service/impl/PayHuiminServiceImpl.java
@@ -1,13 +1,33 @@
package com.dsh.activity.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsh.activity.entity.THuiminAgreement;
import com.dsh.activity.entity.HuiminPayQuery;
import com.dsh.activity.entity.THuiminRecord;
import com.dsh.activity.entity.TPayHuimin;
import com.dsh.activity.mapper.HuiminAgreementMapper;
import com.dsh.activity.entity.TStudent;
import com.dsh.activity.feignclient.account.AppUserClient;
import com.dsh.activity.feignclient.account.StudentClient;
import com.dsh.activity.feignclient.account.model.AppUser;
import com.dsh.activity.mapper.PayHuiminMapper;
import com.dsh.activity.service.HuiminAgreementService;
import com.dsh.activity.model.response.SalesDetailVO;
import com.dsh.activity.service.HuiminRecordService;
import com.dsh.activity.service.PayHuiminService;
import com.dsh.activity.util.DateUtil;
import com.dsh.activity.util.PayMoneyUtil;
import com.dsh.activity.util.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * @author zhibing.pu
@@ -15,5 +35,87 @@
 */
@Service
public class PayHuiminServiceImpl extends ServiceImpl<PayHuiminMapper, TPayHuimin> implements PayHuiminService {
    @Autowired
    private AppUserClient appUserClient;
    @Autowired
    private StudentClient studentClient;
    @Autowired
    private HuiminRecordService huiminRecordService;
    @Resource
    private PayMoneyUtil payMoneyUtil;
    @Override
    public Page<SalesDetailVO> selectPage(HuiminPayQuery query) {
        Page<SalesDetailVO> salesDetailVOPage = baseMapper.selectSalesDetailPage(new Page<>(query.getCurrent(), query.getSize()), query);
        List<SalesDetailVO> records = salesDetailVOPage.getRecords();
        if (CollUtil.isNotEmpty(records)){
            List<Integer> appUserIdList = records.stream().map(SalesDetailVO::getAppUserId).collect(Collectors.toList());
            List<AppUser> appUserList = appUserClient.queryAppUserBatch(appUserIdList);
            Map<Integer, AppUser> appUserMap = appUserList.stream().collect(Collectors.toMap(AppUser::getId, appUser -> appUser));
            records.forEach(item->{
                AppUser appUser = appUserMap.get(item.getAppUserId());
                if (Objects.nonNull(appUser)){
                    item.setUserName(appUser.getName());
                    item.setPhone(appUser.getPhone());
                }
                List<TStudent> studentList = studentClient.getStudentByIds(item.getStudentId());
                if (CollUtil.isNotEmpty(studentList)){
                    item.setStudentName(studentList.stream().map(TStudent::getName).collect(Collectors.joining(",")));
                }
            });
        }
        return salesDetailVOPage;
    }
    @Override
    public Map<String, BigDecimal> getStaticsData(HuiminPayQuery query) {
        return baseMapper.getStaticsData(query);
    }
    @Override
    public ResultUtil<?> refund(Integer id) throws AlipayApiException {
        TPayHuimin payHuimin = this.getById(id);
        if (Objects.nonNull(payHuimin)) {
            Integer count = huiminRecordService.lambdaQuery().eq(THuiminRecord::getAppUserId, payHuimin.getAppUserId())
                    .eq(THuiminRecord::getHuiminCardId, payHuimin.getCardId())
                    .lt(THuiminRecord::getInsertTime, DateUtil.addDay(payHuimin.getPaymentTime(),7))
                    .count();
            if (count > 0 || new Date().after(DateUtil.addDay(payHuimin.getPaymentTime(),7))) {
                //超过七日或者七日内有使用记录的退款:更改状态,实际退款线下操作。
                payHuimin.setRefundStatus(3);
            } else {
                if (payHuimin.getPaymentType() == 1) {
                    Map<String, String> map = payMoneyUtil.wxRefund(payHuimin.getOrderNumber(), payHuimin.getCode(),
                            payHuimin.getSalesMoney().toString(), payHuimin.getSalesMoney().toString(), "/base/worldCup/wxRefundWorldCupCallback");
                    if (!"SUCCESS".equals(map.get("return_code"))) {
                        System.err.println("-------------微信退款失败---------");
                        System.err.println(map.get("return_msg"));
                        return ResultUtil.error("微信退款失败");
                    }
                } else {
                    Map<String, String> map = payMoneyUtil.aliRefund(payHuimin.getOrderNumber(), payHuimin.getSalesMoney().toString());
                    String return_code = map.get("code");
                    if (!"10000".equals(return_code)) {
                        return ResultUtil.error(map.get("msg"));
                    }
                    String refund_id = map.get("trade_no");
                    payHuimin.setRefundNumber(refund_id);
                }
                payHuimin.setRefundStatus(2);
            }
            payHuimin.setStatus(3);
            payHuimin.setRefundTime(new Date());
            this.updateById(payHuimin);
        }
        return ResultUtil.success();
    }
    /**
     * 导出数据
     * @param query
     * @return
     */
    @Override
    public List<SalesDetailVO> exportData(HuiminPayQuery query) {
        return baseMapper.exportData(query);
    }
}
cloud-server-activity/src/main/resources/mapper/PayHuiminMapper.xml
@@ -3,5 +3,180 @@
<mapper namespace="com.dsh.activity.mapper.PayHuiminMapper">
    <select id="selectSalesDetailPage" resultType="com.dsh.activity.model.response.SalesDetailVO">
        SELECT
        tph.id,
        thc.huiMinName,
        thc.huiMinType,
        thc.salesMoney,
        thc.operatorId,
        thc.storeId,
        tph.appUserId,
        tph.paymentTime,
        thc.endTime,
        tph.studentId,
        tph.status,
        CASE
        WHEN tph.id IS NULL THEN NULL
        ELSE COALESCE(COUNT(thr.id), 0)
        END AS useTimes
        FROM
        t_pay_huimin tph
        LEFT JOIN t_huimin_card thc ON tph.cardId = thc.id
        LEFT JOIN t_huimin_record thr ON tph.appUserId= thr.appUserId AND tph.cardId= thr.huiminCardId
        <where>
            tph.id IS NOT NULL
            <if test="query.huiMinName !=null and query.huiMinName != ''">
                AND thc.huiMinName LIKE CONCAT('%',#{query.huiMinName},'%')
            </if>
            <if test="query.huiMinType !=null and query.huiMinType != ''">
                AND thc.huiMinType = #{query.huiMinType}
            </if>
            <if test="query.operatorId !=null and query.operatorId != ''">
                AND thc.huiMinType = #{query.huiMinType}
            </if>
            <if test="query.useId !=null and query.useId != ''">
                AND FIND_IN_SET(#{query.useId},thc.useIds)
            </if>
            <if test="query.useId !=null and query.useId != ''">
                AND FIND_IN_SET(#{query.useId},thc.useIds)
            </if>
            <if test="query.appUserIds != null and query.appUserIds.size()>0">
                AND tph.appUserId IN
                <foreach collection="query.appUserIds" item="appUserId" open="(" separator="," close=")">
                    #{appUserId}
                </foreach>
            </if>
            <if test="query.paymentTimeStart != null and query.paymentTimeEnd!=null">
                AND tph.paymentTime BETWEEN #{query.paymentTimeStart} AND #{query.paymentTimeEnd}
            </if>
            <if test="query.endTimeStart != null and query.endTimeEnd!=null">
                AND tph.endTime BETWEEN #{query.endTimeStart} AND #{query.endTimeEnd}
            </if>
            <if test="query.status!=null and query.status !=''">
                <choose>
                    <when test="query.status == 1">
                        AND tph.status = 2
                    </when>
                    <when test="query.status == 2">
                        AND tph.status = 3
                    </when>
                </choose>
            </if>
        </where>
        ORDER BY tph.insertTime DESC
    </select>
    <select id="getStaticsData" resultType="java.util.Map"
            parameterType="com.dsh.activity.entity.HuiminPayQuery">
        SELECT
        COALESCE(SUM( tph.salesMoney),0) AS totalAmount,
        COALESCE(SUM(CASE WHEN refundStatus IN (2, 3) THEN tph.salesMoney ELSE 0 END),0) AS refundAmount
        FROM t_pay_huimin tph
        LEFT JOIN t_huimin_card thc ON tph.cardId = thc.id
        <where>
            tph.id IS NOT NULL
            <if test="query.huiMinName !=null and query.huiMinName != ''">
                AND thc.huiMinName LIKE CONCAT('%',#{query.huiMinName},'%')
            </if>
            <if test="query.huiMinType !=null and query.huiMinType != ''">
                AND thc.huiMinType = #{query.huiMinType}
            </if>
            <if test="query.operatorId !=null and query.operatorId != ''">
                AND thc.huiMinType = #{query.huiMinType}
            </if>
            <if test="query.useId !=null and query.useId != ''">
                AND FIND_IN_SET(#{query.useId},thc.useIds)
            </if>
            <if test="query.useId !=null and query.useId != ''">
                AND FIND_IN_SET(#{query.useId},thc.useIds)
            </if>
            <if test="query.appUserIds != null and query.appUserIds.size()>0">
                AND tph.appUserId IN
                <foreach collection="query.appUserIds" item="appUserId" open="(" separator="," close=")">
                    #{appUserId}
                </foreach>
            </if>
            <if test="query.paymentTimeStart != null and query.paymentTimeEnd!=null">
                AND tph.paymentTime BETWEEN #{query.paymentTimeStart} AND #{query.paymentTimeEnd}
            </if>
            <if test="query.endTimeStart != null and query.endTimeEnd!=null">
                AND tph.endTime BETWEEN #{query.endTimeStart} AND #{query.endTimeEnd}
            </if>
            <if test="query.status!=null and query.status !=''">
                <choose>
                    <when test="query.status == 1">
                        AND tph.status = 2
                    </when>
                    <when test="query.status == 2">
                        AND tph.status = 3
                    </when>
                </choose>
            </if>
        </where>
    </select>
    <select id="exportData" resultType="com.dsh.activity.model.response.SalesDetailVO"
            parameterType="com.dsh.activity.entity.HuiminPayQuery">
        SELECT
        tph.id,
        thc.huiMinName,
        thc.huiMinType,
        thc.salesMoney,
        thc.operatorId,
        thc.storeId,
        tph.appUserId,
        tph.paymentTime,
        thc.endTime,
        tph.studentId,
        tph.status,
        CASE
        WHEN tph.id IS NULL THEN NULL
        ELSE COALESCE(COUNT(thr.id), 0)
        END AS useTimes
        FROM
        t_pay_huimin tph
        LEFT JOIN t_huimin_card thc ON tph.cardId = thc.id
        LEFT JOIN t_huimin_record thr ON tph.appUserId= thr.appUserId AND tph.cardId= thr.huiminCardId
        <where>
             tph.id IS NOT NULL
            <if test="query.huiMinName !=null and query.huiMinName != ''">
                AND thc.huiMinName LIKE CONCAT('%',#{query.huiMinName},'%')
            </if>
            <if test="query.huiMinType !=null and query.huiMinType != ''">
                AND thc.huiMinType = #{query.huiMinType}
            </if>
            <if test="query.operatorId !=null and query.operatorId != ''">
                AND thc.huiMinType = #{query.huiMinType}
            </if>
            <if test="query.useId !=null and query.useId != ''">
                AND FIND_IN_SET(#{query.useId},thc.useIds)
            </if>
            <if test="query.useId !=null and query.useId != ''">
                AND FIND_IN_SET(#{query.useId},thc.useIds)
            </if>
            <if test="query.appUserIds != null and query.appUserIds.size()>0">
                AND tph.appUserId IN
                <foreach collection="query.appUserIds" item="appUserId" open="(" separator="," close=")">
                    #{appUserId}
                </foreach>
            </if>
            <if test="query.paymentTimeStart != null and query.paymentTimeEnd!=null">
                AND tph.paymentTime BETWEEN #{query.paymentTimeStart} AND #{query.paymentTimeEnd}
            </if>
            <if test="query.endTimeStart != null and query.endTimeEnd!=null">
                AND tph.endTime BETWEEN #{query.endTimeStart} AND #{query.endTimeEnd}
            </if>
            <if test="query.status!=null and query.status !=''">
                <choose>
                    <when test="query.status == 1">
                        AND tph.status = 2
                    </when>
                    <when test="query.status == 2">
                        AND tph.status = 3
                    </when>
                </choose>
            </if>
        </where>
        ORDER BY tph.insertTime DESC
    </select>
</mapper>
cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/PayHuiminClient.java
@@ -1,6 +1,17 @@
package com.dsh.course.feignClient.activity;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsh.course.feignClient.activity.model.HuiminPayQuery;
import com.dsh.guns.modular.system.model.SalesDetailVO;
import com.dsh.guns.modular.system.util.ResultUtil;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
 * @author mitao
@@ -8,4 +19,29 @@
 */
@FeignClient(value = "mb-cloud-activity")
public interface PayHuiminClient {
    /**
     * 获取售卖明细
     * @param query
     * @return
     */
    @PostMapping("/base/huimin-record/list")
    Page<SalesDetailVO> selectPage(@RequestBody HuiminPayQuery query);
    /**
     * 获取售卖明细统计数据
     * @param query
     * @return
     */
    @PostMapping("/base/getStaticsData")
    Map<String, BigDecimal> getStaticsData(@RequestBody HuiminPayQuery query);
    /**
     * 退款惠民卡
     * @param id
     */
    @GetMapping("/base/tPayHuimin/refund/{id}")
    ResultUtil<?> refund(Integer id);
    @PostMapping("/base/tPayHuimin/export-data")
    List<SalesDetailVO> exportData(@RequestBody HuiminPayQuery query);
}
cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/model/HuiminPayQuery.java
New file
@@ -0,0 +1,40 @@
package com.dsh.course.feignClient.activity.model;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import java.util.List;
@Data
public class HuiminPayQuery {
    // 基础查询条件
    private String huiMinName;        // 惠民名称
    private String huiMinType;        // 惠民类型
    private Long operatorId;          // 运营商ID
    private Long useId;               // 使用记录ID
    // 用户信息
    private String userName;          // 用户名
    private String phone;             // 联系方式
    // 时间范围
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date paymentTimeStart; // 支付时间-开始
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date paymentTimeEnd; // 支付时间-结束
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTimeStart;     // 结束时间-开始
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTimeEnd;     // 结束时间-结束
    // 状态查询
    private Integer status;     // 使用状态
    //购买用户
    private List<Integer> appUserIds;
    private long current;
    private long size;
}
cloud-server-management/src/main/java/com/dsh/course/feignClient/activity/model/THuiminCard.java
@@ -129,6 +129,11 @@
     */
    @TableField("storeId")
    private Integer storeId;
    /**
     *运营商id
     */
    @TableField("operatorId")
    private Integer operatorId;
    @Override
cloud-server-management/src/main/java/com/dsh/guns/modular/system/controller/code/TPayHuiminController.java
@@ -1,10 +1,44 @@
package com.dsh.guns.modular.system.controller.code;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dsh.course.feignClient.account.AppUserClient;
import com.dsh.course.feignClient.account.model.TAppUser;
import com.dsh.course.feignClient.activity.PayHuiminClient;
import com.dsh.course.feignClient.activity.model.HuiminPayQuery;
import com.dsh.course.feignClient.activity.model.TPayHuimin;
import com.dsh.guns.core.base.controller.BaseController;
import com.dsh.guns.core.common.constant.factory.PageFactory;
import com.dsh.guns.modular.system.model.AppUserByNameAndPhoneDTO;
import com.dsh.guns.modular.system.model.SalesDetailVO;
import com.dsh.guns.modular.system.model.TOperator;
import com.dsh.guns.modular.system.model.TStore;
import com.dsh.guns.modular.system.service.IStoreService;
import com.dsh.guns.modular.system.service.TOperatorService;
import com.dsh.guns.modular.system.util.DateUtil;
import com.dsh.guns.modular.system.util.ExcelUtil;
import com.dsh.guns.modular.system.util.ResultUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * 惠民卡控制器
@@ -20,12 +54,22 @@
    @Autowired
    private PayHuiminClient payHuiminClient;
    @Autowired
    private TOperatorService operatorService;
    @Autowired
    private IStoreService storeService;
    @Autowired
    private AppUserClient appUserClient;
    /**
     * 跳转到惠民卡首页
     */
    @RequestMapping("")
    public String index() {
    public String index(Model model) {
        //查询运营商列表
        model.addAttribute("operatorList", operatorService.list(new QueryWrapper<TOperator>().eq("state", 1)));
        model.addAttribute("storeList", storeService.list(new QueryWrapper<TStore>().eq("state", 1)));
        return PREFIX + "tPayHuimin.html";
    }
@@ -37,62 +81,141 @@
        return PREFIX + "tPayHuimin_add.html";
    }
  /*  *//**
     * 跳转到修改惠民卡
     *//*
    @RequestMapping("/tPayHuimin_update/{tPayHuiminId}")
    public String tPayHuiminUpdate(@PathVariable Integer tPayHuiminId, Model model) {
        TPayHuimin tPayHuimin = payHuiminClient.selectById(tPayHuiminId);
        model.addAttribute("item",tPayHuimin);
        LogObjectHolder.me().set(tPayHuimin);
        return PREFIX + "tPayHuimin_edit.html";
    }
    *//**
    /**
     * 获取惠民卡列表
     *//*
     */
    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(String condition) {
        return payHuiminClient.selectList(null);
    public Object list(HuiminPayQuery query) {
        Page<TPayHuimin> tPayHuiminPage = new PageFactory<TPayHuimin>().defaultPage();
        query.setCurrent(tPayHuiminPage.getCurrent());
        query.setSize(tPayHuiminPage.getSize());
        List<Integer> appUserIds = Collections.emptyList();
        if (StringUtils.isNotBlank(query.getUserName()) || StringUtils.isNotBlank(query.getPhone())){
            AppUserByNameAndPhoneDTO appUserByNameAndPhoneDTO = new AppUserByNameAndPhoneDTO();
            appUserByNameAndPhoneDTO.setUserName(query.getUserName());
            appUserByNameAndPhoneDTO.setPhone(query.getPhone());
            List<TAppUser> tAppUsers = appUserClient.queryAPPUserByNameAndPhone(appUserByNameAndPhoneDTO);
            appUserIds = tAppUsers.stream()
                    .map(TAppUser::getId)
                    .collect(Collectors.toList());
            if (CollUtil.isEmpty(appUserIds)){
                return new Page<>();
            }
        }
        query.setAppUserIds(appUserIds);
        Page<SalesDetailVO> salesDetailVOPage = payHuiminClient.selectPage(query);
        List<SalesDetailVO> records = salesDetailVOPage.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Integer> operatorIdList = records.stream()
                    .map(SalesDetailVO::getOperatorId)
                    .collect(Collectors.toList());
            List<Integer> storeIdList = records.stream()
                    .map(SalesDetailVO::getStoreId)
                    .collect(Collectors.toList());
            Map<Integer, String> operatorMap = operatorService.listByIds(operatorIdList).stream()
                    .collect(Collectors.toMap(TOperator::getId, TOperator::getName));
            Map<Integer, String> storeMap = storeService.listByIds(storeIdList).stream()
                    .collect(Collectors.toMap(TStore::getId, TStore::getName));
            records.forEach(item->{
                item.setOperatorName(operatorMap.getOrDefault(item.getOperatorId(),""));
                item.setStoreName(storeMap.getOrDefault(item.getStoreId(),""));
            });
        }
        return super.packForBT(salesDetailVOPage);
    }
    *//**
     * 新增惠民卡
     *//*
    @RequestMapping(value = "/add")
    /**
     * 获取统计数据
     * @param query
     * @return
     */
    @RequestMapping("/getStaticsData")
    @ResponseBody
    public Object add(TPayHuimin tPayHuimin) {
        payHuiminClient.insert(tPayHuimin);
        return SUCCESS_TIP;
    public ResultUtil<Map<String, BigDecimal>> getStaticsData(HuiminPayQuery query) {
        Map<String, BigDecimal> map = new HashMap<>();
        map.put("totalAmount",BigDecimal.ZERO);
        map.put("refundAmount",BigDecimal.ZERO);
        List<Integer> appUserIds = Collections.emptyList();
        if (StringUtils.isNotBlank(query.getUserName()) || StringUtils.isNotBlank(query.getPhone())){
            AppUserByNameAndPhoneDTO appUserByNameAndPhoneDTO = new AppUserByNameAndPhoneDTO();
            appUserByNameAndPhoneDTO.setUserName(query.getUserName());
            appUserByNameAndPhoneDTO.setPhone(query.getPhone());
            List<TAppUser> tAppUsers = appUserClient.queryAPPUserByNameAndPhone(appUserByNameAndPhoneDTO);
            appUserIds = tAppUsers.stream()
                    .map(TAppUser::getId)
                    .collect(Collectors.toList());
            if (CollUtil.isEmpty(appUserIds)){
                return ResultUtil.success(map);
            }
        }
        query.setAppUserIds(appUserIds);
        map =  payHuiminClient.getStaticsData(query);
        return ResultUtil.success(map);
    }
    *//**
     * 删除惠民卡
     *//*
    @RequestMapping(value = "/delete")
    /**
     * 退款
     * @param id
     * @return
     */
    @GetMapping("/refund/{id}")
    @ResponseBody
    public Object delete(@RequestParam Integer tPayHuiminId) {
        payHuiminClient.deleteById(tPayHuiminId);
        return SUCCESS_TIP;
    public ResultUtil<?> refund(@PathVariable("id") Integer id) {
        return payHuiminClient.refund(id);
    }
    *//**
     * 修改惠民卡
     *//*
    @RequestMapping(value = "/update")
    @ResponseBody
    public Object update(TPayHuimin tPayHuimin) {
        payHuiminClient.updateById(tPayHuimin);
        return SUCCESS_TIP;
    /**
     * 导出售卖明细
     * @param query
     */
    @GetMapping("/export")
    public void exportData(HuiminPayQuery query, HttpServletResponse response) {
        List<SalesDetailVO> records = payHuiminClient.exportData(query);
        records = records.stream().filter(Objects::nonNull).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(records)) {
            List<Integer> operatorIdList = records.stream()
                    .map(SalesDetailVO::getOperatorId)
                    .collect(Collectors.toList());
            List<Integer> storeIdList = records.stream()
                    .map(SalesDetailVO::getStoreId)
                    .collect(Collectors.toList());
            Map<Integer, String> operatorMap = operatorService.listByIds(operatorIdList).stream()
                    .collect(Collectors.toMap(TOperator::getId, TOperator::getName));
            Map<Integer, String> storeMap = storeService.listByIds(storeIdList).stream()
                    .collect(Collectors.toMap(TStore::getId, TStore::getName));
            records.forEach(item -> {
                item.setOperatorName(operatorMap.getOrDefault(item.getOperatorId(), ""));
                item.setStoreName(storeMap.getOrDefault(item.getStoreId(), ""));
            });
        }
        String[] titleArr = {"惠民卡名称", "惠民卡类型", "售卖金额", "所属运营商", "可用门店", "购买用户", "联系电话", "购买时间", "绑定人员", "已用次数", "有效期", "状态"};
        String[][] values = new String[records.size()][];
        for (int i = 0; i < records.size(); i++) {
            SalesDetailVO salesDetailVO = records.get(i);
            values[i] = new String[titleArr.length];
            values[i][0] = salesDetailVO.getHuiMinName();
            values[i][1] = salesDetailVO.getHuiMinType() == 1 ? "年度卡" : "年内卡";
            values[i][2] = salesDetailVO.getSalesMoney().toString();
            values[i][3] = salesDetailVO.getOperatorName();
            values[i][4] = salesDetailVO.getStoreName();
            values[i][5] = salesDetailVO.getUserName();
            values[i][6] = salesDetailVO.getPhone();
            values[i][7] = DateUtil.format(salesDetailVO.getPaymentTime(), "yyyy-MM-dd HH:mm:ss");
            values[i][8] = salesDetailVO.getStudentName();
            values[i][9] = salesDetailVO.getUseTimes().toString();
            values[i][10] = DateUtil.format(salesDetailVO.getEndTime(), "yyyy-MM-dd HH:mm:ss");
            values[i][11] = salesDetailVO.getStatus() == 2 ? "使用中" : "已退款";
        }
        try {
            HSSFWorkbook wb = ExcelUtil.getHSSFWorkbook("售卖明细", titleArr, values, null);
            ExcelUtil.setResponseHeader(response, "售卖明细.xls");
            OutputStream os = response.getOutputStream();
            wb.write(os);
            os.flush();
            os.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    *//**
     * 惠民卡详情
     *//*
    @RequestMapping(value = "/detail/{tPayHuiminId}")
    @ResponseBody
    public Object detail(@PathVariable("tPayHuiminId") Integer tPayHuiminId) {
        return payHuiminClient.selectById(tPayHuiminId);
    }*/
}
cloud-server-management/src/main/java/com/dsh/guns/modular/system/model/SalesDetailVO.java
New file
@@ -0,0 +1,37 @@
package com.dsh.guns.modular.system.model;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class SalesDetailVO {
    // 基础信息
    private Long id;                    // 主键ID[8]
    private String huiMinName;          // 惠民卡名称
    private Integer huiMinType;          // 惠民卡类型(1:年度卡,2:年内卡)
    private BigDecimal salesMoney;      // 售卖金额(精确计算)
    // 关联信息
    private Integer operatorId;
    private String operatorName;        // 所属运营商
    private Integer storeId;
    private String storeName;           // 可用门店
    private Integer appUserId;           // 购买用户ID
    private String userName;            // 购买用户
    private String phone;               // 联系电话
    // 时间信息
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date paymentTime;  // 购买时间[1,8](@ref)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;      // 有效期
    // 使用信息
    private String studentName;         // 绑定人员
    private String studentId;          // 绑定人员ID
    private Integer useTimes;           // 已用次数
    private Integer status;             // 状态(1:使用中,2:已退款)
}
cloud-server-management/src/main/webapp/WEB-INF/view/system/tHuiminAgreement/tHuiminAgreement.html
@@ -27,6 +27,7 @@
                                <#button name="删除" icon="fa-remove" clickFun="THuiminAgreement.delete()" space="true"/>
                            @}
                        </div>
                        <#table id="THuiminAgreementTable"/>
                    </div>
                </div>
cloud-server-management/src/main/webapp/WEB-INF/view/system/tPayHuimin/tPayHuimin.html
@@ -3,36 +3,114 @@
    <div class="col-sm-12">
        <div class="ibox float-e-margins">
            <div class="ibox-title">
                <h5>惠民卡管理</h5>
                <h5>售卖明细</h5>
            </div>
            <div class="ibox-content">
                <div class="row row-lg">
                    <div class="col-sm-12">
                        <div class="row">
                            <div class="col-sm-3">
                                <#NameCon id="condition" name="名称" />
                            <div class="form-group">
                                <div class="col-sm-3">
                                    <#NameCon id="huiMinName" name="惠民卡名称:" />
                                </div>
                                <div class="col-sm-3">
                                    <#SelectCon id="huiMinType" name="惠民卡类型:">
                                        <option value="">全部</option>
                                        <option value="1">年度卡</option>
                                        <option value="2">年内卡</option>
                                    </#SelectCon>
                                </div>
                                <div class="col-sm-3">
                                    <#SelectCon id="operatorId" name="所属运营商:">
                                        <option value="">全部</option>
                                        @if(isNotEmpty(operatorList)){
                                            @for(item in operatorList){
                                                <option value="${item.id}">${item.name}</option>
                                            @}
                                        @}
                                    </#SelectCon>
                                </div>
                                <div class="col-sm-3">
                                    <#SelectCon id="useId" name="可用门店:">
                                        <option value="">全部</option>
                                        @if(isNotEmpty(storeList)){
                                        @for(item in storeList){
                                        <option value="${item.id}">${item.name}</option>
                                        @}
                                        @}
                                    </#SelectCon>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="col-sm-3">
                                    <#NameCon id="userName" name="购买用户:" />
                                </div>
                                <div class="col-sm-3">
                                    <#NameCon id="phone" name="联系电话:" />
                                </div>
                                <div class="col-sm-3">
                                    <#TimeCon id="paymentTimeStr" name="购买时间:" />
                                </div>
                                <div class="col-sm-3">
                                    <#TimeCon id="endTimeStr" name="有效期至:" />
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="col-sm-3">
                                    <#SelectCon id="status" name="使用状态:">
                                        <option value="">全部</option>
                                        <option value="1">使用中</option>
                                        <option value="2">已退款</option>
                                    </#SelectCon>
                                </div>
                            <div class="col-sm-3">
                                <#button name="搜索" icon="fa-search" clickFun="TPayHuimin.search()"/>
                                <#button name="重置" icon="fa-search" clickFun="TPayHuimin.resetSearch()"/>
                            </div>
                            </div>
                        </div>
                        <div class="hidden-xs" id="TPayHuiminTableToolbar" role="group">
                            @if(shiro.hasPermission("/tPayHuimin/add")){
                                <#button name="添加" icon="fa-plus" clickFun="TPayHuimin.openAddTPayHuimin()"/>
                            @if(shiro.hasPermission("/tPayHuimin/refund")){
                                <#button name="退款" icon="fa-plus" clickFun="TPayHuimin.refund()"/>
                            @}
                            @if(shiro.hasPermission("/tPayHuimin/update")){
                                <#button name="修改" icon="fa-edit" clickFun="TPayHuimin.openTPayHuiminDetail()" space="true"/>
                            @if(shiro.hasPermission("/tPayHuimin/export")){
                                <#button name="导出" icon="fa-edit" clickFun="TPayHuimin.export()" space="true"/>
                            @}
                            @if(shiro.hasPermission("/tPayHuimin/delete")){
                                <#button name="删除" icon="fa-remove" clickFun="TPayHuimin.delete()" space="true"/>
                            @}
                            <div class="form-group">
                                <label> 售卖总金额:¥</label>
                                <label id="totalAmount">0</label>&emsp;&emsp;
                                <label>已退款金额:¥</label>
                                <label id="refundAmount">0</label>
                            </div>
                        </div>
                        <#table id="TPayHuiminTable"/>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="${ctxPath}/static/modular/system/tPayHuimin/tPayHuimin.js"></script>
<script src="${ctxPath}/modular/system/tPayHuimin/tPayHuimin.js"></script>
<script>
    //日期范围选择
    laydate.render({
        elem: '#paymentTimeStr',
        type: 'date'
        ,range: '~' //或 range: '~' 来自定义分割字符
        ,trigger:'click'
    });
    //日期范围选择
    laydate.render({
        elem: '#endTimeStr',
        type: 'date'
        ,range: '~' //或 range: '~' 来自定义分割字符
        ,trigger:'click'
    });
    $(function () {
    });
</script>
@}
cloud-server-management/src/main/webapp/static/modular/system/tPayHuimin/tPayHuimin.js
@@ -14,20 +14,25 @@
TPayHuimin.initColumn = function () {
    return [
        {field: 'selectItem', radio: true},
            {title: '主键id', field: 'id', visible: true, align: 'center', valign: 'middle'},
            {title: '金额', field: 'salesMoney', visible: true, align: 'center', valign: 'middle'},
            {title: '购买用户id', field: 'appUserId', visible: true, align: 'center', valign: 'middle'},
            {title: '绑定人员id,多个逗号拼接,关联student表', field: 'studentId', visible: true, align: 'center', valign: 'middle'},
            {title: '主键id', field: 'id', visible: false, align: 'center', valign: 'middle'},
            {title: '惠民卡名称', field: 'huiMinName', visible: true, align: 'center', valign: 'middle'},
            {title: '惠民卡类型', field: 'huiMinType', visible: true, align: 'center', valign: 'middle',
                formatter:function(value,row,index){
                    return {1: '年度卡', 2: '年内卡'}[value];
                }},
            {title: '售卖金额', field: 'salesMoney', visible: true, align: 'center', valign: 'middle'},
            {title: '所属运营商', field: 'operatorName', visible: true, align: 'center', valign: 'middle'},
            {title: '可用门店', field: 'storeName', visible: true, align: 'center', valign: 'middle'},
            {title: '购买用户', field: 'userName', visible: true, align: 'center', valign: 'middle'},
            {title: '联系电话', field: 'phone', visible: true, align: 'center', valign: 'middle'},
            {title: '购买时间', field: 'paymentTime', visible: true, align: 'center', valign: 'middle'},
            {title: '绑定人员', field: 'studentName', visible: true, align: 'center', valign: 'middle'},
            {title: '已用次数', field: 'useTimes', visible: true, align: 'center', valign: 'middle'},
            {title: '有效期', field: 'endTime', visible: true, align: 'center', valign: 'middle'},
            {title: '状态1使用中2已退款', field: 'status', visible: true, align: 'center', valign: 'middle'},
            {title: '创建时间', field: 'insertTime', visible: true, align: 'center', valign: 'middle'},
            {title: '付款时间', field: 'paymentTime', visible: true, align: 'center', valign: 'middle'},
            {title: '付款方式1微信2支付宝', field: 'paymentType', visible: true, align: 'center', valign: 'middle'},
            {title: '订单号', field: 'code', visible: true, align: 'center', valign: 'middle'},
            {title: '第三方支付流水号', field: 'orderNumber', visible: true, align: 'center', valign: 'middle'},
            {title: '退款时间', field: 'refundTime', visible: true, align: 'center', valign: 'middle'},
            {title: '退款状态 1未退款 2已退款 3线下退款(使用过或超过七日退款)', field: 'refundStatus', visible: true, align: 'center', valign: 'middle'},
            {title: '惠民卡id', field: 'cardId', visible: true, align: 'center', valign: 'middle'}
            {title: '状态', field: 'status', visible: true, align: 'center', valign: 'middle',
                formatter:function(value,row,index){
                    return {1: '使用中', 2: '已退款'}[value];
                }}
    ];
};
@@ -92,19 +97,101 @@
        ajax.start();
    }
};
TPayHuimin.getStaticsData = function (){
    var queryData = TPayHuimin.getQueryParam();
    //提交信息
    var ajax = new $ax(Feng.ctxPath + "/tPayHuimin/getStaticsData", function(data){
        if (data.data!=null && data.data !=''){
            $('#totalAmount').text(data.data.totalAmount);
            $('#refundAmount').text(data.data.refundAmount);
        }
    },function(data){
        Feng.error("获取统计数据失败!" + data.responseJSON.message + "!");
    });
    ajax.setData(queryData);
    ajax.start();
}
TPayHuimin.refund = function (){
    if (this.check()) {
        if (TPayHuimin.seItem.refundStatus != 1){
            Feng.error("该商品已退款");
            return;
        }
        let operation = function(){
            let ajax = new $ax(Feng.ctxPath + "/tPayHuimin/refund", function () {
                Feng.success("退款成功!");
                TPayHuimin.table.refresh();
            }, function (data) {
                Feng.error("退款失败!" + data.responseJSON.message + "!");
            });
            ajax.set("id", TPayHuimin.seItem.id);
            ajax.start();
        };
        Feng.confirm("确认退款所选惠民卡吗?",operation);
    }
}
TPayHuimin.export = function (){
    var queryData = TPayHuimin.getQueryParam();
    // 生成带参数的完整URL
    var exportUrl = Feng.ctxPath + "/tPayHuimin/export?" + $.param(queryData);
    window.location.href = exportUrl;
}
/**
 * 获取查询参数
 * @returns {{}}
 */
TPayHuimin.getQueryParam = function () {
    var queryData = {};
    queryData['huiMinName'] = $("#huiMinName").val();
    queryData['huiMinType'] = $("#huiMinType").val();
    queryData['operatorId'] = $("#operatorId").val();
    queryData['useId'] = $("#useId").val();
    queryData['userName'] = $("#userName").val();
    queryData['phone'] = $("#phone").val();
    let paymentTimeStr = $("#paymentTimeStr").val();
    if (paymentTimeStr){
        queryData['paymentTimeStart'] = paymentTimeStr.split('~')[0]+' 00:00:00';
        queryData['paymentTimeEnd'] = paymentTimeStr.split('~')[1]+' 23:59:59';
    }
    let endTimeStr = $("#endTimeStr").val();
    if (endTimeStr){
        queryData['endTimeStart'] = endTimeStr.split('~')[0]+' 00:00:00';
        queryData['endTimeEnd'] = endTimeStr.split('~')[1]+' 23:59:59';
    }
    queryData['status'] = $("#status").val();
    //过滤空值
    Object.keys(queryData).forEach(key => {
        if (queryData[key] === null || queryData[key] === '') {
            delete queryData[key];
        }
    });
    return queryData;
}
/**
 * 查询惠民卡列表
 */
TPayHuimin.search = function () {
    var queryData = {};
    queryData['condition'] = $("#condition").val();
    var queryData = TPayHuimin.getQueryParam();
    TPayHuimin.table.refresh({query: queryData});
    TPayHuimin.getStaticsData();
};
TPayHuimin.resetSearch = function () {
    var queryData = {};
    $("#huiMinName").val('');
    $("#huiMinType option:first").prop("selected", true);
    $("#operatorId option:first").prop("selected", true);
    $("#useId option:first").prop("selected", true);
    $("#userName").val('');
    $("#phone").val('');
    $("#paymentTimeStr").val('');
    $("#endTimeStr").val('');
    $("#status option:first").prop("selected", true);
    TPayHuimin.search();
};
$(function () {
    var defaultColunms = TPayHuimin.initColumn();
    var table = new BSTable(TPayHuimin.id, "/tPayHuimin/list", defaultColunms);
    table.setPaginationType("client");
    table.setPaginationType("server");
    TPayHuimin.table = table.init();
    TPayHuimin.getStaticsData();
});