admin
2024-08-04 bc56870059cca013649077af0e53891cba8dbfd1
代理新功能完善
38个文件已修改
9个文件已添加
1233 ■■■■ 已修改文件
src/main/java/com/taoke/autopay/controller/WebApiController.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/controller/admin/AdminAgentController.java 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/controller/admin/AdminOrderController.java 136 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/controller/admin/AdminSettingsController.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/controller/agent/AgentController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/controller/client/OrderController.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dao/KeyOrderMapper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dao/UserPayCountMapper.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dao/WxUserOrderCountMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dao/agent/ChannelAgentMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dto/ChannelOrderStatistic.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dto/UserSubmitKeyLimitDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/dto/admin/OrderExcelDataDto.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/entity/SystemConfigKeyEnum.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/entity/UserPayCount.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/factory/OrderFactory.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/manager/ChannelAgentManager.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/manager/OrderPayFailProcessor.java 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/ClientInfoService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/KeyOrderService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/UserSettingService.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/WxUserOrderCountService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/agent/ChannelAgentService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/impl/ClientInfoServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/impl/KeyOrderServiceImpl.java 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/impl/UserSettingServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/impl/WxUserOrderCountServiceImpl.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/impl/agent/ChannelAgentServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/service/impl/agent/ChannelAgentSharingRatioServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/utils/order/OrderChannelUtil.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/vo/admin/AdminOrderVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/vo/admin/OrderSearchVO.java 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/ChannelAgentMapper.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/KeyOrderMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/UserPayCountMapper.xml 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WxUserOrderCountMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/admin/agent-withdraw-list.html 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/admin/index.html 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/admin/order-list.html 78 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/admin/user-actioncount-limit.html 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/agent/css/index.css 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/agent/index.html 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/agent/js/index.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/taoke/autopay/KeyTest.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/taoke/autopay/MapperTest.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/java/com/taoke/autopay/WxUserTests.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/taoke/autopay/controller/WebApiController.java
@@ -109,7 +109,7 @@
                    throw new Exception("口令内容获取失败");
                }
                // 验证内容
                DYOrderDto dto = keyOrderService.verifyKey(tradeInfo.getGoodsTitle(), orderStatus, tradeInfo.getItemRealAmount());
                DYOrderDto dto = keyOrderService.verifyKey(tradeInfo.getGoodsTitle(), orderStatus, tradeInfo.getItemRealAmount(), wxUid);
            } catch (KeyVerifyException ee) {
                try {
                    verifyLogger.warn("校验不通过:【{}】-{}", keyInfo.getKey(), ee.getMessage());
src/main/java/com/taoke/autopay/controller/admin/AdminAgentController.java
@@ -19,6 +19,7 @@
import com.taoke.autopay.exception.ChannelAgentException;
import com.taoke.autopay.factory.AgentFactory;
import com.taoke.autopay.factory.OrderFactory;
import com.taoke.autopay.manager.ChannelAgentManager;
import com.taoke.autopay.service.ClientInfoService;
import com.taoke.autopay.service.KeyOrderService;
import com.taoke.autopay.service.SystemConfigService;
@@ -125,40 +126,15 @@
    }
    @Resource
    private ChannelAgentManager channelAgentManager;
    @ResponseBody
    @RequestMapping("add")
    public String addAgent(AdminChannelAgentVO vo) {
        // 创建代理
        ChannelAgent agent = ChannelAgent.builder()
                .name(vo.getName())
                .account(vo.getAccount())
                .pwd(StringUtil.Md5(vo.getPwd()))
                .alipayAccount(StringUtil.isNullOrEmpty(vo.getAlipayAccount()) ? null : vo.getAlipayAccount())
                .alipayName(StringUtil.isNullOrEmpty(vo.getAlipayName()) ? null : vo.getAlipayName())
                .status(ChannelAgent.STATUS_NOMAL)
                .build();
        try {
            agent = channelAgentService.addChannelAgent(agent);
            // 添加设置
            ChannelAgentSettings settings = ChannelAgentSettings.builder()
                    .id(agent.getId())
                    .startSubmitTime(StringUtil.isNullOrEmpty(vo.getStartSubmitTime()) ? null : vo.getStartSubmitTime())
                    .endSubmitTime(StringUtil.isNullOrEmpty(vo.getEndSubmitTime()) ? null : vo.getEndSubmitTime())
                    .maxKeyCountPerDay(StringUtil.isNullOrEmpty(vo.getMaxKeyCountPerDay()) ? null : Long.parseLong(vo.getMaxKeyCountPerDay()))
                    .maxPayMoneyPerDay(StringUtil.isNullOrEmpty(vo.getMaxPayMoneyPerDay()) ? null : new BigDecimal(vo.getMaxPayMoneyPerDay()))
                    .build();
            channelAgentSettingService.add(settings);
            // 添加分成比例设置
            if (!StringUtil.isNullOrEmpty(vo.getShareRatioInfos())) {
                JSONObject shareRatioData = JSONObject.fromObject(vo.getShareRatioInfos());
                for (Object key : shareRatioData.keySet()) {
                    String value = shareRatioData.optString(key.toString());
                    OrderChannelEnum channel = OrderChannelEnum.valueOf(key.toString());
                    if (!StringUtil.isNullOrEmpty(value)) {
                        channelAgentSharingRatioService.setShareRatio(ChannelAgentSharingRatio.builder().agengId(agent.getId()).orderChannel(channel).shareType(ChannelAgentSharingRatio.SHARE_TYPE_MONEY).shareValue(new BigDecimal(value)).build());
                    }
                }
            }
          ChannelAgent agent=  channelAgentManager.addAgent(vo);
            return JsonUtil.loadTrueResult(agent);
        } catch (ChannelAgentException e) {
            return JsonUtil.loadFalseResult(e.getMessage());
src/main/java/com/taoke/autopay/controller/admin/AdminOrderController.java
@@ -10,9 +10,12 @@
import com.taoke.autopay.dto.admin.OrderExcelDataDto;
import com.taoke.autopay.entity.ClientInfo;
import com.taoke.autopay.entity.KeyOrder;
import com.taoke.autopay.entity.OrderChannelEnum;
import com.taoke.autopay.entity.agent.ChannelAgent;
import com.taoke.autopay.factory.OrderFactory;
import com.taoke.autopay.service.ClientInfoService;
import com.taoke.autopay.service.KeyOrderService;
import com.taoke.autopay.service.agent.ChannelAgentService;
import com.taoke.autopay.utils.Constant;
import com.taoke.autopay.utils.TimeUtil;
import com.taoke.autopay.vo.admin.AdminOrderVO;
@@ -59,35 +62,77 @@
    private KeyOrderService keyOrderService;
    @Resource
    private ClientInfoService clientInfoService;
    @Resource
    private ChannelAgentService channelAgentService;
    private KeyOrderMapper.DaoQuery createOrderQuery(OrderSearchVO vo) throws Exception {
//           <option value="0">按老铁ID</option>
//                               <option value="1">按代理ID</option>
//                               <option value="2">按订单号</option>
        KeyOrderMapper.DaoQuery query = new KeyOrderMapper.DaoQuery();
        if (!StringUtil.isNullOrEmpty(vo.getKey())) {
            switch (vo.getKeyType()) {
                case 0:
                    // 老铁ID
                    if (!NumberUtil.isNumeric(vo.getKey().trim())) {
                        throw new Exception("老铁ID必须为数字");
                    }
                    query.uid = Long.parseLong(vo.getKey());
                    break;
                case 1:
                    // 代理ID
                    if (!NumberUtil.isNumeric(vo.getKey().trim())) {
                        throw new Exception("代理ID必须为数字");
                    }
                    query.agentId = Long.parseLong(vo.getKey().trim());
                    break;
                case 2:
                    // 订单号
                    query.orderNo = vo.getKey().trim();
                case 3:
                    // 支付设备ID
                    if (!NumberUtil.isNumeric(vo.getKey().trim())) {
                        throw new Exception("支付设备ID必须为数字");
                    }
                    query.distributeClientUid = Long.parseLong(vo.getKey().trim());
            }
        }
        if (!StringUtil.isNullOrEmpty(vo.getState())) {
            query.state = Integer.parseInt(vo.getState());
        }
        if (!StringUtil.isNullOrEmpty(vo.getOrderChannel())) {
            query.orderChannel = OrderChannelEnum.valueOf(vo.getOrderChannel()).getKey();
        }
        if (!StringUtil.isNullOrEmpty(vo.getStartDate())) {
            query.minCreateTime = new Date(TimeUtil.convertToTimeTemp(vo.getStartDate(), "yyyy-MM-dd"));
        }
        if (!StringUtil.isNullOrEmpty(vo.getEndDate())) {
            query.maxCreateTime = TimeUtil.getNextDay(1, new Date(TimeUtil.convertToTimeTemp(vo.getEndDate(), "yyyy-MM-dd")).getTime());
        }
        return query;
    }
    @ResponseBody
    @RequestMapping("list")
    public String listOrder(OrderSearchVO search, int page, int limit) {
        //先查询所有的数据
        KeyOrderMapper.DaoQuery query = new KeyOrderMapper.DaoQuery();
        try {
            KeyOrderMapper.DaoQuery query = createOrderQuery(search);
        query.sortList=Arrays.asList(new String[]{"create_time desc"});
        query.start = (page - 1) * limit;
        query.count = limit;
        if (!StringUtil.isNullOrEmpty(search.getKey())) {
            if (search.getKey().length() > 10 || !NumberUtil.isNumeric(search.getKey().trim())) {
                // 订单号
                query.orderNo = search.getKey().trim();
            } else {
                // 用户ID
                query.uid = Long.parseLong(search.getKey().trim());
            }
        }
        if (!StringUtil.isNullOrEmpty(search.getStartDate())) {
            query.minCreateTime =new Date(TimeUtil.convertToTimeTemp(search.getStartDate(),"yyyy-MM-dd"));
        }
        if (!StringUtil.isNullOrEmpty(search.getEndDate())) {
            query.maxCreateTime =TimeUtil.getNextDay(1,new Date(TimeUtil.convertToTimeTemp(search.getEndDate(),"yyyy-MM-dd")).getTime());
        }
        List<KeyOrder> orderList = keyOrderService.list(query);
        long count = keyOrderService.count(query);
            // 统计设备
        Map<Long, ClientInfo> clientMap = new HashMap<>();
        if (orderList.size() > 0) {
            List<Long> cids = new ArrayList<>();
@@ -101,40 +146,40 @@
                clientMap.put(client.getId(), client);
            }
        }
            // 统计代理信息
            Map<Long, ChannelAgent> agentMap = new HashMap<>();
            List<Long> agengIds = new ArrayList<>();
            for (KeyOrder u : orderList) {
                if (u.getAgentId() != null) {
                    agengIds.add(u.getAgentId());
                }
            }
            List<ChannelAgent> agents = channelAgentService.listByIds(agengIds);
            for (ChannelAgent agent : agents) {
                agentMap.put(agent.getId(), agent);
            }
        // 转vo
        List<AdminOrderVO> voList = new ArrayList<>();
        for (KeyOrder order : orderList) {
            voList.add(OrderFactory.createAdminVO(order, clientMap.get(order.getDistributeClientUid())));
                voList.add(OrderFactory.createAdminVO(order, clientMap.get(order.getDistributeClientUid()), agentMap.get(order.getAgentId())));
        }
        JSONObject data = new JSONObject();
        data.put("count", count);
        data.put("list", gson.toJson(voList));
        return JsonUtil.loadTrueResult(data);
        }catch(Exception e){
            return JsonUtil.loadFalseResult(e.getMessage());
    }
    }
    @RequestMapping("downLoadOrder")
    public void downLoadOrder(OrderSearchVO search, HttpServletResponse response) throws IOException {
        KeyOrderMapper.DaoQuery query = new KeyOrderMapper.DaoQuery();
        if (!StringUtil.isNullOrEmpty(search.getKey())) {
            if (search.getKey().length() > 10 || !NumberUtil.isNumeric(search.getKey().trim())) {
                // 订单号
                query.orderNo = search.getKey().trim();
            } else {
                // 用户ID
                query.uid = Long.parseLong(search.getKey().trim());
            }
        }
        if (!StringUtil.isNullOrEmpty(search.getStartDate())) {
            query.minCreateTime =new Date(TimeUtil.convertToTimeTemp(search.getStartDate(),"yyyy-MM-dd"));
        }
        if (!StringUtil.isNullOrEmpty(search.getEndDate())) {
            query.maxCreateTime =TimeUtil.getNextDay(1,new Date(TimeUtil.convertToTimeTemp(search.getEndDate(),"yyyy-MM-dd")).getTime());
        }
        try {
            KeyOrderMapper.DaoQuery query = createOrderQuery(search);
        query.sortList=Arrays.asList(new String[]{"create_time desc"});
        long count = keyOrderService.count(query);
        query.start=0;
@@ -144,6 +189,18 @@
        Map<Long,Integer> userOrderCountMap=new HashMap<>();
        Map<Long, BigDecimal> userOrderMoneyMap=new HashMap<>();
        Map<Long, ClientInfo> payDeviceMap=new HashMap<>();
            // 统计代理信息
            Map<Long, ChannelAgent> agentMap = new HashMap<>();
            List<Long> agengIds = new ArrayList<>();
            for (KeyOrder u : orderList) {
                if (u.getAgentId() != null) {
                    agengIds.add(u.getAgentId());
                }
            }
            List<ChannelAgent> agents = channelAgentService.listByIds(agengIds);
            for (ChannelAgent agent : agents) {
                agentMap.put(agent.getId(), agent);
            }
        List<OrderExcelDataDto> dataList=new ArrayList<>();
        for(KeyOrder order:orderList){
@@ -169,6 +226,7 @@
        for(KeyOrder order:orderList){
            OrderExcelDataDto dto=new OrderExcelDataDto();
            dto.setId(order.getId());
                dto.setAgent(agentMap.get(order.getAgentId()) == null ? "" : agentMap.get(order.getAgentId()).getName());
            dto.setCreateTime(TimeUtil.getGernalTime(order.getCreateTime()));
            dto.setOrderMoney(order.getOrderMoney()==null?"":order.getOrderMoney().toString());
            if(order.getOrderChannel()!=null) {
@@ -246,8 +304,10 @@
        String fileName= URLEncoder.encode(TimeUtil.getGernalTime(System.currentTimeMillis(),"yyyyMMdd_HHmmss"),"UTF-8");
        response.setHeader("Content-disposition","attachment;filename*=utf-8''"+fileName+".xlsx");
        EasyExcel.write(response.getOutputStream(),OrderExcelDataDto.class).sheet("订单").doWrite(dataList);
        }catch(Exception e){
           response.sendError(402,e.getMessage());
    }
    }
}
src/main/java/com/taoke/autopay/controller/admin/AdminSettingsController.java
@@ -1,8 +1,11 @@
package com.taoke.autopay.controller.admin;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.taoke.autopay.dto.UserSubmitKeyLimitDto;
import com.taoke.autopay.entity.SystemConfigKeyEnum;
import com.taoke.autopay.service.SystemConfigService;
import com.taoke.autopay.service.UserSettingService;
import com.taoke.autopay.vo.admin.PayMoneySettingsVO;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
@@ -94,7 +97,6 @@
    }
    @ResponseBody
    @RequestMapping("getPayMoneyAndTime")
    public String getPayMoneyAndTime() {
@@ -103,7 +105,8 @@
        if(StringUtil.isNullOrEmpty(value)){
            vo.setMoneys(new ArrayList<>());
        }else{
            vo.setMoneys(JsonUtil.getSimpleGson().fromJson(value,new TypeToken<List<String>>(){}.getType() ));
            vo.setMoneys(JsonUtil.getSimpleGson().fromJson(value, new TypeToken<List<String>>() {
            }.getType()));
        }
        // 设置时间,用逗号分隔
       value = systemConfigService.getValue(SystemConfigKeyEnum.KEY_SUBMIT_TIME_RANGE);
@@ -117,4 +120,23 @@
        return JsonUtil.loadTrueResult(JsonUtil.getSimpleGson().toJson(vo));
    }
    @Resource
    private UserSettingService userSettingService;
    @ResponseBody
    @RequestMapping("getUserSubmitKeyCountSetting")
    public String getUserSubmitKeyCountSetting() {
        List<UserSubmitKeyLimitDto> list = userSettingService.getUserSubmitKeyCountList(false);
        return JsonUtil.loadTrueResult(new Gson().toJson(list));
    }
    @ResponseBody
    @RequestMapping("setUserSubmitKeyCount")
    public String setUserSubmitKeyCount(String value) {
        List<UserSubmitKeyLimitDto> list =   new Gson().fromJson(value, new TypeToken<List<UserSubmitKeyLimitDto>>() {
        }.getType());
        userSettingService.setUserSubmitKeyCount(list);
        return JsonUtil.loadTrueResult(new Gson().toJson(list));
    }
}
src/main/java/com/taoke/autopay/controller/agent/AgentController.java
@@ -134,7 +134,6 @@
                query.oMinCreateTime = new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(now - 24 * 60 * 60 * 1000L, "yyyy-MM-dd"), "yyyy-MM-dd"));
                break;
            case 2:
                query.oMaxCreateTime = new Date(TimeUtil.convertToTimeTemp(nowDay, "yyyy-MM-dd"));
                query.oMinCreateTime = new Date(TimeUtil.convertToTimeTemp(TimeUtil.getGernalTime(now - 24 * 60 * 60 * 1000L * 3, "yyyy-MM-dd"), "yyyy-MM-dd"));
            case 3:
                Calendar calendar = Calendar.getInstance();
src/main/java/com/taoke/autopay/controller/client/OrderController.java
@@ -104,6 +104,7 @@
        clientInfoService.setActiveTime(filter.getUid(), new Date());
        query.start = (filter.getPage() - 1) * filter.getPageSize();
        query.count = filter.getPageSize();
        query.minCreateTime = new Date(System.currentTimeMillis()-1000*60*30L);
        if (filter.getState() != null) {
            switch (filter.getState()) {
                case OrderFilter.STATE_NOT_PROCESS:
@@ -309,7 +310,7 @@
            DYOrderDto dyOrderDto =null;
            try {
                dyOrderDto = keyOrderService.verifyKey(orderNoDesc, orderStatus, money);
                dyOrderDto = keyOrderService.verifyKey(orderNoDesc, orderStatus, money, null);
            }catch(KeyVerifyException ve){
                throw new KeyOrderException("口令验证失败:" + ve.getMessage());
            }
@@ -360,6 +361,7 @@
                orderUpdate.setPayType(Constant.PAY_TYPE_WITH_ORDER_NO);
            }else{
                orderUpdate.setPayType(Constant.PAY_TYPE_WITH_MONEY);
                orderUpdate.setOrderChannel(OrderChannelEnum.unknown.getKey());
            }
            orderUpdate.setExcutePayTime(new Date());
            keyOrderService.update(orderUpdate);
src/main/java/com/taoke/autopay/dao/KeyOrderMapper.java
@@ -62,6 +62,7 @@
        public List<Integer> stateList;
        public String stateDesc;
        public Long distributeClientUid;
        public String orderChannel;
        public Date minDistributeTime;
        public Date maxDistributeTime;
        public Date minCreateTime;
src/main/java/com/taoke/autopay/dao/UserPayCountMapper.java
New file
@@ -0,0 +1,31 @@
package com.taoke.autopay.dao;
import java.util.Date;
import java.lang.Long;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.taoke.autopay.entity.UserPayCount;
import org.yeshi.utils.mybatis.BaseMapper;
public interface UserPayCountMapper extends BaseMapper<UserPayCount> {
    UserPayCount selectByPrimaryKeyForUpdate(@Param("id") Long id);
    List<UserPayCount> list(@Param("query") DaoQuery query);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery{
        public Long id;
        public Long submitKeyCount;
        public Long payCount;
        public Date minCreateTime;
        public Date maxCreateTime;
        public Date minUpdateTime;
        public Date maxUpdateTime;
        public long start;
        public int count;
        public List<String> sortList;
    }
}
src/main/java/com/taoke/autopay/dao/WxUserOrderCountMapper.java
@@ -17,6 +17,10 @@
    long count(@Param("query") DaoQuery query);
    Long sumOrderCount(@Param("query") DaoQuery query);
    public static class DaoQuery{
        public String id;
        public String day;
src/main/java/com/taoke/autopay/dao/agent/ChannelAgentMapper.java
@@ -16,6 +16,8 @@
    List<ChannelAgent> list(@Param("query") DaoQuery query);
    List<ChannelAgent> listByIds(@Param("ids") List<Long> ids);
    long count(@Param("query") DaoQuery query);
    public static class DaoQuery{
src/main/java/com/taoke/autopay/dto/ChannelOrderStatistic.java
@@ -9,4 +9,5 @@
    private String orderChannel;
    private long count;
    private BigDecimal money;
    private long userCount;
}
src/main/java/com/taoke/autopay/dto/UserSubmitKeyLimitDto.java
New file
@@ -0,0 +1,17 @@
package com.taoke.autopay.dto;
import lombok.Builder;
import lombok.Data;
/**
 * @author hxh
 * @title: UserSubmitKeyLimitDto
 * @description: TODO
 * @date 2024/8/1 22:44
 */
@Data
@Builder
public class UserSubmitKeyLimitDto {
    private int totalCount;
    private int perCount;
}
src/main/java/com/taoke/autopay/dto/admin/OrderExcelDataDto.java
@@ -15,6 +15,8 @@
    private String id;
    @ExcelProperty("老铁ID")
    private Long uid;
    @ExcelProperty("代理")
    private String agent;
    @ExcelProperty("口令")
    private String key;
    @ExcelProperty("口令提交时间")
@@ -163,4 +165,12 @@
    public void setPayDevice(String payDevice) {
        this.payDevice = payDevice;
    }
    public String getAgent() {
        return agent;
    }
    public void setAgent(String agent) {
        this.agent = agent;
    }
}
src/main/java/com/taoke/autopay/entity/SystemConfigKeyEnum.java
@@ -22,6 +22,7 @@
    AGENT_ADMIN_LINK("agent_admin_link", "代理后台管理链接"),
    AGENT_ORDER_CHANNEL_SHARE_RATIO("agent_order_channel_share_ratio", "代理订单渠道分成比例"),
    RE_EXCUTE_PAY_CLIENTS("re_excute_pay_clients", "重新执行支付的账号"),
    USER_SUBMIT_KEY_COUNT_LIMIT("user_submit_key_count_limit", "用户提交口令次数限制"),
    ;
src/main/java/com/taoke/autopay/entity/UserPayCount.java
New file
@@ -0,0 +1,33 @@
package com.taoke.autopay.entity;
import lombok.Builder;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.yeshi.utils.generater.mybatis.Column;
import org.yeshi.utils.generater.mybatis.Table;
import java.util.Date;
/**
 * @author hxh
 * @title: UserPayCount
 * @description: 用户支付次数
 * @date 2024/8/1 22:30
 */
@Data
@Builder
@Table(value = "table_user_pay_count")
public class UserPayCount {
    @Id
    @Column(name="_id")
    private Long id;
    @Column(name="_submit_key_count")
    private Long submitKeyCount;
    @Column(name="_psy_count")
    private Long payCount;
    @Column(name="_create_time")
    private Date createTime;
    @Column(name="_update_time")
    private Date updateTime;
}
src/main/java/com/taoke/autopay/factory/OrderFactory.java
@@ -4,9 +4,11 @@
import com.taoke.autopay.entity.KeyOrder;
import com.taoke.autopay.entity.OrderChannelEnum;
import com.taoke.autopay.entity.WxUserOrderCount;
import com.taoke.autopay.entity.agent.ChannelAgent;
import com.taoke.autopay.utils.Constant;
import com.taoke.autopay.utils.StringUtil;
import com.taoke.autopay.utils.TimeUtil;
import com.taoke.autopay.utils.order.OrderChannelUtil;
import com.taoke.autopay.vo.AgentOrderVO;
import com.taoke.autopay.vo.UserInfoVO;
import com.taoke.autopay.vo.admin.AdminOrderVO;
@@ -91,25 +93,12 @@
    }
    public static AdminOrderVO createAdminVO(KeyOrder order, ClientInfo info) {
    public static AdminOrderVO createAdminVO(KeyOrder order, ClientInfo info, ChannelAgent agent) {
        AdminOrderVO vo = new AdminOrderVO();
        vo.setCreateTime(order.getCreateTime());
        vo.setId(order.getId());
        vo.setKey(order.getKey());
        switch (order.getState()) {
            case KeyOrder.STATE_NOT_PROCESS:
                vo.setState(KeyOrderVO.STATE_NOT_PROCESS);
                break;
            case KeyOrder.STATE_NOT_PAY:
                vo.setState(KeyOrderVO.STATE_PROCESS_ERROR);
                break;
            case KeyOrder.STATE_PAY:
                vo.setState(KeyOrderVO.STATE_PROCESSED);
                break;
            case KeyOrder.STATE_REJECT_PAY:
                vo.setState(KeyOrderVO.STATE_PROCESSED);
                break;
        }
        vo.setState(order.getState());
        vo.setStateDesc(order.getStateDesc());
        vo.setOrderStateDesc(getOrderStateDesc(order.getOrderState(), order.getOrderType()));
        vo.setExcutePayTime(order.getExcutePayTime());
@@ -119,6 +108,14 @@
        vo.setDistributedTime(order.getDistributeTime());
        vo.setDistributedClientInfo(info);
        vo.setUid(order.getUid());
        OrderChannelEnum orderChannel=OrderChannelUtil.getChannelByKey(order.getOrderChannel());
        vo.setOrderChannel(orderChannel==null?"未知":orderChannel.getName());
        if(agent!=null){
            vo.setAgent(agent.getName());
        }else{
            vo.setAgent("");
        }
        return vo;
    }
src/main/java/com/taoke/autopay/manager/ChannelAgentManager.java
New file
@@ -0,0 +1,78 @@
package com.taoke.autopay.manager;
import com.taoke.autopay.entity.OrderChannelEnum;
import com.taoke.autopay.entity.agent.ChannelAgent;
import com.taoke.autopay.entity.agent.ChannelAgentSettings;
import com.taoke.autopay.entity.agent.ChannelAgentSharingRatio;
import com.taoke.autopay.exception.ChannelAgentException;
import com.taoke.autopay.service.agent.ChannelAgentService;
import com.taoke.autopay.service.agent.ChannelAgentSettingService;
import com.taoke.autopay.service.agent.ChannelAgentSharingRatioService;
import com.taoke.autopay.vo.admin.AdminChannelAgentVO;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.yeshi.utils.JsonUtil;
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
 * @author hxh
 * @title: ChannelAgentManager
 * @description: TODO
 * @date 2024/8/4 1:34
 */
@Component
public class ChannelAgentManager {
    @Resource
    private ChannelAgentService channelAgentService;
    @Resource
    private ChannelAgentSettingService channelAgentSettingService;
    @Resource
    private ChannelAgentSharingRatioService channelAgentSharingRatioService;
    @Transactional(rollbackFor = Exception.class)
    public ChannelAgent addAgent(AdminChannelAgentVO vo) throws ChannelAgentException {
        // 创建代理
        ChannelAgent agent = ChannelAgent.builder()
                .name(vo.getName())
                .account(vo.getAccount())
                .pwd(StringUtil.Md5(vo.getPwd()))
                .alipayAccount(StringUtil.isNullOrEmpty(vo.getAlipayAccount()) ? null : vo.getAlipayAccount())
                .alipayName(StringUtil.isNullOrEmpty(vo.getAlipayName()) ? null : vo.getAlipayName())
                .status(ChannelAgent.STATUS_NOMAL)
                .build();
        agent = channelAgentService.addChannelAgent(agent);
        // 添加设置
        ChannelAgentSettings settings = ChannelAgentSettings.builder()
                .id(agent.getId())
                .startSubmitTime(StringUtil.isNullOrEmpty(vo.getStartSubmitTime()) ? null : vo.getStartSubmitTime())
                .endSubmitTime(StringUtil.isNullOrEmpty(vo.getEndSubmitTime()) ? null : vo.getEndSubmitTime())
                .maxKeyCountPerDay(StringUtil.isNullOrEmpty(vo.getMaxKeyCountPerDay()) ? null : Long.parseLong(vo.getMaxKeyCountPerDay()))
                .maxPayMoneyPerDay(StringUtil.isNullOrEmpty(vo.getMaxPayMoneyPerDay()) ? null : new BigDecimal(vo.getMaxPayMoneyPerDay()))
                .build();
        channelAgentSettingService.add(settings);
        // 添加分成比例设置
        if (!StringUtil.isNullOrEmpty(vo.getShareRatioInfos())) {
            JSONObject shareRatioData = JSONObject.fromObject(vo.getShareRatioInfos());
            for (Object key : shareRatioData.keySet()) {
                String value = shareRatioData.optString(key.toString());
                OrderChannelEnum channel = OrderChannelEnum.valueOf(key.toString());
                if (!StringUtil.isNullOrEmpty(value)) {
                    channelAgentSharingRatioService.setShareRatio(ChannelAgentSharingRatio.builder().agengId(agent.getId()).orderChannel(channel).shareType(ChannelAgentSharingRatio.SHARE_TYPE_MONEY).shareValue(new BigDecimal(value)).build());
                }
            }
        }
        return agent;
    }
}
src/main/java/com/taoke/autopay/manager/OrderPayFailProcessor.java
@@ -2,6 +2,7 @@
import com.taoke.autopay.entity.KeyOrder;
import com.taoke.autopay.entity.SystemConfigKeyEnum;
import com.taoke.autopay.service.ClientInfoService;
import com.taoke.autopay.service.KeyOrderService;
import com.taoke.autopay.service.SystemConfigService;
import com.taoke.autopay.utils.StringUtil;
@@ -11,10 +12,7 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.*;
/**
 * @author hxh
@@ -47,6 +45,9 @@
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private ClientInfoService clientInfoService;
    public void clearCacheData() {
        reProcessCountMap.clear();
        orderQueues.clear();
@@ -68,27 +69,29 @@
                return;
            }
            // 超时30分钟不执行
            if(System.currentTimeMillis() - order.getCreateTime().getTime()> 30*60*1000L){
                return;
            }
            if (!reProcessCountMap.containsKey(queue.getId())) {
                reProcessCountMap.put(queue.getId(), 0);
            }
            reProcessCountMap.put(queue.getId(), reProcessCountMap.get(queue.getId()) + 1);
            keyOrderService.removeDistributedClient(queue.getId());
            String clientIds = systemConfigService.getValueCache(SystemConfigKeyEnum.RE_EXCUTE_PAY_CLIENTS);
            List<Long> clientIds = clientInfoService.getRePayClientIds();
            // 移除已经分配的设备,改变状态为未分配
            KeyOrder update = new KeyOrder();
            update.setId(queue.getId());
            update.setState(KeyOrder.STATE_NOT_PROCESS);
            update.setStateDesc("重新分配");
            if (!StringUtil.isNullOrEmpty(clientIds)) {
                String[] cids = clientIds.split(",");
                int index = (int) Math.round(Math.random() * cids.length);
                if (index + 1 > cids.length) {
                    index = cids.length - 1;
            if (clientIds!=null&&clientIds.size()>0) {
                int index = (int) Math.round(Math.random() *clientIds.size());
                if (index + 1 > clientIds.size()) {
                    index = clientIds.size() - 1;
                }
                update.setDistributeClientUid(Long.parseLong(cids[index]));
                update.setDistributeClientUid(clientIds.get(index));
            }
            keyOrderService.update(update);
        }
@@ -108,7 +111,7 @@
            return;
        }
        //加入重试队列
        orderQueues.add(OrderQueue.builder().id(id).expireTime(System.currentTimeMillis() + 2 * 60 * 1000).build());
        orderQueues.add(OrderQueue.builder().id(id).expireTime(System.currentTimeMillis() + 1 * 60 * 1000).build());
        KeyOrder update = new KeyOrder();
        update.setId(id);
        update.setState(KeyOrder.STATE_REJECT_PAY);
src/main/java/com/taoke/autopay/service/ClientInfoService.java
@@ -83,5 +83,13 @@
     **/
    public void setPwd(Long id,String pwd);
    /**
     * @author hxh
     * @description 获取可以重新分配支付的设备
     * @date 18:15 2024/7/30
     * @return java.util.List<java.lang.Long>
     **/
    public List<Long> getRePayClientIds();
}
src/main/java/com/taoke/autopay/service/KeyOrderService.java
@@ -121,7 +121,7 @@
     * @param: money
     * @return void
     **/
    public DYOrderDto verifyKey(String orderNoDesc, String orderStatus, String money) throws KeyVerifyException;
    public DYOrderDto verifyKey(String orderNoDesc, String orderStatus, String money, Long uid) throws KeyVerifyException;
    /**
     * @author hxh 
src/main/java/com/taoke/autopay/service/UserSettingService.java
New file
@@ -0,0 +1,41 @@
package com.taoke.autopay.service;
import com.taoke.autopay.dto.UserSubmitKeyLimitDto;
import java.util.List;
/**
 * @author hxh
 * @title: UserSettingService
 * @description: TODO
 * @date 2024/8/1 22:41
 */
public interface UserSettingService {
    /**
     * @author hxh
     * @description 设置用户提交口令次数限制
     * @date 22:46 2024/8/1
     * @param: limit
     * @return void
     **/
    public void setUserSubmitKeyCount(List<UserSubmitKeyLimitDto> limit);
    /**
     * @author hxh
     * @description 获取用户提交口令限制
     * @date 22:46 2024/8/1
     * @return java.util.List<com.taoke.autopay.dto.UserSubmitKeyLimitDto>
     **/
    public List<UserSubmitKeyLimitDto> getUserSubmitKeyCountList(boolean fromCache);
    /**
     * @author hxh
     * @description 根据总提交次数获取每日提交次数
     * @date 22:47 2024/8/1
     * @param: totalCount
     * @return int
     **/
    public int getLimitCountByTotalCount(int totalCount);
}
src/main/java/com/taoke/autopay/service/WxUserOrderCountService.java
@@ -13,6 +13,8 @@
public interface WxUserOrderCountService {
    public void addOrderCount(Long uid, OrderCountTypeEnum orderType, String day, int count, Integer maxCount) throws WxOrderCountException;
    public void isOrderCountLimit(Long uid, OrderCountTypeEnum orderType, String day, int count, Integer maxCount) throws WxOrderCountException;
    public WxUserOrderCount get(Long uid, OrderCountTypeEnum orderType, String day);
src/main/java/com/taoke/autopay/service/agent/ChannelAgentService.java
@@ -50,4 +50,6 @@
    public ChannelAgent selectByAlias(String alias);
    public List<ChannelAgent> listByIds(List<Long> ids);
}
src/main/java/com/taoke/autopay/service/impl/ClientInfoServiceImpl.java
@@ -2,12 +2,16 @@
import com.taoke.autopay.dao.ClientInfoMapper;
import com.taoke.autopay.entity.ClientInfo;
import com.taoke.autopay.entity.SystemConfigKeyEnum;
import com.taoke.autopay.exception.LoginException;
import com.taoke.autopay.service.ClientInfoService;
import com.taoke.autopay.service.SystemConfigService;
import com.taoke.autopay.utils.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -22,6 +26,9 @@
public class ClientInfoServiceImpl implements ClientInfoService {
    @Resource
    private ClientInfoMapper clientInfoMapper;
    @Resource
    private SystemConfigService systemConfigService;
    @Override
    public ClientInfo login(String account, String pwd) throws LoginException {
@@ -113,4 +120,19 @@
        update.setPwd(pwd);
        clientInfoMapper.updateByPrimaryKeySelective(update);
    }
    @Override
    public List<Long> getRePayClientIds() {
        List<Long> idList = new ArrayList<>();
        String clientIds = systemConfigService.getValueCache(SystemConfigKeyEnum.RE_EXCUTE_PAY_CLIENTS);
        if (StringUtil.isNullOrEmpty(clientIds)) {
            return idList;
        }
        String[] ids = clientIds.trim().split(",");
        for (String id : ids) {
            idList.add(Long.parseLong(id));
        }
        return idList;
    }
}
src/main/java/com/taoke/autopay/service/impl/KeyOrderServiceImpl.java
@@ -10,10 +10,7 @@
import com.taoke.autopay.exception.KeyVerifyException;
import com.taoke.autopay.exception.WxOrderCountException;
import com.taoke.autopay.factory.OrderFactory;
import com.taoke.autopay.service.KeyOrderService;
import com.taoke.autopay.service.SystemConfigService;
import com.taoke.autopay.service.WxUserOrderCountService;
import com.taoke.autopay.service.WxUserSettingService;
import com.taoke.autopay.service.*;
import com.taoke.autopay.service.agent.ChannelAgentService;
import com.taoke.autopay.service.agent.ChannelAgentSharingRatioService;
import com.taoke.autopay.utils.*;
@@ -56,6 +53,9 @@
    @Resource
    private ChannelAgentSharingRatioService channelAgentSharingRatioService;
    @Resource
    private ClientInfoService clientInfoService;
    @Override
@@ -193,6 +193,7 @@
        Map<OrderChannelEnum, BigDecimal> shareMoneyMap = channelAgentSharingRatioService.getShareMoneyMap(query.agentId);
        List<ChannelOrderStatistic> channelOrderStatisticList = keyOrderMapper.statisticChannelOrders(query);
        BigDecimal totalMoney = new BigDecimal(0);
        long totalOrderCount=0;
        for (ChannelOrderStatistic s : channelOrderStatisticList) {
            for (OrderChannelEnum channel : OrderChannelEnum.values()) {
@@ -204,11 +205,13 @@
                    break;
                }
            }
            totalOrderCount+=s.getCount();
        }
        long userCount = keyOrderMapper.countUser(query);
        ChannelOrderStatistic statistic = new ChannelOrderStatistic();
        statistic.setCount(userCount);
        statistic.setUserCount(userCount);
        statistic.setMoney(totalMoney);
        statistic.setCount(totalOrderCount);
        return statistic;
    }
@@ -232,6 +235,15 @@
        if (list == null || list.size() == 0) {
            return null;
        }
        // 排除重新分配的设备
        List<Long> excludeIds =   clientInfoService.getRePayClientIds();
        for(int i=0;i<list.size();i++){
            if(excludeIds.contains(list.get(i).getUid())){
                list.remove(i);
                i--;
            }
        }
        // count小于2直接视为0
        for (OrderDistributeCountInfo info : list) {
            if (info.getCount() < 2) {
@@ -278,7 +290,7 @@
    }
    @Override
    public DYOrderDto verifyKey(String orderNoDesc, String orderStatus, String money) throws KeyVerifyException {
    public DYOrderDto verifyKey(String orderNoDesc, String orderStatus, String money, Long uid) throws KeyVerifyException {
        int orderType = Constant.ORDER_TYPE_UNKNOWN;
        if (orderNoDesc.contains("抖音")||orderNoDesc.contains("上海格物致品")) {
            orderType = Constant.ORDER_TYPE_DY;
@@ -286,6 +298,28 @@
            orderType = Constant.ORDER_TYPE_KS;
        }
        if (uid != null) {
            WxUserSettings settings = wxUserSettingService.getUserSettings(uid);
            OrderCountTypeEnum orderCountType=OrderCountTypeEnum.SUBMIT_TOKEN_COUNT;
            switch (orderType){
                case  Constant.ORDER_TYPE_DY:
                    orderCountType = OrderCountTypeEnum.DY_ORDER_PAY;
                    break;
                case Constant.ORDER_TYPE_KS:
                    orderCountType = OrderCountTypeEnum.KS_ORDER_PAY;
                    break;
            }
            try {
                wxUserOrderCountService.isOrderCountLimit(uid, orderCountType, TimeUtil.getGernalTime(System.currentTimeMillis(),"yyyy-MM-dd"), 1, settings.getTotalOrderCountPerDay());
            } catch (WxOrderCountException e) {
                e.printStackTrace();
            }
        }
        String orderNo = "";
        // 匹配连续的数字
        Pattern pattern = Pattern.compile("\\d+");
src/main/java/com/taoke/autopay/service/impl/UserSettingServiceImpl.java
New file
@@ -0,0 +1,68 @@
package com.taoke.autopay.service.impl;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.taoke.autopay.dto.UserSubmitKeyLimitDto;
import com.taoke.autopay.entity.SystemConfigKeyEnum;
import com.taoke.autopay.service.SystemConfigService;
import com.taoke.autopay.service.UserSettingService;
import com.taoke.autopay.utils.StringUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
 * @author hxh
 * @title: UserSettingServiceImpl
 * @description: TODO
 * @date 2024/8/1 22:42
 */
@Service
public class UserSettingServiceImpl implements UserSettingService {
    @Resource
    private SystemConfigService systemConfigService;
    @Override
    public void setUserSubmitKeyCount(List<UserSubmitKeyLimitDto> limit) {
        if (limit == null) {
            limit = new ArrayList<>();
        }
        limit.sort((UserSubmitKeyLimitDto o1, UserSubmitKeyLimitDto o2) ->
                o2.getTotalCount() - o1.getTotalCount());
        systemConfigService.setValue(SystemConfigKeyEnum.USER_SUBMIT_KEY_COUNT_LIMIT, new Gson().toJson(limit));
    }
    @Override
    public List<UserSubmitKeyLimitDto> getUserSubmitKeyCountList(boolean fromCache) {
        String value = null;
        if (!fromCache) {
            value = systemConfigService.getValue(SystemConfigKeyEnum.USER_SUBMIT_KEY_COUNT_LIMIT);
        } else {
            value = systemConfigService.getValueCache(SystemConfigKeyEnum.USER_SUBMIT_KEY_COUNT_LIMIT);
        }
        if (StringUtil.isNullOrEmpty(value)) {
            return new ArrayList<>();
        }
        return new Gson().fromJson(value, new TypeToken<List<UserSubmitKeyLimitDto>>() {
        }.getType());
    }
    @Override
    public int getLimitCountByTotalCount(int totalCount) {
        List<UserSubmitKeyLimitDto> list = getUserSubmitKeyCountList(true);
        if (list.size() == 0) {
            return Integer.MAX_VALUE;
        }
        for (UserSubmitKeyLimitDto t : list) {
            if (totalCount >= t.getTotalCount()) {
                return t.getPerCount();
            }
        }
        return Integer.MAX_VALUE;
    }
}
src/main/java/com/taoke/autopay/service/impl/WxUserOrderCountServiceImpl.java
@@ -5,6 +5,7 @@
import com.taoke.autopay.entity.WxUserOrderCount;
import com.taoke.autopay.exception.WxOrderCountException;
import com.taoke.autopay.factory.OrderFactory;
import com.taoke.autopay.service.UserSettingService;
import com.taoke.autopay.service.WxUserOrderCountService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -25,10 +26,29 @@
    @Resource
    private WxUserOrderCountMapper wxUserOrderCountMapper;
    @Resource
    private UserSettingService userSettingService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addOrderCount(Long uid, OrderCountTypeEnum orderType, String day, int count, Integer maxCount) throws WxOrderCountException {
        // 统计用户总次数
        WxUserOrderCountMapper.DaoQuery daoQuery=new WxUserOrderCountMapper.DaoQuery();
        daoQuery.uid = uid;
        daoQuery.orderType=orderType.getType();
        Long totalCount = wxUserOrderCountMapper.sumOrderCount(daoQuery);
        if(totalCount==null){
            totalCount = 0L;
        }
        if(totalCount>Integer.MAX_VALUE){
            totalCount = (long)Integer.MAX_VALUE;
        }
       int submitCount = userSettingService.getLimitCountByTotalCount((int)totalCount.longValue());
        if(maxCount==null){
            maxCount =Integer.MAX_VALUE;
        }
        maxCount = Math.min(submitCount, maxCount);
        WxUserOrderCount info = new WxUserOrderCount();
        info.setDay(day);
        info.setOrderType(orderType.getType());
@@ -48,6 +68,9 @@
            update.setUpdateTime(new Date());
            wxUserOrderCountMapper.updateByPrimaryKeySelective(update);
        } else {
            if (maxCount != null && maxCount < count + 0) {
                throw new WxOrderCountException(String.format("今日超过最大提交次数(%s次)", maxCount));
            }
            info.setCreateTime(new Date());
            info.setOrderCount(count);
            wxUserOrderCountMapper.insertSelective(info);
@@ -55,6 +78,40 @@
    }
    @Override
    public void isOrderCountLimit(Long uid, OrderCountTypeEnum orderType, String day, int count, Integer maxCount) throws WxOrderCountException{
        WxUserOrderCountMapper.DaoQuery daoQuery=new WxUserOrderCountMapper.DaoQuery();
        daoQuery.uid = uid;
        daoQuery.orderType=orderType.getType();
        Long totalCount = wxUserOrderCountMapper.sumOrderCount(daoQuery);
        if(totalCount==null){
            totalCount = 0L;
        }
        if(totalCount>Integer.MAX_VALUE){
            totalCount = (long)Integer.MAX_VALUE;
        }
        int submitCount = userSettingService.getLimitCountByTotalCount((int)totalCount.longValue());
        if(maxCount==null){
            maxCount =Integer.MAX_VALUE;
        }
        maxCount = Math.min(submitCount, maxCount);
        WxUserOrderCount info = new WxUserOrderCount();
        info.setDay(day);
        info.setOrderType(orderType.getType());
        info.setUid(uid);
        info.setId(OrderFactory.createId(info));
        // 判断是否存在
        WxUserOrderCount old = wxUserOrderCountMapper.selectByPrimaryKeyForUpdate(info.getId());
        if (old != null) {
            if (maxCount != null && maxCount < count + old.getOrderCount()) {
                throw new WxOrderCountException(String.format("今日超过最大提交次数(%s次)", maxCount));
            }
        }
    }
    @Override
    public WxUserOrderCount get(Long uid, OrderCountTypeEnum orderType, String day) {
        WxUserOrderCountMapper.DaoQuery daoQuery = new WxUserOrderCountMapper.DaoQuery();
        daoQuery.uid = uid;
src/main/java/com/taoke/autopay/service/impl/agent/ChannelAgentServiceImpl.java
@@ -10,6 +10,7 @@
import org.yeshi.utils.StringUtil;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -123,4 +124,12 @@
        }
        return list.get(0);
    }
    @Override
    public List<ChannelAgent> listByIds(List<Long> ids) {
        if(ids==null||ids.size()==0){
            return new ArrayList<>();
        }
        return channelAgentMapper.listByIds(ids);
    }
}
src/main/java/com/taoke/autopay/service/impl/agent/ChannelAgentSharingRatioServiceImpl.java
@@ -36,6 +36,7 @@
            if (shareRatio.getUpdateTime() != null) {
                shareRatio.setUpdateTime(new Date());
            }
            shareRatio.setId(old.getId());
            channelAgentSharingRatioMapper.updateByPrimaryKeySelective(shareRatio);
        } else {
            if (shareRatio.getCreateTime() == null) {
@@ -52,7 +53,7 @@
        ChannelAgentSharingRatioMapper.DaoQuery daoQuery = new ChannelAgentSharingRatioMapper.DaoQuery();
        daoQuery.agengId = agengId;
        daoQuery.orderChannel = orderChannel;
        daoQuery.count = 0;
        daoQuery.count = 1;
        List<ChannelAgentSharingRatio> list = channelAgentSharingRatioMapper.list(daoQuery);
        if (list.isEmpty()) {
            return null;
src/main/java/com/taoke/autopay/utils/order/OrderChannelUtil.java
New file
@@ -0,0 +1,21 @@
package com.taoke.autopay.utils.order;
import com.taoke.autopay.entity.OrderChannelEnum;
/**
 * @author hxh
 * @title: OrderChannelUtil
 * @description: TODO
 * @date 2024/7/31 0:20
 */
public class OrderChannelUtil {
    public static OrderChannelEnum getChannelByKey(String key) {
        for (OrderChannelEnum channel : OrderChannelEnum.values()) {
            if (channel.getKey().equalsIgnoreCase(key)) {
                return channel;
            }
        }
        return null;
    }
}
src/main/java/com/taoke/autopay/vo/admin/AdminOrderVO.java
@@ -24,6 +24,8 @@
    private Date createTime;
    private Date excutePayTime;
    private Date payTime;
    private String agent;
    private String orderChannel;
    public String getId() {
        return id;
@@ -128,4 +130,20 @@
    public void setPayTime(Date payTime) {
        this.payTime = payTime;
    }
    public String getAgent() {
        return agent;
    }
    public void setAgent(String agent) {
        this.agent = agent;
    }
    public String getOrderChannel() {
        return orderChannel;
    }
    public void setOrderChannel(String orderChannel) {
        this.orderChannel = orderChannel;
    }
}
src/main/java/com/taoke/autopay/vo/admin/OrderSearchVO.java
@@ -1,38 +1,20 @@
package com.taoke.autopay.vo.admin;
import lombok.Data;
/**
 * @author hxh
 * @title: OrderSearchVO
 * @description: 订单搜索
 * @date 2024/7/18 22:33
 */
@Data
public class OrderSearchVO {
    private int keyType;
    private String key;
    private String state;
    private String orderChannel;
    private String startDate;
    private String endDate;
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getStartDate() {
        return startDate;
    }
    public void setStartDate(String startDate) {
        this.startDate = startDate;
    }
    public String getEndDate() {
        return endDate;
    }
    public void setEndDate(String endDate) {
        this.endDate = endDate;
    }
}
src/main/resources/application.yml
@@ -1,3 +1,3 @@
spring:
  profiles:
    active: dev
    active: pro
src/main/resources/mapper/ChannelAgentMapper.xml
@@ -53,6 +53,18 @@
        </if>
        limit #{query.start},#{query.count}
    </select>
    <select id="listByIds" resultMap="BaseResultMap">select
        <include refid="Base_Column_List"/>
        from table_agent where 1=1
        <foreach collection="ids" item="item" open=" AND (" close=")" separator=" or ">
            _id=#{item}
        </foreach>
    </select>
    <select id="count" resultType="java.lang.Long">select count(*) from table_agent where 1=1
        <include refid="listWhereSQL"/>
    </select>
src/main/resources/mapper/KeyOrderMapper.xml
@@ -61,6 +61,9 @@
        <if test="query.hasPayTime!=null">AND pay_time is not null</if>
        <if test="query.hasAgentId!=null">AND agent_id is not null</if>
        <if test="query.agentId!=null">AND agent_id = #{query.agentId}</if>
        <if test="query.orderChannel!=null">AND order_channel = #{query.orderChannel}</if>
        <if test="query.stateList!=null">
            <foreach collection="query.stateList" item="state" separator=" or " open=" AND (" close=") ">state =
                #{state}
src/main/resources/mapper/UserPayCountMapper.xml
New file
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.taoke.autopay.dao.UserPayCountMapper">
  <resultMap id="BaseResultMap" type="com.taoke.autopay.entity.UserPayCount">
    <id column="_id" property="id" jdbcType="BIGINT"/>
    <result column="_submit_key_count" property="submitKeyCount" jdbcType="BIGINT"/>
    <result column="_psy_count" property="payCount" jdbcType="BIGINT"/>
    <result column="_create_time" property="createTime" jdbcType="TIMESTAMP"/>
    <result column="_update_time" property="updateTime" jdbcType="TIMESTAMP"/>
  </resultMap>
  <sql id="Base_Column_List">_id,_submit_key_count,_psy_count,_create_time,_update_time</sql>
  <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_user_pay_count where _id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectByPrimaryKeyForUpdate" resultMap="BaseResultMap" parameterType="java.lang.Long">select
    <include refid="Base_Column_List"/> from table_user_pay_count where _id = #{id,jdbcType=BIGINT} for update
  </select>
  <sql id="listWhereSQL">
    <if test="query.id!=null">AND _id = #{query.id}</if>
    <if test="query.submitKeyCount!=null">AND _submit_key_count = #{query.submitKeyCount}</if>
    <if test="query.payCount!=null">AND _psy_count = #{query.payCount}</if>
    <if test="query.minCreateTime!=null">AND _create_time >= #{query.minCreateTime}</if>
    <if test="query.maxCreateTime!=null">AND #{query.maxCreateTime} > _create_time</if>
    <if test="query.minUpdateTime!=null">AND _update_time >= #{query.minUpdateTime}</if>
    <if test="query.maxUpdateTime!=null">AND #{query.maxUpdateTime} > _update_time</if>
  </sql>
  <select id="list" resultMap="BaseResultMap">select
    <include refid="Base_Column_List"/> from table_user_pay_count where 1=1
    <include refid="listWhereSQL"/>
    <if test="query.sortList!=null">
      <foreach collection="query.sortList" item="item" open=" order by " separator=",">#{item}</foreach>
    </if>limit #{query.start},#{query.count}
  </select>
  <select id="count" resultType="java.lang.Long">select count(*) from table_user_pay_count where 1=1
    <include refid="listWhereSQL"/>
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">delete from table_user_pay_count where _id = #{id,jdbcType=BIGINT}</delete>
  <insert id="insert" parameterType="com.taoke.autopay.entity.UserPayCount" useGeneratedKeys="true" keyProperty="id">insert into table_user_pay_count (_id,_submit_key_count,_psy_count,_create_time,_update_time) values (#{id,jdbcType=BIGINT},#{submitKeyCount,jdbcType=BIGINT},#{payCount,jdbcType=BIGINT},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert>
  <insert id="insertSelective" parameterType="com.taoke.autopay.entity.UserPayCount" useGeneratedKeys="true" keyProperty="id">insert into table_user_pay_count
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">_id,</if>
      <if test="submitKeyCount != null">_submit_key_count,</if>
      <if test="payCount != null">_psy_count,</if>
      <if test="createTime != null">_create_time,</if>
      <if test="updateTime != null">_update_time,</if>
    </trim>values
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">#{id,jdbcType=BIGINT},</if>
      <if test="submitKeyCount != null">#{submitKeyCount,jdbcType=BIGINT},</if>
      <if test="payCount != null">#{payCount,jdbcType=BIGINT},</if>
      <if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
    </trim>
  </insert>
  <update id="updateByPrimaryKey" parameterType="com.taoke.autopay.entity.UserPayCount">update table_user_pay_count set _submit_key_count = #{submitKeyCount,jdbcType=BIGINT},_psy_count = #{payCount,jdbcType=BIGINT},_create_time = #{createTime,jdbcType=TIMESTAMP},_update_time = #{updateTime,jdbcType=TIMESTAMP} where _id = #{id,jdbcType=BIGINT}</update>
  <update id="updateByPrimaryKeySelective" parameterType="com.taoke.autopay.entity.UserPayCount">update table_user_pay_count
    <set>
      <if test="submitKeyCount != null">_submit_key_count=#{submitKeyCount,jdbcType=BIGINT},</if>
      <if test="payCount != null">_psy_count=#{payCount,jdbcType=BIGINT},</if>
      <if test="createTime != null">_create_time=#{createTime,jdbcType=TIMESTAMP},</if>
      <if test="updateTime != null">_update_time=#{updateTime,jdbcType=TIMESTAMP},</if>
    </set> where _id = #{id,jdbcType=BIGINT}
  </update>
</mapper>
src/main/resources/mapper/WxUserOrderCountMapper.xml
@@ -39,6 +39,13 @@
  <select id="count" resultType="java.lang.Long">select count(*) from table_wx_user_order_count where 1=1
    <include refid="listWhereSQL"/>
  </select>
  <select id="sumOrderCount" resultType="java.lang.Long">select sum(order_count) from table_wx_user_order_count where 1=1
    <include refid="listWhereSQL"/>
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">delete from table_wx_user_order_count where id = #{id,jdbcType=BIGINT}</delete>
  <insert id="insert" parameterType="com.taoke.autopay.entity.WxUserOrderCount" useGeneratedKeys="true" keyProperty="id">insert into table_wx_user_order_count (id,day,uid,order_count,order_type,create_time,update_time) values (#{id,jdbcType=VARCHAR},#{day,jdbcType=VARCHAR},#{uid,jdbcType=BIGINT},#{orderCount,jdbcType=VARCHAR},#{orderType,jdbcType=VARCHAR},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert>
  <insert id="insertSelective" parameterType="com.taoke.autopay.entity.WxUserOrderCount" useGeneratedKeys="true" keyProperty="id">insert into table_wx_user_order_count
src/main/resources/static/admin/agent-withdraw-list.html
@@ -41,8 +41,8 @@
                    </div>
                    <button class="layui-btn layui-btn-normal" lay-submit lay-filter="search" id="search"><i
                            class="layui-icon layui-icon-search"></i>搜索</button>
                    <a href="javascript:void();" class="layui-btn" id="pass"> 通过</a>
                    <a href="javascript:void();" class="layui-btn layui-btn-danger" id="reject"> 驳回</a>
                    <a href="javascript:void();" class="layui-btn layui-disabled"  onclick="passWidthdraw()" id="pass"> 通过</a>
                    <a href="javascript:void();" class="layui-btn layui-btn-danger layui-disabled"   onclick="rejectWidthdraw()" id="reject"> 驳回</a>
                </div>
            </form>
            <div class="layui-form" id="table-list">
@@ -58,7 +58,7 @@
        <!-- <script src="js/common.js" type="text/javascript" charset="utf-8"></script> -->
        <script>
            function passWidthdraw() {
                var checkStatus = table.checkStatus('table');
                var checkStatus = layui.table.checkStatus('table');
                if(checkStatus.data.length<=0){
                        layer.msg("尚未选中数据");
                    return;
@@ -93,7 +93,7 @@
            function rejectWidthdraw() {
                var checkStatus = table.checkStatus('table');
                var checkStatus = layui.table.checkStatus('table');
                if(checkStatus.data.length<=0){
                        layer.msg("尚未选中数据");
                    return;
@@ -267,15 +267,16 @@
                //第一个实例
                let tableIns = table.render(table_option);
                table.on('checkbox(table)', function(obj) {
                    console.log(obj)
                    // 查询是否要选中
                    var checkStatus = table.checkStatus('table');
                    console.log(checkStatus)
                    if (checkStatus.data.length <= 0) {
                        $("#pass").addClass("disabled");
                        $("#reject").addClass("disabled");
                        $("#pass").addClass("layui-disabled");
                        $("#reject").addClass("layui-disabled");
                    } else {
                        $("#pass").removeClass("disabled");
                        $("#reject").removeClass("disabled");
                        $("#pass").removeClass("layui-disabled");
                        $("#reject").removeClass("layui-disabled");
                    }
                });
src/main/resources/static/admin/index.html
@@ -28,28 +28,29 @@
                  <li class="layui-nav-item layui-nav-itemed">
                    <a href="javascript:;"><i class="iconfont">&#xe606;</i>用户管理</a>
                    <dl class="layui-nav-child">
                      <dd><a href="javascript:;" data-url="user-list.html" data-id='1' data-text="用户列表"><span class="l-line"></span>用户列表</a></dd>
                      <dd><a href="javascript:;" data-url="user-list.html" data-id='11' data-text="用户列表"><span class="l-line"></span>用户列表</a></dd>
                    </dl>
                  </li>
                  <li class="layui-nav-item">
                    <a href="javascript:;"><i class="iconfont">&#xe606;</i>代理管理</a>
                    <dl class="layui-nav-child">
                                        <dd><a href="javascript:;" data-url="agent-list.html" data-id='10' data-text="渠道代理"><span class="l-line"></span>渠道代理</a></dd>
                                      <dd><a href="javascript:;" data-url="agent-settle-list.html" data-id='11' data-text="代理结算"><span class="l-line"></span>代理结算</a></dd>
                                      <dd><a href="javascript:;" data-url="agent-withdraw-list.html" data-id='12' data-text="代理提现"><span class="l-line"></span>代理提现</a></dd>
                                        <dd><a href="javascript:;" data-url="agent-list.html" data-id='20' data-text="渠道代理"><span class="l-line"></span>渠道代理</a></dd>
                                      <dd><a href="javascript:;" data-url="agent-settle-list.html" data-id='21' data-text="代理结算"><span class="l-line"></span>代理结算</a></dd>
                                      <dd><a href="javascript:;" data-url="agent-withdraw-list.html" data-id='22' data-text="代理提现"><span class="l-line"></span>代理提现</a></dd>
                    </dl>
                  </li>
                  <li class="layui-nav-item">
                    <a href="javascript:;"><i class="iconfont">&#xe608;</i>订单管理</a>
                    <dl class="layui-nav-child">
                      <dd><a href="javascript:;" data-url="order-list.html" data-id='3' data-text="订单列表"><span class="l-line"></span>订单列表</a></dd>
                      <dd><a href="javascript:;" data-url="order-list.html" data-id='30' data-text="订单列表"><span class="l-line"></span>订单列表</a></dd>
                    </dl>
                  </li>
                  <li class="layui-nav-item">
                    <a href="javascript:;"><i class="iconfont">&#xe60b;</i>系统设置</a>
                    <dl class="layui-nav-child">
                      <dd><a href="javascript:;" data-url="pay_settings.html" data-id='5' data-text="付款金额设置"><span class="l-line"></span>付款金额设置</a></dd>
                      <dd><a href="javascript:;" data-url="settings_edit.html" data-id='4' data-text="默认参数设置"><span class="l-line"></span>默认参数设置</a></dd>
                      <dd><a href="javascript:;" data-url="pay_settings.html" data-id='40' data-text="付款金额设置"><span class="l-line"></span>付款金额设置</a></dd>
                      <dd><a href="javascript:;" data-url="settings_edit.html" data-id='41' data-text="默认参数设置"><span class="l-line"></span>默认参数设置</a></dd>
                      <dd><a href="javascript:;" data-url="user-actioncount-limit.html" data-id='42' data-text="限制代付单数"><span class="l-line"></span>限制代付单数</a></dd>
                    </dl>
                  </li>
                  <li class="layui-nav-item">
src/main/resources/static/admin/order-list.html
@@ -8,8 +8,8 @@
        <meta name="viewport"
            content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <title>订单列表</title>
        <link rel="stylesheet" type="text/css" href="/admin/layui/css/layui.css" />
        <link rel="stylesheet" type="text/css" href="/admin/css/admin.css" />
        <link rel="stylesheet" type="text/css" href="./layui/css/layui.css" />
        <link rel="stylesheet" type="text/css" href="./css/admin.css" />
    </head>
    <body>
@@ -18,21 +18,49 @@
                <div class="layui-form-item">
                    <div class="layui-inline">
                        <input type="text" name="key" id="key" placeholder="老铁ID/订单号搜索" autocomplete="off"
                            class="layui-input">
                        <select name="keyType" >
                               <option value="0">按老铁ID</option>
                               <option value="1">按代理ID</option>
                               <option value="2">按订单号</option>
                               <option value="3">按支付设备ID</option>
                        </select>
                    </div>
                    <div class="layui-inline">
                        <input type="text" name="startDate"  placeholder="开始时间" autocomplete="off"
                        <input type="text" name="key" id="key" placeholder="搜索" autocomplete="off"
                               class="layui-input">
                    </div>
                    <div class="layui-inline">
                        <input type="text" name="endDate"  placeholder="结束时间" autocomplete="off"
                               class="layui-input">
                     <select name="state" >
                            <option value="">全部状态</option>
                            <option value="1">未支付</option>
                            <option value="2">支付成功</option>
                            <option value="3">支付失败</option>
                          </select>
                    </div>
                    <div class="layui-inline">
                        <select name="orderChannel" >
                               <option value="">全部订单渠道</option>
                               <option value="cyx">超佣享</option>
                               <option value="bps">爆品社</option>
                               <option value="unknown">卡金额</option>
                        </select>
                    </div>
                    <div class="layui-inline">
                        <input type="text" name="startDate" placeholder="开始日期" autocomplete="off" class="layui-input">
                    </div>
                    <div class="layui-inline">
                        <input type="text" name="endDate" placeholder="结束日期" autocomplete="off" class="layui-input">
                    </div>
                    <button class="layui-btn layui-btn-normal" lay-submit lay-filter="search" id="search">搜索</button>
                    <button class="layui-btn layui-btn-normal layui-btn-xs" lay-submit lay-filter="download" id="download">下载</button>
                    <button class="layui-btn layui-btn-normal layui-btn-xs" lay-submit lay-filter="download"
                        id="download">下载</button>
                </div>
            </form>
            <div class="layui-form" id="table-list">
@@ -119,6 +147,19 @@
                            },
                            {
                                field: 'agent',
                                title: '渠道代理',
                                width: 100,
                                sort: false,
                            },
                            {
                                field: 'orderChannel',
                                title: '订单渠道',
                                width: 100,
                                sort: false,
                            },
                            {
                                field: 'orderNo',
                                title: '订单编号',
                                width: 180,
@@ -131,7 +172,14 @@
                                width: 100,
                                sort: false,
                                templet: function(d) {
                                    return d.orderType == 1 ? '抖音' : '其它'
                                    switch (d.orderType) {
                                        case 1:
                                            return "抖音";
                                        case 2:
                                            return "快手";
                                        default:
                                            return "其它";
                                    }
                                }
                            },
@@ -141,7 +189,17 @@
                                title: '执行状态',
                                width: 100,
                                templet: function(d) {
                                    return d.state == 0 ? "未执行" : (d.state == 1 ? "已执行" : "执行错误")
                                    switch(d.state){
                                        case 0:
                                         return "未分配";
                                        case 1:
                                            return "未执行";
                                        case 2:
                                            return "支付成功"
                                        case 3:
                                            return "支付失败"
                                    }
                                    return ""
                                }
                            }, {
                                field: 'stateDesc',
src/main/resources/static/admin/user-actioncount-limit.html
New file
@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
            content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <title>用户次数限制</title>
        <link rel="stylesheet" type="text/css" href="layui/css/layui.css" />
        <style>
            body {
                padding: 10px;
            }
            input {
                display: inline;
            }
            .layui-form-item {
                padding: 0 20px;
                display: flex;
                align-items: center;
            }
            .layui-icon {
                margin-left: 10px;
            }
            input[type=text] {
                margin: 0 10px;
                width: 80px !important;
            }
        </style>
    </head>
    <body>
        <form class="layui-form" lay-filter="edit">
            <div class="layui-form-item">
                <label class="layui-form-label"></label>
                <div class="layui-input-inline">
                    <input class="layui-btn layui-btn-danger" id="add" type="button" value="新增条件" />
                </div>
            </div>
            <div class="layui-input-block">
                <button class="layui-btn layui-btn-normal" lay-submit lay-filter="sure" id="sure">确定</button>
            </div>
        </form>
        <script src="layui/layui.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/jquery.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/http_api.js"></script>
        <script type="text/html" id="payMoneyTemplate">
            <div class="layui-form-item">
                <span>以往订单>=</span>
                <input type="text" name="totalCount_{{d.index}}" required lay-verify="required|num" placeholder="正整数"
                    autocomplete="off" value="{{ d.totalCount }}" class="layui-input totalCount">
                <span>单,限制提交</span>
                <input type="text" name="perCount_{{d.index}}" required lay-verify="required|num" placeholder="正整数"
                    autocomplete="off" value="{{ d.perCount }}" class="layui-input">
                <span>单</span>
                <span class="layui-icon layui-icon-close delete"></span>
            </div>
        </script>
        <script>
            layui.use(['form', 'layedit', 'laydate', 'laytpl'], function() {
                var form = layui.form,
                    layer = layui.layer,
                    laydate = layui.laydate,
                    laytpl = layui.laytpl;
                laydate.render({
                    elem: "#start_submit_time",
                    type: "time",
                    value: new Date(),
                    isInitValue: false
                });
                laydate.render({
                    elem: "#end_submit_time",
                    type: "time",
                    value: new Date(),
                    isInitValue: false
                });
                $("#add").click(function() {
                    const index = $(".totalCount").length + 1;
                    laytpl($('#payMoneyTemplate').html()).render({
                        "index": index,
                        "totalCount": "",
                        "perCount": ""
                    }, function(html) {
                        $("#add").parent().parent().before(html);
                    });
                    $(".delete").bind("click", function(e) {
                        $(e.target).parent().remove();
                    });
                });
                // 在 iframe 内部的子页面中
                // 示例:向父页面发送消息
                window.parent.postMessage('Hello from iframe child!', window.location.href);
                //自定义验证规则
                form.verify({
                    money: [/^\d+(\.\d{1,2})?$/, "金额最多保留2位小数"],
                    num: [/^\d+$/, "必须为正整数"]
                });
                let index = layer.load(1);
                $.post("/admin/api/settings/getUserSubmitKeyCountSetting", {},
                    function(response) {
                        layer.close(index);
                        if (response.code == 0) {
                            // 设置资金
                            for (var i = 0; i < response.data.length; i++) {
                                let item = response.data[i];
                                laytpl($('#payMoneyTemplate').html()).render({
                                    "index": i + 1,
                                    "totalCount": item.totalCount,
                                    "perCount": item.perCount
                                }, function(html) {
                                    $("#add").parent().parent().before(html);
                                    $(".delete").bind("click", function(e) {
                                        $(e.target).parent().remove();
                                    });
                                });
                            }
                        } else {
                            layer.msg(response.msg);
                        }
                    }, 'json').fail(function(jqXHR, textStatus, errorThrown) {
                    layer.msg("网络请求失败");
                    layer.close(index);
                });
                //监听提交
                form.on('submit(sure)', function(data) {
                    var params = [];
                    for (var key in data.field) {
                        if (key.indexOf("totalCount_") == 0) {
                            let index = key.replace("totalCount_", "");
                            params.push({
                                "totalCount": data.field[key],
                                "perCount": data.field["perCount_" + index]
                            });
                        }
                    }
                    console.log(params);
                    $.post("/admin/api/settings/setUserSubmitKeyCount",{ value: JSON.stringify(params)},
                        function(response) {
                            if (response.code == 0) {
                                layer.msg("修改成功");
                            } else {
                                layer.msg(response.msg);
                            }
                        }, 'json').fail(function(jqXHR, textStatus, errorThrown) {
                        layer.msg("网络请求失败");
                    });
                    return false;
                });
            });
        </script>
    </body>
</html>
src/main/resources/static/agent/css/index.css
@@ -4,7 +4,7 @@
}
[v-cloak] {
    display: none;
    display: none !important;
}
.top {
@@ -138,8 +138,9 @@
    display: flex;
    justify-content: space-between;
    color: #888888;
    padding: 0.23rem;
    align-items: flex-end;
    padding:0 0.23rem;
    height: 0.9rem;
    align-items: center;
    background-color: #FFF;
    position: absolute;
    top: 0.8rem;
src/main/resources/static/agent/index.html
@@ -69,6 +69,10 @@
                        <span>共</span>
                        <span class="red">{{order_statistic.order_count}}</span>
                        <span>笔</span>
                        <br>
                        <span>有效</span>
                        <span class="red">{{order_statistic.valid_order_count}}</span>
                        <span>笔</span>
                        <span>共</span>
                        <span class="red">{{order_statistic.total_money}}</span>
@@ -135,6 +139,7 @@
                                    <div class="title">订单数量</div>
                                    <div class="val">{{item.orderCount}}</div>
                                </div>
                                <div>
                                    <div class="title">提现金额</div>
                                    <div class="val">¥{{item.money}}</div>
src/main/resources/static/agent/js/index.js
@@ -12,6 +12,7 @@
            order_statistic: {
                user_count: 0,
                order_count: 0,
                valid_order_count:0,
                total_money: 0.00
            },
            config:{}
@@ -70,8 +71,7 @@
            },
            
            getConfig:function(){
                http_util.post("/agentapi/admin/getConfig", {
                }, function(res) {
                http_util.post("/agentapi/admin/getConfig", {}, function(res) {
                    if (res.code == 0) {
                        app.config = res.data;
                    }
@@ -92,7 +92,8 @@
                        }
                        app.orders = app.orders.concat(res.data.list);
                        app.order_statistic.order_count = res.data.count;
                        app.order_statistic.user_count = res.data.statistic.count;
                        app.order_statistic.valid_order_count = res.data.statistic.count;
                        app.order_statistic.user_count = res.data.statistic.userCount;
                        app.order_statistic.total_money = res.data.statistic.money;
                        if (app.orders.length < app.order_statistic.order_count) {
                            app.hasMore = true;
@@ -129,6 +130,7 @@
                app.order_statistic = {
                    user_count: 0,
                    order_count: 0,
                    valid_order_count: 0,
                    total_money: 0.00
                };
                app.requestOrders();
src/test/java/com/taoke/autopay/KeyTest.java
@@ -3,6 +3,7 @@
import com.taoke.autopay.dao.KeyOrderMapper;
import com.taoke.autopay.dto.DYOrderDto;
import com.taoke.autopay.entity.KeyOrder;
import com.taoke.autopay.entity.OrderCountTypeEnum;
import com.taoke.autopay.entity.SystemConfigKeyEnum;
import com.taoke.autopay.exception.KeyOrderException;
import com.taoke.autopay.exception.KeyVerifyException;
@@ -116,4 +117,23 @@
        System.out.println(list);
    }
    @Test
    public void repaire(){
        KeyOrderMapper.DaoQuery query=new KeyOrderMapper.DaoQuery();
        query.state=3;
        query.minCreateTime=new Date(TimeUtil.convertToTimeTemp("2024-08-02","yyyy-MM-dd"));
        query.stateDesc="订单已支付";
        query.count = 1000;
        List<KeyOrder>  list =  keyOrderService.list(query);
        for(KeyOrder o:list){
            KeyOrder update=new KeyOrder();
            update.setId(o.getId());
            update.setState(KeyOrder.STATE_PAY);
            update.setPayTime(o.getExcutePayTime());
            keyOrderService.update(update);
        }
    }
}
src/test/java/com/taoke/autopay/MapperTest.java
@@ -1,6 +1,7 @@
package com.taoke.autopay;
import com.taoke.autopay.entity.KeyOrder;
import com.taoke.autopay.entity.UserPayCount;
import com.taoke.autopay.entity.agent.*;
import org.junit.jupiter.api.Test;
import org.yeshi.utils.generater.GeneraterManagerV2;
@@ -32,12 +33,12 @@
//        System.out.println(   MyBatisMapperUtil.createSQL(ChannelAgentOrderStatisticRecord.class));
//        System.out.println(   MyBatisMapperUtil.createSQL(ChannelAgentSettings.class));
//        System.out.println(MyBatisMapperUtil.createSQL(ChannelAgentSettleRecord.class));
        System.out.println(   MyBatisMapperUtil.createSQL(ChannelAgentSettleDetail.class));
        System.out.println(   MyBatisMapperUtil.createSQL(UserPayCount.class));
//        MyBatisMapperUtil.createMapper(ChannelAgentOrderStatisticRecord.class);
//        MyBatisMapperUtil.createMapper(ChannelAgentSettings.class);
//        MyBatisMapperUtil.createMapper(ChannelAgentSettleRecord.class);
        MyBatisMapperUtil.createMapper(ChannelAgentSettleDetail.class);
        MyBatisMapperUtil.createMapper(UserPayCount.class);
//      System.out.println(  new BigDecimal("3.26").multiply(new BigDecimal(100)).setScale(0, RoundingMode.FLOOR).intValue());
src/test/java/com/taoke/autopay/WxUserTests.java
@@ -1,5 +1,10 @@
package com.taoke.autopay;
import com.taoke.autopay.dao.WxUserOrderCountMapper;
import com.taoke.autopay.entity.OrderCountTypeEnum;
import com.taoke.autopay.exception.WxOrderCountException;
import com.taoke.autopay.service.UserSettingService;
import com.taoke.autopay.service.WxUserOrderCountService;
import com.taoke.autopay.service.WxUserService;
import com.taoke.autopay.utils.Constant;
import org.junit.jupiter.api.Test;
@@ -20,9 +25,42 @@
    @Resource
    private WxUserService wxUserService;
    @Resource
    private UserSettingService userSettingService;
    @Test
    public void addWxUser(){
//        wxUserService.login("1231231231231234");
    }
    @Test
    public void getPercount() {
        int[] tc = new int[]{1000, 500, 400, 300, 200, 100};
        for (int t : tc) {
            System.out.println(t + "=>" + userSettingService.getLimitCountByTotalCount(t));
        }
    }
    @Resource
    private WxUserOrderCountService wxUserOrderCountService;
    @Resource
    private WxUserOrderCountMapper wxUserOrderCountMapper;
    @Test
    public void testAdd() throws WxOrderCountException {
        long uid = 2L;
        String day="2024-08-01";
        wxUserOrderCountService.addOrderCount(uid, OrderCountTypeEnum.SUBMIT_TOKEN_COUNT, day, 1,100);
    }
    @Test
    public void test1() throws WxOrderCountException {
        WxUserOrderCountMapper.DaoQuery daoQuery=new WxUserOrderCountMapper.DaoQuery();
        daoQuery.uid = 45678942L;
      System.out.println(  wxUserOrderCountMapper.sumOrderCount(daoQuery));
    }
}