pull/1121/head
parent
888f6f1b1e
commit
9a69e37bc4
|
|
@ -4,8 +4,10 @@ import cn.hutool.core.bean.BeanUtil;
|
|||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.constant.CacheConstants;
|
||||
import com.ruoyi.common.core.controller.XktBaseController;
|
||||
|
|
@ -17,6 +19,7 @@ import com.ruoyi.common.enums.BusinessType;
|
|||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.desensitization.DesensitizationUtil;
|
||||
import com.ruoyi.common.utils.file.FileUtils;
|
||||
import com.ruoyi.framework.notice.fs.FsNotice;
|
||||
import com.ruoyi.web.controller.xkt.vo.IdVO;
|
||||
import com.ruoyi.web.controller.xkt.vo.express.ExpressShippingLabelVO;
|
||||
|
|
@ -29,12 +32,14 @@ import com.ruoyi.xkt.dto.express.ExpressInterceptReqDTO;
|
|||
import com.ruoyi.xkt.dto.express.ExpressShippingLabelDTO;
|
||||
import com.ruoyi.xkt.dto.order.*;
|
||||
import com.ruoyi.xkt.enums.EExpressStatus;
|
||||
import com.ruoyi.xkt.enums.EOrderStatus;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EPayPage;
|
||||
import com.ruoyi.xkt.manager.ExpressManager;
|
||||
import com.ruoyi.xkt.manager.PaymentManager;
|
||||
import com.ruoyi.xkt.service.IExpressService;
|
||||
import com.ruoyi.xkt.service.IStoreOrderService;
|
||||
import com.ruoyi.xkt.service.IStoreService;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
|
@ -44,7 +49,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -63,6 +71,8 @@ public class StoreOrderController extends XktBaseController {
|
|||
@Autowired
|
||||
private IExpressService expressService;
|
||||
@Autowired
|
||||
private IStoreService storeService;
|
||||
@Autowired
|
||||
private List<PaymentManager> paymentManagers;
|
||||
@Autowired
|
||||
private FsNotice fsNotice;
|
||||
|
|
@ -162,7 +172,7 @@ public class StoreOrderController extends XktBaseController {
|
|||
@ApiOperation(value = "订单分页查询")
|
||||
@PostMapping("/page")
|
||||
@ResponseHeader
|
||||
public R<PageVO<StoreOrderPageItemVO>> page(@Validated @RequestBody StoreOrderQueryVO vo) {
|
||||
public R<PageVO<StoreOrderPageItemVO>> page(@Validated @RequestBody StoreOrderPageQueryVO vo) {
|
||||
StoreOrderQueryDTO queryDTO = BeanUtil.toBean(vo, StoreOrderQueryDTO.class);
|
||||
if (1 == vo.getSrcPage()) {
|
||||
queryDTO.setOrderUserId(SecurityUtils.getUserId());
|
||||
|
|
@ -174,12 +184,50 @@ public class StoreOrderController extends XktBaseController {
|
|||
}
|
||||
queryDTO.setStoreId(storeId);
|
||||
}
|
||||
Page<StoreOrderPageItemDTO> pageDTO = storeOrderService.page(queryDTO);
|
||||
Page<StoreOrderPageItemDTO> pageDTO = PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
|
||||
storeOrderService.listPageItem(queryDTO);
|
||||
return success(PageVO.of(pageDTO, StoreOrderPageItemVO.class));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasAnyRoles('store')||@ss.hasSupplierSubRole()")
|
||||
@ApiOperation(value = "导出订单")
|
||||
@PostMapping("/export")
|
||||
@ResponseHeader
|
||||
public void export(@Validated @RequestBody StoreOrderQueryVO vo, HttpServletResponse response) {
|
||||
StoreOrderQueryDTO queryDTO = BeanUtil.toBean(vo, StoreOrderQueryDTO.class);
|
||||
Long storeId = SecurityUtils.getStoreId();
|
||||
queryDTO.setStoreId(storeId);
|
||||
String storeName = storeService.getStoreNameByIds(Collections.singletonList(storeId)).get(storeId);
|
||||
String title = StrUtil.emptyIfNull(storeName).concat("代发订单");
|
||||
try (ServletOutputStream os = response.getOutputStream()) {
|
||||
FileUtils.setAttachmentResponseHeader(response, title + ".xlsx");
|
||||
storeOrderService.exportOrder(queryDTO, null, title, os);
|
||||
} catch (IOException e) {
|
||||
logger.error("导出异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasAnyRoles('store')||@ss.hasSupplierSubRole()")
|
||||
@ApiOperation(value = "导出备货单")
|
||||
@PostMapping("/exportPendingShipment")
|
||||
@ResponseHeader
|
||||
public void exportPendingShipment(@Validated @RequestBody StoreOrderQueryVO vo, HttpServletResponse response) {
|
||||
StoreOrderQueryDTO queryDTO = BeanUtil.toBean(vo, StoreOrderQueryDTO.class);
|
||||
Long storeId = SecurityUtils.getStoreId();
|
||||
queryDTO.setStoreId(storeId);
|
||||
queryDTO.setOrderStatus(EOrderStatus.PENDING_SHIPMENT.getValue());
|
||||
String storeName = storeService.getStoreNameByIds(Collections.singletonList(storeId)).get(storeId);
|
||||
String title = StrUtil.emptyIfNull(storeName).concat("代发备货单");
|
||||
try (ServletOutputStream os = response.getOutputStream()) {
|
||||
FileUtils.setAttachmentResponseHeader(response, title + ".xlsx");
|
||||
storeOrderService.exportOrder(queryDTO, EOrderStatus.PENDING_SHIPMENT, title, os);
|
||||
} catch (IOException e) {
|
||||
logger.error("导出异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasAnyRoles('store,seller,agent')||@ss.hasSupplierSubRole()")
|
||||
@ApiOperation(value = "订单物流信息")
|
||||
@ApiOperation(value = "订单统计信息")
|
||||
@GetMapping(value = "/count/{srcPage}")
|
||||
public R<StoreOrderCountVO> count(@PathVariable("srcPage") Integer srcPage) {
|
||||
StoreOrderCountQueryDTO queryDTO = new StoreOrderCountQueryDTO();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
package com.ruoyi.web.controller.xkt.vo.order;
|
||||
|
||||
import com.ruoyi.web.controller.xkt.vo.BasePageVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-14 12:54
|
||||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class StoreOrderPageQueryVO extends BasePageVO {
|
||||
|
||||
@ApiModelProperty(value = "订单ID集合")
|
||||
private List<Long> storeOrderIds;
|
||||
/**
|
||||
* 档口ID
|
||||
*/
|
||||
@ApiModelProperty(value = "档口ID")
|
||||
private Long storeId;
|
||||
// /**
|
||||
// * 下单用户ID
|
||||
// */
|
||||
// @ApiModelProperty(value = "下单用户ID")
|
||||
// private Long orderUserId;
|
||||
/**
|
||||
* 订单号(模糊)
|
||||
*/
|
||||
@ApiModelProperty(value = "订单号(模糊)")
|
||||
private String orderNo;
|
||||
|
||||
@ApiModelProperty(value = "售后订单原订单号")
|
||||
private String originOrderNo;
|
||||
/**
|
||||
* 订单类型[1:销售订单 2:退货订单]
|
||||
*/
|
||||
@ApiModelProperty(value = "订单类型[1:销售订单 2:退货订单]")
|
||||
private Integer orderType;
|
||||
/**
|
||||
* 订单状态(1开头为销售订单状态,2开头为退货订单状态)[10:已取消 11:待付款 12:待发货 13:已发货 14:已完成 21:售后中 22:售后拒绝 23:平台介入 24:售后完成]
|
||||
*/
|
||||
@ApiModelProperty(value = "订单状态(1开头为销售订单状态,2开头为退货订单状态)[10:已取消 11:待付款 12:待发货 13:已发货 14:已完成 21:售后中 22:售后拒绝 23:平台介入 24:售后完成]")
|
||||
private Integer orderStatus;
|
||||
/**
|
||||
* 收货人-名称(模糊)
|
||||
*/
|
||||
@ApiModelProperty(value = "收货人-名称(模糊)")
|
||||
private String destinationContactName;
|
||||
/**
|
||||
* 收货人-电话(模糊)
|
||||
*/
|
||||
@ApiModelProperty(value = "收货人-电话(模糊)")
|
||||
private String destinationContactPhoneNumber;
|
||||
/**
|
||||
* 发货方式[1:货其再发 2:有货先发]
|
||||
*/
|
||||
@ApiModelProperty(value = "发货方式[1:货其再发 2:有货先发]")
|
||||
private Integer deliveryType;
|
||||
/**
|
||||
* 下单开始时间
|
||||
*/
|
||||
@ApiModelProperty(value = "下单开始时间")
|
||||
private Date orderTimeBegin;
|
||||
/**
|
||||
* 下单结束时间
|
||||
*/
|
||||
@ApiModelProperty(value = "下单结束时间")
|
||||
private Date orderTimeEnd;
|
||||
/**
|
||||
* 支付开始时间
|
||||
*/
|
||||
@ApiModelProperty(value = "支付开始时间")
|
||||
private Date payTimeBegin;
|
||||
/**
|
||||
* 支付结束时间
|
||||
*/
|
||||
@ApiModelProperty(value = "支付结束时间")
|
||||
private Date payTimeEnd;
|
||||
|
||||
/**
|
||||
* 物流运单号(模糊)
|
||||
*/
|
||||
@ApiModelProperty(value = "物流运单号(模糊)")
|
||||
private String expressWaybillNo;
|
||||
/**
|
||||
* 商品货号(模糊)
|
||||
*/
|
||||
@ApiModelProperty(value = "商品货号(模糊)")
|
||||
private String prodArtNum;
|
||||
|
||||
@NotNull(message = "来源页面不能为空")
|
||||
@ApiModelProperty(value = "来源页面[1:卖家订单列表 2:档口/平台订单列表]", required = true)
|
||||
private Integer srcPage;
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +1,8 @@
|
|||
package com.ruoyi.web.controller.xkt.vo.order;
|
||||
|
||||
import com.ruoyi.web.controller.xkt.vo.BasePageVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
|
|
@ -17,9 +14,7 @@ import java.util.List;
|
|||
*/
|
||||
@ApiModel
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class StoreOrderQueryVO extends BasePageVO {
|
||||
public class StoreOrderQueryVO {
|
||||
|
||||
@ApiModelProperty(value = "订单ID集合")
|
||||
private List<Long> storeOrderIds;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,25 @@
|
|||
package com.ruoyi.common.utils.poi;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author LH
|
||||
* @date 2021-04-23 13:30:54
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface ExcelColumn {
|
||||
/**
|
||||
* 表头
|
||||
*/
|
||||
String head() default "";
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
int index() default -1;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.ruoyi.common.utils.poi;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-08-16
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ExcelMergeRegion {
|
||||
|
||||
private Integer firstRow;
|
||||
|
||||
private Integer lastRow;
|
||||
|
||||
private Integer firstCol;
|
||||
|
||||
private Integer lastCol;
|
||||
}
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
package com.ruoyi.common.utils.poi;
|
||||
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.resource.ClassPathResource;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author LH
|
||||
* @date 2019/3/20 13:27
|
||||
**/
|
||||
@SuppressWarnings("all")
|
||||
public class ExcelTemplateUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExcelUtil.class);
|
||||
|
||||
private static final String HIDE = "$hide$";
|
||||
|
||||
private static final String COMMON_REGEX = "^(.*)\\$\\{(.+)\\}(.*)$";
|
||||
/**
|
||||
* for 循环表达式
|
||||
*/
|
||||
private static final String FOREACH_REGEX = "^\\$\\{(.+\\[.+\\])\\}$";
|
||||
/**
|
||||
* for 循环表达式中的字段
|
||||
*/
|
||||
private static final String FOREACH_REGEX_FIELD_NAME = "^\\$\\{(.+)\\[.+\\]\\}$";
|
||||
private static final String ARRAY_REGEX = "^.+\\[(.+)\\]$";
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param data 数据源
|
||||
* @param template 模板输入流
|
||||
* @param out excel 输出
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <T> void export(T data, InputStream template, OutputStream out) throws Exception {
|
||||
export(data, template, out, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用4个参数进行导出
|
||||
*
|
||||
* @param data 数据源
|
||||
* @param template 模板输入流
|
||||
* @param out 输出流
|
||||
* @param datePattern 数据格式
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <T> void export(T data, InputStream template, OutputStream out, String datePattern) throws Exception {
|
||||
export(data, template, out, datePattern, 0, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导出excel (用于导出不规则数据)
|
||||
* 支持表达式: ${name}, ${list[name]}, 表达式全部在模板中配置
|
||||
* ${name} : 数据源中属性名存在name
|
||||
* ${list[name]} : 数据源对象中存在属性list(List),并且列表对象中存在属性name
|
||||
*
|
||||
* @param data 数据源
|
||||
* @param template 模板输入流
|
||||
* @param out 输出
|
||||
* @param datePattern 日期格式化样式
|
||||
* @param sheetNumber sheet编号
|
||||
* @param mergeRegions 合并单元格
|
||||
* @throws Exception
|
||||
*/
|
||||
public static <T> void export(T data, InputStream template, OutputStream out, String datePattern, Integer sheetNumber, List<ExcelMergeRegion> mergeRegions) throws Exception {
|
||||
Workbook workbook = WorkbookFactory.create(template);
|
||||
Sheet sheet = workbook.getSheetAt(sheetNumber);
|
||||
|
||||
Row row;
|
||||
Cell cell;
|
||||
boolean foreach;
|
||||
String curListFieldName = null;
|
||||
for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
||||
row = sheet.getRow(rowIndex);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
foreach = false;
|
||||
|
||||
List<String> expressions = new ArrayList<>();
|
||||
Map<String, CellStyle> styleMap = new ConcurrentHashMap<>(20);
|
||||
for (int clumnINdex = 0; clumnINdex <= row.getLastCellNum(); clumnINdex++) {
|
||||
cell = row.getCell(clumnINdex);
|
||||
if (cell == null) {
|
||||
if (foreach) {
|
||||
expressions.add("");
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
String cellValue = getCellText(cell);
|
||||
if (cellValue.matches(FOREACH_REGEX)) {
|
||||
if (!foreach) {
|
||||
foreach = true;
|
||||
clumnINdex = -1;
|
||||
continue;
|
||||
}
|
||||
String expression = cellValue.replaceAll(FOREACH_REGEX, "$1");
|
||||
curListFieldName = cellValue.replaceAll(FOREACH_REGEX_FIELD_NAME, "$1");
|
||||
expressions.add(expression);
|
||||
styleMap.put(expression, cell.getCellStyle());
|
||||
} else if (cellValue.matches(COMMON_REGEX)) {
|
||||
String fieldName = cellValue.replaceAll(COMMON_REGEX, "$2");
|
||||
String fieldValue = getFieldStringValue(data, fieldName);
|
||||
String newValue = cellValue.replaceAll(COMMON_REGEX, "$1" + fieldValue + "$3");
|
||||
setCellValue(cell, newValue, datePattern);
|
||||
if (foreach) {
|
||||
expressions.add(newValue);
|
||||
}
|
||||
} else {
|
||||
if (foreach) {
|
||||
expressions.add(cellValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理for循环表达式
|
||||
if (expressions != null && !expressions.isEmpty()) {
|
||||
int index = 0;
|
||||
List list = getFieldListValue(data, curListFieldName);
|
||||
if (list == null || list.isEmpty()) {
|
||||
sheet.removeRow(row);
|
||||
continue;
|
||||
}
|
||||
// 把表达式行到最后一行的内容往后移动list 大小的行数
|
||||
if (list.size() - 1 != 0 && rowIndex + 1 <= sheet.getLastRowNum()) {
|
||||
sheet.shiftRows(rowIndex + 1, sheet.getLastRowNum(), list.size() - 1);
|
||||
}
|
||||
String expression;
|
||||
Object item;
|
||||
Cell cur;
|
||||
for (int k = 0; k < list.size(); k++) {
|
||||
item = list.get(k);
|
||||
index++;
|
||||
row = sheet.getRow(rowIndex++);
|
||||
if (row == null) {
|
||||
row = sheet.createRow(rowIndex - 1);
|
||||
}
|
||||
for (int i = 0; i < expressions.size(); i++) {
|
||||
cur = row.getCell(i);
|
||||
if (cur == null) {
|
||||
cur = row.createCell(i);
|
||||
}
|
||||
expression = expressions.get(i);
|
||||
if (expression.matches(ARRAY_REGEX)) {
|
||||
// items[waybillNo] -> wayBillNo -> item.waybillNo
|
||||
cur.setCellStyle(styleMap.get(expression));
|
||||
expression = expression.replaceAll(ARRAY_REGEX, "$1");
|
||||
if (expression.equals("INDEX")) {
|
||||
setCellValue(cur, index, datePattern);
|
||||
} else {
|
||||
setCellValue(cur, getFieldValue(item, expression), datePattern);
|
||||
}
|
||||
} else {
|
||||
setCellValue(cur, expression, datePattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
rowIndex--;
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(mergeRegions)) {
|
||||
for (ExcelMergeRegion mergeRegion : mergeRegions) {
|
||||
CellRangeAddress cellAddresses = new CellRangeAddress(mergeRegion.getFirstRow(),
|
||||
mergeRegion.getLastRow(), mergeRegion.getFirstCol(), mergeRegion.getLastCol());
|
||||
sheet.addMergedRegion(cellAddresses);
|
||||
}
|
||||
}
|
||||
workbook.write(out);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Excel 导出
|
||||
* 目标源对象必须使用 @ExcelColumn注解标记属性 例如 @ExcelColumn(index = 0, head = "运单号码")
|
||||
* index: 显示列的顺序, head: excle表头
|
||||
*
|
||||
* @param data 数据源列表
|
||||
* @param out 目标流
|
||||
* @param <T>
|
||||
*/
|
||||
public static <T> void export(List<T> data, OutputStream out) {
|
||||
export(data, out, null, false, null);
|
||||
}
|
||||
|
||||
public static <T> void export(List<T> data, OutputStream out, String datePattern) {
|
||||
export(data, out, datePattern, false, null);
|
||||
}
|
||||
|
||||
public static <T> void export(List<T> data, OutputStream out, boolean xlsx) {
|
||||
export(data, out, null, true, null);
|
||||
}
|
||||
|
||||
public static <T> void export(List<T> data, OutputStream out, List<String> excludes) {
|
||||
export(data, out, null, false, excludes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Excel 导出
|
||||
*
|
||||
* @param data 数据源
|
||||
* @param out 输入目标
|
||||
* @param datePattern 日期
|
||||
* @param xlsx 文件格式是否为xlsx
|
||||
* @param excludes 不需要导出的列
|
||||
* @param <T> <pre>
|
||||
* {@code
|
||||
*/
|
||||
public static <T> void export(List<T> data, OutputStream out, String datePattern, boolean xlsx,
|
||||
List<String> excludes) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
throw new IllegalArgumentException("数据不能为空");
|
||||
}
|
||||
if (datePattern == null) {
|
||||
datePattern = "yyyy-MM-dd HH:mm:ss";
|
||||
}
|
||||
Class<?> dataCls = data.get(0).getClass();
|
||||
Field[] fields = dataCls.getDeclaredFields();
|
||||
List<Column> columns = new ArrayList<>();
|
||||
|
||||
for (Field field : fields) {
|
||||
ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
|
||||
if (annotation != null) {
|
||||
field.setAccessible(true);
|
||||
// 排除列
|
||||
if (excludes != null && excludes.contains(field.getName())) {
|
||||
continue;
|
||||
}
|
||||
Object value = getFieldValue(field, data.get(0));
|
||||
columns.add(new Column(field, annotation.index(), annotation.head()));
|
||||
}
|
||||
}
|
||||
columns.sort((o1, o2) -> Integer.compare(o1.getIndex(), o2.getIndex()));
|
||||
|
||||
Workbook workbook;
|
||||
try {
|
||||
workbook = WorkbookFactory.create(xlsx);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
Sheet sheet = workbook.createSheet();
|
||||
int rowIndex = 0;
|
||||
int cellIndex = 0;
|
||||
Row headRow = sheet.createRow(rowIndex++);
|
||||
for (Column column : columns) {
|
||||
Cell cell = headRow.createCell(cellIndex++);
|
||||
setCellValue(cell, column.getHead());
|
||||
}
|
||||
Row curRow;
|
||||
for (T cur : data) {
|
||||
curRow = sheet.createRow(rowIndex++);
|
||||
Cell cell;
|
||||
cellIndex = 0;
|
||||
for (Column column : columns) {
|
||||
cell = curRow.createCell(cellIndex++);
|
||||
setCellValue(cell, getFieldValue(column.getField(), cur), datePattern);
|
||||
}
|
||||
}
|
||||
try {
|
||||
workbook.write(out);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream getTemplate(String templateName) {
|
||||
String path = "META-INF/excel/" + templateName;
|
||||
return new ClassPathResource(path).getStream();
|
||||
}
|
||||
|
||||
static class Column {
|
||||
private Field field;
|
||||
private int index;
|
||||
private String head;
|
||||
|
||||
public Column(Field field, int index, String head) {
|
||||
this.field = field;
|
||||
this.index = index;
|
||||
this.head = head;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public void setField(Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getHead() {
|
||||
return head;
|
||||
}
|
||||
|
||||
public void setHead(String head) {
|
||||
this.head = head;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getFieldValue(Field field, Object data) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
return field.get(data);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static <T> Object getFieldValue(T data, String fieldName) {
|
||||
try {
|
||||
if (fieldName.equals("list") && data instanceof List) {
|
||||
return data;
|
||||
}
|
||||
if (data instanceof Map) {
|
||||
return ((Map<?, ?>) data).get(fieldName);
|
||||
}
|
||||
Field field = data.getClass().getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
return field.get(data);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new IllegalArgumentException("无字段[" + fieldName + "]");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> String getFieldStringValue(T data, String fieldName) {
|
||||
Object value = getFieldValue(data, fieldName);
|
||||
return value == null ? "" : value.toString();
|
||||
}
|
||||
|
||||
private static <T> List getFieldListValue(T data, String fieldName) {
|
||||
Object value = getFieldValue(data, fieldName);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (!(value instanceof List)) {
|
||||
throw new IllegalArgumentException("字段[" + fieldName + "]非List类型");
|
||||
}
|
||||
return (List) value;
|
||||
}
|
||||
|
||||
private static String getCellText(Cell cell) {
|
||||
if (cell == null) {
|
||||
return "";
|
||||
}
|
||||
CellType cellType = cell.getCellType();
|
||||
|
||||
if (CellType.STRING.equals(cellType)) {
|
||||
return cell.getStringCellValue();
|
||||
} else if (CellType.NUMERIC.equals(cellType)) {
|
||||
return String.valueOf(cell.getNumericCellValue());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void setCellValue(Cell cell, Object value) {
|
||||
setCellValue(cell, value, null);
|
||||
}
|
||||
|
||||
private static void setCellValue(Cell cell, Object value, String datePattern) {
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
if (value instanceof Double) {
|
||||
cell.setCellValue((Double) value);
|
||||
} else if (value instanceof String) {
|
||||
cell.setCellValue((String) value);
|
||||
} else if (value instanceof BigDecimal) {
|
||||
BigDecimal val = (BigDecimal) value;
|
||||
cell.setCellValue(val.doubleValue());
|
||||
} else if (value instanceof Date) {
|
||||
if (datePattern == null) {
|
||||
datePattern = "yyyy-MM-dd HH:mm:ss";
|
||||
}
|
||||
Date date = (Date) value;
|
||||
String formatValue = new SimpleDateFormat(datePattern).format(date);
|
||||
cell.setCellValue(formatValue);
|
||||
} else if (value instanceof Number) {
|
||||
cell.setCellValue(Double.valueOf(value.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.ruoyi.xkt.dto.order;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-08-17
|
||||
*/
|
||||
@Data
|
||||
public class StoreOrderExportDTO {
|
||||
|
||||
private String title;
|
||||
|
||||
private List<Item> items;
|
||||
|
||||
@Data
|
||||
public static class Item {
|
||||
|
||||
private Integer seqNo;
|
||||
|
||||
private String orderNo;
|
||||
|
||||
private String createTime;
|
||||
|
||||
private String prodArtNum;
|
||||
|
||||
private String colorName;
|
||||
|
||||
private Integer size;
|
||||
|
||||
private Integer goodsQuantity;
|
||||
|
||||
private String detailStatus;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
package com.ruoyi.xkt.service;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.ruoyi.xkt.domain.StoreOrder;
|
||||
import com.ruoyi.xkt.dto.express.ExpressShippingLabelDTO;
|
||||
import com.ruoyi.xkt.dto.express.ExpressTrackDTO;
|
||||
import com.ruoyi.xkt.dto.order.*;
|
||||
import com.ruoyi.xkt.enums.EOrderStatus;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EPayPage;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
|
@ -92,7 +93,17 @@ public interface IStoreOrderService {
|
|||
* @param queryDTO
|
||||
* @return
|
||||
*/
|
||||
Page<StoreOrderPageItemDTO> page(StoreOrderQueryDTO queryDTO);
|
||||
List<StoreOrderPageItemDTO> listPageItem(StoreOrderQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 导出订单
|
||||
*
|
||||
* @param queryDTO
|
||||
* @param detailStatus
|
||||
* @param title
|
||||
* @param os
|
||||
*/
|
||||
void exportOrder(StoreOrderQueryDTO queryDTO, EOrderStatus detailStatus, String title, OutputStream os);
|
||||
|
||||
/**
|
||||
* 订单统计
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import cn.hutool.core.util.IdUtil;
|
|||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.SimpleEntity;
|
||||
|
|
@ -20,6 +19,8 @@ import com.ruoyi.common.core.domain.entity.SysUser;
|
|||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.bean.BeanValidators;
|
||||
import com.ruoyi.common.utils.poi.ExcelMergeRegion;
|
||||
import com.ruoyi.common.utils.poi.ExcelTemplateUtil;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.system.mapper.SysUserMapper;
|
||||
import com.ruoyi.xkt.domain.*;
|
||||
|
|
@ -40,6 +41,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
|
@ -549,12 +551,10 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Page<StoreOrderPageItemDTO> page(StoreOrderQueryDTO queryDTO) {
|
||||
Page<StoreOrderPageItemDTO> page = PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize(),
|
||||
"so.create_time DESC");
|
||||
storeOrderMapper.listStoreOrderPageItem(queryDTO);
|
||||
if (CollUtil.isNotEmpty(page.getResult())) {
|
||||
List<StoreOrderPageItemDTO> list = page.getResult();
|
||||
public List<StoreOrderPageItemDTO> listPageItem(StoreOrderQueryDTO queryDTO) {
|
||||
PageHelper.orderBy("so.create_time DESC");
|
||||
List<StoreOrderPageItemDTO> list = storeOrderMapper.listStoreOrderPageItem(queryDTO);
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
Set<Long> soIds = list.stream().map(StoreOrderPageItemDTO::getId).collect(Collectors.toSet());
|
||||
List<StoreOrderDetailInfoDTO> orderDetailList = storeOrderDetailMapper.listInfoByStoreOrderIds(soIds);
|
||||
List<Long> spIds = orderDetailList.stream().map(StoreOrderDetailInfoDTO::getStoreProdId).distinct()
|
||||
|
|
@ -593,7 +593,65 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
order.setExpressWaybillNoInfos(new ArrayList<>(expressWaybillNoInfos));
|
||||
}
|
||||
}
|
||||
return page;
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportOrder(StoreOrderQueryDTO queryDTO, EOrderStatus detailStatus, String title, OutputStream os) {
|
||||
PageHelper.orderBy("so.create_time DESC");
|
||||
List<StoreOrderPageItemDTO> pageItems = storeOrderMapper.listStoreOrderPageItem(queryDTO);
|
||||
Map<Long, List<StoreOrderDetailInfoDTO>> orderDetailGroup;
|
||||
if (CollUtil.isNotEmpty(pageItems)) {
|
||||
Set<Long> soIds = pageItems.stream().map(StoreOrderPageItemDTO::getId).collect(Collectors.toSet());
|
||||
List<StoreOrderDetailInfoDTO> orderDetailList = storeOrderDetailMapper.listInfoByStoreOrderIds(soIds);
|
||||
orderDetailGroup = orderDetailList
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(StoreOrderDetailDTO::getStoreOrderId));
|
||||
} else {
|
||||
orderDetailGroup = MapUtil.empty();
|
||||
}
|
||||
StoreOrderExportDTO exportDTO = new StoreOrderExportDTO();
|
||||
exportDTO.setTitle(title);
|
||||
List<StoreOrderExportDTO.Item> items = new ArrayList<>();
|
||||
exportDTO.setItems(items);
|
||||
List<ExcelMergeRegion> mergeRegions = new ArrayList<>();
|
||||
int seqNo = 1;
|
||||
int lineNo = 1;
|
||||
for (StoreOrderPageItemDTO pageItem : pageItems) {
|
||||
List<StoreOrderDetailInfoDTO> details = orderDetailGroup.get(pageItem.getId()).stream().filter(o -> {
|
||||
if (detailStatus != null) {
|
||||
return detailStatus.getValue().equals(o.getDetailStatus());
|
||||
}
|
||||
return true;
|
||||
}).collect(Collectors.toList());
|
||||
int size = details.size();
|
||||
if (size > 1) {
|
||||
mergeRegions.add(new ExcelMergeRegion(lineNo + 1, lineNo + size, 0, 0));
|
||||
mergeRegions.add(new ExcelMergeRegion(lineNo + 1, lineNo + size, 1, 1));
|
||||
mergeRegions.add(new ExcelMergeRegion(lineNo + 1, lineNo + size, 2, 2));
|
||||
}
|
||||
for (StoreOrderDetailInfoDTO detail : details) {
|
||||
StoreOrderExportDTO.Item item = new StoreOrderExportDTO.Item();
|
||||
item.setSeqNo(seqNo);
|
||||
item.setOrderNo(pageItem.getOrderNo());
|
||||
item.setCreateTime(DateUtil.formatDateTime(pageItem.getCreateTime()));
|
||||
item.setProdArtNum(detail.getProdArtNum());
|
||||
item.setColorName(detail.getColorName());
|
||||
item.setSize(detail.getSize());
|
||||
item.setGoodsQuantity(detail.getGoodsQuantity());
|
||||
item.setDetailStatus(EOrderStatus.of(detail.getDetailStatus()).getLabel());
|
||||
items.add(item);
|
||||
lineNo++;
|
||||
}
|
||||
seqNo++;
|
||||
}
|
||||
try {
|
||||
ExcelTemplateUtil.export(exportDTO, ExcelTemplateUtil.getTemplate("order_export.xlsx"),
|
||||
os, null, 0, mergeRegions);
|
||||
} catch (Exception e) {
|
||||
log.error("订单导出异常", e);
|
||||
throw new ServiceException("订单导出失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue