11个文件已添加
12个文件已修改
1 文件已重命名
File was renamed from src/main/java/com/taoke/autopay/controller/admin/AdminClientInfoJS2Controller.java |
| | |
| | | package com.taoke.autopay.controller.admin; |
| | | package com.taoke.autopay.controller.admin.js2; |
| | | |
| | | import com.google.gson.Gson; |
| | | import com.google.gson.GsonBuilder; |
| | |
| | | import com.taoke.autopay.service.ClientInfoService; |
| | | import com.taoke.autopay.utils.Constant; |
| | | import com.taoke.autopay.utils.TimeUtil; |
| | | import com.taoke.autopay.utils.encrypt.AESUtil; |
| | | import com.taoke.autopay.vo.admin.AdminOrderClientInfoVO; |
| | | import net.sf.json.JSONObject; |
| | | import org.springframework.stereotype.Controller; |
| | |
| | | import org.springframework.web.bind.annotation.ResponseBody; |
| | | import org.yeshi.utils.JsonUtil; |
| | | import org.yeshi.utils.StringUtil; |
| | | import org.yeshi.utils.encrypt.AESUtil; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.IOException; |
New file |
| | |
| | | package com.taoke.autopay.controller.admin.js2; |
| | | |
| | | import com.google.gson.Gson; |
| | | import com.google.gson.GsonBuilder; |
| | | import com.google.gson.TypeAdapter; |
| | | import com.google.gson.stream.JsonReader; |
| | | import com.google.gson.stream.JsonWriter; |
| | | import com.taoke.autopay.dao.OrderTaskExecutionDetailMapper; |
| | | import com.taoke.autopay.dao.OrderTaskMapper; |
| | | import com.taoke.autopay.entity.js2.OrderTask; |
| | | import com.taoke.autopay.entity.js2.OrderTaskExecutionDetail; |
| | | import com.taoke.autopay.exception.OrderTaskException; |
| | | import com.taoke.autopay.factory.js2.OrderTaskFactory; |
| | | import com.taoke.autopay.service.js2.OrderTaskService; |
| | | import com.taoke.autopay.utils.TimeUtil; |
| | | import com.taoke.autopay.vo.admin.js2.OrderTaskVO; |
| | | import net.sf.json.JSONObject; |
| | | import org.springframework.stereotype.Controller; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.ResponseBody; |
| | | import org.yeshi.utils.JsonUtil; |
| | | import org.yeshi.utils.StringUtil; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.IOException; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.Calendar; |
| | | import java.util.ArrayList; |
| | | |
| | | /** |
| | | * 下单任务管理 |
| | | */ |
| | | @Controller |
| | | @RequestMapping("/admin/api/ordertask/js2") |
| | | public class AdminOrderTaskController { |
| | | |
| | | @Resource |
| | | private OrderTaskService orderTaskService; |
| | | |
| | | @Resource |
| | | private OrderTaskExecutionDetailMapper orderTaskExecutionDetailMapper; |
| | | |
| | | private Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new TypeAdapter<Date>() { |
| | | @Override |
| | | public void write(JsonWriter out, Date value) throws IOException { |
| | | String desc = ""; |
| | | if (value != null) { |
| | | // 判断是否是同一天 |
| | | desc = TimeUtil.getGernalTime(value.getTime(), "yyyy-MM-dd HH:mm:ss"); |
| | | out.value(desc); |
| | | } else { |
| | | out.value(""); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Date read(JsonReader in) throws IOException { |
| | | return new Date(); |
| | | } |
| | | }).create(); |
| | | |
| | | /** |
| | | * 任务列表查询(按照关键字,日期查询) |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("list") |
| | | public String list(String keyword, String startDate, String endDate, Integer status, int page, int limit) { |
| | | try { |
| | | OrderTaskMapper.DaoQuery query = new OrderTaskMapper.DaoQuery(); |
| | | if (!StringUtil.isNullOrEmpty(keyword)) { |
| | | query.keywordContent = keyword; |
| | | } |
| | | |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | if (!StringUtil.isNullOrEmpty(startDate)) { |
| | | query.minCreateTime = sdf.parse(startDate); |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(endDate)) { |
| | | Date end = sdf.parse(endDate); |
| | | // 设置为当天的最后时刻 |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(end); |
| | | cal.set(Calendar.HOUR_OF_DAY, 23); |
| | | cal.set(Calendar.MINUTE, 59); |
| | | cal.set(Calendar.SECOND, 59); |
| | | query.maxCreateTime = cal.getTime(); |
| | | } |
| | | |
| | | if (status != null) { |
| | | query.status = status; |
| | | } |
| | | |
| | | query.sortList = Arrays.asList(new String[]{"create_time desc"}); |
| | | query.start = (page - 1) * limit; |
| | | query.count = limit; |
| | | |
| | | List<OrderTask> list = orderTaskService.listOrderTasks(query, page, limit); |
| | | long count = orderTaskService.countOrderTasks(query); |
| | | |
| | | // 转换为VO对象 |
| | | List<OrderTaskVO> voList = new ArrayList<>(); |
| | | for (OrderTask orderTask : list) { |
| | | voList.add(OrderTaskFactory.createOrderTaskVO(orderTask)); |
| | | } |
| | | |
| | | JSONObject data = new JSONObject(); |
| | | data.put("list", gson.toJson(voList)); |
| | | data.put("count", count); |
| | | return JsonUtil.loadTrueResult(data); |
| | | } catch (ParseException e) { |
| | | return JsonUtil.loadFalseResult("日期格式错误"); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取单个任务信息 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("get") |
| | | public String get(Long id) { |
| | | try { |
| | | if (id == null) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | OrderTask orderTask = orderTaskService.getOrderTaskById(id); |
| | | if (orderTask == null) { |
| | | return JsonUtil.loadFalseResult("任务不存在"); |
| | | } |
| | | |
| | | OrderTaskVO orderTaskVO = OrderTaskFactory.createOrderTaskVO(orderTask); |
| | | return JsonUtil.loadTrueResult(gson.toJson(orderTaskVO)); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 新增任务 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("add") |
| | | public String add(OrderTaskVO orderTaskVO) { |
| | | try { |
| | | if (orderTaskVO == null) { |
| | | return JsonUtil.loadFalseResult("任务信息不能为空"); |
| | | } |
| | | |
| | | // 将VO转换为实体 |
| | | OrderTask orderTask = OrderTaskFactory.createOrderTask(orderTaskVO); |
| | | OrderTask result = orderTaskService.createOrderTask(orderTask); |
| | | OrderTaskVO resultVO = OrderTaskFactory.createOrderTaskVO(result); |
| | | return JsonUtil.loadTrueResult(gson.toJson(resultVO)); |
| | | } catch (ParseException e) { |
| | | return JsonUtil.loadFalseResult("日期格式错误:" + e.getMessage()); |
| | | } catch (OrderTaskException e) { |
| | | return JsonUtil.loadFalseResult(e.getMessage()); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 删除任务 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("delete") |
| | | public String delete(Long id) { |
| | | try { |
| | | if (id == null) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | orderTaskService.deleteOrderTask(id); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (OrderTaskException e) { |
| | | return JsonUtil.loadFalseResult(e.getMessage()); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 修改任务 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("update") |
| | | public String update(OrderTaskVO orderTaskVO) { |
| | | try { |
| | | if (orderTaskVO == null || orderTaskVO.getId() == null) { |
| | | return JsonUtil.loadFalseResult("任务信息不完整"); |
| | | } |
| | | |
| | | // 先从数据库获取原始任务信息 |
| | | OrderTask orderTask = orderTaskService.getOrderTaskByIdForUpdate(orderTaskVO.getId()); |
| | | if (orderTask == null) { |
| | | return JsonUtil.loadFalseResult("任务不存在"); |
| | | } |
| | | OrderTask newOrderTask = OrderTaskFactory.createOrderTask(orderTaskVO); |
| | | newOrderTask.setUpdateTime(new Date()); |
| | | orderTaskService.updateOrderTask(newOrderTask); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (ParseException e) { |
| | | return JsonUtil.loadFalseResult("日期格式错误:" + e.getMessage()); |
| | | } catch (OrderTaskException e) { |
| | | return JsonUtil.loadFalseResult(e.getMessage()); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 任务客户端分配 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("assign") |
| | | public String assign(Long taskId) { |
| | | try { |
| | | if (taskId == null) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | int result = orderTaskService.assignTask(taskId); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("result", result); |
| | | return JsonUtil.loadTrueResult(data); |
| | | } catch (OrderTaskException e) { |
| | | return JsonUtil.loadFalseResult(e.getMessage()); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 查询任务已分配的客户端列表 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("assignedClients") |
| | | public String assignedClients(Long taskId, int page, int limit) { |
| | | try { |
| | | if (taskId == null) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | OrderTaskExecutionDetailMapper.DaoQuery query = new OrderTaskExecutionDetailMapper.DaoQuery(); |
| | | query.taskId = taskId; |
| | | query.start = (page - 1) * limit; |
| | | query.count = limit; |
| | | query.sortList = Arrays.asList("create_time desc"); |
| | | |
| | | List<OrderTaskExecutionDetail> list = orderTaskExecutionDetailMapper.list(query); |
| | | long count = orderTaskExecutionDetailMapper.count(query); |
| | | |
| | | JSONObject data = new JSONObject(); |
| | | data.put("list", gson.toJson(list)); |
| | | data.put("count", count); |
| | | return JsonUtil.loadTrueResult(data); |
| | | } catch (Exception e) { |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.taoke.autopay.controller.client.js2; |
| | | |
| | | import com.google.gson.Gson; |
| | | import com.google.gson.GsonBuilder; |
| | | import com.google.gson.TypeAdapter; |
| | | import com.google.gson.stream.JsonReader; |
| | | import com.google.gson.stream.JsonWriter; |
| | | import com.taoke.autopay.dao.OrderTaskExecutionDetailMapper; |
| | | import com.taoke.autopay.entity.ClientAdditionalInfo; |
| | | import com.taoke.autopay.entity.js2.OrderTask; |
| | | import com.taoke.autopay.entity.js2.OrderTaskExecutionDetail; |
| | | import com.taoke.autopay.factory.js2.OrderTaskExecutionDetailFactory; |
| | | import com.taoke.autopay.service.ClientAdditionalInfoService; |
| | | import com.taoke.autopay.service.js2.OrderTaskExecutionDetailService; |
| | | import com.taoke.autopay.service.js2.OrderTaskService; |
| | | import com.taoke.autopay.utils.TimeUtil; |
| | | import com.taoke.autopay.vo.OrderTaskExecutionDetailVO; |
| | | import net.sf.json.JSONObject; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.stereotype.Controller; |
| | | 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.io.IOException; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 手机客户端下单任务控制器 |
| | | */ |
| | | @Controller |
| | | @RequestMapping("api/client/js2/task") |
| | | public class OrderTaskController { |
| | | |
| | | @Resource |
| | | private ClientAdditionalInfoService clientAdditionalInfoService; |
| | | |
| | | private Logger loggerTask = LoggerFactory.getLogger("taskLogger"); |
| | | |
| | | private Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new TypeAdapter<Date>() { |
| | | @Override |
| | | public void write(JsonWriter out, Date value) throws IOException { |
| | | String desc = ""; |
| | | if (value != null) { |
| | | desc = TimeUtil.getGernalTime(value.getTime(), "yyyy-MM-dd HH:mm:ss"); |
| | | out.value(desc); |
| | | } else { |
| | | out.value(""); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Date read(JsonReader in) throws IOException { |
| | | return new Date(); |
| | | } |
| | | }).create(); |
| | | |
| | | @Resource |
| | | private OrderTaskExecutionDetailService orderTaskExecutionDetailService; |
| | | |
| | | @Resource |
| | | private OrderTaskService orderTaskService; |
| | | |
| | | /** |
| | | * 获取设备可执行的任务列表 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param page 页码 |
| | | * @param pageSize 每页数量 |
| | | * @return 任务列表 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("list") |
| | | public String list(Long uid, int page, int pageSize) { |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | List<OrderTaskExecutionDetailVO> voList= new ArrayList<>(); |
| | | List<OrderTaskExecutionDetail> list = orderTaskExecutionDetailService.listCanExcuteTaskDetail(uid, (page-1)*pageSize,pageSize); |
| | | if(!list.isEmpty()){ |
| | | List<Long> taskIds=new ArrayList<>(); |
| | | for (OrderTaskExecutionDetail detail : list) { |
| | | if(taskIds.contains(detail.getTaskId())){ |
| | | continue; |
| | | } |
| | | taskIds.add(detail.getTaskId()); |
| | | } |
| | | // 获取手机号与支付宝账号信息 |
| | | ClientAdditionalInfo clientAdditionalInfo = clientAdditionalInfoService.getClientAdditionalInfoByClientId(uid); |
| | | List<OrderTask> orderTaskList = orderTaskService.getOrderTaskByIds(taskIds); |
| | | Map<Long, OrderTask> orderTaskMap=new HashMap<>(); |
| | | for(OrderTask task:orderTaskList){ |
| | | orderTaskMap.put(task.getId(),task); |
| | | } |
| | | for(OrderTaskExecutionDetail detail:list){ |
| | | OrderTaskExecutionDetailVO vo = OrderTaskExecutionDetailFactory.createOrderTaskExecutionDetailVO(orderTaskMap.get(detail.getTaskId()),detail,clientAdditionalInfo); |
| | | voList.add(vo); |
| | | } |
| | | } |
| | | long count = orderTaskExecutionDetailService.countCanExcuteTaskDetail(uid); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("list", gson.toJson(voList)); |
| | | data.put("count", count); |
| | | return JsonUtil.loadTrueResult(data); |
| | | } catch (Exception e) { |
| | | loggerTask.error("获取任务列表失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 下单成功 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param id 任务执行详情ID |
| | | * @param orderNo 订单号 |
| | | * @param productTitle 商品标题 |
| | | * @param shopName 店铺名称 |
| | | * @param orderTimeStr 下单时间字符串 |
| | | * @return 操作结果 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("orderSuccess") |
| | | public String orderSuccess(Long uid, String id, String orderNo, String productTitle, String shopName, String orderTimeStr) { |
| | | loggerTask.info("orderSuccess[{}]: {}-{}-{}-{}-{}", uid, id, orderNo, productTitle, shopName, orderTimeStr); |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(id)) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(orderNo)) { |
| | | return JsonUtil.loadFalseResult("订单号不能为空"); |
| | | } |
| | | |
| | | Date orderTime = null; |
| | | if (!StringUtil.isNullOrEmpty(orderTimeStr)) { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | orderTime = sdf.parse(orderTimeStr); |
| | | } else { |
| | | orderTime = new Date(); |
| | | } |
| | | |
| | | orderTaskExecutionDetailService.orderSuccess(id, orderNo, productTitle, shopName, orderTime); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (ParseException e) { |
| | | loggerTask.error("下单成功处理失败,时间格式错误: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("时间格式错误"); |
| | | } catch (Exception e) { |
| | | loggerTask.error("下单成功处理失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 下单失败,上传失败原因 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param id 任务执行详情ID |
| | | * @param failureReason 失败原因 |
| | | * @return 操作结果 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("orderFailure") |
| | | public String orderFailure(Long uid, String id, String failureReason) { |
| | | loggerTask.info("orderFailure[{}]: {}-{}", uid, id, failureReason); |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(id)) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(failureReason)) { |
| | | return JsonUtil.loadFalseResult("失败原因不能为空"); |
| | | } |
| | | |
| | | orderTaskExecutionDetailService.orderFailure(id, failureReason); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (Exception e) { |
| | | loggerTask.error("下单失败处理失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 确认收货成功,上传券码 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param id 任务执行详情ID |
| | | * @param couponCode 券码 |
| | | * @return 操作结果 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("confirmReceiptSuccess") |
| | | public String confirmReceiptSuccess(Long uid, String id, String couponCode) { |
| | | loggerTask.info("confirmReceiptSuccess[{}]: {}-{}", uid, id, couponCode); |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(id)) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(couponCode)) { |
| | | return JsonUtil.loadFalseResult("券码不能为空"); |
| | | } |
| | | |
| | | orderTaskExecutionDetailService.confirmReceiptSuccess(id, couponCode); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (Exception e) { |
| | | loggerTask.error("确认收货成功处理失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 确认收货失败,上传失败原因 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param id 任务执行详情ID |
| | | * @param reason 失败原因 |
| | | * @return 操作结果 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("confirmReceiptFailure") |
| | | public String confirmReceiptFailure(Long uid, String id, String reason) { |
| | | loggerTask.info("confirmReceiptFailure[{}]: {}-{}", uid, id, reason); |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(id)) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(reason)) { |
| | | return JsonUtil.loadFalseResult("失败原因不能为空"); |
| | | } |
| | | |
| | | orderTaskExecutionDetailService.confirmReceiptFailure(id, reason); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (Exception e) { |
| | | loggerTask.error("确认收货失败处理失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 评价成功 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param id 任务执行详情ID |
| | | * @return 操作结果 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("reviewSuccess") |
| | | public String reviewSuccess(Long uid, String id) { |
| | | loggerTask.info("reviewSuccess[{}]: {}", uid, id); |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(id)) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | orderTaskExecutionDetailService.reviewSuccess(id); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (Exception e) { |
| | | loggerTask.error("评价成功处理失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 评价失败,上传失败原因 |
| | | * |
| | | * @param uid 客户端ID |
| | | * @param id 任务执行详情ID |
| | | * @param reason 失败原因 |
| | | * @return 操作结果 |
| | | */ |
| | | @ResponseBody |
| | | @RequestMapping("reviewFailure") |
| | | public String reviewFailure(Long uid, String id, String reason) { |
| | | loggerTask.info("reviewFailure[{}]: {}-{}", uid, id, reason); |
| | | try { |
| | | if (uid == null) { |
| | | return JsonUtil.loadFalseResult("客户端ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(id)) { |
| | | return JsonUtil.loadFalseResult("任务ID不能为空"); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(reason)) { |
| | | return JsonUtil.loadFalseResult("失败原因不能为空"); |
| | | } |
| | | |
| | | orderTaskExecutionDetailService.reviewFailure(id, reason); |
| | | return JsonUtil.loadTrueResult(""); |
| | | } catch (Exception e) { |
| | | loggerTask.error("评价失败处理失败: {}", e.getMessage(), e); |
| | | return JsonUtil.loadFalseResult("系统异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | List<OrderTaskExecutionDetail> listByIds(@Param("ids") List<String> ids); |
| | | |
| | | long count(@Param("query") DaoQuery query); |
| | | |
| | | |
| | | /** |
| | | * 可执行的任务详情列表 |
| | | * @param clientId |
| | | * @param minCreateTime |
| | | * @return |
| | | */ |
| | | List<OrderTaskExecutionDetail> listCanExcuteTaskDetail(@Param("clientId") Long clientId,@Param("minCreateTime") Date minCreateTime,@Param("start") long start,@Param("count") int count); |
| | | |
| | | long countCanExcuteTaskDetail(@Param("clientId") Long clientId,@Param("minCreateTime") Date minCreateTime); |
| | | |
| | | /** |
| | | * 根据执行状态分组统计clientId的数量 |
| | | * @return 包含执行状态和对应clientId数量的映射列表 |
| | |
| | | public Long clientId; |
| | | public Integer executionStatus; |
| | | public String statusDescription; |
| | | public Date executionTime; |
| | | public String orderNo; |
| | | public String productName; |
| | | public String shopName; |
| | |
| | | private Integer rule; |
| | | @Column(name = "client_type") |
| | | private Integer clientType; |
| | | |
| | | public static enum ClientType{ |
| | | AGENT_PAYMENT(CLIENT_TYPE_AGENT_PAYMENT, "c"), |
| | | ORDER(CLIENT_TYPE_ORDER, "s"); |
| | | private int value; |
| | | private String accountPrefix; |
| | | ClientType(int value, String accountPrefix){ |
| | | this.value = value; |
| | | this.accountPrefix = accountPrefix; |
| | | } |
| | | public int getValue(){ |
| | | return value; |
| | | } |
| | | |
| | | public String getAccountPrefix(){ |
| | | return accountPrefix; |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.experimental.Tolerate; |
| | | import org.springframework.data.annotation.Id; |
| | | import org.yeshi.utils.generater.mybatis.Column; |
| | | import org.yeshi.utils.generater.mybatis.Table; |
| | |
| | | /** 已分配 */ |
| | | public static final int STATUS_ASSIGNED = 2; |
| | | |
| | | @Tolerate |
| | | public OrderTask(){ |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 主键ID(自增) |
| | | */ |
New file |
| | |
| | | package com.taoke.autopay.factory.js2; |
| | | |
| | | import com.taoke.autopay.entity.ClientAdditionalInfo; |
| | | import com.taoke.autopay.entity.js2.OrderTask; |
| | | import com.taoke.autopay.entity.js2.OrderTaskExecutionDetail; |
| | | import com.taoke.autopay.utils.TimeUtil; |
| | | import com.taoke.autopay.vo.OrderTaskExecutionDetailVO; |
| | | import org.yeshi.utils.StringUtil; |
| | | |
| | | /** |
| | | * @author |
| | | * @title: OrderTaskExecutionDetailFactory |
| | | * @description: 下单任务执行详情工厂类 |
| | | * @date 2025/8/8 |
| | | */ |
| | | public class OrderTaskExecutionDetailFactory { |
| | | |
| | | /** |
| | | * 根据OrderTask、OrderTaskExecutionDetail和ClientAdditionalInfo创建OrderTaskExecutionDetailVO |
| | | * |
| | | * @param orderTask 下单任务实体 |
| | | * @param orderTaskExecutionDetail 下单任务执行详情实体 |
| | | * @param clientAdditionalInfo 客户端附加信息 |
| | | * @return OrderTaskExecutionDetailVO对象 |
| | | */ |
| | | public static OrderTaskExecutionDetailVO createOrderTaskExecutionDetailVO( |
| | | OrderTask orderTask, |
| | | OrderTaskExecutionDetail orderTaskExecutionDetail, |
| | | ClientAdditionalInfo clientAdditionalInfo) { |
| | | |
| | | if (orderTask == null || orderTaskExecutionDetail == null) { |
| | | return null; |
| | | } |
| | | |
| | | OrderTaskExecutionDetailVO.OrderTaskExecutionDetailVOBuilder builder = OrderTaskExecutionDetailVO.builder(); |
| | | |
| | | // 设置基本字段 |
| | | builder.id(orderTaskExecutionDetail.getId()) |
| | | .taskId(orderTaskExecutionDetail.getTaskId()) |
| | | .clientId(orderTaskExecutionDetail.getClientId()) |
| | | .orderNo(orderTaskExecutionDetail.getOrderNo()) |
| | | .productName(orderTaskExecutionDetail.getProductName()) |
| | | .shopName(orderTaskExecutionDetail.getShopName()); |
| | | |
| | | // 设置客户端附加信息 |
| | | if (clientAdditionalInfo != null) { |
| | | builder.mobile(clientAdditionalInfo.getMobile()) |
| | | .alipayAccount(clientAdditionalInfo.getAlipayAccount()) |
| | | .alipayPassword(clientAdditionalInfo.getAlipayPassword()); |
| | | } |
| | | |
| | | // 根据执行状态设置执行类型 |
| | | Integer executionStatus = orderTaskExecutionDetail.getExecutionStatus(); |
| | | if (executionStatus != null) { |
| | | if (executionStatus == OrderTaskExecutionDetail.STATUS_NOT_ORDERED) { |
| | | builder.executionType(OrderTaskExecutionDetailVO.EXECUTION_TYPE_ORDER); |
| | | } else if (executionStatus == OrderTaskExecutionDetail.STATUS_ORDERED) { |
| | | builder.executionType(OrderTaskExecutionDetailVO.EXECUTION_TYPE_RECEIVE); |
| | | } else if (executionStatus == OrderTaskExecutionDetail.STATUS_RECEIVE_SUCCESS) { |
| | | builder.executionType(OrderTaskExecutionDetailVO.EXECUTION_TYPE_REVIEW); |
| | | } |
| | | } |
| | | |
| | | // 设置口令内容作为key |
| | | if (!StringUtil.isNullOrEmpty(orderTask.getKeywordContent())) { |
| | | builder.key(orderTask.getKeywordContent()); |
| | | } |
| | | |
| | | // 处理时间字段 |
| | | if (orderTaskExecutionDetail.getCreateTime() != null) { |
| | | builder.createTime(TimeUtil.getGernalTime(orderTaskExecutionDetail.getCreateTime().getTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | |
| | | |
| | | return builder.build(); |
| | | } |
| | | } |
New file |
| | |
| | | package com.taoke.autopay.factory.js2; |
| | | |
| | | import com.taoke.autopay.entity.js2.OrderTask; |
| | | import com.taoke.autopay.vo.admin.js2.OrderTaskVO; |
| | | import com.taoke.autopay.utils.TimeUtil; |
| | | import org.yeshi.utils.StringUtil; |
| | | |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @author |
| | | * @title: OrderTaskFactory |
| | | * @description: 下单任务工厂类 |
| | | * @date 2025/7/31 |
| | | */ |
| | | public class OrderTaskFactory { |
| | | |
| | | /** |
| | | * 将OrderTask转换为OrderTaskVO |
| | | * @param orderTask OrderTask实体 |
| | | * @return OrderTaskVO对象 |
| | | */ |
| | | public static OrderTaskVO createOrderTaskVO(OrderTask orderTask) { |
| | | if (orderTask == null) { |
| | | return null; |
| | | } |
| | | |
| | | OrderTaskVO.OrderTaskVOBuilder builder = OrderTaskVO.builder(); |
| | | |
| | | builder.id(orderTask.getId()) |
| | | .keywordContent(orderTask.getKeywordContent()) |
| | | .keywordMd5(orderTask.getKeywordMd5()) |
| | | .productSource(orderTask.getProductSource()) |
| | | .productName(orderTask.getProductName()) |
| | | .shopName(orderTask.getShopName()) |
| | | .requiredOrderCount(orderTask.getRequiredOrderCount()) |
| | | .completedOrderCount(orderTask.getCompletedOrderCount()) |
| | | .receivedOrderCount(orderTask.getReceivedOrderCount()) |
| | | .reviewedOrderCount(orderTask.getReviewedOrderCount()) |
| | | .receiveCycleHours(orderTask.getReceiveCycleHours()) |
| | | .status(orderTask.getStatus()) |
| | | .statusDescription(orderTask.getStatusDescription()); |
| | | |
| | | // 处理日期字段转换为字符串 |
| | | if (orderTask.getOrderStartTime() != null) { |
| | | builder.orderStartTime(TimeUtil.getGernalTime(orderTask.getOrderStartTime().getTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | |
| | | if (orderTask.getOrderEndTime() != null) { |
| | | builder.orderEndTime(TimeUtil.getGernalTime(orderTask.getOrderEndTime().getTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | |
| | | if (orderTask.getCreateTime() != null) { |
| | | builder.createTime(TimeUtil.getGernalTime(orderTask.getCreateTime().getTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | |
| | | if (orderTask.getUpdateTime() != null) { |
| | | builder.updateTime(TimeUtil.getGernalTime(orderTask.getUpdateTime().getTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | |
| | | if (orderTask.getEstimatedReceiveTime() != null) { |
| | | builder.estimatedReceiveTime(TimeUtil.getGernalTime(orderTask.getEstimatedReceiveTime().getTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | |
| | | return builder.build(); |
| | | } |
| | | |
| | | /** |
| | | * 将OrderTaskVO转换为OrderTask |
| | | * @param orderTaskVO OrderTaskVO对象 |
| | | * @return OrderTask实体 |
| | | */ |
| | | public static OrderTask createOrderTask(OrderTaskVO orderTaskVO) throws ParseException { |
| | | if (orderTaskVO == null) { |
| | | return null; |
| | | } |
| | | |
| | | OrderTask.OrderTaskBuilder builder = OrderTask.builder(); |
| | | |
| | | builder.id(orderTaskVO.getId()) |
| | | .keywordContent(orderTaskVO.getKeywordContent()) |
| | | .keywordMd5(orderTaskVO.getKeywordMd5()) |
| | | .productSource(orderTaskVO.getProductSource()) |
| | | .productName(orderTaskVO.getProductName()) |
| | | .shopName(orderTaskVO.getShopName()) |
| | | .requiredOrderCount(orderTaskVO.getRequiredOrderCount()) |
| | | .completedOrderCount(orderTaskVO.getCompletedOrderCount()) |
| | | .receivedOrderCount(orderTaskVO.getReceivedOrderCount()) |
| | | .reviewedOrderCount(orderTaskVO.getReviewedOrderCount()) |
| | | .receiveCycleHours(orderTaskVO.getReceiveCycleHours()) |
| | | .status(orderTaskVO.getStatus()) |
| | | .statusDescription(orderTaskVO.getStatusDescription()); |
| | | |
| | | // 处理字符串字段转换为日期 |
| | | SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | if (!StringUtil.isNullOrEmpty(orderTaskVO.getOrderStartTime())) { |
| | | builder.orderStartTime(dateTimeFormat.parse(orderTaskVO.getOrderStartTime())); |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(orderTaskVO.getOrderEndTime())) { |
| | | builder.orderEndTime(dateTimeFormat.parse(orderTaskVO.getOrderEndTime())); |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(orderTaskVO.getCreateTime())) { |
| | | builder.createTime(dateTimeFormat.parse(orderTaskVO.getCreateTime())); |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(orderTaskVO.getUpdateTime())) { |
| | | builder.updateTime(dateTimeFormat.parse(orderTaskVO.getUpdateTime())); |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(orderTaskVO.getEstimatedReceiveTime())) { |
| | | builder.estimatedReceiveTime(dateTimeFormat.parse(orderTaskVO.getEstimatedReceiveTime())); |
| | | } |
| | | |
| | | return builder.build(); |
| | | } |
| | | } |
| | |
| | | query.count = 1; |
| | | List<ClientInfo> list = list(query); |
| | | long maxId = 0; |
| | | if (list.size() > 0) { |
| | | maxId = list.get(0).getId(); |
| | | if (!list.isEmpty()) { |
| | | maxId =Long.parseLong(StringUtil.getNumberFromString(list.get(0).getAccount()).split(",")[0]) + 1; |
| | | } |
| | | if(info.getClientType()==ClientInfo.CLIENT_TYPE_AGENT_PAYMENT) { |
| | | info.setAccount("c" + maxId); |
| | | info.setAccount(ClientInfo.ClientType.AGENT_PAYMENT.getAccountPrefix() + maxId); |
| | | }else if(info.getClientType()==ClientInfo.CLIENT_TYPE_ORDER){ |
| | | info.setAccount("s" + maxId); |
| | | info.setAccount(ClientInfo.ClientType.ORDER.getAccountPrefix() + maxId); |
| | | } |
| | | } |
| | | clientInfoMapper.insertSelective(info); |
| | |
| | | logger.info("任务执行详情ID:{} 评价失败,原因:{}", id, reason); |
| | | } |
| | | |
| | | @Override |
| | | public List<OrderTaskExecutionDetail> listCanExcuteTaskDetail(Long clientId, int page, int pageSize) { |
| | | // 获取30分钟以内的订单任务执行详情 |
| | | return orderTaskExecutionDetailMapper.listCanExcuteTaskDetail(clientId, new Date(System.currentTimeMillis() - 1000*60*30L)); |
| | | } |
| | | |
| | | @Override |
| | | public long countCanExcuteTaskDetail(Long clientId) { |
| | | return orderTaskExecutionDetailMapper.countCanExcuteTaskDetail(clientId, new Date(System.currentTimeMillis() - 1000*60*30L)); |
| | | } |
| | | |
| | | /** |
| | | * 验证订单任务执行详情的必填字段 |
| | | * |
| | |
| | | } |
| | | return orderTaskMapper.selectByPrimaryKey(id); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public List<OrderTask> getOrderTaskByIds(List<Long> ids) { |
| | | if(ids==null||ids.isEmpty()){ |
| | | return new ArrayList<>(); |
| | | } |
| | | return orderTaskMapper.listByIds(ids); |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @Override |
| | | public OrderTask getOrderTaskByIdForUpdate(Long id) { |
| | |
| | | } |
| | | } |
| | | // 统计所有设备正在执行任务的数量 |
| | | |
| | | List<ClientCountDTO> clientCountList = orderTaskExecutionDetailMapper.statisticClientIdsCountByStatus(Arrays.asList( new Integer[]{OrderTaskExecutionDetail.STATUS_NOT_ORDERED})); |
| | | Map<Long, Integer> clientCountMap = new HashMap<>(); |
| | | for(ClientCountDTO dto:clientCountList){ |
| | | clientCountMap.put(dto.getClientId(), dto.getCount()); |
| | | } |
| | | |
| | | // 剔除已经存在2个任务以上的设备 |
| | | for(int i=0;i<clientInfoList.size();i++){ |
| | | if(clientCountMap.containsKey(clientInfoList.get(i).getId())&&clientCountMap.get(clientInfoList.get(i).getId())>=2){ |
| | | clientInfoList.remove(i); |
| | | i--; |
| | | } |
| | | } |
| | | |
| | | clientInfoList.sort(new Comparator<ClientInfo>() { |
| | | @Override |
| | |
| | | import com.taoke.autopay.dao.OrderTaskExecutionDetailMapper; |
| | | import com.taoke.autopay.entity.js2.OrderTaskExecutionDetail; |
| | | import com.taoke.autopay.exception.OrderTaskExecutionDetailException; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | |
| | | * @throws OrderTaskExecutionDetailException 任务执行详情更新异常 |
| | | */ |
| | | void reviewFailure(String id, String reason) throws OrderTaskExecutionDetailException; |
| | | |
| | | /** |
| | | * 获取可执行的任务详情列表 |
| | | * @param clientId |
| | | * @return |
| | | */ |
| | | List<OrderTaskExecutionDetail> listCanExcuteTaskDetail(Long clientId, int page, int pageSize); |
| | | |
| | | /** |
| | | * 统计可执行任务详情数量 |
| | | * @param clientId |
| | | * @return |
| | | */ |
| | | long countCanExcuteTaskDetail(@Param("clientId") Long clientId); |
| | | |
| | | } |
| | |
| | | * @return 下单任务实体 |
| | | */ |
| | | OrderTask getOrderTaskById(Long id); |
| | | |
| | | |
| | | /** |
| | | * 根据ID批量查询下单任务 |
| | | * @param ids |
| | | * @return |
| | | */ |
| | | List<OrderTask> getOrderTaskByIds(List<Long> ids); |
| | | |
| | | /** |
| | | * 根据ID更新下单任务(带锁) |
New file |
| | |
| | | package com.taoke.autopay.task; |
| | | |
| | | import com.taoke.autopay.dao.OrderTaskMapper; |
| | | import com.taoke.autopay.entity.js2.OrderTask; |
| | | import com.taoke.autopay.service.js2.OrderTaskService; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | @Configuration |
| | | @EnableScheduling |
| | | public class OrderTaskDistributeTask { |
| | | |
| | | @Value("${task-enable}") |
| | | private boolean taskEnable; |
| | | |
| | | @Resource |
| | | private OrderTaskService orderTaskService; |
| | | |
| | | |
| | | /** |
| | | * 为下单任务分配客户端设备 |
| | | */ |
| | | @Scheduled(cron = "0/5 * * * * ? ") |
| | | private void assignOrderTask() { |
| | | if(!taskEnable){ |
| | | return; |
| | | } |
| | | // 对处于分配中的任务进行分配 |
| | | try { |
| | | OrderTaskMapper.DaoQuery query=new OrderTaskMapper.DaoQuery(); |
| | | query.status = OrderTask.STATUS_ASSIGNING; |
| | | // 对1小时内创建的任务进行分配 |
| | | query.minCreateTime=new Date(System.currentTimeMillis() - 1000 * 60 * 60L); |
| | | List<OrderTask> orderTaskList = orderTaskService.listOrderTasks(query, 1, 20); |
| | | if (orderTaskList != null) { |
| | | for (OrderTask orderTask : orderTaskList) { |
| | | orderTaskService.assignTask(orderTask.getId()); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.taoke.autopay.utils.encrypt; |
| | | |
| | | import javax.crypto.Cipher; |
| | | import javax.crypto.KeyGenerator; |
| | | import javax.crypto.SecretKey; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import java.security.SecureRandom; |
| | | import java.util.Base64; |
| | | |
| | | /** |
| | | * AES加密解密工具类 |
| | | */ |
| | | public class AESUtil { |
| | | |
| | | private static final String ALGORITHM = "AES"; |
| | | private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding"; |
| | | |
| | | /** |
| | | * AES加密 |
| | | * @param content 待加密内容 |
| | | * @param key 加密密钥 |
| | | * @return 加密后的字符串 |
| | | */ |
| | | public static String encrypt(String content, String key) { |
| | | try { |
| | | // 创建AES密钥 |
| | | SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), ALGORITHM); |
| | | |
| | | // 创建密码器 |
| | | Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); |
| | | |
| | | // 初始化为加密模式 |
| | | cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); |
| | | |
| | | // 执行加密操作 |
| | | byte[] encrypted = cipher.doFinal(content.getBytes("utf-8")); |
| | | |
| | | // 使用Base64编码返回 |
| | | return Base64.getEncoder().encodeToString(encrypted); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("AES加密失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * AES解密 |
| | | * @param content 待解密内容 |
| | | * @param key 解密密钥 |
| | | * @return 解密后的字符串 |
| | | */ |
| | | public static String decrypt(String content, String key) { |
| | | try { |
| | | // 使用Base64解码 |
| | | byte[] encrypted = Base64.getDecoder().decode(content); |
| | | |
| | | // 创建AES密钥 |
| | | SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), ALGORITHM); |
| | | |
| | | // 创建密码器 |
| | | Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); |
| | | |
| | | // 初始化为解密模式 |
| | | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); |
| | | |
| | | // 执行解密操作 |
| | | byte[] decrypted = cipher.doFinal(encrypted); |
| | | |
| | | // 转换为字符串返回 |
| | | return new String(decrypted, "utf-8"); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("AES解密失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 生成AES密钥 |
| | | * @return 生成的密钥字符串 |
| | | */ |
| | | public static String generateKey() { |
| | | try { |
| | | // 创建KeyGenerator对象 |
| | | KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); |
| | | |
| | | // 初始化密钥长度为128位 |
| | | keyGenerator.init(128); |
| | | |
| | | // 生成密钥 |
| | | SecretKey secretKey = keyGenerator.generateKey(); |
| | | |
| | | // 获取密钥字节数组 |
| | | byte[] keyBytes = secretKey.getEncoded(); |
| | | |
| | | // 使用Base64编码返回 |
| | | return Base64.getEncoder().encodeToString(keyBytes); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("生成AES密钥失败", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据密码生成固定密钥 |
| | | * @param password 密码 |
| | | * @return 固定密钥 |
| | | */ |
| | | public static String generateKeyByPassword(String password) { |
| | | try { |
| | | // 创建随机数生成器 |
| | | SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); |
| | | secureRandom.setSeed(password.getBytes()); |
| | | |
| | | // 创建KeyGenerator对象 |
| | | KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); |
| | | |
| | | // 初始化随机数生成器 |
| | | keyGenerator.init(128, secureRandom); |
| | | |
| | | // 生成密钥 |
| | | SecretKey secretKey = keyGenerator.generateKey(); |
| | | |
| | | // 获取密钥字节数组 |
| | | byte[] keyBytes = secretKey.getEncoded(); |
| | | |
| | | // 使用Base64编码返回 |
| | | return Base64.getEncoder().encodeToString(keyBytes); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("根据密码生成密钥失败", e); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.taoke.autopay.vo; |
| | | |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.experimental.Tolerate; |
| | | |
| | | @Data |
| | | @Builder |
| | | public class OrderTaskExecutionDetailVO { |
| | | |
| | | // 下单 |
| | | public final static int EXECUTION_TYPE_ORDER = 1; |
| | | // 确认收货 |
| | | public final static int EXECUTION_TYPE_RECEIVE = 2; |
| | | // 评价 |
| | | public final static int EXECUTION_TYPE_REVIEW = 3; |
| | | |
| | | |
| | | @Tolerate |
| | | public OrderTaskExecutionDetailVO(){ |
| | | |
| | | } |
| | | |
| | | private String id; |
| | | private String key; |
| | | private Long taskId; |
| | | private Long clientId; |
| | | private Integer executionType; |
| | | private String orderNo; |
| | | private String productName; |
| | | private String shopName; |
| | | private String mobile; |
| | | private String alipayAccount; |
| | | private String alipayPassword; |
| | | private String createTime; |
| | | } |
New file |
| | |
| | | package com.taoke.autopay.vo.admin.js2; |
| | | |
| | | import lombok.Builder; |
| | | import lombok.Data; |
| | | import lombok.experimental.Tolerate; |
| | | |
| | | /** |
| | | * @author |
| | | * @title: OrderTaskVO |
| | | * @description: 下单任务VO实体类 |
| | | * @date 2025/7/31 |
| | | */ |
| | | @Data |
| | | @Builder |
| | | public class OrderTaskVO { |
| | | @Tolerate |
| | | public OrderTaskVO() { |
| | | } |
| | | |
| | | /** |
| | | * 主键ID(自增) |
| | | */ |
| | | private Long id; |
| | | |
| | | /** |
| | | * 口令内容 |
| | | */ |
| | | private String keywordContent; |
| | | |
| | | /** |
| | | * 口令md5 |
| | | */ |
| | | private String keywordMd5; |
| | | |
| | | /** |
| | | * 商品来源 |
| | | */ |
| | | private Integer productSource; |
| | | |
| | | /** |
| | | * 商品名称 |
| | | */ |
| | | private String productName; |
| | | |
| | | /** |
| | | * 店铺名称 |
| | | */ |
| | | private String shopName; |
| | | |
| | | /** |
| | | * 任务所需下单数量 |
| | | */ |
| | | private Integer requiredOrderCount; |
| | | |
| | | /** |
| | | * 已经下单数量 |
| | | */ |
| | | private Integer completedOrderCount; |
| | | |
| | | /** |
| | | * 已经确认收货的数量 |
| | | */ |
| | | private Integer receivedOrderCount; |
| | | |
| | | /** |
| | | * 已经评价的数量 |
| | | */ |
| | | private Integer reviewedOrderCount; |
| | | |
| | | /** |
| | | * 确认收货周期(小时) |
| | | */ |
| | | private Integer receiveCycleHours; |
| | | |
| | | /** |
| | | * 下单开始时间 |
| | | */ |
| | | private String orderStartTime; |
| | | |
| | | /** |
| | | * 下单结束时间 |
| | | */ |
| | | private String orderEndTime; |
| | | |
| | | /** |
| | | * 创建时间 |
| | | */ |
| | | private String createTime; |
| | | |
| | | /** |
| | | * 更新时间 |
| | | */ |
| | | private String updateTime; |
| | | |
| | | /** |
| | | * 预估确认收货时间 |
| | | */ |
| | | private String estimatedReceiveTime; |
| | | |
| | | /** |
| | | * 状态(int型) |
| | | */ |
| | | private Integer status; |
| | | |
| | | /** |
| | | * 状态简介 |
| | | */ |
| | | private String statusDescription; |
| | | } |
| | |
| | | |
| | | </resultMap> |
| | | |
| | | <sql id="Base_Column_List">id,task_id,client_id,execution_status,status_description,execution_time,order_no,product_name,shop_name,coupon_code,order_time,receive_time,review_time,create_time,update_time</sql> |
| | | <sql id="Base_Column_List">id,task_id,client_id,execution_status,status_description,order_no,product_name,shop_name,coupon_code,order_time,receive_time,review_time,create_time,update_time</sql> |
| | | <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String">select |
| | | <include refid="Base_Column_List"/> |
| | | from table_order_task_execution_detail where id = #{id,jdbcType=VARCHAR} |
| | |
| | | <select id="count" resultType="java.lang.Long">select count(*) from table_order_task_execution_detail where 1=1 |
| | | <include refid="listWhereSQL"/> |
| | | </select> |
| | | |
| | | |
| | | |
| | | |
| | | <select id="listCanExcuteTaskDetail" resultMap="BaseResultMap" > |
| | | select |
| | | <include refid="Base_Column_List"/> |
| | | from `table_order_task_execution_detail` d LEFT JOIN `table_order_task` t ON t.`id`=d.`task_id` |
| | | WHERE |
| | | client_id = #{clientId} |
| | | AND |
| | | ( |
| | | (d.`execution_status`=0 AND d.`create_time` > #{minCreateTime}) |
| | | OR (d.`execution_status`=1 AND UNIX_TIMESTAMP(d.`order_time`) + t.receive_cycle_hours*60*60 < UNIX_TIMESTAMP(NOW())) |
| | | OR (d.`execution_status`=2) |
| | | ) order by d.create_time limit #{start},#{count} |
| | | </select> |
| | | |
| | | <select id="countCanExcuteTaskDetail" resultType="java.lang.Long">select count(*) from |
| | | `table_order_task_execution_detail` d LEFT JOIN `table_order_task` t ON t.`id`=d.`task_id` |
| | | WHERE |
| | | client_id = #{clientId} |
| | | AND |
| | | ( |
| | | (d.`execution_status`=0 AND d.`create_time` > #{minCreateTime}) |
| | | OR (d.`execution_status`=1 AND UNIX_TIMESTAMP(d.`order_time`) + t.receive_cycle_hours*60*60 < UNIX_TIMESTAMP(NOW())) |
| | | OR (d.`execution_status`=2) |
| | | ) |
| | | </select> |
| | | |
| | | |
| | | |
| | | <select id="statisticClientIdsCountByStatus" resultMap="ClientCountResultMap"> |
| | | SELECT client_id as clientId,count(*) as count |
| | | FROM table_order_task_execution_detail where |
| | |
| | | <delete id="deleteByPrimaryKey" |
| | | parameterType="java.lang.String">delete from table_order_task_execution_detail where id = #{id,jdbcType=VARCHAR}</delete> |
| | | <insert id="insert" parameterType="com.taoke.autopay.entity.js2.OrderTaskExecutionDetail" useGeneratedKeys="true" |
| | | keyProperty="id">insert into table_order_task_execution_detail (id,task_id,client_id,execution_status,status_description,execution_time,order_no,product_name,shop_name,coupon_code,order_time,receive_time,review_time,create_time,update_time) values (#{id,jdbcType=VARCHAR},#{taskId,jdbcType=BIGINT},#{clientId,jdbcType=BIGINT},#{executionStatus,jdbcType=INTEGER},#{statusDescription,jdbcType=VARCHAR},#{executionTime,jdbcType=TIMESTAMP},#{orderNo,jdbcType=VARCHAR},#{productName,jdbcType=VARCHAR},#{shopName,jdbcType=VARCHAR},#{couponCode,jdbcType=VARCHAR},#{orderTime,jdbcType=TIMESTAMP},#{receiveTime,jdbcType=TIMESTAMP},#{reviewTime,jdbcType=TIMESTAMP},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert> |
| | | keyProperty="id">insert into table_order_task_execution_detail (id,task_id,client_id,execution_status,status_description,order_no,product_name,shop_name,coupon_code,order_time,receive_time,review_time,create_time,update_time) values (#{id,jdbcType=VARCHAR},#{taskId,jdbcType=BIGINT},#{clientId,jdbcType=BIGINT},#{executionStatus,jdbcType=INTEGER},#{statusDescription,jdbcType=VARCHAR},#{orderNo,jdbcType=VARCHAR},#{productName,jdbcType=VARCHAR},#{shopName,jdbcType=VARCHAR},#{couponCode,jdbcType=VARCHAR},#{orderTime,jdbcType=TIMESTAMP},#{receiveTime,jdbcType=TIMESTAMP},#{reviewTime,jdbcType=TIMESTAMP},#{createTime,jdbcType=TIMESTAMP},#{updateTime,jdbcType=TIMESTAMP})</insert> |
| | | <insert id="insertSelective" parameterType="com.taoke.autopay.entity.js2.OrderTaskExecutionDetail" useGeneratedKeys="true" |
| | | keyProperty="id">insert into table_order_task_execution_detail |
| | | <trim prefix="(" suffix=")" suffixOverrides=","> |
| | |
| | | </trim> |
| | | </insert> |
| | | <update id="updateByPrimaryKey" |
| | | parameterType="com.taoke.autopay.entity.js2.OrderTaskExecutionDetail">update table_order_task_execution_detail set task_id = #{taskId,jdbcType=BIGINT},client_id = #{clientId,jdbcType=BIGINT},execution_status = #{executionStatus,jdbcType=INTEGER},status_description = #{statusDescription,jdbcType=VARCHAR},execution_time = #{executionTime,jdbcType=TIMESTAMP},order_no = #{orderNo,jdbcType=VARCHAR},product_name = #{productName,jdbcType=VARCHAR},shop_name = #{shopName,jdbcType=VARCHAR},coupon_code = #{couponCode,jdbcType=VARCHAR},order_time = #{orderTime,jdbcType=TIMESTAMP},receive_time = #{receiveTime,jdbcType=TIMESTAMP},review_time = #{reviewTime,jdbcType=TIMESTAMP},create_time = #{createTime,jdbcType=TIMESTAMP},update_time = #{updateTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=VARCHAR}</update> |
| | | parameterType="com.taoke.autopay.entity.js2.OrderTaskExecutionDetail">update table_order_task_execution_detail set task_id = #{taskId,jdbcType=BIGINT},client_id = #{clientId,jdbcType=BIGINT},execution_status = #{executionStatus,jdbcType=INTEGER},status_description = #{statusDescription,jdbcType=VARCHAR},order_no = #{orderNo,jdbcType=VARCHAR},product_name = #{productName,jdbcType=VARCHAR},shop_name = #{shopName,jdbcType=VARCHAR},coupon_code = #{couponCode,jdbcType=VARCHAR},order_time = #{orderTime,jdbcType=TIMESTAMP},receive_time = #{receiveTime,jdbcType=TIMESTAMP},review_time = #{reviewTime,jdbcType=TIMESTAMP},create_time = #{createTime,jdbcType=TIMESTAMP},update_time = #{updateTime,jdbcType=TIMESTAMP} where id = #{id,jdbcType=VARCHAR}</update> |
| | | <update id="updateByPrimaryKeySelective" parameterType="com.taoke.autopay.entity.js2.OrderTaskExecutionDetail">update table_order_task_execution_detail |
| | | <set> |
| | | <if test="taskId != null">task_id=#{taskId,jdbcType=BIGINT},</if> |
| | |
| | | <li class="layui-nav-item"> |
| | | <a href="javascript:;"><i class="iconfont"></i>JS2系统</a> |
| | | <dl class="layui-nav-child"> |
| | | <dd><a href="javascript:;" data-url="order-task-list.html" data-id='71' data-text="下单任务列表"><span class="l-line"></span>下单任务列表</a></dd> |
| | | <dd><a href="javascript:;" data-url="order-client-list.html" data-id='7' data-text="下单设备列表"><span class="l-line"></span>下单设备列表</a></dd> |
| | | </dl> |
| | | </li> |
| | |
| | | }); |
| | | } |
| | | |
| | | function updatePwd(id) { |
| | | // 修改密码 |
| | | layer.prompt({ |
| | | formType: 2, |
| | | value: '', |
| | | title: '请输入密码', |
| | | area: ['200px', '50px'] //自定义文本域宽高 |
| | | }, function(value, index, elem){ |
| | | if(value.length < 6){ |
| | | layer.msg("密码不能少于6位数"); |
| | | return; |
| | | } |
| | | $.post("/admin/api/clientinfo/js2/setpwd", {"id":id,"pwd":value}, function(response) { |
| | | if (response.code == 0) { |
| | | layer.close(index); |
| | | layer.msg("密码修改成功"); |
| | | } else { |
| | | layer.msg(response.msg); |
| | | } |
| | | }, 'json').fail(function(jqXHR, textStatus, errorThrown) { |
| | | layer.msg("网络请求失败"); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | |
| | | layui.use(['form', 'jquery', 'layer', 'table'], function() { |
| | | var table = layui.table; |
| | | var form = layui.form; |
| | |
| | | { |
| | | field: '', |
| | | title: '操作', |
| | | width: 120, |
| | | width: 200, |
| | | fixed: 'right', |
| | | align: 'center', |
| | | templet: function(d) { |
| | | return '<div><a href="javascript:void(0)" onclick="updateClient(' + d["client.id"] + ')" class="layui-table-link">修改</a></div>'; |
| | | return '<div><a href="javascript:void" onclick="updatePwd(' + d["client.id"] + ')" class="layui-table-link">设置密码</a> <a href="javascript:void(0)" onclick="updateClient(' + d["client.id"] + ')" class="layui-table-link">修改</a></div>'; |
| | | } |
| | | } |
| | | ] |
| | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">支付宝密码:</label> |
| | | <div class="layui-input-inline"> |
| | | <input type="text" name="alipayPassword" required lay-verify="" placeholder="无更改无需填写" autocomplete="off" class="layui-input"> |
| | | <input type="password" name="alipayPassword" required lay-verify="" placeholder="无更改无需填写" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="zh"> |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <meta name="renderer" content="webkit"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <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"/> |
| | | <script src="js/http_api.js"></script> |
| | | <style> |
| | | .layui-table-cell { |
| | | height: 50px; |
| | | white-space: normal; |
| | | max-height: 50px; |
| | | } |
| | | |
| | | /* 添加横向滚动样式 */ |
| | | .scroll-x { |
| | | overflow: hidden !important; |
| | | overflow-x: auto !important; |
| | | white-space: nowrap; |
| | | outline: none; |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <div class="page-content-wrap"> |
| | | |
| | | <div class="scroll-x"> |
| | | <table class="layui-table" lay-even lay-skin="nob" id="clientsTable" style="height: 100%"></table> |
| | | </div> |
| | | </div> |
| | | |
| | | <script src="/admin/layui/layui.js" type="text/javascript" charset="utf-8"></script> |
| | | <script src="/admin/js/jquery.min.js" type="text/javascript" charset="utf-8"></script> |
| | | <script> |
| | | layui.use(['table', 'layer'], function () { |
| | | var table = layui.table; |
| | | var layer = layui.layer; |
| | | var urlParams = new URLSearchParams(window.location.search); |
| | | var taskId = urlParams.get('taskId'); |
| | | |
| | | // 渲染表格 |
| | | var tableIns = table.render({ |
| | | elem: '#clientsTable', |
| | | url: '/admin/api/ordertask/js2/assignedClients', |
| | | where: { |
| | | taskId: taskId |
| | | }, |
| | | parseData: function(res) { |
| | | return { |
| | | "code": res.code, |
| | | "msg": res.msg, |
| | | "count": res.data.count, |
| | | "data": res.data.list |
| | | } |
| | | }, |
| | | page: true, |
| | | cols: [[ |
| | | {field: 'clientId', title: '客户端ID', width: 100}, |
| | | {field: 'orderNo', title: '订单号', width: 150}, |
| | | {field: 'productName', title: '商品名称', width: 150}, |
| | | {field: 'shopName', title: '店铺名称', width: 120}, |
| | | {field: 'couponCode', title: '券码', width: 120}, |
| | | { |
| | | field: 'executionStatus', title: '执行状态', width: 120, templet: function (d) { |
| | | switch (d.executionStatus) { |
| | | case 0: return '<span style="color: #999">未下单</span>'; |
| | | case 1: return '<span style="color: #009900">已下单</span>'; |
| | | case -1: return '<span style="color: #ff0000">下单失败</span>'; |
| | | case 2: return '<span style="color: #009900">确认收货成功</span>'; |
| | | case -2: return '<span style="color: #ff0000">确认收货失败</span>'; |
| | | case 3: return '<span style="color: #009900">评价成功</span>'; |
| | | case -3: return '<span style="color: #ff0000">评价失败</span>'; |
| | | default: return '未知状态'; |
| | | } |
| | | } |
| | | }, |
| | | {field: 'statusDescription', title: '状态说明', width: 150}, |
| | | {field: 'orderTime', title: '下单时间', width: 160}, |
| | | {field: 'receiveTime', title: '收货时间', width: 160}, |
| | | {field: 'reviewTime', title: '评价时间', width: 160}, |
| | | {field: 'createTime', title: '创建时间', width: 160}, |
| | | {field: 'updateTime', title: '更新时间', width: 160} |
| | | ]] |
| | | }); |
| | | }); |
| | | </script> |
| | | </body> |
| | | </html> |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html> |
| | | |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <meta name="renderer" content="webkit"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <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"/> |
| | | <style> |
| | | .layui-table-cell { |
| | | height: 50px; |
| | | white-space: normal; |
| | | max-height: 50px; |
| | | } |
| | | |
| | | |
| | | #add_task { |
| | | padding: 10px; |
| | | } |
| | | </style> |
| | | </head> |
| | | |
| | | <body> |
| | | <div class="page-content-wrap"> |
| | | <form class="layui-form" action="" lay-filter='search'> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <input type="text" name="keyword" id="keyword" placeholder="按口令内容搜索" autocomplete="off" |
| | | class="layui-input"> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <input type="text" name="startDate" id="startDate" placeholder="开始日期" autocomplete="off" |
| | | class="layui-input" readonly> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <input type="text" name="endDate" id="endDate" placeholder="结束日期" autocomplete="off" |
| | | class="layui-input" readonly> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <select name="status" id="status"> |
| | | <option value="">全部状态</option> |
| | | <option value="0">未分配</option> |
| | | <option value="1">分配中</option> |
| | | <option value="2">已分配</option> |
| | | </select> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <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 layui-btn-warm" onclick="showCreateTask()"><i |
| | | class="layui-icon layui-icon-add-circle"></i> 添加任务</a> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | <div> |
| | | <table class="layui-table" lay-even lay-skin="nob" id="table"> |
| | | |
| | | </table> |
| | | </div> |
| | | </div> |
| | | |
| | | <div id="add_task" style="display: none; padding: 20px;"> |
| | | <form class="layui-form" action="" lay-filter='add-task'> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">口令内容</label> |
| | | <div class="layui-input-block"> |
| | | <textarea type="text" name="keywordContent" rows="5" required lay-verify="required" placeholder="请输入口令内容" |
| | | autocomplete="off" class="layui-textarea"></textarea> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">商品来源</label> |
| | | <div class="layui-input-block"> |
| | | <select name="productSource" required lay-verify="required"> |
| | | <option value="">请选择商品来源</option> |
| | | <option value="1">抖音</option> |
| | | <option value="2">快手</option> |
| | | </select> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">商品名称</label> |
| | | <div class="layui-input-block"> |
| | | <textarea type="text" name="productName" rows="3" required lay-verify="required" placeholder="请输入商品名称" |
| | | autocomplete="off" class="layui-textarea"></textarea> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">店铺名称</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="shopName" placeholder="请输入店铺名称" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">所需下单数量</label> |
| | | <div class="layui-input-block"> |
| | | <input type="number" name="requiredOrderCount" required lay-verify="required|number" min="1" |
| | | placeholder="请输入所需下单数量" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">收货周期(小时)</label> |
| | | <div class="layui-input-block"> |
| | | <input type="number" name="receiveCycleHours" required lay-verify="required|number" min="1" |
| | | placeholder="请输入收货周期(小时)" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">下单开始时间</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="orderStartTime" id="orderStartTime" required lay-verify="required" |
| | | placeholder="请选择下单开始时间" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">下单结束时间</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="orderEndTime" id="orderEndTime" required lay-verify="required" |
| | | placeholder="请选择下单结束时间" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-input-block"> |
| | | <button class="layui-btn" lay-submit lay-filter="add-task">立即创建</button> |
| | | <button type="reset" class="layui-btn layui-btn-primary">重置</button> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | </div> |
| | | |
| | | <script src="/admin/layui/layui.js" type="text/javascript" charset="utf-8"></script> |
| | | <script src="/admin/js/jquery.min.js" type="text/javascript" charset="utf-8"></script> |
| | | <script> |
| | | // 修改任务信息 |
| | | function updateTask(id) { |
| | | var layerIndex = layer.open({ |
| | | title: "修改下单任务信息", |
| | | type: 2, |
| | | area: ['600px', '600px'], |
| | | shade: 0.3, |
| | | shadeClose: false, |
| | | resize: false, |
| | | content: '/admin/order-task-update.html?id=' + id, |
| | | btn: ['确定', '取消'], |
| | | yes: function (index) { |
| | | //submit方法为弹框内容中的方法 |
| | | window["layui-layer-iframe" + index].submit(function (res) { |
| | | let fdata = { |
| | | id: id |
| | | }; |
| | | for (let key in res) { |
| | | if (key.indexOf(".") >= 0) { |
| | | let k1 = key.split(".")[0]; |
| | | let k2 = key.split(".")[1]; |
| | | if (k1 in fdata) { |
| | | } else { |
| | | fdata[k1] = {}; |
| | | } |
| | | fdata[k1][k2] = res[key]; |
| | | } else { |
| | | fdata[key] = res[key] |
| | | } |
| | | } |
| | | for (let key in fdata) { |
| | | if (typeof (fdata[key]) == 'object') { |
| | | fdata[key] = JSON.stringify(fdata[key]); |
| | | } |
| | | } |
| | | try { |
| | | var loadIndex = layer.load(1); |
| | | $.post("/admin/api/ordertask/js2/update", fdata, function (response) { |
| | | layer.close(loadIndex); |
| | | if (response.code == 0) { |
| | | layer.close(layerIndex); |
| | | layer.msg("更改成功"); |
| | | // 重新加载表格 |
| | | tableIns.reload(); |
| | | } else { |
| | | layer.msg(response.msg); |
| | | } |
| | | }, 'json').fail(function (jqXHR, textStatus, errorThrown) { |
| | | layer.close(loadIndex); |
| | | layer.msg("网络请求失败"); |
| | | }); |
| | | } catch (e) { |
| | | console.log(e); |
| | | } |
| | | }); |
| | | }, |
| | | cancel: function () { |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 删除任务 |
| | | function deleteTask(id) { |
| | | layer.confirm('确定要删除这个任务吗?', { |
| | | btn: ['确定', '取消'] |
| | | }, function (index) { |
| | | $.post("/admin/api/ordertask/js2/delete", {"id": id}, function (response) { |
| | | if (response.code == 0) { |
| | | layer.msg("删除成功"); |
| | | // 重新加载表格 |
| | | tableIns.reload(); |
| | | } else { |
| | | layer.msg(response.msg); |
| | | } |
| | | }, 'json').fail(function (jqXHR, textStatus, errorThrown) { |
| | | layer.msg("网络请求失败"); |
| | | }); |
| | | layer.close(index); |
| | | }); |
| | | } |
| | | |
| | | // 分配任务 |
| | | function assignTask(id) { |
| | | layer.confirm('确定要分配这个任务吗?', { |
| | | btn: ['确定', '取消'] |
| | | }, function (index) { |
| | | $.post("/admin/api/ordertask/js2/assign", {"taskId": id}, function (response) { |
| | | if (response.code == 0) { |
| | | layer.msg("分配成功"); |
| | | // 重新加载表格 |
| | | tableIns.reload(); |
| | | } else { |
| | | layer.msg(response.msg); |
| | | } |
| | | }, 'json').fail(function (jqXHR, textStatus, errorThrown) { |
| | | layer.msg("网络请求失败"); |
| | | }); |
| | | layer.close(index); |
| | | }); |
| | | } |
| | | |
| | | // 查看已分配设备 |
| | | function viewAssignedClients(id) { |
| | | var layerIndex = layer.open({ |
| | | title: "已分配设备列表", |
| | | type: 2, |
| | | area: ['1200px', '600px'], |
| | | shade: 0.3, |
| | | shadeClose: false, |
| | | resize: false, |
| | | content: '/admin/order-task-assigned-clients.html?taskId=' + id |
| | | }); |
| | | } |
| | | |
| | | function formatDateTime(date, format) { |
| | | var now = date; |
| | | var year = now.getFullYear(); |
| | | var month = (now.getMonth() + 1).toString().padStart(2, '0'); |
| | | var day = now.getDate().toString().padStart(2, '0'); |
| | | var hours = now.getHours().toString().padStart(2, '0'); |
| | | var minutes = now.getMinutes().toString().padStart(2, '0'); |
| | | var seconds = now.getSeconds().toString().padStart(2, '0'); |
| | | |
| | | // 默认格式 |
| | | if (!format) { |
| | | return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds; |
| | | } |
| | | |
| | | // 自定义格式支持 |
| | | return format |
| | | .replace('YYYY', year) |
| | | .replace('MM', month) |
| | | .replace('DD', day) |
| | | .replace('HH', hours) |
| | | .replace('mm', minutes) |
| | | .replace('ss', seconds); |
| | | } |
| | | |
| | | function showCreateTask() { |
| | | // 开始与结束时间赋当前时间 |
| | | // 创建任务 |
| | | $("input[name=orderStartTime]").val(formatDateTime(new Date())); |
| | | $("input[name=orderEndTime]").val(formatDateTime(new Date(new Date().getTime()+1000*60*60*24))); |
| | | var index = layer.open({ |
| | | type: 1, |
| | | title: "创建下单任务", |
| | | content: $("#add_task"), |
| | | area: ['600px', '700px'], |
| | | end: function (e) { |
| | | $("#add_task").css("display", "none"); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | layui.use(['form', 'jquery', 'layer', 'table', 'laydate'], function () { |
| | | var table = layui.table; |
| | | var form = layui.form; |
| | | var $ = layui.jquery; |
| | | var laydate = layui.laydate; |
| | | |
| | | // 日期控件初始化 |
| | | laydate.render({ |
| | | elem: '#startDate', |
| | | theme: '#448aff' |
| | | }); |
| | | |
| | | laydate.render({ |
| | | elem: '#endDate', |
| | | theme: '#448aff' |
| | | }); |
| | | |
| | | laydate.render({ |
| | | elem: '#orderStartTime', |
| | | type: 'datetime', |
| | | theme: '#448aff' |
| | | }); |
| | | |
| | | laydate.render({ |
| | | elem: '#orderEndTime', |
| | | type: 'datetime', |
| | | theme: '#448aff' |
| | | }); |
| | | |
| | | let table_option = { |
| | | elem: '#table', |
| | | url: '/admin/api/ordertask/js2/list', |
| | | where: { |
| | | 'keyword': $("#keyword").val(), |
| | | 'startDate': $("#startDate").val(), |
| | | 'endDate': $("#endDate").val(), |
| | | 'status': $("#status").val() |
| | | }, |
| | | parseData: function(res) { //res 即为原始返回的数据 |
| | | return { |
| | | "code": res.code, //解析接口状态 |
| | | "msg": res.msg, //解析提示文本 |
| | | "count": res.data.count, //解析数据长度 |
| | | "data": res.data.list //解析数据列表 |
| | | } |
| | | }, |
| | | page: true, |
| | | cols: [[ |
| | | {field: 'id', title: '任务ID', width: 80, fixed: 'left'}, |
| | | {field: 'keywordContent', title: '口令内容', width: 150}, |
| | | { |
| | | field: 'productSource', title: '商品来源', width: 90, templet: function (d) { |
| | | if (d.productSource == 1) { |
| | | return '抖音'; |
| | | } else if (d.productSource == 2) { |
| | | return '快手'; |
| | | } |
| | | return '未知'; |
| | | } |
| | | }, |
| | | {field: 'productName', title: '商品名称', width: 150}, |
| | | {field: 'shopName', title: '店铺名称', width: 120}, |
| | | {field: 'requiredOrderCount', title: '需下单数', width: 90}, |
| | | {field: 'completedOrderCount', title: '已下单数', width: 90}, |
| | | {field: 'receivedOrderCount', title: '已收货数', width: 90}, |
| | | {field: 'reviewedOrderCount', title: '已评价数', width: 90}, |
| | | {field: 'receiveCycleHours', title: '收货周期(小时)', width: 120}, |
| | | {field: 'orderStartTime', title: '下单开始时间', width: 160}, |
| | | {field: 'orderEndTime', title: '下单结束时间', width: 160}, |
| | | {field: 'createTime', title: '创建时间', width: 160}, |
| | | { |
| | | field: 'status', title: '状态', width: 100, templet: function (d) { |
| | | if (d.status == 0) { |
| | | return '<span style="color: #999">未分配</span>'; |
| | | } else if (d.status == 1) { |
| | | return '<span style="color: #ff9900">分配中</span>'; |
| | | } else if (d.status == 2) { |
| | | return '<span style="color: #009900">已分配</span>'; |
| | | } |
| | | return '未知'; |
| | | } |
| | | }, |
| | | { |
| | | field: '', title: '操作', width: 200, align: 'center', fixed:"right", templet: function (d) { |
| | | let html = '<div>'; |
| | | html += '<a href="javascript:void(0)" onclick="updateTask(' + d.id + ')" class="layui-table-link">修改</a> '; |
| | | html += '<a href="javascript:void(0)" onclick="deleteTask(' + d.id + ')" class="layui-table-link">删除</a> '; |
| | | if (d.status == 0) { |
| | | html += '<a href="javascript:void(0)" onclick="assignTask(' + d.id + ')" class="layui-table-link">分配</a>'; |
| | | }else{ |
| | | html += '<a href="javascript:void(0)" onclick="viewAssignedClients(' + d.id + ')" class="layui-table-link">已分配设备</a>'; |
| | | } |
| | | html += '</div>'; |
| | | return html; |
| | | } |
| | | } |
| | | ]] |
| | | }; |
| | | |
| | | //第一个实例 |
| | | let tableIns = table.render(table_option); |
| | | |
| | | //监听提交 |
| | | form.on('submit(search)', function (data) { |
| | | tableIns.reload({ |
| | | where: data.field, |
| | | page: { |
| | | curr: 1 //重新从第 1 页开始 |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | form.on('submit(add-task)', function (data) { |
| | | $.post("/admin/api/ordertask/js2/add", data.field, function (response) { |
| | | if (response.code == 0) { |
| | | layer.msg("添加成功"); |
| | | // 关闭弹窗 |
| | | layer.closeAll('page'); |
| | | // 重新加载表格 |
| | | tableIns.reload(); |
| | | } else { |
| | | layer.msg(response.msg); |
| | | } |
| | | }, 'json').fail(function (jqXHR, textStatus, errorThrown) { |
| | | layer.msg("网络请求失败"); |
| | | }); |
| | | |
| | | return false; |
| | | }); |
| | | }); |
| | | </script> |
| | | </body> |
| | | |
| | | </html> |
New file |
| | |
| | | <!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; |
| | | } |
| | | |
| | | #sure { |
| | | visibility: hidden; |
| | | } |
| | | |
| | | .layui-form-label { |
| | | width: 150px; |
| | | } |
| | | |
| | | .layui-input-block { |
| | | margin-left: 180px; |
| | | max-width: 400px; |
| | | } |
| | | </style> |
| | | </head> |
| | | |
| | | <body> |
| | | |
| | | <form class="layui-form" lay-filter="edit"> |
| | | <input type="hidden" name="id"/> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">口令内容:</label> |
| | | <div class="layui-input-block"> |
| | | <textarea name="keywordContent" rows="5" required lay-verify="required" placeholder="口令内容" |
| | | autocomplete="off" class="layui-textarea"></textarea> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">商品来源:</label> |
| | | <div class="layui-input-block"> |
| | | <select name="productSource" required lay-verify="required"> |
| | | <option value="">请选择商品来源</option> |
| | | <option value="1">抖音</option> |
| | | <option value="2">快手</option> |
| | | </select> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">商品名称:</label> |
| | | <div class="layui-input-block"> |
| | | <textarea name="productName" rows="3" required lay-verify="required" placeholder="商品名称" autocomplete="off" |
| | | class="layui-textarea"></textarea> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">店铺名称:</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="shopName" placeholder="店铺名称" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">所需下单数量:</label> |
| | | <div class="layui-input-block"> |
| | | <input type="number" name="requiredOrderCount" required lay-verify="required|number" min="1" |
| | | placeholder="所需下单数量" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">收货周期(小时):</label> |
| | | <div class="layui-input-block"> |
| | | <input type="number" name="receiveCycleHours" required lay-verify="required|number" min="1" |
| | | placeholder="收货周期(小时)" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">下单开始时间:</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="orderStartTime" id="orderStartTime" required lay-verify="required" |
| | | placeholder="下单开始时间" autocomplete="off" class="layui-input"> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">下单结束时间:</label> |
| | | <div class="layui-input-block"> |
| | | <input type="text" name="orderEndTime" id="orderEndTime" required lay-verify="required" |
| | | placeholder="下单结束时间" autocomplete="off" class="layui-input"> |
| | | </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> |
| | | var listener; |
| | | |
| | | function submit(callback) { |
| | | //暂存回调方法 |
| | | listener = callback; |
| | | //表单提交按钮 |
| | | $("#sure").click(); |
| | | } |
| | | |
| | | layui.use(['form', 'layedit', 'laydate'], function () { |
| | | var form = layui.form, |
| | | layer = layui.layer, |
| | | laydate = layui.laydate; |
| | | |
| | | //自定义验证规则 |
| | | form.verify({ |
| | | num: [/^\d+$/, "必须为正整数"], |
| | | money: [/^\d+(\.\d{1,2})?$/, "金额最多保留2位小数"] |
| | | }); |
| | | |
| | | // 日期控件初始化 |
| | | laydate.render({ |
| | | elem: '#orderStartTime', |
| | | type: 'datetime', |
| | | theme: '#448aff' |
| | | }); |
| | | |
| | | laydate.render({ |
| | | elem: '#orderEndTime', |
| | | type: 'datetime', |
| | | theme: '#448aff' |
| | | }); |
| | | |
| | | var id = http_util.getQueryString("id"); |
| | | // 获取值 |
| | | $.post("/admin/api/ordertask/js2/get", { |
| | | "id": id |
| | | }, function (response) { |
| | | if (response.code == 0) { |
| | | form.val("edit", response.data); |
| | | } else { |
| | | layer.msg(response.msg); |
| | | } |
| | | }, 'json').fail(function (jqXHR, textStatus, errorThrown) { |
| | | layer.msg("网络请求失败"); |
| | | }); |
| | | |
| | | //监听提交 |
| | | form.on('submit(sure)', function (data) { |
| | | listener(data.field); |
| | | return false; |
| | | }); |
| | | }); |
| | | </script> |
| | | </body> |
| | | |
| | | </html> |