diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageController.java index 01e79d598..4498bcb8f 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageController.java @@ -6,20 +6,26 @@ import com.ruoyi.common.core.controller.XktBaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.Page; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.web.controller.xkt.vo.storeProdStorage.StoreProdStoragePageVO; import com.ruoyi.web.controller.xkt.vo.storeProdStorage.StoreProdStorageResVO; import com.ruoyi.web.controller.xkt.vo.storeProdStorage.StoreProdStorageVO; +import com.ruoyi.web.controller.xkt.vo.storeSale.StoreSaleExportVO; import com.ruoyi.xkt.dto.storeProdStorage.StoreProdStorageDTO; import com.ruoyi.xkt.dto.storeProdStorage.StoreProdStoragePageDTO; import com.ruoyi.xkt.dto.storeProdStorage.StoreProdStoragePageResDTO; +import com.ruoyi.xkt.dto.storeSale.StoreSaleDownloadDTO; +import com.ruoyi.xkt.dto.storeSale.StoreSaleExportDTO; import com.ruoyi.xkt.service.IStoreProductStorageService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + /** * 档口商品入库Controller * @@ -34,10 +40,6 @@ public class StoreProductStorageController extends XktBaseController { final IStoreProductStorageService storeProdStorageService; - /** - * 新增档口商品入库 - */ - // @PreAuthorize("@ss.hasPermi('system:storage:add')") @ApiOperation(value = "新增档口商品入库", httpMethod = "POST", response = R.class) @Log(title = "新增档口商品入库", businessType = BusinessType.INSERT) @PostMapping @@ -45,30 +47,18 @@ public class StoreProductStorageController extends XktBaseController { return R.ok(storeProdStorageService.create(BeanUtil.toBean(storeProdStorageVO, StoreProdStorageDTO.class))); } - /** - * 查询档口商品入库列表 - */ - // @PreAuthorize("@ss.hasPermi('system:product:list')") @ApiOperation(value = "查询档口商品入库列表", httpMethod = "POST", response = R.class) @PostMapping("/page") public R> page(@Validated @RequestBody StoreProdStoragePageVO pageVO) { return R.ok(storeProdStorageService.page(BeanUtil.toBean(pageVO, StoreProdStoragePageDTO.class))); } - /** - * 获取档口商品入库详细信息 - */ - // @PreAuthorize("@ss.hasPermi('system:storage:query')") @ApiOperation(value = "获取档口商品入库详细信息", httpMethod = "GET", response = R.class) @GetMapping(value = "/{storeProdStorageId}") public R getInfo(@PathVariable("storeProdStorageId") Long storeProdStorageId) { return R.ok(BeanUtil.toBean(storeProdStorageService.selectByStoreProdStorageId(storeProdStorageId), StoreProdStorageResVO.class)); } - /** - * 撤销档口商品入库 - */ - // @PreAuthorize("@ss.hasPermi('system:storage:remove')") @ApiOperation(value = "撤销档口商品入库", httpMethod = "DELETE", response = R.class) @Log(title = "撤销档口商品入库", businessType = BusinessType.DELETE) @DeleteMapping("/{storeProdStorageId}") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageDetailController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageDetailController.java index b67dbd9d6..1d6c875b0 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageDetailController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreProductStorageDetailController.java @@ -1,19 +1,30 @@ package com.ruoyi.web.controller.xkt; +import cn.hutool.core.bean.BeanUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.XktBaseController; import com.ruoyi.common.core.domain.R; -import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.poi.ExcelUtil; -import com.ruoyi.xkt.domain.StoreProductStorageDetail; +import com.ruoyi.web.controller.xkt.vo.storeProdStorage.StoreStorageExportVO; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageDetailDownloadDTO; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageExportDTO; import com.ruoyi.xkt.service.IStoreProductStorageDetailService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.List; +import java.util.UUID; /** * 档口商品入库明细Controller @@ -21,71 +32,24 @@ import java.util.List; * @author ruoyi * @date 2025-03-26 */ +@Api(tags = "档口商品入库明细") @RestController +@RequiredArgsConstructor @RequestMapping("/rest/v1/storage-details") public class StoreProductStorageDetailController extends XktBaseController { - @Autowired - private IStoreProductStorageDetailService storeProductStorageDetailService; - /** - * 查询档口商品入库明细列表 - */ - // @PreAuthorize("@ss.hasPermi('system:detail:list')") - @GetMapping("/list") - public TableDataInfo list(StoreProductStorageDetail storeProductStorageDetail) { - startPage(); - List list = storeProductStorageDetailService.selectStoreProductStorageDetailList(storeProductStorageDetail); - return getDataTable(list); - } + final IStoreProductStorageDetailService storageDetailService; - /** - * 导出档口商品入库明细列表 - */ - // @PreAuthorize("@ss.hasPermi('system:detail:export')") - @Log(title = "档口商品入库明细", businessType = BusinessType.EXPORT) + @ApiOperation(value = "导出入库记录", httpMethod = "POST", response = R.class) + @Log(title = "导出入库记录", businessType = BusinessType.EXPORT) @PostMapping("/export") - public void export(HttpServletResponse response, StoreProductStorageDetail storeProductStorageDetail) { - List list = storeProductStorageDetailService.selectStoreProductStorageDetailList(storeProductStorageDetail); - ExcelUtil util = new ExcelUtil(StoreProductStorageDetail.class); - util.exportExcel(response, list, "档口商品入库明细数据"); + public void export(HttpServletResponse response, @Validated @RequestBody StoreStorageExportVO exportVO) throws UnsupportedEncodingException { + List downloadList = storageDetailService.export(BeanUtil.toBean(exportVO, StoreStorageExportDTO.class)); + ExcelUtil util = new ExcelUtil<>(StoreStorageDetailDownloadDTO.class); + // 设置下载excel名 + String encodedFileName = URLEncoder.encode("入库记录" + DateUtils.getDate(), "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx"); + util.exportExcel(response, downloadList, "入库记录"); } - /** - * 获取档口商品入库明细详细信息 - */ - // @PreAuthorize("@ss.hasPermi('system:detail:query')") - @GetMapping(value = "/{storeProdStorDetailId}") - public R getInfo(@PathVariable("storeProdStorDetailId") Long storeProdStorDetailId) { - return success(storeProductStorageDetailService.selectStoreProductStorageDetailByStoreProdStorDetailId(storeProdStorDetailId)); - } - - /** - * 新增档口商品入库明细 - */ - // @PreAuthorize("@ss.hasPermi('system:detail:add')") - @Log(title = "档口商品入库明细", businessType = BusinessType.INSERT) - @PostMapping - public R add(@RequestBody StoreProductStorageDetail storeProductStorageDetail) { - return success(storeProductStorageDetailService.insertStoreProductStorageDetail(storeProductStorageDetail)); - } - - /** - * 修改档口商品入库明细 - */ - // @PreAuthorize("@ss.hasPermi('system:detail:edit')") - @Log(title = "档口商品入库明细", businessType = BusinessType.UPDATE) - @PutMapping - public R edit(@RequestBody StoreProductStorageDetail storeProductStorageDetail) { - return success(storeProductStorageDetailService.updateStoreProductStorageDetail(storeProductStorageDetail)); - } - - /** - * 删除档口商品入库明细 - */ - // @PreAuthorize("@ss.hasPermi('system:detail:remove')") - @Log(title = "档口商品入库明细", businessType = BusinessType.DELETE) - @DeleteMapping("/{storeProdStorDetailIds}") - public R remove(@PathVariable Long[] storeProdStorDetailIds) { - return success(storeProductStorageDetailService.deleteStoreProductStorageDetailByStoreProdStorDetailIds(storeProdStorDetailIds)); - } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java index 682ceb143..79b8b25fa 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreSaleController.java @@ -6,6 +6,9 @@ import com.ruoyi.common.core.controller.XktBaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.Page; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysOperLog; import com.ruoyi.web.controller.xkt.vo.storeCustomer.StoreCusGeneralSaleVO; import com.ruoyi.web.controller.xkt.vo.storeSale.*; import com.ruoyi.xkt.dto.storeSale.*; @@ -17,6 +20,11 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; + /** * 档口销售出库Controller * @@ -77,7 +85,8 @@ public class StoreSaleController extends XktBaseController { return R.ok(storeSaleService.clearStoreCusDebt(BeanUtil.toBean(payStatusVO, StoreSalePayStatusDTO.class))); } - @Log(title = "档口销售出库", businessType = BusinessType.DELETE) + @ApiOperation(value = "删除档口销售出库", httpMethod = "PUT", response = R.class) + @Log(title = "删除档口销售出库", businessType = BusinessType.DELETE) @DeleteMapping("/{storeSaleId}") public R remove(@PathVariable Long storeSaleId) { return R.ok(storeSaleService.deleteStoreSaleByStoreSaleId(storeSaleId)); @@ -90,4 +99,16 @@ public class StoreSaleController extends XktBaseController { return R.ok(storeSaleService.updateMemo(BeanUtil.toBean(updateMemoVO, StoreSaleUpdateMemoDTO.class))); } + @ApiOperation(value = "导出销售出库列表", httpMethod = "POST", response = R.class) + @Log(title = "导出销售出库列表", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, @Validated @RequestBody StoreSaleExportVO exportVO) throws UnsupportedEncodingException { + List downloadList = storeSaleService.export(BeanUtil.toBean(exportVO, StoreSaleExportDTO.class)); + ExcelUtil util = new ExcelUtil<>(StoreSaleDownloadDTO.class); + // 设置下载excel名 + String encodedFileName = URLEncoder.encode("销售出库" + DateUtils.getDate(), "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx"); + util.exportExcel(response, downloadList, "销售出库"); + } + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java index 4399c48ce..d60b4ca9e 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java @@ -1,9 +1,11 @@ package com.ruoyi.web.controller.xkt; import cn.hutool.core.bean.BeanUtil; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.controller.XktBaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.Page; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.web.controller.xkt.vo.advertRound.app.category.APPCateVO; import com.ruoyi.web.controller.xkt.vo.advertRound.app.index.APPIndexHotSaleRightFixVO; import com.ruoyi.web.controller.xkt.vo.advertRound.app.index.APPIndexMidBrandVO; @@ -53,6 +55,7 @@ public class WebsiteController extends XktBaseController { final IWebsitePCService websitePCService; final IWebsiteAPPService websiteAPPService; + final RedisCache redisCache; @ApiOperation(value = "PC 首页 为你推荐", httpMethod = "POST", response = R.class) @PostMapping("/pc/index/recommend") @@ -245,4 +248,10 @@ public class WebsiteController extends XktBaseController { return R.ok(BeanUtil.copyToList(websiteAPPService.getAppOwnGuessLikeList(), APPOwnGuessLikeVO.class)); } + @ApiOperation(value = "热门搜索", httpMethod = "GET", response = R.class) + @GetMapping("/search-hot") + public R> getSearchHotList() { + return R.ok(redisCache.getCacheObject(CacheConstants.SEARCH_HOT_KEY)); + } + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexHotSaleRightFixVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexHotSaleRightFixVO.java index edd7e58f1..f016f6d98 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexHotSaleRightFixVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexHotSaleRightFixVO.java @@ -21,6 +21,8 @@ public class APPIndexHotSaleRightFixVO { private Integer displayType; @ApiModelProperty(value = "档口商品ID") private Long storeProdId; + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "排序") private Integer orderNum; @ApiModelProperty(value = "售价") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexMidBrandVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexMidBrandVO.java index 7677374f3..d2dfeb6bd 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexMidBrandVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/app/index/APPIndexMidBrandVO.java @@ -21,6 +21,8 @@ public class APPIndexMidBrandVO { private Integer displayType; @ApiModelProperty(value = "档口商品ID") private Long storeProdId; + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "排序") private Integer orderNum; @ApiModelProperty(value = "售价") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexBottomPopularVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexBottomPopularVO.java index bc3b1eb62..2d299ce2f 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexBottomPopularVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexBottomPopularVO.java @@ -50,6 +50,8 @@ public class PCIndexBottomPopularVO { @Data public static class PCIBPPopularRightVO { + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "2商品") private Integer displayType; @ApiModelProperty(value = "档口商品ID") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexSearchRecommendProdVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexSearchRecommendProdVO.java index 4d9d84f24..4ccc825e7 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexSearchRecommendProdVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/pc/index/PCIndexSearchRecommendProdVO.java @@ -18,6 +18,8 @@ public class PCIndexSearchRecommendProdVO { private Integer displayType; @ApiModelProperty(value = "档口商品ID") private Long storeProdId; + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "商品货号") private String prodArtNum; @ApiModelProperty(value = "排序") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeProdStorage/StoreStorageExportVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeProdStorage/StoreStorageExportVO.java new file mode 100644 index 000000000..67f0d1aac --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeProdStorage/StoreStorageExportVO.java @@ -0,0 +1,32 @@ +package com.ruoyi.web.controller.xkt.vo.storeProdStorage; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口入库导出数据") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreStorageExportVO { + + @NotNull(message = "storeId不能为空!") + @ApiModelProperty(value = "storeId") + private Long storeId; + @ApiModelProperty(value = "storeProdStorageId") + private List storeProdStorageIdList; + @ApiModelProperty(value = "导出开始时间") + private Date voucherDateStart; + @ApiModelProperty(value = "导出结束时间") + private Date voucherDateEnd; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleExportVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleExportVO.java new file mode 100644 index 000000000..29280af9e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/storeSale/StoreSaleExportVO.java @@ -0,0 +1,32 @@ +package com.ruoyi.web.controller.xkt.vo.storeSale; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Date; +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口销售导出数据") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreSaleExportVO { + + @NotNull(message = "storeId不能为空!") + @ApiModelProperty(value = "storeId") + private Long storeId; + @ApiModelProperty(value = "storeSaleIdList") + private List storeSaleIdList; + @ApiModelProperty(value = "导出开始时间") + private Date voucherDateStart; + @ApiModelProperty(value = "导出结束时间") + private Date voucherDateEnd; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java index 9191c7a12..cecbd0109 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -9,21 +9,15 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.math.BigDecimal; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.text.DecimalFormat; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; + import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.reflect.FieldUtils; @@ -39,7 +33,6 @@ import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.DataValidationConstraint; import org.apache.poi.ss.usermodel.DataValidationHelper; @@ -88,16 +81,15 @@ import com.ruoyi.common.utils.reflect.ReflectUtils; /** * Excel相关处理 - * - * @author ruoyi + * + * @author IT_Scc */ -public class ExcelUtil -{ +public class ExcelUtil { private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; - public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + public static final String[] FORMULA_STR = {"=", "-", "+", "@"}; /** * 用于dictType属性数据存储,避免重复查缓存 @@ -189,50 +181,37 @@ public class ExcelUtil */ private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + /** + * 合并 + */ + private Map>> mergeMap = new LinkedHashMap<>(); + /** * 实体对象 */ public Class clazz; - /** - * 需要显示列属性 - */ - public String[] includeFields; - /** * 需要排除列属性 */ public String[] excludeFields; - public ExcelUtil(Class clazz) - { + public ExcelUtil(Class clazz) { this.clazz = clazz; } - /** - * 仅在Excel中显示列属性 - * - * @param fields 列属性名 示例[单个"name"/多个"id","name"] - */ - public void showColumn(String... fields) - { - this.includeFields = fields; - } - /** * 隐藏Excel中列属性 * * @param fields 列属性名 示例[单个"name"/多个"id","name"] + * @throws Exception */ - public void hideColumn(String... fields) - { + public void hideColumn(String... fields) { this.excludeFields = fields; } - public void init(List list, String sheetName, String title, Type type) - { - if (list == null) - { + public void init(List list, String sheetName, String title, Type type) { + if (list == null) { list = new ArrayList(); } this.list = list; @@ -248,56 +227,44 @@ public class ExcelUtil /** * 创建excel第一行标题 */ - public void createTitle() - { - if (StringUtils.isNotEmpty(title)) - { - int titleLastCol = this.fields.size() - 1; - if (isSubList()) - { - titleLastCol = titleLastCol + subFields.size() - 1; - } + public void createTitle() { + if (StringUtils.isNotEmpty(title)) { Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); titleRow.setHeightInPoints(30); Cell titleCell = titleRow.createCell(0); - titleCell.setCellStyle(styles.get("title")); titleCell.setCellValue(title); - sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol)); + sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), this.fields.size() - 1)); + // 确保合并的所有单元格应用相同的样式 + for (int i = 0; i <= this.fields.size() - 1; i++) { + Cell cell = titleRow.getCell(i); + if (cell == null) { + cell = titleRow.createCell(i); + } + cell.setCellStyle(styles.get("title")); + } } } /** * 创建对象的子列表名称 */ - public void createSubHead() - { - if (isSubList()) - { + public void createSubHead() { + if (isSubList()) { + subMergedFirstRowNum++; + subMergedLastRowNum++; Row subRow = sheet.createRow(rownum); - int column = 0; - int subFieldSize = subFields != null ? subFields.size() : 0; - for (Object[] objects : fields) - { - Field field = (Field) objects[0]; + int excelNum = 0; + for (Object[] objects : fields) { Excel attr = (Excel) objects[1]; - if (Collection.class.isAssignableFrom(field.getType())) - { - Cell cell = subRow.createCell(column); - cell.setCellValue(attr.name()); - cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); - if (subFieldSize > 1) - { - CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1); - sheet.addMergedRegion(cellAddress); - } - column += subFieldSize; - } - else - { - Cell cell = subRow.createCell(column++); - cell.setCellValue(attr.name()); - cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); - } + Cell headCell1 = subRow.createCell(excelNum); + headCell1.setCellValue(attr.name()); + headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + excelNum++; + } + int headFirstRow = excelNum - 1; + int headLastRow = headFirstRow + subFields.size() - 1; + if (headLastRow > headFirstRow) { + sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); } rownum++; } @@ -305,115 +272,93 @@ public class ExcelUtil /** * 对excel表单默认第一个索引名转换成list - * + * * @param is 输入流 * @return 转换后集合 */ - public List importExcel(InputStream is) - { - return importExcel(is, 0); - } - - /** - * 对excel表单默认第一个索引名转换成list - * - * @param is 输入流 - * @param titleNum 标题占用行数 - * @return 转换后集合 - */ - public List importExcel(InputStream is, int titleNum) - { + public List importExcel(InputStream is) { List list = null; - try - { - list = importExcel(StringUtils.EMPTY, is, titleNum); - } - catch (Exception e) - { + try { + list = importExcel(is, 0); + } catch (Exception e) { log.error("导入Excel异常{}", e.getMessage()); throw new UtilException(e.getMessage()); - } - finally - { + } finally { IOUtils.closeQuietly(is); } return list; } /** - * 对excel表单指定表格索引名转换成list - * - * @param sheetName 表格索引名 + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 * @param titleNum 标题占用行数 - * @param is 输入流 * @return 转换后集合 */ - public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception - { + public List importExcel(InputStream is, int titleNum) throws Exception { + return importExcel(StringUtils.EMPTY, is, titleNum); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param titleNum 标题占用行数 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception { this.type = Type.IMPORT; this.wb = WorkbookFactory.create(is); List list = new ArrayList(); // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); - if (sheet == null) - { + if (sheet == null) { throw new IOException("文件sheet不存在"); } boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); Map pictures; - if (isXSSFWorkbook) - { + if (isXSSFWorkbook) { pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); - } - else - { + } else { pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); } // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 int rows = sheet.getLastRowNum(); - if (rows > 0) - { + if (rows > 0) { // 定义一个map用于存放excel列的序号和field. Map cellMap = new HashMap(); // 获取表头 Row heard = sheet.getRow(titleNum); - for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) - { + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) { Cell cell = heard.getCell(i); - if (StringUtils.isNotNull(cell)) - { + if (StringUtils.isNotNull(cell)) { String value = this.getCellValue(heard, i).toString(); cellMap.put(value, i); - } - else - { + } else { cellMap.put(null, i); } } // 有数据时才处理 得到类的所有field. List fields = this.getFields(); Map fieldsMap = new HashMap(); - for (Object[] objects : fields) - { + for (Object[] objects : fields) { Excel attr = (Excel) objects[1]; Integer column = cellMap.get(attr.name()); - if (column != null) - { + if (column != null) { fieldsMap.put(column, objects); } } - for (int i = titleNum + 1; i <= rows; i++) - { + for (int i = titleNum + 1; i <= rows; i++) { // 从第2行开始取数据,默认第一行是表头. Row row = sheet.getRow(i); // 判断当前行是否是空行 - if (isRowEmpty(row)) - { + if (isRowEmpty(row)) { continue; } T entity = null; - for (Map.Entry entry : fieldsMap.entrySet()) - { + for (Map.Entry entry : fieldsMap.entrySet()) { Object val = this.getCellValue(row, entry.getKey()); // 如果不存在实例则新建. @@ -423,94 +368,53 @@ public class ExcelUtil Excel attr = (Excel) entry.getValue()[1]; // 取得类型,并根据对象类型设置值. Class fieldType = field.getType(); - if (String.class == fieldType) - { + if (String.class == fieldType) { String s = Convert.toStr(val); - if (StringUtils.endsWith(s, ".0")) - { + if (StringUtils.endsWith(s, ".0")) { val = StringUtils.substringBefore(s, ".0"); - } - else - { + } else { String dateFormat = field.getAnnotation(Excel.class).dateFormat(); - if (StringUtils.isNotEmpty(dateFormat)) - { + if (StringUtils.isNotEmpty(dateFormat)) { val = parseDateToStr(dateFormat, val); - } - else - { + } else { val = Convert.toStr(val); } } - } - else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) - { + } else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) { val = Convert.toInt(val); - } - else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) - { + } else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) { val = Convert.toLong(val); - } - else if (Double.TYPE == fieldType || Double.class == fieldType) - { + } else if (Double.TYPE == fieldType || Double.class == fieldType) { val = Convert.toDouble(val); - } - else if (Float.TYPE == fieldType || Float.class == fieldType) - { + } else if (Float.TYPE == fieldType || Float.class == fieldType) { val = Convert.toFloat(val); - } - else if (BigDecimal.class == fieldType) - { + } else if (BigDecimal.class == fieldType) { val = Convert.toBigDecimal(val); - } - else if (Date.class == fieldType) - { - if (val instanceof String) - { + } else if (Date.class == fieldType) { + if (val instanceof String) { val = DateUtils.parseDate(val); - } - else if (val instanceof Double) - { + } else if (val instanceof Double) { val = DateUtil.getJavaDate((Double) val); } - } - else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) - { + } else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) { val = Convert.toBool(val, false); } - if (StringUtils.isNotNull(fieldType)) - { + if (StringUtils.isNotNull(fieldType)) { String propertyName = field.getName(); - if (StringUtils.isNotEmpty(attr.targetAttr())) - { + if (StringUtils.isNotEmpty(attr.targetAttr())) { propertyName = field.getName() + "." + attr.targetAttr(); } - if (StringUtils.isNotEmpty(attr.readConverterExp())) - { + if (StringUtils.isNotEmpty(attr.readConverterExp())) { val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); - } - else if (StringUtils.isNotEmpty(attr.dictType())) - { - if (!sysDictMap.containsKey(attr.dictType() + val)) - { - String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); - sysDictMap.put(attr.dictType() + val, dictValue); - } - val = sysDictMap.get(attr.dictType() + val); - } - else if (!attr.handler().equals(ExcelHandlerAdapter.class)) - { + } else if (StringUtils.isNotEmpty(attr.dictType())) { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } else if (!attr.handler().equals(ExcelHandlerAdapter.class)) { val = dataFormatHandlerAdapter(val, attr, null); - } - else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) - { + } else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) { PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); - if (image == null) - { + if (image == null) { val = ""; - } - else - { + } else { byte[] data = image.getData(); val = FileUtils.writeImportBytes(data); } @@ -526,54 +430,50 @@ public class ExcelUtil /** * 对list数据源将其里面的数据导入到excel表单 - * - * @param list 导出数据集合 + * + * @param list 导出数据集合 * @param sheetName 工作表的名称 * @return 结果 */ - public AjaxResult exportExcel(List list, String sheetName) - { + public AjaxResult exportExcel(List list, String sheetName) { return exportExcel(list, sheetName, StringUtils.EMPTY); } /** * 对list数据源将其里面的数据导入到excel表单 - * - * @param list 导出数据集合 + * + * @param list 导出数据集合 * @param sheetName 工作表的名称 - * @param title 标题 + * @param title 标题 * @return 结果 */ - public AjaxResult exportExcel(List list, String sheetName, String title) - { + public AjaxResult exportExcel(List list, String sheetName, String title) { this.init(list, sheetName, title, Type.EXPORT); return exportExcel(); } /** * 对list数据源将其里面的数据导入到excel表单 - * - * @param response 返回数据 - * @param list 导出数据集合 + * + * @param response 返回数据 + * @param list 导出数据集合 * @param sheetName 工作表的名称 * @return 结果 */ - public void exportExcel(HttpServletResponse response, List list, String sheetName) - { + public void exportExcel(HttpServletResponse response, List list, String sheetName) { exportExcel(response, list, sheetName, StringUtils.EMPTY); } /** * 对list数据源将其里面的数据导入到excel表单 - * - * @param response 返回数据 - * @param list 导出数据集合 + * + * @param response 返回数据 + * @param list 导出数据集合 * @param sheetName 工作表的名称 - * @param title 标题 + * @param title 标题 * @return 结果 */ - public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) - { + public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); this.init(list, sheetName, title, Type.EXPORT); @@ -582,48 +482,44 @@ public class ExcelUtil /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @param sheetName 工作表的名称 * @return 结果 */ - public AjaxResult importTemplateExcel(String sheetName) - { + public AjaxResult importTemplateExcel(String sheetName) { return importTemplateExcel(sheetName, StringUtils.EMPTY); } /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @param sheetName 工作表的名称 - * @param title 标题 + * @param title 标题 * @return 结果 */ - public AjaxResult importTemplateExcel(String sheetName, String title) - { + public AjaxResult importTemplateExcel(String sheetName, String title) { this.init(null, sheetName, title, Type.IMPORT); return exportExcel(); } /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @param sheetName 工作表的名称 * @return 结果 */ - public void importTemplateExcel(HttpServletResponse response, String sheetName) - { + public void importTemplateExcel(HttpServletResponse response, String sheetName) { importTemplateExcel(response, sheetName, StringUtils.EMPTY); } /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @param sheetName 工作表的名称 - * @param title 标题 + * @param title 标题 * @return 结果 */ - public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) - { + public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); this.init(null, sheetName, title, Type.IMPORT); @@ -632,49 +528,37 @@ public class ExcelUtil /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @return 结果 */ - public void exportExcel(HttpServletResponse response) - { - try - { + public void exportExcel(HttpServletResponse response) { + try { writeSheet(); wb.write(response.getOutputStream()); - } - catch (Exception e) - { + } catch (Exception e) { log.error("导出Excel异常{}", e.getMessage()); - } - finally - { + } finally { IOUtils.closeQuietly(wb); } } /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @return 结果 */ - public AjaxResult exportExcel() - { + public AjaxResult exportExcel() { OutputStream out = null; - try - { + try { writeSheet(); String filename = encodingFilename(sheetName); out = new FileOutputStream(getAbsoluteFile(filename)); wb.write(out); return AjaxResult.success(filename); - } - catch (Exception e) - { + } catch (Exception e) { log.error("导出Excel异常{}", e.getMessage()); throw new UtilException("导出Excel失败,请联系网站管理员!"); - } - finally - { + } finally { IOUtils.closeQuietly(wb); IOUtils.closeQuietly(out); } @@ -683,37 +567,29 @@ public class ExcelUtil /** * 创建写入数据到Sheet */ - public void writeSheet() - { + public void writeSheet() { // 取出一共有多少个sheet. int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize)); - for (int index = 0; index < sheetNo; index++) - { + for (int index = 0; index < sheetNo; index++) { createSheet(sheetNo, index); // 产生一行 Row row = sheet.createRow(rownum); int column = 0; // 写入各个字段的列头名称 - for (Object[] os : fields) - { + for (Object[] os : fields) { Field field = (Field) os[0]; Excel excel = (Excel) os[1]; - if (Collection.class.isAssignableFrom(field.getType())) - { - for (Field subField : subFields) - { + if (Collection.class.isAssignableFrom(field.getType())) { + for (Field subField : subFields) { Excel subExcel = subField.getAnnotation(Excel.class); this.createHeadCell(subExcel, row, column++); } - } - else - { + } else { this.createHeadCell(excel, row, column++); } } - if (Type.EXPORT.equals(type)) - { + if (Type.EXPORT.equals(type)) { fillExcelData(index, row); addStatisticsRow(); } @@ -722,110 +598,45 @@ public class ExcelUtil /** * 填充excel数据 - * + * * @param index 序号 - * @param row 单元格行 + * @param row 单元格行 */ @SuppressWarnings("unchecked") - public void fillExcelData(int index, Row row) - { + public void fillExcelData(int index, Row row) { int startNo = index * sheetSize; int endNo = Math.min(startNo + sheetSize, list.size()); - int currentRowNum = rownum + 1; // 从标题行后开始 - - for (int i = startNo; i < endNo; i++) - { - row = sheet.createRow(currentRowNum); + //当前行 + int currentRow = 0; + for (int i = startNo; i < endNo; i++) { + // 判断是否加入表格title,同时处理合并 + int tempIndex = rownum == 0 ? i + 1 - startNo : i + 1 - startNo + 1; + row = sheet.createRow(tempIndex); + currentRow = tempIndex; + // 得到导出对象. T vo = (T) list.get(i); + /** + *取下一个对象 与当前对象对比,如果相同,记住当前列,再与下一个对比,一直对比到不相同,执行合并代码 + * 注解加入 合并行列标识 + */ int column = 0; - int maxSubListSize = getCurrentMaxSubListSize(vo); - for (Object[] os : fields) - { + for (Object[] os : fields) { Field field = (Field) os[0]; Excel excel = (Excel) os[1]; - if (Collection.class.isAssignableFrom(field.getType())) - { - try - { - Collection subList = (Collection) getTargetValue(vo, field, excel); - if (subList != null && !subList.isEmpty()) - { - int subIndex = 0; - for (Object subVo : subList) - { - Row subRow = sheet.getRow(currentRowNum + subIndex); - if (subRow == null) - { - subRow = sheet.createRow(currentRowNum + subIndex); - } - - int subColumn = column; - for (Field subField : subFields) - { - Excel subExcel = subField.getAnnotation(Excel.class); - addCell(subExcel, subRow, (T) subVo, subField, subColumn++); - } - subIndex++; - } - column += subFields.size(); - } - } - catch (Exception e) - { - log.error("填充集合数据失败", e); - } - } - else - { - // 创建单元格并设置值 - addCell(excel, row, vo, field, column); - if (maxSubListSize > 1 && excel.needMerge()) - { - sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column)); - } - column++; - } - } - currentRowNum += maxSubListSize; - } - } - - /** - * 获取子列表最大数 - */ - private int getCurrentMaxSubListSize(T vo) - { - int maxSubListSize = 1; - for (Object[] os : fields) - { - Field field = (Field) os[0]; - if (Collection.class.isAssignableFrom(field.getType())) - { - try - { - Collection subList = (Collection) getTargetValue(vo, field, (Excel) os[1]); - if (subList != null && !subList.isEmpty()) - { - maxSubListSize = Math.max(maxSubListSize, subList.size()); - } - } - catch (Exception e) - { - log.error("获取集合大小失败", e); - } + // 设置实体类私有属性可访问 + field.setAccessible(true); + this.addCell(excel, row, vo, field, column++, currentRow); } } - return maxSubListSize; } /** * 创建表格样式 - * + * * @param wb 工作薄对象 * @return 样式列表 */ - private Map createStyles(Workbook wb) - { + private Map createStyles(Workbook wb) { // 写入各条记录,每条记录对应excel表中的一行 Map styles = new HashMap(); CellStyle style = wb.createCellStyle(); @@ -836,8 +647,6 @@ public class ExcelUtil titleFont.setFontHeightInPoints((short) 16); titleFont.setBold(true); style.setFont(titleFont); - DataFormat dataFormat = wb.createDataFormat(); - style.setDataFormat(dataFormat.getFormat("@")); styles.put("title", style); style = wb.createCellStyle(); @@ -875,19 +684,16 @@ public class ExcelUtil /** * 根据Excel注解创建表格头样式 - * + * * @param wb 工作薄对象 * @return 自定义样式列表 */ - private Map annotationHeaderStyles(Workbook wb, Map styles) - { + private Map annotationHeaderStyles(Workbook wb, Map styles) { Map headerStyles = new HashMap(); - for (Object[] os : fields) - { + for (Object[] os : fields) { Excel excel = (Excel) os[1]; String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor()); - if (!headerStyles.containsKey(key)) - { + if (!headerStyles.containsKey(key)) { CellStyle style = wb.createCellStyle(); style.cloneStyleFrom(styles.get("data")); style.setAlignment(HorizontalAlignment.CENTER); @@ -900,9 +706,6 @@ public class ExcelUtil headerFont.setBold(true); headerFont.setColor(excel.headerColor().index); style.setFont(headerFont); - // 设置表格头单元格文本形式 - DataFormat dataFormat = wb.createDataFormat(); - style.setDataFormat(dataFormat.getFormat("@")); headerStyles.put(key, style); } } @@ -911,138 +714,85 @@ public class ExcelUtil /** * 根据Excel注解创建表格列样式 - * + * * @param wb 工作薄对象 * @return 自定义样式列表 */ - private Map annotationDataStyles(Workbook wb) - { + private Map annotationDataStyles(Workbook wb) { Map styles = new HashMap(); - for (Object[] os : fields) - { - Field field = (Field) os[0]; + for (Object[] os : fields) { Excel excel = (Excel) os[1]; - if (Collection.class.isAssignableFrom(field.getType())) - { - ParameterizedType pt = (ParameterizedType) field.getGenericType(); - Class subClass = (Class) pt.getActualTypeArguments()[0]; - List subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); - for (Field subField : subFields) - { - Excel subExcel = subField.getAnnotation(Excel.class); - annotationDataStyles(styles, subField, subExcel); - } - } - else - { - annotationDataStyles(styles, field, excel); + String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor()); + if (!styles.containsKey(key)) { + CellStyle style = wb.createCellStyle(); + style.setAlignment(excel.align()); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setFillForegroundColor(excel.backgroundColor().getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + dataFont.setColor(excel.color().index); + style.setFont(dataFont); + styles.put(key, style); } } return styles; } - /** - * 根据Excel注解创建表格列样式 - * - * @param styles 自定义样式列表 - * @param field 属性列信息 - * @param excel 注解信息 - */ - public void annotationDataStyles(Map styles, Field field, Excel excel) - { - String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText()); - if (!styles.containsKey(key)) - { - CellStyle style = wb.createCellStyle(); - style.setAlignment(excel.align()); - style.setVerticalAlignment(VerticalAlignment.CENTER); - style.setBorderRight(BorderStyle.THIN); - style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderLeft(BorderStyle.THIN); - style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderTop(BorderStyle.THIN); - style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setBorderBottom(BorderStyle.THIN); - style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); - style.setFillPattern(FillPatternType.SOLID_FOREGROUND); - style.setFillForegroundColor(excel.backgroundColor().getIndex()); - style.setWrapText(excel.wrapText()); - Font dataFont = wb.createFont(); - dataFont.setFontName("Arial"); - dataFont.setFontHeightInPoints((short) 10); - dataFont.setColor(excel.color().index); - style.setFont(dataFont); - if (ColumnType.TEXT == excel.cellType()) - { - DataFormat dataFormat = wb.createDataFormat(); - style.setDataFormat(dataFormat.getFormat("@")); - } - styles.put(key, style); - } - } - /** * 创建单元格 */ - public Cell createHeadCell(Excel attr, Row row, int column) - { + public Cell createHeadCell(Excel attr, Row row, int column) { // 创建列 Cell cell = row.createCell(column); // 写入列信息 cell.setCellValue(attr.name()); setDataValidation(attr, row, column); cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); - if (isSubList()) - { + if (isSubList()) { // 填充默认样式,防止合并单元格样式失效 - sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); - if (attr.needMerge()) - { - sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); - } + sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); } return cell; } /** * 设置单元格信息 - * + * * @param value 单元格值 - * @param attr 注解相关 - * @param cell 单元格信息 + * @param attr 注解相关 + * @param cell 单元格信息 */ - public void setCellVo(Object value, Excel attr, Cell cell) - { - if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType()) - { + public void setCellVo(Object value, Excel attr, Cell cell) { + if (ColumnType.STRING == attr.cellType()) { String cellValue = Convert.toStr(value); // 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。 - if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) - { + if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) { cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0"); } - if (value instanceof Collection && StringUtils.equals("[]", cellValue)) - { + if (value instanceof Collection && StringUtils.equals("[]", cellValue)) { cellValue = StringUtils.EMPTY; } cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix()); - } - else if (ColumnType.NUMERIC == attr.cellType()) - { - if (StringUtils.isNotNull(value)) - { + } else if (ColumnType.NUMERIC == attr.cellType()) { + if (StringUtils.isNotNull(value)) { cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); } - } - else if (ColumnType.IMAGE == attr.cellType()) - { + } else if (ColumnType.IMAGE == attr.cellType()) { ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1); String imagePath = Convert.toStr(value); - if (StringUtils.isNotEmpty(imagePath)) - { + if (StringUtils.isNotEmpty(imagePath)) { byte[] data = ImageUtils.getImage(imagePath); - getDrawingPatriarch(cell.getSheet()).createPicture(anchor, - cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); } } } @@ -1050,10 +800,8 @@ public class ExcelUtil /** * 获取画布 */ - public static Drawing getDrawingPatriarch(Sheet sheet) - { - if (sheet.getDrawingPatriarch() == null) - { + public static Drawing getDrawingPatriarch(Sheet sheet) { + if (sheet.getDrawingPatriarch() == null) { sheet.createDrawingPatriarch(); } return sheet.getDrawingPatriarch(); @@ -1062,15 +810,11 @@ public class ExcelUtil /** * 获取图片类型,设置图片插入类型 */ - public int getImageType(byte[] value) - { + public int getImageType(byte[] value) { String type = FileTypeUtils.getFileExtendName(value); - if ("JPG".equalsIgnoreCase(type)) - { + if ("JPG".equalsIgnoreCase(type)) { return Workbook.PICTURE_TYPE_JPEG; - } - else if ("PNG".equalsIgnoreCase(type)) - { + } else if ("PNG".equalsIgnoreCase(type)) { return Workbook.PICTURE_TYPE_PNG; } return Workbook.PICTURE_TYPE_JPEG; @@ -1079,39 +823,20 @@ public class ExcelUtil /** * 创建表格样式 */ - public void setDataValidation(Excel attr, Row row, int column) - { - if (attr.name().indexOf("注:") >= 0) - { + public void setDataValidation(Excel attr, Row row, int column) { + if (attr.name().contains("注:")) { sheet.setColumnWidth(column, 6000); - } - else - { + } else { // 设置列宽 sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); } - if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict()) - { - String[] comboArray = attr.combo(); - if (attr.comboReadDict()) - { - if (!sysDictMap.containsKey("combo_" + attr.dictType())) - { - String labels = DictUtils.getDictLabels(attr.dictType()); - sysDictMap.put("combo_" + attr.dictType(), labels); - } - String val = sysDictMap.get("combo_" + attr.dictType()); - comboArray = StringUtils.split(val, DictUtils.SEPARATOR); - } - if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255) - { + if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) { + if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) { // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到 - setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column); - } - else - { + setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } else { // 提示信息或只能选择不能输入的列内容. - setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column); + setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); } } } @@ -1119,26 +844,16 @@ public class ExcelUtil /** * 添加单元格 */ - public Cell addCell(Excel attr, Row row, T vo, Field field, int column) - { + public Cell addCell(Excel attr, Row row, T vo, Field field, int column, int currentRow) { Cell cell = null; - try - { + try { // 设置行高 row.setHeight(maxHeight); // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. - if (attr.isExport()) - { + if (attr.isExport()) { // 创建cell cell = row.createCell(column); - if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) - { - if (subMergedLastRowNum >= subMergedFirstRowNum) - { - sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column)); - } - } - cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText()))); + cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); // 用于读取对象中的属性 Object value = getTargetValue(vo, field, attr); @@ -1146,79 +861,101 @@ public class ExcelUtil String readConverterExp = attr.readConverterExp(); String separator = attr.separator(); String dictType = attr.dictType(); - if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) - { - cell.getCellStyle().setDataFormat(this.wb.getCreationHelper().createDataFormat().getFormat(dateFormat)); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) { cell.setCellValue(parseDateToStr(dateFormat, value)); - } - else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) - { + } else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) { cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); - } - else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) - { - if (!sysDictMap.containsKey(dictType + value)) - { + } else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) { + if (!sysDictMap.containsKey(dictType + value)) { String lable = convertDictByExp(Convert.toStr(value), dictType, separator); sysDictMap.put(dictType + value, lable); } cell.setCellValue(sysDictMap.get(dictType + value)); - } - else if (value instanceof BigDecimal && -1 != attr.scale()) - { + } else if (value instanceof BigDecimal && -1 != attr.scale()) { cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); - } - else if (!attr.handler().equals(ExcelHandlerAdapter.class)) - { + } else if (!attr.handler().equals(ExcelHandlerAdapter.class)) { cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell)); - } - else - { + } else { // 设置列类型 setCellVo(value, attr, cell); } addStatisticsData(column, Convert.toStr(value), attr); + mergeExcelData(attr, vo, field, column, currentRow); } - } - catch (Exception e) - { + } catch (Exception e) { log.error("导出Excel失败{}", e); } return cell; } /** - * 设置 POI XSSFSheet 单元格提示或选择框 - * - * @param sheet 表单 - * @param textlist 下拉框显示的内容 - * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 + * 对需要合并的数据进行合并 */ - public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, - int firstCol, int endCol) - { + public void mergeExcelData(Excel attr, T vo, Field field, int column, int currentRow) { + try { + // 用于读取对象中的属性 + Object cellValue = getTargetValue(vo, field, attr); + if (attr.needMerge()) { + LinkedHashMap> columnMergeInfo = mergeMap.computeIfAbsent(column, k -> new LinkedHashMap<>()); + + if (columnMergeInfo.containsKey(cellValue)) { + // 获取最新的分组信息 + Map.Entry> latestEntry = columnMergeInfo.entrySet().stream().reduce((first, second) -> second).orElse(null); + if (latestEntry != null && latestEntry.getKey().toString().equals(cellValue.toString())) { + Integer minRow = Collections.min(latestEntry.getValue()); + CellRangeAddress newMergeRegion = new CellRangeAddress(minRow, currentRow, column, column); + + // 移除重叠的合并区域 + for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) { + CellRangeAddress existingRegion = sheet.getMergedRegion(i); + if (existingRegion.intersects(newMergeRegion)) { + sheet.removeMergedRegion(i); + } + } + + // 添加新的合并区域 + sheet.addMergedRegion(newMergeRegion); + } + // 更新分组信息 + latestEntry.getValue().add(currentRow); + } else { + // 新的值,创建新的分组信息 + List rowList = new ArrayList<>(); + rowList.add(currentRow); + columnMergeInfo.put(cellValue, rowList); + } + mergeMap.put(column, columnMergeInfo); + } + } catch (Exception ignored) {} + } + + + /** + * 设置 POI XSSFSheet 单元格提示或选择框 + * + * @param sheet 表单 + * @param textlist 下拉框显示的内容 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) { DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1"); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); DataValidation dataValidation = helper.createValidation(constraint, regions); - if (StringUtils.isNotEmpty(promptContent)) - { + if (StringUtils.isNotEmpty(promptContent)) { // 如果设置了提示信息则鼠标放上去提示 dataValidation.createPromptBox("", promptContent); dataValidation.setShowPromptBox(true); } // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { + if (dataValidation instanceof XSSFDataValidation) { dataValidation.setSuppressDropDownArrow(true); dataValidation.setShowErrorBox(true); - } - else - { + } else { dataValidation.setSuppressDropDownArrow(false); } sheet.addValidationData(dataValidation); @@ -1226,21 +963,19 @@ public class ExcelUtil /** * 设置某些列的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框). - * - * @param sheet 要设置的sheet. - * @param textlist 下拉框显示的内容 + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 */ - public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) - { + public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) { String hideSheetName = "combo_" + firstCol + "_" + endCol; Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 - for (int i = 0; i < textlist.length; i++) - { + for (int i = 0; i < textlist.length; i++) { hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); } // 创建名称,可被其他单元格引用 @@ -1254,20 +989,16 @@ public class ExcelUtil CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); // 数据有效性对象 DataValidation dataValidation = helper.createValidation(constraint, regions); - if (StringUtils.isNotEmpty(promptContent)) - { + if (StringUtils.isNotEmpty(promptContent)) { // 如果设置了提示信息则鼠标放上去提示 dataValidation.createPromptBox("", promptContent); dataValidation.setShowPromptBox(true); } // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { + if (dataValidation instanceof XSSFDataValidation) { dataValidation.setSuppressDropDownArrow(true); dataValidation.setShowErrorBox(true); - } - else - { + } else { dataValidation.setSuppressDropDownArrow(false); } @@ -1278,34 +1009,26 @@ public class ExcelUtil /** * 解析导出值 0=男,1=女,2=未知 - * + * * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 + * @param converterExp 翻译注解 + * @param separator 分隔符 * @return 解析后值 */ - public static String convertByExp(String propertyValue, String converterExp, String separator) - { + public static String convertByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { + for (String item : convertSource) { String[] itemArray = item.split("="); - if (StringUtils.containsAny(propertyValue, separator)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[0].equals(value)) - { + if (StringUtils.containsAny(propertyValue, separator)) { + for (String value : propertyValue.split(separator)) { + if (itemArray[0].equals(value)) { propertyString.append(itemArray[1] + separator); break; } } - } - else - { - if (itemArray[0].equals(propertyValue)) - { + } else { + if (itemArray[0].equals(propertyValue)) { return itemArray[1]; } } @@ -1315,34 +1038,26 @@ public class ExcelUtil /** * 反向解析值 男=0,女=1,未知=2 - * + * * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 + * @param converterExp 翻译注解 + * @param separator 分隔符 * @return 解析后值 */ - public static String reverseByExp(String propertyValue, String converterExp, String separator) - { + public static String reverseByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { + for (String item : convertSource) { String[] itemArray = item.split("="); - if (StringUtils.containsAny(propertyValue, separator)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[1].equals(value)) - { + if (StringUtils.containsAny(propertyValue, separator)) { + for (String value : propertyValue.split(separator)) { + if (itemArray[1].equals(value)) { propertyString.append(itemArray[0] + separator); break; } } - } - else - { - if (itemArray[1].equals(propertyValue)) - { + } else { + if (itemArray[1].equals(propertyValue)) { return itemArray[0]; } } @@ -1352,47 +1067,41 @@ public class ExcelUtil /** * 解析字典值 - * + * * @param dictValue 字典值 - * @param dictType 字典类型 + * @param dictType 字典类型 * @param separator 分隔符 * @return 字典标签 */ - public static String convertDictByExp(String dictValue, String dictType, String separator) - { + public static String convertDictByExp(String dictValue, String dictType, String separator) { return DictUtils.getDictLabel(dictType, dictValue, separator); } /** * 反向解析值字典值 - * + * * @param dictLabel 字典标签 - * @param dictType 字典类型 + * @param dictType 字典类型 * @param separator 分隔符 * @return 字典值 */ - public static String reverseDictByExp(String dictLabel, String dictType, String separator) - { + public static String reverseDictByExp(String dictLabel, String dictType, String separator) { return DictUtils.getDictValue(dictType, dictLabel, separator); } /** * 数据处理器 - * + * * @param value 数据值 * @param excel 数据注解 * @return */ - public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell) - { - try - { + public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell) { + try { Object instance = excel.handler().newInstance(); - Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class }); + Method formatMethod = excel.handler().getMethod("format", new Class[]{Object.class, String[].class, Cell.class, Workbook.class}); value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb); - } - catch (Exception e) - { + } catch (Exception e) { log.error("不能格式化数据 " + excel.handler(), e.getMessage()); } return Convert.toStr(value); @@ -1401,21 +1110,15 @@ public class ExcelUtil /** * 合计统计信息 */ - private void addStatisticsData(Integer index, String text, Excel entity) - { - if (entity != null && entity.isStatistics()) - { + private void addStatisticsData(Integer index, String text, Excel entity) { + if (entity != null && entity.isStatistics()) { Double temp = 0D; - if (!statistics.containsKey(index)) - { + if (!statistics.containsKey(index)) { statistics.put(index, temp); } - try - { + try { temp = Double.valueOf(text); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { } statistics.put(index, statistics.get(index) + temp); } @@ -1424,18 +1127,15 @@ public class ExcelUtil /** * 创建统计行 */ - public void addStatisticsRow() - { - if (statistics.size() > 0) - { + public void addStatisticsRow() { + if (statistics.size() > 0) { Row row = sheet.createRow(sheet.getLastRowNum() + 1); Set keys = statistics.keySet(); Cell cell = row.createCell(0); cell.setCellStyle(styles.get("total")); cell.setCellValue("合计"); - for (Integer key : keys) - { + for (Integer key : keys) { cell = row.createCell(key); cell.setCellStyle(styles.get("total")); cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); @@ -1447,22 +1147,20 @@ public class ExcelUtil /** * 编码文件名 */ - public String encodingFilename(String filename) - { - return UUID.randomUUID() + "_" + filename + ".xlsx"; + public String encodingFilename(String filename) { + filename = UUID.randomUUID() + "_" + filename + ".xlsx"; + return filename; } /** * 获取下载路径 - * + * * @param filename 文件名称 */ - public String getAbsoluteFile(String filename) - { + public String getAbsoluteFile(String filename) { String downloadPath = RuoYiConfig.getDownloadPath() + filename; File desc = new File(downloadPath); - if (!desc.getParentFile().exists()) - { + if (!desc.getParentFile().exists()) { desc.getParentFile().mkdirs(); } return downloadPath; @@ -1470,30 +1168,23 @@ public class ExcelUtil /** * 获取bean中的属性值 - * - * @param vo 实体对象 + * + * @param vo 实体对象 * @param field 字段 * @param excel 注解 * @return 最终的属性值 * @throws Exception */ - private Object getTargetValue(T vo, Field field, Excel excel) throws Exception - { - field.setAccessible(true); + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception { Object o = field.get(vo); - if (StringUtils.isNotEmpty(excel.targetAttr())) - { + if (StringUtils.isNotEmpty(excel.targetAttr())) { String target = excel.targetAttr(); - if (target.contains(".")) - { + if (target.contains(".")) { String[] targets = target.split("[.]"); - for (String name : targets) - { + for (String name : targets) { o = getValue(o, name); } - } - else - { + } else { o = getValue(o, target); } } @@ -1502,16 +1193,14 @@ public class ExcelUtil /** * 以类的属性的get方法方法形式获取值 - * + * * @param o * @param name * @return value * @throws Exception */ - private Object getValue(Object o, String name) throws Exception - { - if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) - { + private Object getValue(Object o, String name) throws Exception { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) { Class clazz = o.getClass(); Field field = clazz.getDeclaredField(name); field.setAccessible(true); @@ -1523,8 +1212,7 @@ public class ExcelUtil /** * 得到所有定义字段 */ - private void createExcelField() - { + private void createExcelField() { this.fields = getFields(); this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); this.maxHeight = getRowHeight(); @@ -1533,99 +1221,50 @@ public class ExcelUtil /** * 获取字段注解信息 */ - public List getFields() - { + public List getFields() { List fields = new ArrayList(); List tempFields = new ArrayList<>(); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - if (StringUtils.isNotEmpty(includeFields)) - { - for (Field field : tempFields) - { - if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class)) - { - addField(fields, field); + for (Field field : tempFields) { + if (!ArrayUtils.contains(this.excludeFields, field.getName())) { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) { + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) { + field.setAccessible(true); + fields.add(new Object[]{field, attr}); + } + if (Collection.class.isAssignableFrom(field.getType())) { + subMethod = getSubMethod(field.getName(), clazz); + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + Class subClass = (Class) pt.getActualTypeArguments()[0]; + this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); + } } - } - } - else if (StringUtils.isNotEmpty(excludeFields)) - { - for (Field field : tempFields) - { - if (!ArrayUtils.contains(this.excludeFields, field.getName())) - { - addField(fields, field); + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel attr : excels) { + if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) { + field.setAccessible(true); + fields.add(new Object[]{field, attr}); + } + } } } } - else - { - for (Field field : tempFields) - { - addField(fields, field); - } - } return fields; } - /** - * 添加字段信息 - */ - public void addField(List fields, Field field) - { - // 单注解 - if (field.isAnnotationPresent(Excel.class)) - { - Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { - fields.add(new Object[] { field, attr }); - } - if (Collection.class.isAssignableFrom(field.getType())) - { - subMethod = getSubMethod(field.getName(), clazz); - ParameterizedType pt = (ParameterizedType) field.getGenericType(); - Class subClass = (Class) pt.getActualTypeArguments()[0]; - this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); - } - } - - // 多注解 - if (field.isAnnotationPresent(Excels.class)) - { - Excels attrs = field.getAnnotation(Excels.class); - Excel[] excels = attrs.value(); - for (Excel attr : excels) - { - if (StringUtils.isNotEmpty(includeFields)) - { - if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr()) - && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) - { - fields.add(new Object[] { field, attr }); - } - } - else - { - if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) - && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) - { - fields.add(new Object[] { field, attr }); - } - } - } - } - } - /** * 根据注解获取最大行高 */ - public short getRowHeight() - { + public short getRowHeight() { double maxHeight = 0; - for (Object[] os : this.fields) - { + for (Object[] os : this.fields) { Excel excel = (Excel) os[1]; maxHeight = Math.max(maxHeight, excel.height()); } @@ -1635,8 +1274,7 @@ public class ExcelUtil /** * 创建一个工作簿 */ - public void createWorkbook() - { + public void createWorkbook() { this.wb = new SXSSFWorkbook(500); this.sheet = wb.createSheet(); wb.setSheetName(0, sheetName); @@ -1645,15 +1283,13 @@ public class ExcelUtil /** * 创建工作表 - * + * * @param sheetNo sheet数量 - * @param index 序号 + * @param index 序号 */ - public void createSheet(int sheetNo, int index) - { + public void createSheet(int sheetNo, int index) { // 设置工作表的名称. - if (sheetNo > 1 && index > 0) - { + if (sheetNo > 1 && index > 0) { this.sheet = wb.createSheet(); this.createTitle(); wb.setSheetName(index, sheetName + index); @@ -1662,59 +1298,40 @@ public class ExcelUtil /** * 获取单元格值 - * - * @param row 获取的行 + * + * @param row 获取的行 * @param column 获取单元格列号 * @return 单元格值 */ - public Object getCellValue(Row row, int column) - { - if (row == null) - { + public Object getCellValue(Row row, int column) { + if (row == null) { return row; } Object val = ""; - try - { + try { Cell cell = row.getCell(column); - if (StringUtils.isNotNull(cell)) - { - if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) - { + if (StringUtils.isNotNull(cell)) { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) { val = cell.getNumericCellValue(); - if (DateUtil.isCellDateFormatted(cell)) - { + if (DateUtil.isCellDateFormatted(cell)) { val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 - } - else - { - if ((Double) val % 1 != 0) - { + } else { + if ((Double) val % 1 != 0) { val = new BigDecimal(val.toString()); - } - else - { + } else { val = new DecimalFormat("0").format(val); } } - } - else if (cell.getCellType() == CellType.STRING) - { + } else if (cell.getCellType() == CellType.STRING) { val = cell.getStringCellValue(); - } - else if (cell.getCellType() == CellType.BOOLEAN) - { + } else if (cell.getCellType() == CellType.BOOLEAN) { val = cell.getBooleanCellValue(); - } - else if (cell.getCellType() == CellType.ERROR) - { + } else if (cell.getCellType() == CellType.ERROR) { val = cell.getErrorCellValue(); } } - } - catch (Exception e) - { + } catch (Exception e) { return val; } return val; @@ -1722,21 +1339,17 @@ public class ExcelUtil /** * 判断是否是空行 - * + * * @param row 判断的行 * @return */ - private boolean isRowEmpty(Row row) - { - if (row == null) - { + private boolean isRowEmpty(Row row) { + if (row == null) { return true; } - for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) - { + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) { Cell cell = row.getCell(i); - if (cell != null && cell.getCellType() != CellType.BLANK) - { + if (cell != null && cell.getCellType() != CellType.BLANK) { return false; } } @@ -1746,21 +1359,17 @@ public class ExcelUtil /** * 获取Excel2003图片 * - * @param sheet 当前sheet对象 + * @param sheet 当前sheet对象 * @param workbook 工作簿对象 * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData */ - public static Map getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook) - { + public static Map getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook) { Map sheetIndexPicMap = new HashMap(); List pictures = workbook.getAllPictures(); - if (!pictures.isEmpty()) - { - for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) - { + if (!pictures.isEmpty()) { + for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) { HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor(); - if (shape instanceof HSSFPicture) - { + if (shape instanceof HSSFPicture) { HSSFPicture pic = (HSSFPicture) shape; int pictureIndex = pic.getPictureIndex() - 1; HSSFPictureData picData = pictures.get(pictureIndex); @@ -1769,9 +1378,7 @@ public class ExcelUtil } } return sheetIndexPicMap; - } - else - { + } else { return sheetIndexPicMap; } } @@ -1779,23 +1386,18 @@ public class ExcelUtil /** * 获取Excel2007图片 * - * @param sheet 当前sheet对象 + * @param sheet 当前sheet对象 * @param workbook 工作簿对象 * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData */ - public static Map getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook) - { + public static Map getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook) { Map sheetIndexPicMap = new HashMap(); - for (POIXMLDocumentPart dr : sheet.getRelations()) - { - if (dr instanceof XSSFDrawing) - { + for (POIXMLDocumentPart dr : sheet.getRelations()) { + if (dr instanceof XSSFDrawing) { XSSFDrawing drawing = (XSSFDrawing) dr; List shapes = drawing.getShapes(); - for (XSSFShape shape : shapes) - { - if (shape instanceof XSSFPicture) - { + for (XSSFShape shape : shapes) { + if (shape instanceof XSSFPicture) { XSSFPicture pic = (XSSFPicture) shape; XSSFClientAnchor anchor = pic.getPreferredSize(); CTMarker ctMarker = anchor.getFrom(); @@ -1810,32 +1412,23 @@ public class ExcelUtil /** * 格式化不同类型的日期对象 - * + * * @param dateFormat 日期格式 - * @param val 被格式化的日期对象 + * @param val 被格式化的日期对象 * @return 格式化后的日期字符 */ - public String parseDateToStr(String dateFormat, Object val) - { - if (val == null) - { + public String parseDateToStr(String dateFormat, Object val) { + if (val == null) { return ""; } String str; - if (val instanceof Date) - { + if (val instanceof Date) { str = DateUtils.parseDateToStr(dateFormat, (Date) val); - } - else if (val instanceof LocalDateTime) - { + } else if (val instanceof LocalDateTime) { str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val)); - } - else if (val instanceof LocalDate) - { + } else if (val instanceof LocalDate) { str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val)); - } - else - { + } else { str = val.toString(); } return str; @@ -1844,31 +1437,25 @@ public class ExcelUtil /** * 是否有对象的子列表 */ - public boolean isSubList() - { + public boolean isSubList() { return StringUtils.isNotNull(subFields) && subFields.size() > 0; } /** * 是否有对象的子列表,集合不为空 */ - public boolean isSubListValue(T vo) - { + public boolean isSubListValue(T vo) { return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; } /** * 获取集合的值 */ - public Collection getListCellValue(Object obj) - { + public Collection getListCellValue(Object obj) { Object value; - try - { - value = subMethod.invoke(obj, new Object[] {}); - } - catch (Exception e) - { + try { + value = subMethod.invoke(obj, new Object[]{}); + } catch (Exception e) { return new ArrayList(); } return (Collection) value; @@ -1876,23 +1463,19 @@ public class ExcelUtil /** * 获取对象的子列表方法 - * - * @param name 名称 + * + * @param name 名称 * @param pojoClass 类对象 * @return 子列表方法 */ - public Method getSubMethod(String name, Class pojoClass) - { + public Method getSubMethod(String name, Class pojoClass) { StringBuffer getMethodName = new StringBuffer("get"); getMethodName.append(name.substring(0, 1).toUpperCase()); getMethodName.append(name.substring(1)); Method method = null; - try - { - method = pojoClass.getMethod(getMethodName.toString(), new Class[] {}); - } - catch (Exception e) - { + try { + method = pojoClass.getMethod(getMethodName.toString(), new Class[]{}); + } catch (Exception e) { log.error("获取对象异常{}", e.getMessage()); } return method; diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java index f709d1ee6..f562063dd 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/DailyTaskController.java @@ -102,6 +102,12 @@ public class DailyTaskController extends BaseController { return R.ok(); } + @PostMapping("/search-hot") + public R dailySearchHot(SysJob sysJob) { + task.dailyUpdateSearchHotToRedis(); + return R.ok(); + } + } diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java index d2b86af34..15a93331d 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java @@ -652,7 +652,7 @@ public class XktTask { CollectionUtils.addAll(redisSearchList, tempList); }); Map searchCountMap = redisSearchList.stream().collect(Collectors.groupingBy(UserSearchHistoryDTO::getSearchContent, - Collectors.summingLong(UserSearchHistoryDTO::getId))); + Collectors.summingLong(UserSearchHistoryDTO::getUserId))); // searchCountMap 按照 value 大小倒序排,取前20条热搜 List> top20List = searchCountMap.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()) .limit(20).collect(Collectors.toList()); diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreProductStorage.java b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreProductStorage.java index e661d7d4c..770de3453 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/StoreProductStorage.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/StoreProductStorage.java @@ -36,9 +36,9 @@ public class StoreProductStorage extends XktBaseEntity { */ private Long storeId; /** - * 入库CODE + * code */ - @Excel(name = "入库CODE") + @Excel(name = "code") private String code; /** * 入库类型 生产入库 1 PROD_STORAGE 其它入库 2 OTHER_STORAGE 维修入库 3 REPAIR_STORAGE diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexHotSaleRightFixDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexHotSaleRightFixDTO.java index ce1da2231..2a9a16738 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexHotSaleRightFixDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexHotSaleRightFixDTO.java @@ -23,6 +23,8 @@ public class APPIndexHotSaleRightFixDTO { private Integer displayType; @ApiModelProperty(value = "档口商品ID") private Long storeProdId; + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "排序") private Integer orderNum; @ApiModelProperty(value = "售价") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexMidBrandDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexMidBrandDTO.java index 32a527eda..598a8a840 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexMidBrandDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/app/index/APPIndexMidBrandDTO.java @@ -23,6 +23,8 @@ public class APPIndexMidBrandDTO { private Integer displayType; @ApiModelProperty(value = "档口商品ID") private Long storeProdId; + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "排序") private Integer orderNum; @ApiModelProperty(value = "售价") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexBottomPopularDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexBottomPopularDTO.java index c70cfa653..517389f2b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexBottomPopularDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexBottomPopularDTO.java @@ -58,6 +58,8 @@ public class PCIndexBottomPopularDTO { @ApiModel(value = "右侧商品") @Accessors(chain = true) public static class PCIBPPopularRightDTO { + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "2商品") private Integer displayType; @ApiModelProperty(value = "档口商品ID") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexSearchRecommendProdDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexSearchRecommendProdDTO.java index 3facc9cd0..1c68f4f7b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexSearchRecommendProdDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/pc/index/PCIndexSearchRecommendProdDTO.java @@ -20,6 +20,8 @@ public class PCIndexSearchRecommendProdDTO { private Integer displayType; @ApiModelProperty(value = "档口商品ID") private Long storeProdId; + @ApiModelProperty(value = "档口ID") + private Long storeId; @ApiModelProperty(value = "商品货号") private String prodArtNum; @ApiModelProperty(value = "排序") diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeProdStorage/StoreStorageDetailDownloadDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeProdStorage/StoreStorageDetailDownloadDTO.java new file mode 100644 index 000000000..e8a165401 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeProdStorage/StoreStorageDetailDownloadDTO.java @@ -0,0 +1,68 @@ +package com.ruoyi.xkt.dto.storeProdStorage; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.annotation.Excel; +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口入库导出数据") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreStorageDetailDownloadDTO { + + @Excel(name = "序号", cellType = Excel.ColumnType.NUMERIC, needMerge = true) + private Integer orderNum; + @Excel(name = "单据编号", needMerge = true) + private String code; + @Excel(name = "出库日期", width = 30, dateFormat = "yyyy-MM-dd", needMerge = true) + private Date createTime; + @Excel(name = "总生产成本", needMerge = true) + private BigDecimal produceAmount; + @Excel(name = "结款状态", readConverterExp = "1=生产入库,2=其它入库,3=维修入库", needMerge = true) + private Integer storageType; + @Excel(name = "货号", needMerge = true) + private String prodArtNum; + @Excel(name = "颜色", needMerge = true) + private String colorName; + @Excel(name = "30") + private Integer size30Quantity; + @Excel(name = "31") + private Integer size31Quantity; + @Excel(name = "32") + private Integer size32Quantity; + @Excel(name = "33") + private Integer size33Quantity; + @Excel(name = "34") + private Integer size34Quantity; + @Excel(name = "35") + private Integer size35Quantity; + @Excel(name = "36") + private Integer size36Quantity; + @Excel(name = "37") + private Integer size37Quantity; + @Excel(name = "38") + private Integer size38Quantity; + @Excel(name = "39") + private Integer size39Quantity; + @Excel(name = "40") + private Integer size40Quantity; + @Excel(name = "41") + private Integer size41Quantity; + @Excel(name = "42") + private Integer size42Quantity; + @Excel(name = "43") + private Integer size43Quantity; + @Excel(name = "入库总量") + private Integer totalQuantity; + @Excel(name = "操作人名称") + private String operatorName; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeProdStorage/StoreStorageExportDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeProdStorage/StoreStorageExportDTO.java new file mode 100644 index 000000000..c945d06cd --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeProdStorage/StoreStorageExportDTO.java @@ -0,0 +1,30 @@ +package com.ruoyi.xkt.dto.storeProdStorage; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口入库导出数据") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreStorageExportDTO { + + @ApiModelProperty(value = "storeId") + private Long storeId; + @ApiModelProperty(value = "storeProdStorageId") + private List storeProdStorageIdList; + @ApiModelProperty(value = "导出开始时间") + private Date voucherDateStart; + @ApiModelProperty(value = "导出结束时间") + private Date voucherDateEnd; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDownloadDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDownloadDTO.java new file mode 100644 index 000000000..8abcc1a46 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleDownloadDTO.java @@ -0,0 +1,44 @@ +package com.ruoyi.xkt.dto.storeSale; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.annotation.Excel; +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口销售导出数据") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreSaleDownloadDTO { + + @Excel(name = "序号", cellType = Excel.ColumnType.NUMERIC) + private Integer orderNum; + @Excel(name = "单据编号") + private String code; + @Excel(name = "客户") + private String storeCusName; + @Excel(name = "出库日期", width = 30, dateFormat = "yyyy-MM-dd") + private Date voucherDate; + @Excel(name = "销售总额") + private BigDecimal amount; + @Excel(name = "销售数量") + private String quantity; + @Excel(name = "抹零金额") + private BigDecimal roundOff; + @Excel(name = "结款状态", readConverterExp = "1=已结清,2=欠款") + private Integer paymentStatus; + @Excel(name = "支付方式", readConverterExp = "1=支付宝,2=微信支付,3=现金,4=欠款") + private Integer payWay; + @Excel(name = "销售类型", readConverterExp = "1=销售,2=退货,3=销售/退货") + private Integer saleType; + @Excel(name = "操作人名称") + private String operatorName; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleExportDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleExportDTO.java new file mode 100644 index 000000000..26c564fa7 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/storeSale/StoreSaleExportDTO.java @@ -0,0 +1,30 @@ +package com.ruoyi.xkt.dto.storeSale; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口销售导出数据") +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StoreSaleExportDTO { + + @ApiModelProperty(value = "storeId") + private Long storeId; + @ApiModelProperty(value = "storeSaleIdList") + private List storeSaleIdList; + @ApiModelProperty(value = "导出开始时间") + private Date voucherDateStart; + @ApiModelProperty(value = "导出结束时间") + private Date voucherDateEnd; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreProductStorageDetailMapper.java b/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreProductStorageDetailMapper.java index 32f13c06e..c89680377 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreProductStorageDetailMapper.java +++ b/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreProductStorageDetailMapper.java @@ -2,7 +2,10 @@ package com.ruoyi.xkt.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.xkt.domain.StoreProductStorageDetail; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageDetailDownloadDTO; +import org.apache.ibatis.annotations.Param; +import java.util.Date; import java.util.List; /** @@ -12,51 +15,22 @@ import java.util.List; * @date 2025-03-26 */ public interface StoreProductStorageDetailMapper extends BaseMapper { - /** - * 查询档口商品入库明细 - * - * @param id 档口商品入库明细主键 - * @return 档口商品入库明细 - */ - public StoreProductStorageDetail selectStoreProductStorageDetailByStoreProdStorDetailId(Long id); /** - * 查询档口商品入库明细列表 + * 导出选定的入库记录 * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 档口商品入库明细集合 + * @param storeProdStorageIdList 入库单ID列表 + * @return 入库记录 */ - public List selectStoreProductStorageDetailList(StoreProductStorageDetail storeProductStorageDetail); + List selectExportList(@Param("storeProdStorageIdList") List storeProdStorageIdList); /** - * 新增档口商品入库明细 + * 导出指定时间段内的入库记录 * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 结果 + * @param voucherDateStart 开始时间 + * @param voucherDateEnd 结束时间 + * @return 入库记录 */ - public int insertStoreProductStorageDetail(StoreProductStorageDetail storeProductStorageDetail); + List selectExportListVoucherDateBetween(@Param("voucherDateStart") Date voucherDateStart, @Param("voucherDateEnd") Date voucherDateEnd); - /** - * 修改档口商品入库明细 - * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 结果 - */ - public int updateStoreProductStorageDetail(StoreProductStorageDetail storeProductStorageDetail); - - /** - * 删除档口商品入库明细 - * - * @param id 档口商品入库明细主键 - * @return 结果 - */ - public int deleteStoreProductStorageDetailByStoreProdStorDetailId(Long id); - - /** - * 批量删除档口商品入库明细 - * - * @param storeProdStorDetailIds 需要删除的数据主键集合 - * @return 结果 - */ - public int deleteStoreProductStorageDetailByStoreProdStorDetailIds(Long[] storeProdStorDetailIds); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleMapper.java b/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleMapper.java index 418efa1ea..6c98b5417 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleMapper.java +++ b/xkt/src/main/java/com/ruoyi/xkt/mapper/StoreSaleMapper.java @@ -2,9 +2,12 @@ package com.ruoyi.xkt.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.xkt.domain.StoreSale; +import com.ruoyi.xkt.dto.storeSale.StoreSaleDownloadDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageDTO; import com.ruoyi.xkt.dto.storeSale.StoreSalePageResDTO; +import org.apache.ibatis.annotations.Param; +import java.util.Date; import java.util.List; /** @@ -17,4 +20,21 @@ public interface StoreSaleMapper extends BaseMapper { List selectPage(StoreSalePageDTO pageDTO); + /** + * 导出指定id列表 + * + * @param storeSaleIdList 导出入参 + * @return List + */ + List selectExportList(@Param("storeSaleIdList") List storeSaleIdList); + + /** + * 导出指定时间段内的数据 + * + * @param voucherDateStart 开始时间 + * @param voucherDateEnd 结束时间 + * @return + */ + List selectExportListVoucherDateBetween(@Param("voucherDateStart") Date voucherDateStart, @Param("voucherDateEnd") Date voucherDateEnd); + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStorageDetailService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStorageDetailService.java index 99727b3f3..ed94bb397 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStorageDetailService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStorageDetailService.java @@ -1,6 +1,7 @@ package com.ruoyi.xkt.service; -import com.ruoyi.xkt.domain.StoreProductStorageDetail; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageDetailDownloadDTO; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageExportDTO; import java.util.List; @@ -11,51 +12,13 @@ import java.util.List; * @date 2025-03-26 */ public interface IStoreProductStorageDetailService { - /** - * 查询档口商品入库明细 - * - * @param storeProdStorDetailId 档口商品入库明细主键 - * @return 档口商品入库明细 - */ - public StoreProductStorageDetail selectStoreProductStorageDetailByStoreProdStorDetailId(Long storeProdStorDetailId); /** - * 查询档口商品入库明细列表 + * 导出档口商品入库明细 * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 档口商品入库明细集合 + * @param exportDTO 导出参数 + * @return 导出数据 */ - public List selectStoreProductStorageDetailList(StoreProductStorageDetail storeProductStorageDetail); + List export(StoreStorageExportDTO exportDTO); - /** - * 新增档口商品入库明细 - * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 结果 - */ - public int insertStoreProductStorageDetail(StoreProductStorageDetail storeProductStorageDetail); - - /** - * 修改档口商品入库明细 - * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 结果 - */ - public int updateStoreProductStorageDetail(StoreProductStorageDetail storeProductStorageDetail); - - /** - * 批量删除档口商品入库明细 - * - * @param storeProdStorDetailIds 需要删除的档口商品入库明细主键集合 - * @return 结果 - */ - public int deleteStoreProductStorageDetailByStoreProdStorDetailIds(Long[] storeProdStorDetailIds); - - /** - * 删除档口商品入库明细信息 - * - * @param storeProdStorDetailId 档口商品入库明细主键 - * @return 结果 - */ - public int deleteStoreProductStorageDetailByStoreProdStorDetailId(Long storeProdStorDetailId); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java index e3a2b9b49..4ae5db39d 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreSaleService.java @@ -5,6 +5,8 @@ import com.ruoyi.xkt.dto.dailySale.StoreTodaySaleDTO; import com.ruoyi.xkt.dto.storeCustomer.StoreCusGeneralSaleDTO; import com.ruoyi.xkt.dto.storeSale.*; +import java.util.List; + /** * 档口销售出库Service接口 * @@ -88,4 +90,13 @@ public interface IStoreSaleService { * @return Integer */ Integer updateMemo(StoreSaleUpdateMemoDTO updateMemoDTO); + + /** + * 导出销售出库列表 + * + * @param exportDTO 导出入参 + * @return List + */ + List export(StoreSaleExportDTO exportDTO); + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java index 6c0909225..097799024 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductServiceImpl.java @@ -590,12 +590,8 @@ public class StoreProductServiceImpl implements IStoreProductService { final String mainPicUrl = fileList.stream().filter(x -> Objects.equals(x.getFileType(), FileType.MAIN_PIC.getValue())) .filter(x -> Objects.equals(x.getOrderNum(), ORDER_NUM_1)).map(StoreProdFileResDTO::getFileUrl).findAny().orElse(""); // 将用户浏览足迹添加到redis中 - try { - this.updateUserBrowsingToRedis(storeProdId, appResDTO.getStoreId(), appResDTO.getStoreName(), appResDTO.getProdArtNum(), - appResDTO.getProdTitle(), appResDTO.getMinPrice(), mainPicUrl); - } catch (Exception e) { - e.printStackTrace(); - } + this.updateUserBrowsingToRedis(storeProdId, appResDTO.getStoreId(), appResDTO.getStoreName(), appResDTO.getProdArtNum(), + appResDTO.getProdTitle(), appResDTO.getMinPrice(), mainPicUrl); return appResDTO.setTags(StringUtils.isNotBlank(appResDTO.getTagStr()) ? StrUtil.split(appResDTO.getTagStr(), ",") : null) // 拼接几色几码 .setSpecification((CollectionUtils.isNotEmpty(colorList) ? colorList.size() + "色" : "") + @@ -726,11 +722,7 @@ public class StoreProductServiceImpl implements IStoreProductService { final String mainPicUrl = fileList.stream().filter(x -> Objects.equals(x.getFileType(), FileType.MAIN_PIC.getValue())) .filter(x -> Objects.equals(x.getOrderNum(), ORDER_NUM_1)).map(StoreProdFileResDTO::getFileUrl).findAny().orElse(""); // 将用户浏览足迹添加到redis中 - try { - this.updateUserBrowsingToRedis(storeProdId, prodInfoDTO.getStoreId(), prodInfoDTO.getStoreName(), prodInfoDTO.getProdArtNum(), prodInfoDTO.getProdTitle(), minPrice, mainPicUrl); - } catch (Exception e) { - e.printStackTrace(); - } + this.updateUserBrowsingToRedis(storeProdId, prodInfoDTO.getStoreId(), prodInfoDTO.getStoreName(), prodInfoDTO.getProdArtNum(), prodInfoDTO.getProdTitle(), minPrice, mainPicUrl); return prodInfoDTO.setColorList(colorList); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductStorageDetailServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductStorageDetailServiceImpl.java index e08b9d94f..932557bd0 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductStorageDetailServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreProductStorageDetailServiceImpl.java @@ -1,10 +1,14 @@ package com.ruoyi.xkt.service.impl; -import com.ruoyi.common.utils.DateUtils; -import com.ruoyi.xkt.domain.StoreProductStorageDetail; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageDetailDownloadDTO; +import com.ruoyi.xkt.dto.storeProdStorage.StoreStorageExportDTO; import com.ruoyi.xkt.mapper.StoreProductStorageDetailMapper; import com.ruoyi.xkt.service.IStoreProductStorageDetailService; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -17,80 +21,27 @@ import java.util.List; * @date 2025-03-26 */ @Service +@RequiredArgsConstructor public class StoreProductStorageDetailServiceImpl implements IStoreProductStorageDetailService { - @Autowired - private StoreProductStorageDetailMapper storeProductStorageDetailMapper; + + final StoreProductStorageDetailMapper storageDetailMapper; /** - * 查询档口商品入库明细 + * 导出档口商品入库明细 * - * @param storeProdStorDetailId 档口商品入库明细主键 - * @return 档口商品入库明细 + * @param exportDTO 导出参数 + * @return 导出数据 */ @Override @Transactional(readOnly = true) - public StoreProductStorageDetail selectStoreProductStorageDetailByStoreProdStorDetailId(Long storeProdStorDetailId) { - return storeProductStorageDetailMapper.selectStoreProductStorageDetailByStoreProdStorDetailId(storeProdStorDetailId); - } - - /** - * 查询档口商品入库明细列表 - * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 档口商品入库明细 - */ - @Override - @Transactional(readOnly = true) - public List selectStoreProductStorageDetailList(StoreProductStorageDetail storeProductStorageDetail) { - return storeProductStorageDetailMapper.selectStoreProductStorageDetailList(storeProductStorageDetail); - } - - /** - * 新增档口商品入库明细 - * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 结果 - */ - @Override - @Transactional - public int insertStoreProductStorageDetail(StoreProductStorageDetail storeProductStorageDetail) { - storeProductStorageDetail.setCreateTime(DateUtils.getNowDate()); - return storeProductStorageDetailMapper.insertStoreProductStorageDetail(storeProductStorageDetail); - } - - /** - * 修改档口商品入库明细 - * - * @param storeProductStorageDetail 档口商品入库明细 - * @return 结果 - */ - @Override - @Transactional - public int updateStoreProductStorageDetail(StoreProductStorageDetail storeProductStorageDetail) { - storeProductStorageDetail.setUpdateTime(DateUtils.getNowDate()); - return storeProductStorageDetailMapper.updateStoreProductStorageDetail(storeProductStorageDetail); - } - - /** - * 批量删除档口商品入库明细 - * - * @param storeProdStorDetailIds 需要删除的档口商品入库明细主键 - * @return 结果 - */ - @Override - @Transactional - public int deleteStoreProductStorageDetailByStoreProdStorDetailIds(Long[] storeProdStorDetailIds) { - return storeProductStorageDetailMapper.deleteStoreProductStorageDetailByStoreProdStorDetailIds(storeProdStorDetailIds); - } - - /** - * 删除档口商品入库明细信息 - * - * @param storeProdStorDetailId 档口商品入库明细主键 - * @return 结果 - */ - @Override - public int deleteStoreProductStorageDetailByStoreProdStorDetailId(Long storeProdStorDetailId) { - return storeProductStorageDetailMapper.deleteStoreProductStorageDetailByStoreProdStorDetailId(storeProdStorDetailId); + public List export(StoreStorageExportDTO exportDTO) { + if (CollectionUtils.isNotEmpty(exportDTO.getStoreProdStorageIdList())) { + return this.storageDetailMapper.selectExportList(exportDTO.getStoreProdStorageIdList()); + } else { + if (ObjectUtils.isEmpty(exportDTO.getVoucherDateStart()) && ObjectUtils.isEmpty(exportDTO.getVoucherDateEnd())) { + throw new ServiceException("全量导出时,开始时间和结束时间不能为空!", HttpStatus.ERROR); + } + return this.storageDetailMapper.selectExportListVoucherDateBetween(exportDTO.getVoucherDateStart(), exportDTO.getVoucherDateEnd()); + } } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java index aa5c804c8..15115bc4b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreSaleServiceImpl.java @@ -176,6 +176,27 @@ public class StoreSaleServiceImpl implements IStoreSaleService { return this.storeSaleMapper.updateById(storeSale); } + /** + * 导出销售出库列表 + * + * @param exportDTO 导出入参 + * @return List + */ + @Override + @Transactional(readOnly = true) + public List export(StoreSaleExportDTO exportDTO) { + // 导出指定销售出库单 + if (CollectionUtils.isNotEmpty(exportDTO.getStoreSaleIdList())) { + return this.storeSaleMapper.selectExportList(exportDTO.getStoreSaleIdList()); + } else { + // 如果是全量导出,则开始时间 和 结束时间 不能为空 + if (ObjectUtils.isEmpty(exportDTO.getVoucherDateStart()) && ObjectUtils.isEmpty(exportDTO.getVoucherDateEnd())) { + throw new ServiceException("全量导出时,开始时间和结束时间不能为空!", HttpStatus.ERROR); + } + return this.storeSaleMapper.selectExportListVoucherDateBetween(exportDTO.getVoucherDateStart(), exportDTO.getVoucherDateEnd()); + } + } + /** * 新增档口销售出库 * @@ -207,7 +228,7 @@ public class StoreSaleServiceImpl implements IStoreSaleService { int count = storeSaleMapper.insert(storeSale); // 处理订单明细 List saleDetailList = storeSaleDTO.getDetailList().stream().map(x -> BeanUtil.toBean(x, StoreSaleDetail.class) - .setSaleType(storeSaleDTO.getSaleType()).setStoreSaleId(storeSale.getId()).setStoreId(storeSale.getStoreId()).setVoucherDate(voucherDate)) + .setSaleType(storeSaleDTO.getSaleType()).setStoreSaleId(storeSale.getId()).setStoreId(storeSale.getStoreId()).setVoucherDate(voucherDate)) .collect(Collectors.toList()); this.storeSaleDetailMapper.insert(saleDetailList); // 先汇总当前这笔订单商品明细的销售数量,包括销售及退货 key: prodArtNum + storeProdId + storeProdColorId + colorName, value: map(key:size,value:count) @@ -268,7 +289,7 @@ public class StoreSaleServiceImpl implements IStoreSaleService { this.storeSaleDetailMapper.updateById(saleDetailList.stream().peek(x -> x.setDelFlag(Constants.DELETED)).collect(Collectors.toList())); // 再新增档口销售出库明细数据 List detailList = storeSaleDTO.getDetailList().stream().map(x -> BeanUtil.toBean(x, StoreSaleDetail.class) - .setSaleType(storeSaleDTO.getSaleType()).setStoreSaleId(storeSale.getId()).setStoreId(storeSale.getStoreId()).setVoucherDate(voucherDate)) + .setSaleType(storeSaleDTO.getSaleType()).setStoreSaleId(storeSale.getId()).setStoreId(storeSale.getStoreId()).setVoucherDate(voucherDate)) .collect(Collectors.toList()); this.storeSaleDetailMapper.insert(detailList); // 汇总编辑的存货总数量 diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java index 02acfc4c6..8a317724d 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsiteAPPServiceImpl.java @@ -384,7 +384,8 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService { } else { appIndexMidBrandList = launchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { final Long storeProdId = Long.parseLong(x.getProdIdStr()); - return new APPIndexMidBrandDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(x.getPosition())) + return new APPIndexMidBrandDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + .setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); }).limit(5).collect(Collectors.toList()); @@ -408,8 +409,7 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService { @Override @Transactional(readOnly = true) public List getAppIndexHotSaleRightFix() { - return null; - /*// 从redis中获取数据 + // 从redis中获取数据 List appIndexHotSaleRightFixList; // 从redis 中获取数据 List redisList = redisCache.getCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_HOT_SALE_RIGHT_FIX); @@ -432,7 +432,7 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService { if (CollectionUtils.isEmpty(launchingList)) { appIndexHotSaleRightFixList = expiredList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { Long storeProdId = Long.parseLong(x.getProdIdStr()); - return new APPIndexHotSaleRightFixDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + return new APPIndexHotSaleRightFixDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setStoreId(x.getStoreId()) .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); }).limit(5).collect(Collectors.toList()); for (int i = 0; i < appIndexHotSaleRightFixList.size(); i++) { @@ -441,13 +441,14 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService { } else { appIndexHotSaleRightFixList = launchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { Long storeProdId = Long.parseLong(x.getProdIdStr()); - return new APPIndexHotSaleRightFixDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(x.getPosition())) + return new APPIndexHotSaleRightFixDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + .setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); }).limit(5).collect(Collectors.toList()); } // 放到redis中,有效期1天 redisCache.setCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_HOT_SALE_RIGHT_FIX, appIndexHotSaleRightFixList, 1, TimeUnit.DAYS); - return appIndexHotSaleRightFixList;*/ + return appIndexHotSaleRightFixList; } /** @@ -567,7 +568,7 @@ public class WebsiteAPPServiceImpl implements IWebsiteAPPService { private List getAppIndexMidBrandList(List advertRoundList, int limitCount, Map prodPriceAndMainPicMap) { return advertRoundList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { final Long storeProdId = Long.parseLong(x.getProdIdStr()); - return new APPIndexMidBrandDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + return new APPIndexMidBrandDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setStoreId(x.getStoreId()) .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); }).limit(limitCount).collect(Collectors.toList()); diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java index 858357f0d..5515da153 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java @@ -650,7 +650,7 @@ public class WebsitePCServiceImpl implements IWebsitePCService { bottomRightList = rightLaunchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { final Long storeProdId = Long.parseLong(x.getProdIdStr()); return new PCIndexBottomPopularDTO.PCIBPPopularRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(x.getPosition())) + .setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); @@ -787,7 +787,7 @@ public class WebsitePCServiceImpl implements IWebsitePCService { .forEach((storeId, list) -> { AdvertRound advertRound = list.get(0); final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - tempList.add(new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + tempList.add(new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setStoreId(advertRound.getStoreId()) .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); }); @@ -798,7 +798,8 @@ public class WebsitePCServiceImpl implements IWebsitePCService { } else { recommendList = launchingList.stream().map(advertRound -> { final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - return new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(advertRound.getPosition())) + return new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + .setOrderNum(this.positionToNumber(advertRound.getPosition())).setStoreId(advertRound.getStoreId()) .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); }).collect(Collectors.toList()); @@ -1421,7 +1422,7 @@ public class WebsitePCServiceImpl implements IWebsitePCService { AdvertRound advertRound = list.get(0); final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); tempRightList.add(new PCIndexBottomPopularDTO.PCIBPPopularRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreProdId(Long.valueOf(advertRound.getProdIdStr())) + .setStoreProdId(Long.valueOf(advertRound.getProdIdStr())).setStoreId(advertRound.getStoreId()) .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); diff --git a/xkt/src/main/resources/mapper/StoreProductStorageDetailMapper.xml b/xkt/src/main/resources/mapper/StoreProductStorageDetailMapper.xml index 9c2dead2d..e239990d0 100644 --- a/xkt/src/main/resources/mapper/StoreProductStorageDetailMapper.xml +++ b/xkt/src/main/resources/mapper/StoreProductStorageDetailMapper.xml @@ -3,174 +3,86 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select id, store_prod_stor_id, store_prod_color_id, store_prod_id, size_30, size_31, size_32, size_33, size_34, size_35, size_36, size_37, size_38, size_39, size_40, size_41, size_42, size_43, total_num, produce_price, total_produce_price, version, del_flag, create_by, create_time, update_by, update_time from store_product_storage_detail - - - - - + SELECT + DENSE_RANK() OVER (ORDER BY sps.code, sps.create_time DESC) AS orderNum, + sps.`code`, + sps.create_time, + sps.quantity, + sps.produce_amount, + sps.storage_type, + spsd.prod_art_num, + spsd.color_name, + spsd.size_30 AS size30Quantity, + spsd.size_31 AS size31Quantity, + spsd.size_32 AS size32Quantity, + spsd.size_33 AS size33Quantity, + spsd.size_34 AS size34Quantity, + spsd.size_35 AS size35Quantity, + spsd.size_36 AS size36Quantity, + spsd.size_37 AS size37Quantity, + spsd.size_38 AS size38Quantity, + spsd.size_39 AS size39Quantity, + spsd.size_40 AS size40Quantity, + spsd.size_41 AS size41Quantity, + spsd.size_42 AS size42Quantity, + spsd.size_43 AS size43Quantity, + COALESCE(spsd.size_30, 0) + COALESCE(spsd.size_31, 0) + + COALESCE(spsd.size_32, 0) + COALESCE(spsd.size_33, 0) + + COALESCE(spsd.size_34, 0) + COALESCE(spsd.size_35, 0) + + COALESCE(spsd.size_36, 0) + COALESCE(spsd.size_37, 0) + + COALESCE(spsd.size_38, 0) + COALESCE(spsd.size_39, 0) + + COALESCE(spsd.size_40, 0) + COALESCE(spsd.size_41, 0) + + COALESCE(spsd.size_42, 0) + COALESCE(spsd.size_43, 0) AS totalQuantity, + sps.operator_name + FROM + store_product_storage_detail spsd JOIN store_product_storage sps ON spsd.store_prod_stor_id = sps.id + WHERE + spsd.del_flag = 0 + AND sps.id IN + + #{item} + - - insert into store_product_storage_detail - - store_prod_stor_id, - store_prod_color_id, - store_prod_id, - size_30, - size_31, - size_32, - size_33, - size_34, - size_35, - size_36, - size_37, - size_38, - size_39, - size_40, - size_41, - size_42, - size_43, - total_num, - produce_price, - total_produce_price, - version, - del_flag, - create_by, - create_time, - update_by, - update_time, - - - #{storeProdStorId}, - #{storeProdColorId}, - #{storeProdId}, - #{size30}, - #{size31}, - #{size32}, - #{size33}, - #{size34}, - #{size35}, - #{size36}, - #{size37}, - #{size38}, - #{size39}, - #{size40}, - #{size41}, - #{size42}, - #{size43}, - #{totalNum}, - #{producePrice}, - #{totalProducePrice}, - #{version}, - #{delFlag}, - #{createBy}, - #{createTime}, - #{updateBy}, - #{updateTime}, - - + - - update store_product_storage_detail - - store_prod_stor_id = #{storeProdStorId}, - store_prod_color_id = #{storeProdColorId}, - store_prod_id = #{storeProdId}, - size_30 = #{size30}, - size_31 = #{size31}, - size_32 = #{size32}, - size_33 = #{size33}, - size_34 = #{size34}, - size_35 = #{size35}, - size_36 = #{size36}, - size_37 = #{size37}, - size_38 = #{size38}, - size_39 = #{size39}, - size_40 = #{size40}, - size_41 = #{size41}, - size_42 = #{size42}, - size_43 = #{size43}, - total_num = #{totalNum}, - produce_price = #{producePrice}, - total_produce_price = #{totalProducePrice}, - version = #{version}, - del_flag = #{delFlag}, - create_by = #{createBy}, - create_time = #{createTime}, - update_by = #{updateBy}, - update_time = #{updateTime}, - - where id = #{id} - - - - delete from store_product_storage_detail where id = #{id} - - - - delete from store_product_storage_detail where id in - - #{id} - - \ No newline at end of file diff --git a/xkt/src/main/resources/mapper/StoreSaleMapper.xml b/xkt/src/main/resources/mapper/StoreSaleMapper.xml index 4cf60b8d6..eb8714082 100644 --- a/xkt/src/main/resources/mapper/StoreSaleMapper.xml +++ b/xkt/src/main/resources/mapper/StoreSaleMapper.xml @@ -24,5 +24,50 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ss.create_time DESC + + + + \ No newline at end of file