1
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
package com.ruoyi.web.controller.jarvis;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.jarvis.service.IInstructionService;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令执行控制器:将 jd/JDUtil 的指令处理迁移为 HTTP 接口
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/jarvis/instruction")
|
||||||
|
public class InstructionController extends BaseController {
|
||||||
|
|
||||||
|
private final IInstructionService instructionService;
|
||||||
|
|
||||||
|
public InstructionController(IInstructionService instructionService) {
|
||||||
|
this.instructionService = instructionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行文本指令
|
||||||
|
* body: { command: "京今日统计" }
|
||||||
|
*/
|
||||||
|
@PostMapping("/execute")
|
||||||
|
public AjaxResult execute(@RequestBody Map<String, String> body) {
|
||||||
|
String cmd = body != null ? body.get("command") : null;
|
||||||
|
String result = instructionService.execute(cmd);
|
||||||
|
return AjaxResult.success(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.ruoyi.jarvis.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令执行服务
|
||||||
|
*/
|
||||||
|
public interface IInstructionService {
|
||||||
|
/**
|
||||||
|
* 执行文本指令,返回结果文本
|
||||||
|
* @param command 指令内容
|
||||||
|
* @return 执行结果文本
|
||||||
|
*/
|
||||||
|
String execute(String command);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
package com.ruoyi.jarvis.service.impl;
|
||||||
|
|
||||||
|
import com.ruoyi.jarvis.domain.OrderRows;
|
||||||
|
import com.ruoyi.jarvis.domain.JDOrder;
|
||||||
|
import com.ruoyi.jarvis.service.IInstructionService;
|
||||||
|
import com.ruoyi.jarvis.service.IOrderRowsService;
|
||||||
|
import com.ruoyi.jarvis.service.IJDOrderService;
|
||||||
|
import com.ruoyi.jarvis.service.SuperAdminService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 jd 项目中 JDUtil 的指令能力,抽取为无微信依赖的本地执行版。
|
||||||
|
* 仅实现最常用统计/订单查询与转链占位能力,按需扩展。
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class InstructionServiceImpl implements IInstructionService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IOrderRowsService orderRowsService;
|
||||||
|
@Resource
|
||||||
|
private IJDOrderService jdOrderService;
|
||||||
|
@Resource
|
||||||
|
private SuperAdminService superAdminService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(String command) {
|
||||||
|
if (command == null || command.trim().isEmpty()) {
|
||||||
|
return "请输入指令";
|
||||||
|
}
|
||||||
|
String input = command.trim();
|
||||||
|
|
||||||
|
// 一级命令分流:京系(统计/订单)、录单/慢单、转链/礼金…
|
||||||
|
if (input.startsWith("京") || menuKeywords().contains(input)) {
|
||||||
|
return handleJingFen(input.replaceFirst("^京", ""));
|
||||||
|
}
|
||||||
|
if (input.startsWith("录单") || input.startsWith("慢单") || input.startsWith("慢搜") || input.startsWith("慢查") || input.startsWith("单")) {
|
||||||
|
return handleRecordLike(input);
|
||||||
|
}
|
||||||
|
if (input.startsWith("转链") || input.startsWith("文案") || input.startsWith("转")) {
|
||||||
|
return handleTransferLike(input);
|
||||||
|
}
|
||||||
|
return helpText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> menuKeywords() {
|
||||||
|
return new HashSet<>(Arrays.asList("菜单","今日统计","昨日统计","三日统计","七日统计","一个月统计","两个月统计","三个月统计","这个月统计","上个月统计","今日订单","昨日订单","七日订单","总统计"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String handleJingFen(String cmd) {
|
||||||
|
String action = cmd.trim();
|
||||||
|
if (action.isEmpty() || action.equals("菜单")) {
|
||||||
|
return jingMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取出所有订单(排除被删除/无效:这里沿用 OrderRowsService 的常规查询,必要时可增加过滤参数)
|
||||||
|
List<OrderRows> all = orderRowsService.selectOrderRowsList(new OrderRows());
|
||||||
|
if (all == null) all = Collections.emptyList();
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case "今日统计": return statsText(filterByDays(all, 0), "今日统计");
|
||||||
|
case "昨日统计": return statsText(filterYesterday(all), "昨日统计");
|
||||||
|
case "三日统计": return statsText(filterByRange(all, 3), "三日统计");
|
||||||
|
case "七日统计": return statsText(filterByRange(all, 7), "七日统计");
|
||||||
|
case "一个月统计": return statsText(filterByRange(all, 30), "一个月统计");
|
||||||
|
case "两个月统计": return statsText(filterByRange(all, 60), "两个月统计");
|
||||||
|
case "三个月统计": return statsText(filterByRange(all, 90), "三个月统计");
|
||||||
|
case "这个月统计": return statsText(filterThisMonth(all), "这个月统计");
|
||||||
|
case "上个月统计": return statsText(filterLastMonth(all), "上个月统计");
|
||||||
|
case "总统计": return statsText(all, "总统计");
|
||||||
|
case "今日订单": return listOrders(filterByDays(all, 0), "今日订单");
|
||||||
|
case "昨日订单": return listOrders(filterYesterday(all), "昨日订单");
|
||||||
|
case "七日订单": return listOrders(filterByRange(all, 7), "七日订单");
|
||||||
|
default:
|
||||||
|
// 高级命令:违规N、SKU、搜索、JF… 此处按需扩展
|
||||||
|
if (action.startsWith("高级")) {
|
||||||
|
return "高级指令暂未开放";
|
||||||
|
}
|
||||||
|
return jingMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String handleRecordLike(String input) {
|
||||||
|
// 仅实现“慢搜/慢查 关键词”与“录单/慢单 日期范围”的只读输出,避免侵入写库
|
||||||
|
if (input.startsWith("慢搜") || input.startsWith("慢查")) {
|
||||||
|
String kw = input.replaceFirst("^慢搜|^慢查", "").trim();
|
||||||
|
if (kw.isEmpty()) return "请输入搜索关键词";
|
||||||
|
List<JDOrder> list = jdOrderService.selectJDOrderList(new JDOrder());
|
||||||
|
if (list == null) list = Collections.emptyList();
|
||||||
|
String low = kw.toLowerCase(Locale.ROOT);
|
||||||
|
List<JDOrder> matched = list.stream().filter(o ->
|
||||||
|
contains(o.getRemark(), low) || contains(o.getOrderId(), low) || contains(o.getModelNumber(), low) || contains(o.getAddress(), low) || contains(o.getBuyer(), low)
|
||||||
|
).limit(50).collect(Collectors.toList());
|
||||||
|
if (matched.isEmpty()) return "未找到匹配的订单";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int i = 0;
|
||||||
|
for (JDOrder o : matched) {
|
||||||
|
i++;
|
||||||
|
sb.append(i).append(", 单:").append(nvl(o.getRemark()))
|
||||||
|
.append("\n分销标记:").append(nvl(o.getDistributionMark()))
|
||||||
|
.append("\n型号:").append(nvl(o.getModelNumber()))
|
||||||
|
.append("\n链接:").append(nvl(o.getLink()))
|
||||||
|
.append("\n下单付款:").append(nvl(o.getPaymentAmount()))
|
||||||
|
.append("\n后返金额:").append(nvl(o.getRebateAmount()))
|
||||||
|
.append("\n地址:").append(nvl(o.getAddress()))
|
||||||
|
.append("\n物流链接:").append(nvl(o.getLogisticsLink()))
|
||||||
|
.append("\n订单号:").append(nvl(o.getOrderId()))
|
||||||
|
.append("\n下单人:").append(nvl(o.getBuyer()))
|
||||||
|
.append("\n下单时间:").append(nvl(o.getOrderTime()))
|
||||||
|
.append("\n备注:").append(nvl(o.getStatus()))
|
||||||
|
.append("\n━━━━━━━━━━━━\n");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
if (input.startsWith("录单") || input.startsWith("慢单")) {
|
||||||
|
// 提取日期(yyyyMMdd 或 yyyyMMdd-yyyyMMdd 或 关键词:昨日/三日/七日)
|
||||||
|
List<LocalDate> range = parseDateRange(input.replaceFirst("^录单|^慢单", "").trim());
|
||||||
|
if (range == null) {
|
||||||
|
LocalDate today = effectiveToday().toLocalDate();
|
||||||
|
range = Arrays.asList(today, today);
|
||||||
|
}
|
||||||
|
Date start = Date.from(range.get(0).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||||
|
Date end = Date.from(range.get(1).atTime(LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
List<JDOrder> list = jdOrderService.selectJDOrderList(new JDOrder());
|
||||||
|
if (list == null) list = Collections.emptyList();
|
||||||
|
List<JDOrder> filtered = list.stream().filter(o -> o.getOrderTime()!=null && !o.getOrderTime().before(start) && !o.getOrderTime().after(end)).collect(Collectors.toList());
|
||||||
|
if (filtered.isEmpty()) return "时间范围内没有订单";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (JDOrder o : filtered) {
|
||||||
|
sb.append(nvl(o.getRemark())).append('\t')
|
||||||
|
.append(nvl(o.getOrderId())).append('\t')
|
||||||
|
.append(fmt(o.getOrderTime())).append('\t')
|
||||||
|
.append(nvl(o.getModelNumber())).append('\t')
|
||||||
|
.append(nvl(o.getAddress())).append('\t')
|
||||||
|
.append(nvl(o.getLogisticsLink())).append('\t')
|
||||||
|
.append('\t').append(nvl(o.getBuyer())).append('\t')
|
||||||
|
.append(nvl(o.getPaymentAmount())).append('\t')
|
||||||
|
.append(nvl(o.getRebateAmount())).append('\t')
|
||||||
|
.append(mapDistribution(o.getDistributionMark())).append('\t')
|
||||||
|
.append(nvl(o.getStatus())).append("\n");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
// 单… 的解析/入库在 jd 工程内较复杂,这里仅返回模板校验结果
|
||||||
|
if (input.startsWith("单")) {
|
||||||
|
return "录单模板校验暂未开放(仅支持 慢搜/慢查、录单/慢单 查询)";
|
||||||
|
}
|
||||||
|
return helpText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String handleTransferLike(String input) {
|
||||||
|
// 前端仍复用已有 /jarvis/jdorder/generatePromotionContent 接口,这里仅提供一个回显占位
|
||||||
|
return "指令入口:请在\"一键转链\"页面使用(输入文案/链接后点生成)";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 统计与列表渲染 =====
|
||||||
|
private String statsText(List<OrderRows> rows, String title) {
|
||||||
|
long total = rows.size();
|
||||||
|
long paid = rows.stream().filter(o -> Integer.valueOf(16).equals(o.getValidCode())).count();
|
||||||
|
long pending = rows.stream().filter(o -> Integer.valueOf(15).equals(o.getValidCode())).count();
|
||||||
|
long completed = rows.stream().filter(o -> Integer.valueOf(17).equals(o.getValidCode())).count();
|
||||||
|
long canceled = rows.stream().filter(o -> o.getValidCode()!=null && o.getValidCode()!=16 && o.getValidCode()!=17).count();
|
||||||
|
long violation = rows.stream().filter(o -> o.getValidCode()!=null && (o.getValidCode()==13 || o.getValidCode()==25 || o.getValidCode()==26 || o.getValidCode()==27 || o.getValidCode()==28 || o.getValidCode()==29)).count();
|
||||||
|
double paidCommission = rows.stream().filter(o -> Integer.valueOf(16).equals(o.getValidCode()) && o.getEstimateFee()!=null).mapToDouble(OrderRows::getEstimateFee).sum();
|
||||||
|
double pendingCommission = rows.stream().filter(o -> Integer.valueOf(15).equals(o.getValidCode()) && o.getEstimateFee()!=null).mapToDouble(OrderRows::getEstimateFee).sum();
|
||||||
|
double completedCommission = rows.stream().filter(o -> Integer.valueOf(17).equals(o.getValidCode()) && o.getEstimateFee()!=null).mapToDouble(OrderRows::getEstimateFee).sum();
|
||||||
|
double violationCommission = rows.stream().filter(o -> o.getValidCode()!=null && (o.getValidCode()==13 || o.getValidCode()==25 || o.getValidCode()==26 || o.getValidCode()==27 || o.getValidCode()==28 || o.getValidCode()==29) && o.getEstimateCosPrice()!=null && o.getCommissionRate()!=null).mapToDouble(o -> o.getEstimateCosPrice()*o.getCommissionRate()*0.01).sum();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("* ").append(title).append(" *\n")
|
||||||
|
.append("━━━━━━━━━━━━\n")
|
||||||
|
.append("订单总数:").append(total).append("\n")
|
||||||
|
.append("有效订单:").append(total - canceled).append("\n")
|
||||||
|
.append("已取消:").append(canceled).append("\n")
|
||||||
|
.append("────────────\n")
|
||||||
|
.append("已付款:").append(paid).append("\n")
|
||||||
|
.append("已付款佣金:").append(fmt(paidCommission)).append("\n")
|
||||||
|
.append("────────────\n")
|
||||||
|
.append("待付款:").append(pending).append("\n")
|
||||||
|
.append("待付款佣金:").append(fmt(pendingCommission)).append("\n")
|
||||||
|
.append("────────────\n")
|
||||||
|
.append("已完成:").append(completed).append("\n")
|
||||||
|
.append("已完成佣金:").append(fmt(completedCommission)).append("\n")
|
||||||
|
.append("────────────\n")
|
||||||
|
.append("违规订单:").append(violation).append("\n")
|
||||||
|
.append("违规佣金:").append(fmt(violationCommission)).append("\n")
|
||||||
|
.append("━━━━━━━━━━━━");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String listOrders(List<OrderRows> rows, String title) {
|
||||||
|
if (rows.isEmpty()) return title + ":无";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(title).append("(").append(rows.size()).append("条)\n");
|
||||||
|
int i = 0;
|
||||||
|
for (OrderRows r : rows) {
|
||||||
|
i++;
|
||||||
|
sb.append(i).append(". ").append(Optional.ofNullable(r.getSkuName()).orElse("-"))
|
||||||
|
.append(" | 订单号:").append(Optional.ofNullable(r.getOrderId()).map(String::valueOf).orElse("-"))
|
||||||
|
.append(" | 时间:").append(fmt(r.getOrderTime()))
|
||||||
|
.append(" | 有效:").append(r.getValidCode()==null?"-":r.getValidCode()).append("\n");
|
||||||
|
if (i>=100) break; // 最多100条
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 过滤器 =====
|
||||||
|
private List<OrderRows> filterByDays(List<OrderRows> list, int daysBack) {
|
||||||
|
LocalDate now = LocalDate.now();
|
||||||
|
return list.stream().filter(o -> {
|
||||||
|
Date d = o.getOrderTime();
|
||||||
|
if (d == null) return false;
|
||||||
|
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||||
|
if (daysBack == 0) return od.equals(now);
|
||||||
|
return !od.isBefore(now.minusDays(daysBack)) && !od.isAfter(now);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<OrderRows> filterByRange(List<OrderRows> list, int days) {
|
||||||
|
return filterByDays(list, days);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<OrderRows> filterYesterday(List<OrderRows> list) {
|
||||||
|
LocalDate y = LocalDate.now().minusDays(1);
|
||||||
|
return list.stream().filter(o -> {
|
||||||
|
Date d = o.getOrderTime(); if (d==null) return false;
|
||||||
|
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||||
|
return od.equals(y);
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<OrderRows> filterThisMonth(List<OrderRows> list) {
|
||||||
|
LocalDate now = LocalDate.now();
|
||||||
|
return list.stream().filter(o -> {
|
||||||
|
Date d = o.getOrderTime(); if (d==null) return false;
|
||||||
|
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||||
|
return od.getYear()==now.getYear() && od.getMonth()==now.getMonth();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<OrderRows> filterLastMonth(List<OrderRows> list) {
|
||||||
|
LocalDate now = LocalDate.now().minusMonths(1);
|
||||||
|
return list.stream().filter(o -> {
|
||||||
|
Date d = o.getOrderTime(); if (d==null) return false;
|
||||||
|
LocalDate od = d.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||||
|
return od.getYear()==now.getYear() && od.getMonth()==now.getMonth();
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 工具 =====
|
||||||
|
private String jingMenu() {
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
content.append("菜单:京+命令,如: 京今日统计\r\n")
|
||||||
|
.append("今日统计\r\n")
|
||||||
|
.append("昨日统计\r\n")
|
||||||
|
.append("七日统计\r\n")
|
||||||
|
.append("一个月统计\r\n")
|
||||||
|
.append("两个月统计\r\n")
|
||||||
|
.append("三个月统计\r\n")
|
||||||
|
.append("总统计\r\n")
|
||||||
|
.append("这个月统计\r\n")
|
||||||
|
.append("上个月统计\r\n")
|
||||||
|
.append("\r\n")
|
||||||
|
.append("今日订单\r\n")
|
||||||
|
.append("昨日订单\r\n")
|
||||||
|
.append("七日订单\r\n");
|
||||||
|
return content.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDateTime effectiveToday() {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
if (now.getHour() < 8) return now.minusDays(1);
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<LocalDate> parseDateRange(String s) {
|
||||||
|
if (s==null || s.isEmpty()) return null;
|
||||||
|
if ("昨日".equals(s)) {
|
||||||
|
LocalDate y = LocalDate.now().minusDays(1);
|
||||||
|
return Arrays.asList(y, y);
|
||||||
|
}
|
||||||
|
if ("三日".equals(s)) {
|
||||||
|
LocalDate end = LocalDate.now().minusDays(1);
|
||||||
|
LocalDate start = LocalDate.now().minusDays(3);
|
||||||
|
return Arrays.asList(start, end);
|
||||||
|
}
|
||||||
|
if ("七日".equals(s)) {
|
||||||
|
LocalDate end = LocalDate.now().minusDays(1);
|
||||||
|
LocalDate start = LocalDate.now().minusDays(7);
|
||||||
|
return Arrays.asList(start, end);
|
||||||
|
}
|
||||||
|
Pattern p = Pattern.compile("(\\d{8})(?:-(\\d{8}))?");
|
||||||
|
Matcher m = p.matcher(s);
|
||||||
|
if (m.find()) {
|
||||||
|
LocalDate d1 = parseYmd(m.group(1));
|
||||||
|
LocalDate d2 = m.group(2)!=null ? parseYmd(m.group(2)) : d1;
|
||||||
|
return Arrays.asList(d1, d2);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDate parseYmd(String ymd) {
|
||||||
|
int y = Integer.parseInt(ymd.substring(0,4));
|
||||||
|
int mo = Integer.parseInt(ymd.substring(4,6));
|
||||||
|
int d = Integer.parseInt(ymd.substring(6,8));
|
||||||
|
return LocalDate.of(y, mo, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String mapDistribution(String v) {
|
||||||
|
if (v == null) return "";
|
||||||
|
if (v.startsWith("H")) return "鸿";
|
||||||
|
if (v.startsWith("F")) return "凡";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean contains(Object field, String kwLower) {
|
||||||
|
if (field == null) return false;
|
||||||
|
return String.valueOf(field).toLowerCase(Locale.ROOT).contains(kwLower);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String nvl(Object v) {
|
||||||
|
return v == null ? "" : String.valueOf(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String fmt(Object v) {
|
||||||
|
if (v == null) return "";
|
||||||
|
if (v instanceof Number) {
|
||||||
|
return String.format(Locale.ROOT, "%.2f", ((Number) v).doubleValue());
|
||||||
|
}
|
||||||
|
if (v instanceof Date) {
|
||||||
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
return sdf.format((Date) v);
|
||||||
|
}
|
||||||
|
return String.valueOf(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user