Browse Source

Merge branch 'dev' of http://git.hobbystocks.cn/AHX-Bid/auction into dev

lilinhui 16 hours ago
parent
commit
eae419483a
62 changed files with 3459 additions and 137 deletions
  1. 133 0
      auc/src/main/java/cn/hobbystocks/auc/web/DiamondPositionController.java
  2. 18 6
      auc/src/main/java/cn/hobbystocks/auc/web/LotController.java
  3. 2 2
      auc/src/main/java/cn/hobbystocks/auc/web/LotGroupController.java
  4. 1 1
      auc/src/main/resources/application.yml
  5. 0 50
      bid/src/main/java/cn/hobbystocks/auc/web/FansController.java
  6. 31 5
      bid/src/main/java/cn/hobbystocks/auc/web/LotController.java
  7. 70 0
      bid/src/main/java/cn/hobbystocks/auc/web/LotFansController.java
  8. 1 1
      bid/src/main/resources/application.yml
  9. 20 0
      lot/pom.xml
  10. 49 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/EasyConfig.java
  11. 13 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/DictTypeFormat.java
  12. 40 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/HeadMerge.java
  13. 13 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/IsMust.java
  14. 13 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/ReadConverterExpFormat.java
  15. 20 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyColumnEnums.java
  16. 406 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyExcelFactory.java
  17. 25 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyExcelTypeEnums.java
  18. 228 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/handler/EasyDataFormatHandler.java
  19. 192 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/util/EasyExcelImportUtil.java
  20. 254 0
      lot/src/main/java/cn/hobbystocks/auc/common/easy/util/EasyExcelUtil.java
  21. 134 0
      lot/src/main/java/cn/hobbystocks/auc/common/poi/ExcelUtil.java
  22. 38 4
      lot/src/main/java/cn/hobbystocks/auc/common/utils/DateUtils.java
  23. 5 1
      lot/src/main/java/cn/hobbystocks/auc/common/utils/ExcelUtils.java
  24. 27 0
      lot/src/main/java/cn/hobbystocks/auc/convert/DiamondPositionConvert.java
  25. 27 0
      lot/src/main/java/cn/hobbystocks/auc/convert/LotConvert.java
  26. 34 0
      lot/src/main/java/cn/hobbystocks/auc/convert/SpuCategoryConvert.java
  27. 124 0
      lot/src/main/java/cn/hobbystocks/auc/domain/DiamondPosition.java
  28. 5 0
      lot/src/main/java/cn/hobbystocks/auc/domain/Lot.java
  29. 38 3
      lot/src/main/java/cn/hobbystocks/auc/domain/LotFans.java
  30. 71 0
      lot/src/main/java/cn/hobbystocks/auc/domain/SpuCategory.java
  31. 25 0
      lot/src/main/java/cn/hobbystocks/auc/dto/ExportFieldDto.java
  32. 19 5
      lot/src/main/java/cn/hobbystocks/auc/dto/LotExportDTO.java
  33. 25 0
      lot/src/main/java/cn/hobbystocks/auc/mapper/DiamondPositionMapper.java
  34. 4 0
      lot/src/main/java/cn/hobbystocks/auc/mapper/LotFansMapper.java
  35. 1 0
      lot/src/main/java/cn/hobbystocks/auc/mapper/LotMapper.java
  36. 23 0
      lot/src/main/java/cn/hobbystocks/auc/mapper/SpuCategoryMapper.java
  37. 16 0
      lot/src/main/java/cn/hobbystocks/auc/request/CategoryQueryRequest.java
  38. 26 0
      lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionPageRequest.java
  39. 19 0
      lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionQueryRequest.java
  40. 57 0
      lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionRequest.java
  41. 52 0
      lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionSaveRequest.java
  42. 16 0
      lot/src/main/java/cn/hobbystocks/auc/request/LotFansTogglePageRequest.java
  43. 23 0
      lot/src/main/java/cn/hobbystocks/auc/request/LotFansToggleRequest.java
  44. 68 0
      lot/src/main/java/cn/hobbystocks/auc/request/LotQueryRequest.java
  45. 66 0
      lot/src/main/java/cn/hobbystocks/auc/response/DiamondPositionResponse.java
  46. 25 0
      lot/src/main/java/cn/hobbystocks/auc/response/FavoriteOperationResponse.java
  47. 88 0
      lot/src/main/java/cn/hobbystocks/auc/response/LotFansResponse.java
  48. 34 0
      lot/src/main/java/cn/hobbystocks/auc/response/SpuChildCategoryResponse.java
  49. 40 0
      lot/src/main/java/cn/hobbystocks/auc/response/SpuMainCategoryResponse.java
  50. 53 0
      lot/src/main/java/cn/hobbystocks/auc/service/IDiamondPositionService.java
  51. 0 26
      lot/src/main/java/cn/hobbystocks/auc/service/ILotFansService.java
  52. 17 1
      lot/src/main/java/cn/hobbystocks/auc/service/ILotService.java
  53. 42 0
      lot/src/main/java/cn/hobbystocks/auc/service/LotFansService.java
  54. 22 0
      lot/src/main/java/cn/hobbystocks/auc/service/SpuCategoryService.java
  55. 95 0
      lot/src/main/java/cn/hobbystocks/auc/service/impl/DiamondPositionServiceImpl.java
  56. 110 10
      lot/src/main/java/cn/hobbystocks/auc/service/impl/LotFansServiceImpl.java
  57. 53 7
      lot/src/main/java/cn/hobbystocks/auc/service/impl/LotServiceImpl.java
  58. 76 0
      lot/src/main/java/cn/hobbystocks/auc/service/impl/SpuCategoryServiceImpl.java
  59. 146 0
      lot/src/main/resources/mapper/DiamondPositionMapper.xml
  60. 48 15
      lot/src/main/resources/mapper/LotFansMapper.xml
  61. 20 0
      lot/src/main/resources/mapper/LotMapper.xml
  62. 118 0
      lot/src/main/resources/mapper/SpuCategoryMapper.xml

+ 133 - 0
auc/src/main/java/cn/hobbystocks/auc/web/DiamondPositionController.java

@@ -0,0 +1,133 @@
+package cn.hobbystocks.auc.web;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+import cn.hobbystocks.auc.common.constant.Constants;
+import cn.hobbystocks.auc.common.core.domain.AjaxResult;
+import cn.hobbystocks.auc.common.user.UserInfo;
+import cn.hobbystocks.auc.common.user.UserUtils;
+import cn.hobbystocks.auc.common.utils.DateUtils;
+import cn.hobbystocks.auc.convert.DiamondPositionConvert;
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.request.*;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import cn.hobbystocks.auc.service.IDiamondPositionService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 金刚位管理Controller
+ */
+@RestController
+@RequestMapping("/auction/admin/diamond")
+@Slf4j
+@Api(tags = "金刚位管理")
+public class DiamondPositionController extends AdminBaseController {
+
+    @Resource
+    IDiamondPositionService diamondPositionService;
+
+    /**
+     * 分页查询金刚位列表
+     */
+    @ApiOperation(value = "分页查询金刚位列表", notes = "分页查询金刚位列表", response = DiamondPositionResponse.class, responseContainer = "List<DiamondPositionResponse>")
+    @PostMapping("/page")
+    @ApiResponses({
+            @ApiResponse(code = 0, message = "请求成功", response = DiamondPositionResponse.class)
+    })
+    public AjaxResult page(@RequestBody DiamondPositionPageRequest request) {
+        UserInfo userInfo = UserUtils.getSimpleUserInfo();
+        if (Objects.isNull(userInfo)) {
+            return AjaxResult.error("请先登录");
+        }
+
+        DiamondPosition diamondPosition = new DiamondPosition();
+        BeanUtils.copyProperties(request, diamondPosition);
+
+        List<DiamondPositionResponse> list = diamondPositionService.selectDiamondPositionPageList(request);
+        return AjaxResult.successPage(list);
+    }
+
+
+    /**
+     * 新增金刚位\修改金刚位
+     */
+    @ApiOperation(value = "新增金刚位/修改金刚位", notes = "新增金刚位", response = AjaxResult.class, responseContainer = "AjaxResult.success")
+    @PostMapping("/saveOrUpdate")
+    public AjaxResult saveOrUpdate(@RequestBody DiamondPositionSaveRequest request) {
+        UserInfo userInfo = UserUtils.getSimpleUserInfo();
+        if (Objects.isNull(userInfo)) {
+            return AjaxResult.error("请先登录");
+        }
+
+        int result = diamondPositionService.saveOrUpdate(request);
+        return result > 0 ? AjaxResult.success("操作成功") : AjaxResult.error("操作失败");
+    }
+
+
+    /**
+     * 获取金刚位详细信息
+     */
+    @ApiOperation(value = "获取金刚位详细信息", notes = "根据ID获取金刚位详细信息", response = DiamondPositionResponse.class)
+    @GetMapping(value = "/{id}")
+    @ApiResponses({
+            @ApiResponse(code = 0, message = "请求成功", response = DiamondPositionResponse.class)
+    })
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        UserInfo userInfo = UserUtils.getSimpleUserInfo();
+        if (Objects.isNull(userInfo)) {
+            return AjaxResult.error("请先登录");
+        }
+
+        DiamondPosition diamondPosition = diamondPositionService.selectDiamondPositionById(id);
+        if (diamondPosition == null) {
+            return AjaxResult.error("金刚位不存在");
+        }
+        DiamondPositionResponse diamondPositionResponse = DiamondPositionConvert.INSTANCE.toDiamondPositionResponse(diamondPosition);
+        return AjaxResult.success(diamondPositionResponse);
+    }
+
+
+
+
+    /**
+     * 删除金刚位(逻辑删除)
+     */
+    @ApiOperation(value = "删除金刚位", notes = "逻辑删除金刚位", response = AjaxResult.class)
+    @GetMapping("/delete/{id}")
+    public AjaxResult remove(@PathVariable("id") Long id) {
+        UserInfo userInfo = UserUtils.getSimpleUserInfo();
+        if (Objects.isNull(userInfo)) {
+            return AjaxResult.error("请先登录");
+        }
+
+        int result = diamondPositionService.deleteDiamondPositionById(id, getUsername());
+        return result > 0 ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
+    }
+
+    /**
+     * 查询有效的金刚位列表
+     */
+    @ApiOperation(value = "查询有效的金刚位列表", notes = "查询当前有效的金刚位列表", response = DiamondPositionResponse.class, responseContainer = "List<DiamondPositionResponse>")
+    @GetMapping("/active")
+    @ApiResponses({
+            @ApiResponse(code = 0, message = "请求成功", response = DiamondPositionResponse.class)
+    })
+    public AjaxResult active(@RequestBody DiamondPositionQueryRequest request) {
+//        List<DiamondPosition> list = diamondPositionService.selectActiveDiamondPositions(businessModule, version);
+        DiamondPositionResponse response = new DiamondPositionResponse();
+        return AjaxResult.success(response);
+    }
+}

+ 18 - 6
auc/src/main/java/cn/hobbystocks/auc/web/LotController.java

@@ -6,6 +6,10 @@ import java.util.*;
 import cn.hobbystocks.auc.annotation.RequireRoles;
 import cn.hobbystocks.auc.app.AppClient;
 import cn.hobbystocks.auc.common.core.domain.AjaxResult;
+import cn.hobbystocks.auc.common.easy.factory.EasyColumnEnums;
+import cn.hobbystocks.auc.common.easy.factory.EasyExcelFactory;
+import cn.hobbystocks.auc.common.easy.factory.EasyExcelTypeEnums;
+import cn.hobbystocks.auc.common.poi.ExcelUtil;
 import cn.hobbystocks.auc.common.user.UserInfo;
 import cn.hobbystocks.auc.common.user.UserUtils;
 import cn.hobbystocks.auc.common.utils.ExcelUtils;
@@ -14,6 +18,7 @@ import cn.hobbystocks.auc.common.utils.UserType;
 import cn.hobbystocks.auc.domain.Bid;
 import cn.hobbystocks.auc.domain.Lot;
 import cn.hobbystocks.auc.common.constant.Constants;
+import cn.hobbystocks.auc.dto.ExportFieldDto;
 import cn.hobbystocks.auc.dto.LotExportDTO;
 import cn.hobbystocks.auc.mapper.BidMapper;
 import cn.hobbystocks.auc.request.LotRequest;
@@ -24,8 +29,8 @@ import cn.hobbystocks.auc.vo.LotVO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
+import com.google.common.net.HttpHeaders;
+import io.swagger.annotations.*;
 import org.apache.logging.log4j.util.Strings;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -188,12 +193,19 @@ public class LotController extends AdminBaseController {
 
     @ApiOperation(value = "导出拍品列表信息", notes = "拍品列表信息\n", response = AjaxResult.class, responseContainer = "AjaxResult.success")
     @PostMapping("/export")
-    public AjaxResult export(@RequestBody LotRequest request, HttpServletResponse response) {
+    @ResponseBody
+    public void export(@RequestBody LotRequest request, HttpServletResponse response) {
 
         List<LotExportDTO> lotList = lotService.exportLotList(request);
-        ExcelUtils<LotExportDTO> util = new ExcelUtils<>(LotExportDTO.class);
-        util.exportExcelHttp(lotList, response, "拍品管理导出");
-        return AjaxResult.success();
+//        ExcelUtils<LotExportDTO> util = new ExcelUtils<>(LotExportDTO.class);
+//        util.exportExcelHttp(lotList, response, "拍品管理导出");
+
+
+        List<ExportFieldDto> excelFields = new ExcelUtil<>(LotExportDTO.class).getExcelFields();
+        EasyExcelFactory.init(EasyExcelTypeEnums.EXPORT , LotExportDTO.class, "拍品管理导出", EasyColumnEnums.include, excelFields)
+            .build()
+            .doWriteStream(lotList);
+
     }
 
 

+ 2 - 2
auc/src/main/java/cn/hobbystocks/auc/web/LotGroupController.java

@@ -11,7 +11,7 @@ import cn.hobbystocks.auc.common.utils.UserType;
 import cn.hobbystocks.auc.domain.Bid;
 import cn.hobbystocks.auc.domain.Lot;
 import cn.hobbystocks.auc.domain.LotGroup;
-import cn.hobbystocks.auc.service.ILotFansService;
+import cn.hobbystocks.auc.service.LotFansService;
 import cn.hobbystocks.auc.vo.LotGroupVO;
 import cn.hobbystocks.auc.vo.SkuDTO;
 import io.swagger.annotations.Api;
@@ -41,7 +41,7 @@ public class LotGroupController extends AdminBaseController {
 	@Autowired
 	private AppClient appClient;
 	@Autowired
-	ILotFansService lotFansService;
+    LotFansService lotFansService;
 
 
 	@ApiOperation(value = "克隆商品", notes = "insertLotGroup with no id", response = AjaxResult.class, responseContainer = "AjaxResult")

+ 1 - 1
auc/src/main/resources/application.yml

@@ -4,7 +4,7 @@ spring:
   application:
     name: auction-ahx
   datasource:
-    url: ${DB_URL:jdbc:postgresql://192.168.50.8:5432/ahx_auction}
+    url: ${DB_URL:jdbc:postgresql://192.168.50.8:5432/ahx_app}
     username: ${DB_USERNAME:postgres}
     password: ${DB_PASSWORD:123456}
   mvc:

+ 0 - 50
bid/src/main/java/cn/hobbystocks/auc/web/FansController.java

@@ -1,50 +0,0 @@
-package cn.hobbystocks.auc.web;
-
-import cn.hobbystocks.auc.common.core.domain.AjaxResult;
-import cn.hobbystocks.auc.common.user.UserUtils;
-import cn.hobbystocks.auc.domain.LotFans;
-import cn.hobbystocks.auc.service.ILotFansService;
-import cn.hobbystocks.auc.vo.FansVO;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.List;
-
-@RestController
-@RequestMapping("/bid/fans")
-@Slf4j
-@Api(tags = "关注拍品相关接口")
-public class FansController {
-
-    @Autowired
-    private ILotFansService lotFansService;
-
-    @ApiOperation("关注拍卖品")
-    @PostMapping
-    public AjaxResult fans(@RequestBody FansVO fansVO) {
-        lotFansService.fans(fansVO);
-        return AjaxResult.success();
-    }
-
-
-    @ApiOperation("检查当前用户是否关注了指定的拍卖品")
-    @PostMapping("/isFans")
-    public AjaxResult isFans(@RequestBody FansVO fansVO) {
-        List<LotFans> lotFansList = lotFansService.selectLotFansList(LotFans.builder()
-                .lotId(fansVO.getLotId())
-                .userId(UserUtils.getSimpleUserInfo().getId().longValue())
-                .type("user_like")
-                .build());
-        return AjaxResult.success(!CollectionUtils.isEmpty(lotFansList));
-    }
-
-
-
-}

+ 31 - 5
bid/src/main/java/cn/hobbystocks/auc/web/LotController.java

@@ -3,7 +3,12 @@ package cn.hobbystocks.auc.web;
 import cn.hobbystocks.auc.common.core.controller.BaseController;
 import cn.hobbystocks.auc.common.core.domain.AjaxResult;
 import cn.hobbystocks.auc.domain.Lot;
+import cn.hobbystocks.auc.request.CategoryQueryRequest;
+import cn.hobbystocks.auc.request.LotQueryRequest;
+import cn.hobbystocks.auc.response.LotFansResponse;
+import cn.hobbystocks.auc.response.SpuMainCategoryResponse;
 import cn.hobbystocks.auc.service.ILotService;
+import cn.hobbystocks.auc.service.SpuCategoryService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -12,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.annotation.Resource;
 import java.util.List;
 
 @Api(tags = "移动端拍品查询")
@@ -19,8 +25,13 @@ import java.util.List;
 @RestController
 public class LotController extends BaseController {
 
-    @Autowired
+    @Resource
     ILotService lotService;
+
+    @Resource
+    SpuCategoryService spuCategoryService;
+
+
     /**
      * 热门拍品查询:查询正在竞拍中的拍品
      */
@@ -41,12 +52,27 @@ public class LotController extends BaseController {
      */
     @PostMapping("/list/search")
     @ApiOperation("资产-珍品搜索查询")
-    public AjaxResult searchLotList(@RequestBody Lot lot){
+    public AjaxResult searchLotList(@RequestBody LotQueryRequest request){
         /*
          * 查询拍品,关键字模糊匹配拍品名称
          */
-        startPage(lot);
-        List<Lot> lots = lotService.queryLotByCategory(lot);
-        return AjaxResult.success(lots);
+        List<LotFansResponse> responses = lotService.queryLotByCategory(request);
+        return AjaxResult.successPage(responses);
+    }
+
+
+    /**
+     * 根据分类查询拍品
+     */
+    @PostMapping("/category/query")
+    @ApiOperation("资产·珍品-拍品分类")
+    public AjaxResult queryAllCategory(@RequestBody CategoryQueryRequest request){
+        List<SpuMainCategoryResponse> allCategoryList = spuCategoryService.queryAllCategory(request);
+        return AjaxResult.success(allCategoryList);
     }
+
+
+
+
+
 }

+ 70 - 0
bid/src/main/java/cn/hobbystocks/auc/web/LotFansController.java

@@ -0,0 +1,70 @@
+package cn.hobbystocks.auc.web;
+
+import cn.hobbystocks.auc.common.core.domain.AjaxResult;
+import cn.hobbystocks.auc.common.user.UserUtils;
+import cn.hobbystocks.auc.domain.LotFans;
+import cn.hobbystocks.auc.request.LotFansTogglePageRequest;
+import cn.hobbystocks.auc.request.LotFansToggleRequest;
+import cn.hobbystocks.auc.response.LotFansResponse;
+import cn.hobbystocks.auc.response.FavoriteOperationResponse;
+import cn.hobbystocks.auc.service.LotFansService;
+import cn.hobbystocks.auc.vo.FansVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/bid/fans")
+@Slf4j
+@Api(tags = "关注拍品相关接口")
+public class LotFansController {
+
+    @Autowired
+    private LotFansService lotFansService;
+
+    /**
+     * 收藏/取消收藏拍品
+     */
+    @ApiOperation(value = "收藏/取消收藏拍品", notes = "根据isLike参数进行收藏或取消收藏操作", response = FavoriteOperationResponse.class)
+    @PostMapping("/toggle")
+    public AjaxResult toggleFavorite(@RequestBody LotFansToggleRequest request) {
+        Boolean result = lotFansService.toggleFavorite(request);
+        if (Boolean.TRUE.equals(result)) {
+            return AjaxResult.success();
+        } else {
+            return AjaxResult.error();
+        }
+    }
+
+    /**
+     * 查询用户收藏的拍品列表(分页)
+     */
+    @ApiOperation(value = "查询用户收藏的拍品列表(分页)", notes = "分页查询当前用户收藏的拍品列表", response = LotFansResponse.class, responseContainer = "List<LotFansResponse>")
+    @PostMapping("/fansPage")
+    public AjaxResult page(@RequestBody LotFansTogglePageRequest  request) {
+
+        List<LotFansResponse> list = lotFansService.page(request);
+        return AjaxResult.successPage(list);
+    }
+
+
+
+    @ApiOperation("检查当前用户是否关注了指定的拍卖品")
+    @PostMapping("/isFans")
+    public AjaxResult isFans(@RequestBody FansVO fansVO) {
+        List<LotFans> lotFansList = lotFansService.selectLotFansList(LotFans.builder()
+                .lotId(fansVO.getLotId())
+                .userId(UserUtils.getSimpleUserInfo().getId().longValue())
+                .type("user_like")
+                .build());
+        return AjaxResult.success(!CollectionUtils.isEmpty(lotFansList));
+    }
+
+
+
+}

+ 1 - 1
bid/src/main/resources/application.yml

@@ -4,7 +4,7 @@ spring:
   application:
     name: bid-hk
   datasource:
-    url: ${DB_URL:jdbc:postgresql://192.168.50.8:5432/ahx_auction}
+    url: ${DB_URL:jdbc:postgresql://192.168.50.8:5432/ahx_app}
     username: ${DB_USERNAME:postgres}
     password: ${DB_PASSWORD:123456}
 

+ 20 - 0
lot/pom.xml

@@ -203,6 +203,26 @@
 			<version>3.17</version>
 		</dependency>
 
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>easyexcel</artifactId>
+			<version>3.3.2</version>
+		</dependency>
+
+		<!-- MapStruct核心依赖 -->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct</artifactId>
+			<version>1.5.5.Final</version>
+		</dependency>
+		<!-- MapStruct注解处理器 必须加,核心!编译期生成代码 -->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct-processor</artifactId>
+			<version>1.5.5.Final</version>
+			<scope>provided</scope>
+		</dependency>
+
 
 	</dependencies>
 </project>

+ 49 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/EasyConfig.java

@@ -0,0 +1,49 @@
+package cn.hobbystocks.auc.common.easy;
+
+import cn.hobbystocks.auc.dto.ExportFieldDto;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class EasyConfig {
+
+    //sheet
+    private List<Sheet> sheet;
+
+    @Data
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class Sheet {
+
+        public Sheet(String type,String key, String name, Map<String, String> header){
+            this.type = type;
+            this.key = key;
+            this.name = name;
+            this.header = header;
+        }
+        //类型: map , bean
+        private String type;
+        //index
+        private int index;
+        //sheet映射的字段
+        private String key;
+        //sheet名称
+        private String name;
+        //sheet头
+        private Map<String, String> header;
+        //数据
+        private List<Map<String, String>> data;
+        //数据【非自定义头时使用】
+        private List<Object> beanDatas;
+        //导出字段
+        private List<ExportFieldDto> excelFields;
+
+    }
+
+
+
+}

+ 13 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/DictTypeFormat.java

@@ -0,0 +1,13 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+import java.lang.annotation.*;
+
+/**
+ * 字典表转换注解
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DictTypeFormat {
+    String value();
+}

+ 40 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/HeadMerge.java

@@ -0,0 +1,40 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.FIELD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface HeadMerge {
+    /**
+     * 是否需要合并
+     */
+    boolean merge() default false;
+
+    /**
+     * 合并方向:ROW 行合并,COLUMN 列合并
+     */
+    MergeDirection mergeDirection() default MergeDirection.ROW;
+
+    /**
+     * 合并单元格数量(默认为1)
+     */
+    int mergeSpan() default 1;
+
+    /**
+     * 描述信息(默认为空)
+     */
+    String description() default "";
+
+    /**
+     * 自定义样式(默认无样式)
+     */
+    String style() default "";
+
+    /**
+     * 合并方向枚举
+     */
+    enum MergeDirection {
+        ROW, COLUMN
+    }
+}

+ 13 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/IsMust.java

@@ -0,0 +1,13 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+
+import java.lang.annotation.*;
+
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface IsMust {
+
+
+
+}

+ 13 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/annotion/ReadConverterExpFormat.java

@@ -0,0 +1,13 @@
+package cn.hobbystocks.auc.common.easy.annotion;
+
+import java.lang.annotation.*;
+
+/**
+ * 列举数据转换注解
+ */
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface ReadConverterExpFormat {
+    String value();
+}

+ 20 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyColumnEnums.java

@@ -0,0 +1,20 @@
+package cn.hobbystocks.auc.common.easy.factory;
+
+import lombok.Getter;
+
+@Getter
+public enum EasyColumnEnums {
+    //包含
+    include("import"),
+    //忽略
+    export("export");
+
+    private String type;
+
+    EasyColumnEnums(String type)
+    {
+        this.type = type;
+    }
+
+
+}

+ 406 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyExcelFactory.java

@@ -0,0 +1,406 @@
+package cn.hobbystocks.auc.common.easy.factory;
+
+import cn.hobbystocks.auc.common.easy.EasyConfig;
+import cn.hobbystocks.auc.common.easy.util.EasyExcelImportUtil;
+import cn.hobbystocks.auc.common.easy.util.EasyExcelUtil;
+import cn.hobbystocks.auc.common.utils.DateUtils;
+import cn.hobbystocks.auc.common.utils.Global;
+import cn.hobbystocks.auc.common.utils.ServletUtils;
+import cn.hobbystocks.auc.common.utils.StringUtils;
+import cn.hobbystocks.auc.dto.ExportFieldDto;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.list.TreeList;
+
+import javax.servlet.ServletOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ *
+ */
+@Slf4j
+public class EasyExcelFactory<T,R> {
+    private EasyExcelTypeEnums type;
+    private final int pageSize = 1000;
+    //调用对象
+    protected Object service;
+    //调用方法
+    protected String methodName;
+    //查询总数
+    protected String countMethodName;
+    //查询参数
+    protected Object param;
+    // 是否合并表头
+    private Boolean headMerge;
+
+    private EasyExcelUtil<T, Object> easyExcelUtil;
+    private EasyExcelImportUtil<T, T> importerUtil;
+    private List<T> list ;
+    private String path;
+    private Class<T> clazz;
+    private String sheetName;
+    private EasyColumnEnums columnsType;
+    private List<ExportFieldDto> exportFields;
+    private File file;
+    private EasyConfig easyConfig;
+
+    /**
+     * @param type
+     * @param service
+     * @param methodName
+     * @param countMethodName
+     * @param param
+     * @return
+     */
+    public static EasyExcelFactory initConfig(EasyExcelTypeEnums type,Object service, String methodName,String countMethodName, Object param){
+        EasyExcelFactory factory = new EasyExcelFactory();
+        factory.type = type;
+        factory.service = service;
+        factory.methodName = methodName;
+        factory.countMethodName = countMethodName;
+        factory.param = param;
+        return factory;
+    }
+
+    /**
+     * @param clazz
+     * @param name
+     * @param columnsType
+     * @param exportFields
+     * @param <T>
+     * @param <R>
+     * @return
+     */
+    public static <T, R> EasyExcelFactory<T,R> init(EasyExcelTypeEnums type,Class<T> clazz, String name,EasyColumnEnums columnsType, List<ExportFieldDto> exportFields){
+        EasyExcelFactory<T,R> factory = new EasyExcelFactory<>();
+        factory.type = type;
+        factory.clazz = clazz;
+        factory.sheetName = name;
+        factory.columnsType = columnsType;
+        factory.exportFields = exportFields;
+        return factory;
+    }
+
+    /**
+     * @param type
+     * @param clazz
+     * @param url
+     * @param <T>
+     * @param <R>
+     * @return
+     */
+    public static <T, R> EasyExcelFactory<T, R> init(EasyExcelTypeEnums type,Class<T> clazz, String url){
+        EasyExcelFactory<T,R> factory = new EasyExcelFactory<>();
+        factory.type = type;
+        factory.clazz = clazz;
+        factory.path = url;
+        return factory;
+    }
+
+    public EasyExcelFactory<T,R> easyConfig(EasyConfig easyConfig){
+        this.easyConfig = easyConfig;
+        return this;
+    }
+
+    /**
+     * @param headMerge
+     * @return
+     */
+    public EasyExcelFactory<T,R> headMerge(boolean headMerge){
+        this.headMerge = headMerge;
+        return this;
+    }
+
+
+    /**
+     * @param clazz
+     * @param <T>
+     * @return
+     */
+    public static<T> Object getExcelFields(Class<T> clazz) {
+        List<ExportFieldDto> exportFields = new ArrayList<>();
+        if(!Objects.isNull(clazz)){
+            Arrays.asList(clazz.getDeclaredFields()).forEach(field -> {
+                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
+                if(!Objects.isNull(excelProperty)){
+                    ExportFieldDto exportFieldDto = new ExportFieldDto(excelProperty.value()[0],false);
+                    exportFields.add(exportFieldDto);
+                }
+            });
+        }
+        return exportFields;
+    }
+
+    /**
+     * @return
+     */
+    public EasyExcelFactory<T,R> build(){
+        switch (type){
+            case EXPORT: //导出
+                path = Global.getDownloadPath() + "//easyDownload-" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date()) + "//" + this.sheetName + ".xlsx";
+                if(Objects.isNull(easyConfig)){
+                    Set<String> exportColumns = name2Column(this.clazz, exportFields);
+                    easyExcelUtil = EasyExcelUtil.init(this.clazz, this.sheetName)
+                                                 .path(path)
+                                                 .headMerge(!Objects.isNull(this.headMerge) && this.headMerge)
+                                                 //设置包含选中的字段导出
+                                                 .includeColumns(this.columnsType, exportColumns)
+                                                 .build();
+                }
+                break;
+            case IMPORT: //导入
+                list = new ArrayList<>();
+                importerUtil = EasyExcelImportUtil.create(clazz, list::addAll, Function.identity())
+                                                  .batch();
+                break;
+        }
+        return this;
+    }
+
+    /**
+     * @param tList
+     */
+    private void writeFile(List<T> tList){
+        try {
+            if (!Objects.isNull(tList)) {
+                easyExcelUtil.doWrite(tList);
+            }
+        }catch (Exception e){
+            log.error("导出excel失败",e);
+        } finally {
+            Optional.ofNullable(tList).orElseGet(ArrayList::new).clear();
+        }
+    }
+
+    /**
+     * 导出流
+     * @param tList
+     */
+    public void doWriteStream(List<T> tList){
+        try {
+            writeFile(tList);
+            if (!Objects.isNull(easyExcelUtil)) {
+                easyExcelUtil.finish();
+                ServletOutputStream outputStream = ServletUtils.getResponse().getOutputStream();
+                outputStream.write(easyExcelUtil.getBytes());
+            }
+        } catch (Exception e) {
+            log.error("easy导出excel失败",e);
+        } finally {
+            clear();
+        }
+    }
+
+    /**
+     *
+     */
+    public void finish(){
+        if(!Objects.isNull(easyExcelUtil)) {
+            easyExcelUtil.finish();
+        }
+    }
+
+    /**
+     *
+     */
+    public void clear(){
+        if(!Objects.isNull(easyExcelUtil)) {
+            easyExcelUtil.clear();
+        }
+        if(StringUtils.isNotBlank(path) && !path.startsWith("http")){
+            try {
+                File file = new File(path);
+                if(file.exists()){
+                    file.delete();
+                }
+                if(file.getParentFile().exists()){
+                    file.getParentFile().delete();
+                }
+            }catch (Exception e){
+                log.error("删除文件失败",e);
+            }
+        }
+    }
+
+
+    private int searchCount(){
+        try {
+            Method method = service.getClass().getMethod(countMethodName, param.getClass());
+            return (int) method.invoke(service, param);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+    /**
+     * @param fieldName
+     * @param clazz
+     * @return
+     */
+    private Object getValueByField(String fieldName,Class<?> clazz) {
+        try {
+            Field field = this.param.getClass().getDeclaredField(fieldName);
+            field.setAccessible(true);
+            Object value = field.get(this.param);
+            if(!Objects.isNull(value) && clazz.getName().equals(value.getClass().getName())){
+                return value;
+            }
+            return field.get(this.param);
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+            try {
+                Field field = this.param.getClass().getSuperclass().getDeclaredField(fieldName);
+                field.setAccessible(true);
+                Object value = field.get(this.param);
+                if(!Objects.isNull(value) && clazz.getName().equals(value.getClass().getName())){
+                    return value;
+                }
+                return field.get(this.param);
+            } catch (NoSuchFieldException | IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            }
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * @return
+     */
+    private List searchList() {
+        try {
+            Method method = service.getClass().getMethod(methodName, param.getClass());
+            return (List) method.invoke(service, param);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    private Set<String> name2Column(Class<T> claszz, List<ExportFieldDto> exportFields) {
+        Set<String> columns = new HashSet<>();
+        Field[] fields = claszz.getDeclaredFields();
+        Set<String> sets = Optional.ofNullable(exportFields).orElse(new ArrayList<>()).stream().map(ExportFieldDto::getName).collect(Collectors.toSet());
+        for (Field field : fields) {
+            field.setAccessible(true);
+            //获取属性名
+            //是否存在注解
+            if(field.isAnnotationPresent(ExcelProperty.class)) {
+                ExcelProperty excelProperty =  field.getAnnotation(ExcelProperty.class);
+                if (CollectionUtils.isEmpty(exportFields) || sets.contains(Optional.ofNullable(excelProperty.value()).orElse(new String[]{"default"})[0])){
+                    columns.add(field.getName());
+                }
+            }
+        }
+        return columns;
+    }
+
+    /**
+     * @param easyConfig
+     * @param excelWriter
+     */
+    public void doWriteBySheetFinal(EasyConfig easyConfig, ExcelWriter excelWriter){
+        if (Objects.nonNull(easyConfig) && CollectionUtils.isNotEmpty(easyConfig.getSheet())) {
+            List<EasyConfig.Sheet> sheets = easyConfig.getSheet();
+            for (int i = 0; i < sheets.size(); i++) {
+                EasyConfig.Sheet sheet = sheets.get(i);
+                if (StringUtils.isNotBlank(sheet.getType())) {
+                    if (Objects.equals(sheet.getType(), "map")) {
+                        //header 按照key值正序排序 转成List<List<String>>
+                        Map<String, String> headerMap = sheet.getHeader();
+                        List<List<String>> header = headerMap.entrySet()
+                                                             .stream()
+                                                             .sorted(Map.Entry.comparingByKey())
+                                                             .map(item -> {
+                                                                 String value = item.getValue();
+                                                                 return Collections.singletonList(value);
+                                                             })
+                                                             .collect(Collectors.toList());
+                        List<String> headerKeys = headerMap.entrySet()
+                                                           .stream()
+                                                           .sorted(Map.Entry.comparingByKey())
+                                                           .map(Map.Entry::getKey)
+                                                           .collect(Collectors.toList());
+                        List<Map<String, String>> i18nSheetDatas = sheet.getData();
+                        //以header 对 i8nSheetData 进行排序 并返回 List<List<String>>
+                        List<List<String>> i18nSheetData = i18nSheetDatas.stream()
+                                                                         //根据headerKeys 值进行排序
+                                                                         .sorted(Comparator.comparing(item -> {
+                                                                             //判断头部是否存在 如果不存在则在最后添加一条
+                                                                             //获取 item key value
+                                                                             Set<String> keySet = item.keySet();
+                                                                             keySet.forEach(key -> {
+                                                                                 if (!headerKeys.contains(key)) {
+                                                                                     headerKeys.add(key);
+                                                                                     header.add(Collections.singletonList(key));
+                                                                                 }
+                                                                             });
+                                                                             return Optional.ofNullable(item.get(headerKeys.iterator()
+                                                                                                                           .next()))
+                                                                                            .orElse("");
+                                                                         }))
+                                                                         .map(item -> {
+                                                                             List<String> dataList = new TreeList();
+                                                                             headerKeys.forEach(kk -> {
+                                                                                 String vv = item.get(kk);
+                                                                                 if (org.apache.commons.lang3.StringUtils.isEmpty(vv)) {
+                                                                                     vv = "";
+                                                                                 }
+                                                                                 dataList.add(vv);
+                                                                             });
+                                                                             return dataList;
+                                                                         })
+                                                                         .collect(Collectors.toList());
+                        //对i18nSheetData 做去重处理
+                        i18nSheetData = i18nSheetData.stream()
+                                                     .distinct()
+                                                     .collect(Collectors.toList());
+                        WriteSheet writeSheet = EasyExcel.writerSheet(i, sheet.getName())
+                                                         .head(header)
+                                                         .useDefaultStyle(true)
+                                                         .build();
+                        excelWriter.write(i18nSheetData, writeSheet);
+                    } else {
+                        List<Object> beanDatas = sheet.getBeanDatas();
+                        List<String> fieldNames = null;
+                        if(CollectionUtils.isNotEmpty(sheet.getExcelFields())){
+                            fieldNames = sheet.getExcelFields()
+                                              .stream()
+                                              .map(ExportFieldDto::getName)
+                                              .collect(Collectors.toList());
+                        }
+                        Object beanData = beanDatas.get(0);
+                        WriteSheet writeSheet;
+                        if (CollectionUtils.isNotEmpty(fieldNames)) {
+                            writeSheet = EasyExcel.writerSheet(i, sheet.getName())
+                                                  .head(beanData.getClass())
+                                                  .useDefaultStyle(true)
+                                                  //设置包含选中的字段导出
+                                                  .includeColumnFieldNames(fieldNames)
+                                                  .build();
+                        } else {
+                            writeSheet = EasyExcel.writerSheet(i, sheet.getName())
+                                                  .head(beanData.getClass())
+                                                  .useDefaultStyle(true)
+                                                  .build();
+                        }
+                        excelWriter.write(beanDatas, writeSheet);
+                    }
+                }
+            }
+        }
+
+    }
+
+
+}

+ 25 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/factory/EasyExcelTypeEnums.java

@@ -0,0 +1,25 @@
+package cn.hobbystocks.auc.common.easy.factory;
+
+import lombok.Getter;
+
+@Getter
+public enum EasyExcelTypeEnums {
+
+    //导入
+    IMPORT("import", "导入"),
+
+    //导出
+    EXPORT("export", "导出");
+
+    private String type;
+
+    private String desc;
+
+    EasyExcelTypeEnums(String type, String desc) {
+        this.type = type;
+        this.desc = desc;
+    }
+
+
+
+}

+ 228 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/handler/EasyDataFormatHandler.java

@@ -0,0 +1,228 @@
+package cn.hobbystocks.auc.common.easy.handler;
+
+import cn.hobbystocks.auc.common.easy.annotion.DictTypeFormat;
+import cn.hobbystocks.auc.common.easy.annotion.ReadConverterExpFormat;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.Head;
+import com.alibaba.excel.metadata.data.WriteCellData;
+import com.alibaba.excel.metadata.property.FontProperty;
+import com.alibaba.excel.metadata.property.StyleProperty;
+import com.alibaba.excel.write.handler.CellWriteHandler;
+import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
+import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Row;
+
+import java.lang.reflect.Field;
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 字典表查询注解监听
+ * 列数据格式化
+ */
+@Slf4j
+public class EasyDataFormatHandler implements CellWriteHandler {
+
+    // 用于记录每列的最大宽度
+    public final Map<Integer, Integer> maxWidthMap = new HashMap<>();
+    @Setter
+    private int dataSize = 0;
+    private boolean headMerge;
+
+
+    public static EasyDataFormatHandler init(Integer dataSize){
+        EasyDataFormatHandler handler = new EasyDataFormatHandler();
+        handler.setDataSize(dataSize);
+        return handler;
+    }
+
+    public EasyDataFormatHandler headMerge(boolean headMerge) {
+        this.headMerge = headMerge;
+        return this;
+    }
+
+    @Override
+    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
+                                 Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {
+        if (isHead) {
+            // 设置头部 列宽
+            int currentWidth = calculateTextLength(head.getHeadNameList().get(0));
+            maxWidthMap.put(columnIndex, Math.max(maxWidthMap.getOrDefault(columnIndex, 0), currentWidth));
+            log.info(" 设置头部 列宽 ");
+            // 设置表头样式
+            StyleProperty styleProperty = new StyleProperty();
+            styleProperty.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//灰色
+            head.setHeadStyleProperty(styleProperty);
+            //设置字号 11
+            FontProperty fontProperty = new FontProperty();
+            fontProperty.setFontHeightInPoints((short) 11);
+            head.setHeadFontProperty(fontProperty);
+        }
+    }
+
+    /**
+     * @param writeSheetHolder
+     * @param writeTableHolder
+     * @param cell
+     * @param head
+     * @param relativeRowIndex
+     * @param isHead
+     */
+    @Override
+    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
+                                Head head, Integer relativeRowIndex, Boolean isHead) {
+        //判断是否是最后一条 row
+        if(dataSize == relativeRowIndex + 1 || (dataSize == 0 && isHead)) {
+            // 所有数据写入完成后,设置列宽
+            writeSheetHolder.getSheet()
+                            .forEach(row -> {
+                                row.forEach(r -> {
+                                    int columnIndex = r.getColumnIndex();
+                                    Integer maxWidth = maxWidthMap.get(columnIndex);
+                                    if (maxWidth != null && maxWidth > 0) {
+                                        // 设置列宽,单位是 1/256 字符宽度
+                                        writeSheetHolder.getSheet()
+                                                        .setColumnWidth(columnIndex, (maxWidth) * 256);
+                                    }
+                                });
+                            });
+        }
+    }
+
+    @Override
+    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
+                                       WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex,
+                                       Boolean isHead) {
+        if (!isHead && !Objects.isNull(head) && head.getField().isAnnotationPresent(ReadConverterExpFormat.class)) {
+            Field field = head.getField();
+            field.setAccessible(true);
+            ReadConverterExpFormat annotation = field.getAnnotation(ReadConverterExpFormat.class);
+            if(!Objects.isNull(annotation) && StringUtils.isNotBlank(annotation.value())){
+                String cellValue = cellData.getStringValue();
+                switch (cellData.getType()){
+                    case NUMBER:
+                        cellValue = String.valueOf(cellData.getNumberValue());
+                        break;
+                    case STRING:
+                        break;
+                    case DATE:
+                        LocalDateTime dateValue = cellData.getDateValue();
+                        //LocalDateTime 转 String
+//                        cellValue = DateUtils.parseLocalDateToStr(annotation.value(), dateValue);
+                        break;
+                }
+                String[] expDatas = annotation.value().split(",");
+                String finalCellValue = cellValue;
+                Arrays.asList(expDatas).forEach(expData -> {
+                    String[] expDataArr = expData.split("=");
+                    if(Objects.equals(finalCellValue, expDataArr[0])){
+                        cellData.setType(CellDataTypeEnum.STRING);
+                        cellData.setStringValue(expDataArr[1]);
+                        cell.setCellType(CellType.STRING);
+                        cell.setCellValue(expDataArr[1]);
+                    }
+                });
+            }
+        }else if(!isHead && !Objects.isNull(head) && head.getField().isAnnotationPresent(DictTypeFormat.class)){
+            //查询字典表数据
+            DictTypeFormat annotation = head.getField().getAnnotation(DictTypeFormat.class);
+            if(!Objects.isNull(annotation) && StringUtils.isNotBlank(annotation.value())){
+                String cellValue = cellData.getStringValue();
+                switch (cellData.getType()){
+                    case NUMBER:
+                        cellValue = String.valueOf(cellData.getNumberValue());
+                        break;
+                    case STRING:
+                        break;
+                    case DATE:
+                        LocalDateTime dateValue = cellData.getDateValue();
+                        //LocalDateTime 转 String
+//                        cellValue = DateUtils.parseLocalDateToStr(annotation.value(), dateValue);
+                        break;
+                    }
+                if (StringUtils.isNotBlank(cellValue)) {
+//                    String dictValue = DictUtils.getDictLabel(annotation.value(), cellValue, ",");
+                    cellData.setType(CellDataTypeEnum.STRING);
+//                    cellData.setStringValue(dictValue);
+                }
+            }
+        }else if(!isHead && !Objects.isNull(head) && head.getField().isAnnotationPresent(DateTimeFormat.class)){
+            //如果有时间格式化注解
+            DateTimeFormat annotation = head.getField().getAnnotation(DateTimeFormat.class);
+            if(!Objects.isNull(annotation) && StringUtils.isNotBlank(annotation.value())){
+                LocalDateTime dateValue = cellData.getDateValue();
+                //LocalDateTime 转 String
+//                String cellValue = DateUtils.parseLocalDateToStr(annotation.value(), dateValue);
+//                if (StringUtils.isNotBlank(cellValue)) {
+//                    cellData.setType(CellDataTypeEnum.STRING);
+//                    cellData.setStringValue(cellValue);
+//                }
+            }
+        }
+        // 设置列最大宽度
+        checkCellMaxWith(cellData, cell);
+    }
+
+    /**
+     * 设置列最大宽度
+     * @param cellData
+     * @param cell
+     */
+    private void checkCellMaxWith(WriteCellData<?> cellData, Cell cell) {
+        int columnIndex = cell.getColumnIndex();
+        int currentWidth = 0;
+
+        switch (cellData.getType()) {
+            case STRING:
+                //currentWidth = 中文字符 * 2  || currentWidth = 英文 等字符 * 1
+                currentWidth = calculateTextLength(cellData.getStringValue());
+                break;
+            case NUMBER:
+                currentWidth = String.valueOf(cellData.getNumberValue()).length();
+                break;
+            case BOOLEAN:
+                currentWidth = String.valueOf(cellData.getBooleanValue()).length();
+                break;
+            case DATE:
+                currentWidth = String.valueOf(cellData.getDateValue()).length();
+                break;
+            case ERROR:
+            case EMPTY:
+            default:
+                break;
+        }
+
+        // 更新最大宽度
+        maxWidthMap.put(columnIndex, Math.max(maxWidthMap.getOrDefault(columnIndex, 0), currentWidth));
+    }
+    private int calculateTextLength(String text) {
+        if (text == null || text.isEmpty()) {
+            return 0;
+        }
+
+        int length = 0;
+        for (char c : text.toCharArray()) {
+            if (String.valueOf(c).getBytes().length > 1) {
+                // 中文字符,占 2 个英文字符宽度
+                length += 2;
+            } else {
+                // 英文字符,占 1 个英文字符宽度
+                length += 1;
+            }
+        }
+        if(length > 255){
+            length = 255;
+        }
+        return length;
+    }
+}

+ 192 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/util/EasyExcelImportUtil.java

@@ -0,0 +1,192 @@
+package cn.hobbystocks.auc.common.easy.util;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * @author hdd
+ * @description
+ * @date 2024/4/9 12:26
+ */
+public class EasyExcelImportUtil<T, R> {
+
+    /**
+     * excel行数据转换
+     */
+    private Function<T, R> rowConverter;
+
+    /**
+     * 解析后的数据处理
+     */
+    private Consumer<List<R>> consumer;
+
+    /**
+     * 是否对读取到的数据进行批量处理
+     */
+    private boolean batch;
+
+    /**
+     * 批处理数
+     */
+    private int batchCount = 500;
+
+    /**
+     * 是否异步处理读取到到数据
+     */
+    private boolean async;
+
+    /**
+     * excel行数据读取后转换成指定类对象
+     */
+    private Class<T> clazz;
+
+    /**
+     * 异步线程池
+     */
+    private ThreadPoolExecutor executor;
+
+    /**
+     * 构建
+     */
+    public static <T, R> EasyExcelImportUtil<T, R> create(Class<T> clazz, Consumer<List<R>> consumer, Function<T, R> rowConverter) {
+        EasyExcelImportUtil<T, R> util = new EasyExcelImportUtil<>();
+        util.clazz = clazz;
+        util.consumer = consumer;
+        util.rowConverter = rowConverter;
+        return util;
+    }
+
+    /**
+     * 批处理
+     */
+    public EasyExcelImportUtil<T, R> batch() {
+        return batch(batchCount);
+    }
+
+    /**
+     * 批处理
+     */
+    public EasyExcelImportUtil<T, R> batch(Integer batchCount) {
+        if (batchCount == null || batchCount <= 0) {
+            throw new IllegalArgumentException("批处理数必须大于0");
+        }
+        this.batch = true;
+        this.batchCount = batchCount;
+        return this;
+    }
+
+    /**
+     * 异步操作设置线程池
+     */
+    public EasyExcelImportUtil<T, R> async(ThreadPoolExecutor executor) {
+        this.executor = executor;
+        this.async = true;
+        return this;
+    }
+
+    /**
+     * 设置转换器
+     *
+     * @param rowConverter
+     * @return
+     */
+    public EasyExcelImportUtil<T, R> rowConverter(Function<T, R> rowConverter) {
+        this.rowConverter = rowConverter;
+        return this;
+    }
+
+    /**
+     * 读取并处理excel
+     */
+    public void doRead(InputStream inputStream) {
+        EasyExcel.read(inputStream, this.clazz, new DefaultListener()).sheet().doRead();
+    }
+
+    /**
+     * 读取并处理excel
+     */
+    public void doReadByHttp(String fileUrl) throws Exception {
+        InputStream inputStream = null;
+        try {
+            inputStream = download(fileUrl);
+            EasyExcel.read(inputStream, this.clazz, new DefaultListener()).sheet().doRead();
+        } finally {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+        }
+    }
+
+    private InputStream download(String path) throws IOException {
+        URL url = new URL(path);
+        //打开链接
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        //设置请求方式为"GET"
+        conn.setRequestMethod("GET");
+        //超时响应时间为20秒
+        conn.setConnectTimeout(20 * 1000);
+        conn.setReadTimeout(120 * 1000);
+        //通过输入流获取图片数据
+        return conn.getInputStream();
+    }
+
+    private class DefaultListener extends AnalysisEventListener<T> {
+
+        private final List<R> list = new ArrayList<>();
+
+        private final List<CompletableFuture<Void>> futureList = new ArrayList<>();
+
+        /**
+         * 处理每行的时候都会调用
+         */
+        @Override
+        public void invoke(T t, AnalysisContext analysisContext) {
+            list.add(rowConverter.apply(t));
+            if (!batch || list.size() >= batchCount) {
+                handle();
+            }
+        }
+
+        /**
+         * 处理结束的时候
+         */
+        @Override
+        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+            handle();
+            // 异步处理时等待所有线程执行结束
+            if (async) {
+                CompletableFuture[] futures = futureList.toArray(new CompletableFuture[futureList.size()]);
+                CompletableFuture<Void> future = CompletableFuture.allOf(futures);
+                future.join();
+            }
+        }
+
+        private void handle() {
+            if (list.isEmpty()) {
+                return;
+            }
+            List<R> newList = new ArrayList<>(list);
+            list.clear();
+            if (!async) {
+                consumer.accept(newList);
+            } else {
+                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> consumer.accept(newList), executor);
+                futureList.add(future);
+            }
+        }
+
+    }
+
+}

+ 254 - 0
lot/src/main/java/cn/hobbystocks/auc/common/easy/util/EasyExcelUtil.java

@@ -0,0 +1,254 @@
+package cn.hobbystocks.auc.common.easy.util;
+
+import cn.hobbystocks.auc.common.easy.factory.EasyColumnEnums;
+import cn.hobbystocks.auc.common.easy.handler.EasyDataFormatHandler;
+import cn.hobbystocks.auc.common.exception.ServiceException;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.builder.ExcelWriterBuilder;
+import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * 导出工具类
+ */
+@Slf4j
+public class EasyExcelUtil<T, R> {
+
+    /**
+     *
+     */
+    private Class<T> clazz;
+    /**
+     *
+     */
+    private String sheet;
+    /**
+     *
+     */
+    private List<T> data;
+
+    /**
+     *
+     */
+    private String path;
+
+    /**
+     *
+     */
+    private File file ;
+
+    private ExcelWriter writer;
+    private WriteSheet writeSheet;
+    private ExcelWriterSheetBuilder writerSheetBuilder;
+    //
+    private EasyColumnEnums columnsType;
+    //字段
+    private Set<String> columns;
+    //
+    private int startIndex;
+    // 是否合并表头
+    private boolean headMerge;
+
+
+    /**
+     * @param clazz
+     * @param data
+     * @return
+     */
+    public static <T, R> EasyExcelUtil<T, R> init(Class<T> clazz, List<T> data) {
+        EasyExcelUtil<T, R> that = new EasyExcelUtil<T, R>();
+        that.clazz = clazz;
+        that.data = data;
+        return that;
+    }
+
+    /**
+     * @param clazz
+     * @param data
+     * @param sheet
+     * @return
+     */
+    public static <T, R> EasyExcelUtil<T, R> init(Class<T> clazz, List<T> data, String sheet) {
+        EasyExcelUtil<T, R> that = new EasyExcelUtil<T, R>();
+        that.clazz = clazz;
+        that.data = data;
+        that.sheet = sheet;
+        return that;
+    }
+
+    public static <T, R> EasyExcelUtil<T, R> init(Class<T> clazz, String sheet) {
+        EasyExcelUtil<T, R> that = new EasyExcelUtil<T, R>();
+        that.clazz = clazz;
+        that.sheet = sheet;
+        return that;
+    }
+
+    /**
+     * @param path
+     * @return
+     */
+    public EasyExcelUtil<T, R> path(String path){
+        this.path = path;
+        return this;
+    }
+
+    /**
+     *
+     * @param columns
+     * @return
+     * @see EasyColumnEnums
+     */
+    public EasyExcelUtil<T, R> includeColumns(EasyColumnEnums columnsType, Set<String> columns){
+        this.columnsType = columnsType;
+        this.columns = columns;
+        return this;
+    }
+
+    public EasyExcelUtil<T, R> headMerge(boolean headMerge){
+        this.headMerge = headMerge;
+        return this;
+    }
+    /**
+     * @return
+     */
+    public EasyExcelUtil<T, R> build() {
+        File file = new File(path);
+        if (!file.getParentFile().exists()) {
+            file.getParentFile().mkdirs();
+        }
+        this.file = file;
+        this.writer = EasyExcel.write(path, this.clazz).build();
+        int size = Objects.isNull(data)?0:data.size();
+        if (CollectionUtils.isNotEmpty(columns)) {
+            if (Objects.nonNull(columnsType)) {
+                switch (columnsType) {
+                    case include: //包含
+                        this.writerSheetBuilder = EasyExcel.writerSheet(sheet)
+//                                                   .registerWriteHandler(EasyDataFormatHandler.init(size).headMerge(this.headMerge))
+                                                   .includeColumnFieldNames(columns)
+                                                   .useDefaultStyle(true)
+                                                   ;
+                        break;
+                    case export: //排除
+                        this.writerSheetBuilder = EasyExcel
+                                                   .writerSheet(sheet)
+//                                                   .registerWriteHandler(EasyDataFormatHandler.init(size).headMerge(this.headMerge))
+                                                   .excludeColumnFieldNames(columns)
+                                                   .useDefaultStyle(true)
+                                                   ;
+                        break;
+                }
+            }
+        } else {
+            this.writerSheetBuilder = EasyExcel.writerSheet(sheet)
+                                       .useDefaultStyle(true)
+                                       ;
+        }
+        if(!Objects.equals(size, 0)){
+            this.writerSheetBuilder = this.writerSheetBuilder.registerWriteHandler(EasyDataFormatHandler.init(size));
+        }
+        return this;
+    }
+
+
+    public void doWrite(List<T> data) {
+        //是否存在文件
+        try {
+            if (Objects.isNull(this.file)) {
+                throw new ServiceException("文件不存在",500);
+            }
+            int size = Objects.isNull(data)?0:data.size();
+            this.writer.write(data,this.writerSheetBuilder.registerWriteHandler(EasyDataFormatHandler.init(size).headMerge(this.headMerge)).build());
+        } catch (Exception e) {
+            log.error(" 生成excel文件时异常 doWrite:",e);
+            throw new ServiceException("生成excel文件时异常[doWrite]",500 );
+        }
+    }
+
+    public void finish() {
+        try {
+            if (Objects.isNull(this.file)) {
+                throw new ServiceException("文件不存在", 500);
+            }
+            this.writer.finish();
+        } catch (Exception e) {
+            log.error(" 生成excel文件时异常 finish {} ",e);
+            throw new ServiceException("生成excel文件时异常[finish]", 500);
+        }
+    }
+
+    /**
+     *
+     */
+    public void doWrite(String path) {
+        //是否存在文件
+        try {
+            File file = new File(path);
+            if (!file.getParentFile().exists()) {
+                file.getParentFile().mkdirs();
+            }
+            ExcelWriterBuilder write = EasyExcel.write(path, clazz);
+            write.sheet(sheet).useDefaultStyle(true)
+                 .doWrite(data);
+            this.path = path;
+            this.file = file;
+        } catch (Exception e) {
+            log.error(" 生成excel文件时异常{} ",e);
+            throw new ServiceException("下载文件时异常",500 );
+        }
+    }
+
+
+    /**
+     *
+     */
+    public void doWriteStream(OutputStream out) {
+        //是否存在文件
+        try {
+            EasyExcel.write(out,clazz).sheet(sheet).doWrite(data);
+        } catch (Exception e) {
+            log.error(" 生成excel流时异常{} ",e);
+            throw new ServiceException("下载文件时异常",500);
+        }
+    }
+    /**
+     *
+     */
+    public void clear( ){
+        File file = new File(path);
+        if(!Objects.isNull(file)){
+            boolean delete = file.delete();
+            if (delete) {
+                file.getParentFile().delete();
+            }
+        }
+
+    }
+
+    public byte[] getBytes() {
+        try {
+            return Files.readAllBytes(this.file.toPath());
+        } catch (Exception e) {
+            log.error(" 获取文件流异常{} ",e);
+            throw new ServiceException("获取文件流异常",500);
+        }
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public void setFile(File file) {
+        this.file = file;
+    }
+}

+ 134 - 0
lot/src/main/java/cn/hobbystocks/auc/common/poi/ExcelUtil.java

@@ -0,0 +1,134 @@
+package cn.hobbystocks.auc.common.poi;
+
+
+import cn.hobbystocks.auc.common.core.text.Convert;
+import cn.hobbystocks.auc.common.utils.*;
+import cn.hobbystocks.auc.common.utils.reflect.ReflectUtils;
+import cn.hobbystocks.auc.dto.ExportFieldDto;
+import org.apache.poi.hssf.usermodel.HSSFDateUtil;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * Excel相关处理
+ *
+ * @author zheng
+ */
+public class ExcelUtil<T>
+{
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+    /**
+     * Excel sheet最大行数,默认65536
+     */
+    public static final int sheetSize = 65536;
+    /**
+     * 文件保存路径
+     */
+    private String filepath;
+
+    /**
+     * 工作表名称
+     */
+    private String sheetName;
+
+    /**
+     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
+     */
+    private Excel.Type type;
+
+    /**
+     * 工作薄对象
+     */
+    private Workbook wb;
+
+    /**
+     * 工作表对象
+     */
+    private Sheet sheet;
+
+    /**
+     * 样式列表
+     */
+    private Map<String, CellStyle> styles;
+
+    /**
+     * 导入导出数据列表
+     */
+    private List<T> list;
+
+    /**
+     * 注解列表
+     */
+    private List<Object[]> fields;
+
+    /**
+     * 实体对象
+     */
+    public Class<T> clazz;
+
+    public ExcelUtil(Class<T> clazz)
+    {
+        this.clazz = clazz;
+    }
+
+    public void init(List<T> list, String sheetName, Excel.Type type)
+    {
+        if (list == null)
+        {
+            list = new ArrayList<T>();
+        }
+        this.list = list;
+        this.sheetName = sheetName;
+        this.type = type;
+    }
+
+    /**
+     * 得到所有定义字段
+     */
+    public List<ExportFieldDto> getExcelFields()
+    {
+        List<ExportFieldDto> fields = new ArrayList<ExportFieldDto>();
+        List<Field> tempFields = new ArrayList<>();
+        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+        for (Field field : tempFields)
+        {
+            // 单注解
+            if (field.isAnnotationPresent(Excel.class))
+            {
+                fields.add(new ExportFieldDto(field.getAnnotation(Excel.class).name(),field.getAnnotation(Excel.class).isMust()));
+            }
+
+            // 多注解
+            if (field.isAnnotationPresent(Excels.class))
+            {
+                Excels attrs = field.getAnnotation(Excels.class);
+                Excel[] excels = attrs.value();
+                for (Excel excel : excels)
+                {
+                    fields.add(new ExportFieldDto(excel.name(),excel.isMust()));
+                }
+            }
+        }
+        return fields;
+    }
+
+}

+ 38 - 4
lot/src/main/java/cn/hobbystocks/auc/common/utils/DateUtils.java

@@ -11,7 +11,7 @@ import org.apache.commons.lang3.time.DateFormatUtils;
 
 /**
  * 时间工具类
- * 
+ *
  * @author ruoyi
  */
 public class DateUtils extends org.apache.commons.lang3.time.DateUtils
@@ -27,13 +27,16 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
     public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
 
     private static String[] parsePatterns = {
-            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
             "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
             "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
 
+    // 系统默认时区(避免时区偏移问题)
+    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();
+
     /**
      * 获取当前Date型日期
-     * 
+     *
      * @return Date() 当前日期
      */
     public static Date getNowDate()
@@ -43,7 +46,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
 
     /**
      * 获取当前日期, 默认格式为yyyy-MM-dd
-     * 
+     *
      * @return String
      */
     public static String getDate()
@@ -208,4 +211,35 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
             throw new IllegalArgumentException("时间格式无效,请使用 HH:mm:ss 格式", e);
         }
     }
+
+    /**
+     * 获取当前时间
+     * @return
+     */
+    public static String parseDateToStr(Date date) {
+        return parseDateToStr(YYYY_MM_DD_HH_MM_SS, date);
+    }
+
+    /**
+     * string类型时间转localdatetime
+     * @return
+     */
+    public static LocalDateTime parseStringToLocalDateTime(String time) {
+        return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
+    }
+
+    /**
+     * 当前时间 + n天
+     * @param days 偏移天数(正数=往后,负数=往前,0=当前时间)
+     * @return 偏移后的Date类型时间(兼容旧代码)
+     */
+
+
+    public static Date addDays(int days) {
+        LocalDateTime currentTime = LocalDateTime.now();
+        LocalDateTime targetTime = currentTime.plusDays(days);
+        // 转换为Date类型(若不需要Date,可直接返回LocalDateTime)
+        return Date.from(targetTime.atZone(DEFAULT_ZONE_ID).toInstant());
+    }
+
 }

+ 5 - 1
lot/src/main/java/cn/hobbystocks/auc/common/utils/ExcelUtils.java

@@ -1,5 +1,6 @@
 package cn.hobbystocks.auc.common.utils;
 
+import com.google.common.net.HttpHeaders;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddressList;
@@ -13,6 +14,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -110,8 +112,10 @@ public class ExcelUtils<T> {
             out = new FileOutputStream(getAbsoluteFile(filename));
 //            wb.write(out);
             //导出数据
+            String encodedFileName = new String(sheetName.getBytes("gb2312"), "ISO8859-1") + ".xlsx";
+
             //设置Http响应头告诉浏览器下载这个附件
-            response.setHeader("Content-Disposition", "attachment;Filename=" + new String(sheetName.getBytes("gb2312"), "ISO8859-1") + ".xlsx");
+            response.setHeader("Content-Disposition", "attachment;Filename=" + encodedFileName);
             out = response.getOutputStream();
             wb.write(out);
         } catch (Exception e) {

+ 27 - 0
lot/src/main/java/cn/hobbystocks/auc/convert/DiamondPositionConvert.java

@@ -0,0 +1,27 @@
+package cn.hobbystocks.auc.convert;
+
+
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+
+/**
+ * 金刚位转换器
+ *
+ * @author: gengjintao
+ * @date: 2026/01/20
+ */
+@Mapper
+public interface DiamondPositionConvert {
+
+    DiamondPositionConvert INSTANCE = Mappers.getMapper(DiamondPositionConvert.class);
+
+
+
+    DiamondPositionResponse toDiamondPositionResponse(DiamondPosition po);
+
+
+
+}

+ 27 - 0
lot/src/main/java/cn/hobbystocks/auc/convert/LotConvert.java

@@ -0,0 +1,27 @@
+package cn.hobbystocks.auc.convert;
+
+
+import cn.hobbystocks.auc.domain.Lot;
+import cn.hobbystocks.auc.response.LotFansResponse;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+
+/**
+ * 拍品转换器
+ *
+ * @author: gengjintao
+ * @date: 2026/01/20
+ */
+@Mapper
+public interface LotConvert {
+
+    LotConvert INSTANCE = Mappers.getMapper(LotConvert.class);
+
+
+
+    LotFansResponse toLotFansResponse(Lot po);
+
+
+
+}

+ 34 - 0
lot/src/main/java/cn/hobbystocks/auc/convert/SpuCategoryConvert.java

@@ -0,0 +1,34 @@
+package cn.hobbystocks.auc.convert;
+
+
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.domain.SpuCategory;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import cn.hobbystocks.auc.response.SpuChildCategoryResponse;
+import cn.hobbystocks.auc.response.SpuMainCategoryResponse;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.factory.Mappers;
+
+
+/**
+ * 金刚位转换器
+ *
+ * @author: gengjintao
+ * @date: 2026/01/20
+ */
+@Mapper
+public interface SpuCategoryConvert {
+
+    SpuCategoryConvert INSTANCE = Mappers.getMapper(SpuCategoryConvert.class);
+
+
+    @Mapping(source = "id", target = "categoryId")
+    SpuMainCategoryResponse toSpuMainCategoryResponse(SpuCategory po);
+
+    @Mapping(source = "id", target = "categoryId")
+    SpuChildCategoryResponse toSpuChildCategoryResponse(SpuCategory po);
+
+
+
+}

+ 124 - 0
lot/src/main/java/cn/hobbystocks/auc/domain/DiamondPosition.java

@@ -0,0 +1,124 @@
+package cn.hobbystocks.auc.domain;
+
+
+import cn.hobbystocks.auc.annotation.Sensitive;
+import cn.hobbystocks.auc.annotation.View;
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 金刚位管理表
+ *
+ * @author ruoyi
+ */
+
+@Data
+@ApiModel("金刚位管理表")
+public class DiamondPosition {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 金刚位名称
+     */
+    private String name;
+
+    /**
+     * 图标URL
+     */
+    private String iconUrl;
+
+    /**
+     * 类型:home_ad-首页横屏异形banner图、home_alien_banner-首页新版异形轮播图
+     */
+    private String type;
+
+    /**
+     * 跳转地址/路径
+     */
+    private String jumpUrl;
+
+    /**
+     * 跳转参数(JSON格式)
+     */
+    private String jumpParams;
+
+    /**
+     * 描述
+     */
+    private String description;
+
+    /**
+     * 业务模块(如HOME-首页,ORDER-订单,USER-用户中心)
+     */
+    private String businessModule;
+
+    /**
+     * 版本
+     */
+    private String version;
+
+    /**
+     * 状态:0-禁用,1-启用
+     */
+    private Integer status;
+
+
+    /**
+     * 备注说明
+     */
+    private String remark;
+
+
+    /**
+     * 删除标识:0-未删,1-已删
+     */
+    private Integer delFlag;
+
+    /**
+     * 生效开始时间
+     */
+    private LocalDateTime effectiveStartTime;
+
+    /**
+     * 生效结束时间
+     */
+    private LocalDateTime effectiveEndTime;
+
+    /**
+     * 创建id
+     */
+    private String createUser;
+
+    /**
+     * 更新id
+     */
+    private String updateUser;
+
+    /** 创建时间 */
+    private LocalDateTime createTime;
+
+
+    /** 更新时间 */
+    private LocalDateTime updateTime;
+
+    /**
+     * 排序(数字越小越靠前)
+     */
+    private Integer sort;
+}

+ 5 - 0
lot/src/main/java/cn/hobbystocks/auc/domain/Lot.java

@@ -2,6 +2,7 @@ package cn.hobbystocks.auc.domain;
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 import cn.hobbystocks.auc.annotation.Sensitive;
 import cn.hobbystocks.auc.annotation.View;
@@ -202,4 +203,8 @@ public class Lot extends BaseEntity
     private String subCategory;
     @ApiModelProperty("拍品属性json")
     private JsonNode properties;
+
+
+    @ApiModelProperty("拍品id集合")
+    private List<Long> ids;
 }

+ 38 - 3
lot/src/main/java/cn/hobbystocks/auc/domain/LotFans.java

@@ -1,9 +1,9 @@
 package cn.hobbystocks.auc.domain;
 
-import cn.hobbystocks.auc.common.core.domain.BaseEntity;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
+import java.time.LocalDateTime;
 import java.util.Date;
 
 @Data
@@ -12,20 +12,55 @@ import java.util.Date;
 @NoArgsConstructor
 @Builder
 @TableName("lot_fans")
-public class LotFans extends BaseEntity
-{
+public class LotFans {
     private static final long serialVersionUID = 1L;
 
+    /**
+     * 主键id
+     */
     private Long id;
 
+    /**
+     * 用户id
+     */
     private Long userId;
 
+    /**
+     * 拍品id
+     */
     private Long lotId;
 
+    /**
+     * 关注类型
+     */
     private String type;
 
+    /**
+     * 过期时间
+     */
     private Date expire;
 
+    /**
+     * 商家id
+     */
     private Long merchantId;
 
+    /**
+     * 创建id
+     */
+    private String createUser;
+
+    /**
+     * 更新id
+     */
+    private String updateUser;
+
+    /** 创建时间 */
+    private LocalDateTime createTime;
+
+
+    /** 更新时间 */
+    private LocalDateTime updateTime;
+
+
 }

+ 71 - 0
lot/src/main/java/cn/hobbystocks/auc/domain/SpuCategory.java

@@ -0,0 +1,71 @@
+package cn.hobbystocks.auc.domain;
+
+import cn.hobbystocks.auc.annotation.Sensitive;
+import cn.hobbystocks.auc.annotation.View;
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Locale;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SpuCategory {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+
+    /**
+     * 是否级联 0-否 1-是
+     */
+    private Integer isCascade;
+
+    /**
+     * 子标签/扩展标签(JSON/文本存储)
+     */
+    private String subLabel;
+
+    /**
+     * 排序号(数字越小越靠前)
+     */
+    private Integer sort;
+
+    /**
+     * 父分类ID(顶级分类为0)
+     */
+    private Long parentId;
+
+    /**
+     * 分类图标URL
+     */
+    private String iconUrl;
+
+    /**
+     * 状态 0-禁用 1-启用(默认1)
+     */
+    private Integer status;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+
+}

+ 25 - 0
lot/src/main/java/cn/hobbystocks/auc/dto/ExportFieldDto.java

@@ -0,0 +1,25 @@
+package cn.hobbystocks.auc.dto;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+
+@Data
+@ToString
+@NoArgsConstructor
+public class ExportFieldDto {
+
+    public ExportFieldDto(String name, boolean isMust){
+        this.name = name;
+        this.isMust = isMust;
+    }
+
+    private String name;
+
+    private String dateFormat;
+
+    private boolean isMust;
+
+
+
+}

+ 19 - 5
lot/src/main/java/cn/hobbystocks/auc/dto/LotExportDTO.java

@@ -3,6 +3,7 @@ package cn.hobbystocks.auc.dto;
 import cn.hobbystocks.auc.annotation.Sensitive;
 import cn.hobbystocks.auc.annotation.View;
 import cn.hobbystocks.auc.common.utils.Excel;
+import com.alibaba.excel.annotation.ExcelProperty;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
@@ -17,65 +18,78 @@ import java.util.Date;
 public class LotExportDTO {
 
     @Excel(name = "拍品ID")
+    @ExcelProperty(value = "拍品ID") // 新增
     private String id;
 
     /** 商品ID */
     @Excel(name = "商品ID")
+    @ExcelProperty(value = "商品ID") // 新增
     private String goodsId;
 
     @Excel(name = "商品名称")
+    @ExcelProperty(value = "商品名称") // 新增
     private String goodsName;
 
     @Excel(name = "商品种类")
+    @ExcelProperty(value = "商品种类") // 新增
     private String goodsType;
 
     /** 排序 */
     @Excel(name = "排序")
+    @ExcelProperty(value = "排序") // 新增
     private String sort;
 
     /** 出价次数 */
     @Excel(name = "出价次数")
+    @ExcelProperty(value = "出价次数") // 新增
     private String bidCount;
 
     /** (1已上架  2已下架  0未审核) */
     @Excel(name = "状态")
+    @ExcelProperty(value = "状态") // 新增
     private String pubStatus;
 
-
     /** 拍卖状态(Waiting:未开始;Starting:开启中;Bidding:进行中;Finished:拍卖结束;Cancelled:撤拍;Pass:流拍;Sold:成交) */
     @Excel(name = "拍卖状态")
+    @ExcelProperty(value = "拍卖状态") // 新增
     private String status;
 
     /** 创建时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @Excel(name = "创建时间")
-    private Date createTime;
+    @ExcelProperty(value = "创建时间") // 新增
+    private String createTime;
 
     /** 拍卖开始时间 */
     @Excel(name = "拍卖开始时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date startTime;
+    @ExcelProperty(value = "拍卖开始时间") // 新增
+    private String startTime;
 
     /** 拍卖结束时间 */
     @Excel(name = "拍卖结束时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    private Date endTime;
+    @ExcelProperty(value = "拍卖结束时间") // 新增
+    private String endTime;
 
     /** 保证金(元) */
     @Excel(name ="保证金(元)")
+    @ExcelProperty(value = "保证金(元)") // 新增
     private String deposit;
 
     /** 服务费(%) */
     @Excel(name ="服务费(%)")
+    @ExcelProperty(value = "服务费(%)") // 新增
     private String serviceTariff;
 
     /** 规则类型:traditional_delay;标准延时,traditional_delay_v2:重置延时,traditional_delay_v3:增价拍卖 */
     @Excel(name ="拍卖方式")
+    @ExcelProperty(value = "拍卖方式") // 新增
     private String ruleType;
 
     /** 最新价格 */
     @Excel(name ="起拍价/当前价")
+    @ExcelProperty(value = "起拍价/当前价") // 新增
     private String lastPrice;
 
-
 }

+ 25 - 0
lot/src/main/java/cn/hobbystocks/auc/mapper/DiamondPositionMapper.java

@@ -0,0 +1,25 @@
+package cn.hobbystocks.auc.mapper;
+
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.request.DiamondPositionPageRequest;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface DiamondPositionMapper extends BaseMapper<DiamondPosition> {
+
+    DiamondPosition selectDiamondPositionById(Long id);
+
+    List<DiamondPosition> selectDiamondPositionList(IPage<DiamondPosition> page, @Param("request") DiamondPositionPageRequest request);
+
+    List<DiamondPosition> selectActiveDiamondPositions(@Param("businessModule") String businessModule,
+                                                        @Param("version") String version);
+
+    int insertDiamondPosition(DiamondPosition diamondPosition);
+
+    int updateDiamondPosition(DiamondPosition diamondPosition);
+
+    int deleteDiamondPositionById(@Param("id") Long id, @Param("updateUser") String updateUser);
+}

+ 4 - 0
lot/src/main/java/cn/hobbystocks/auc/mapper/LotFansMapper.java

@@ -3,6 +3,7 @@ package cn.hobbystocks.auc.mapper;
 
 import cn.hobbystocks.auc.domain.LotFans;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -28,4 +29,7 @@ public interface LotFansMapper extends BaseMapper<LotFans> {
     int updateLotFansDel(Long id);
 
     LotFans selectLotFansByLotIdAndType(@Param("lotId") Long lotId, @Param("type") String type);
+
+    List<LotFans> selectLotFansPageList(IPage<LotFans> lotFansIPage,@Param("request") LotFans lotFans);
+
 }

+ 1 - 0
lot/src/main/java/cn/hobbystocks/auc/mapper/LotMapper.java

@@ -60,4 +60,5 @@ public interface LotMapper extends BaseMapper<Lot> {
 
     List<Lot> queryLotListByCategory(Lot lot);
 
+    List<Lot> selectLotListByLotIds(@Param("lotIds") List<Long> lotIds);
 }

+ 23 - 0
lot/src/main/java/cn/hobbystocks/auc/mapper/SpuCategoryMapper.java

@@ -0,0 +1,23 @@
+package cn.hobbystocks.auc.mapper;
+
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.domain.SpuCategory;
+import cn.hobbystocks.auc.request.DiamondPositionPageRequest;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface SpuCategoryMapper {
+
+
+    List<SpuCategory> selectAllMainCategory();
+
+
+    List<SpuCategory> selectChildCategoryByParentIds(List<Long> mainCategoryIds);
+
+    List<Long> listChildByParentId(@Param("mainCategoryId") Long mainCategoryId);
+
+    List<Long> listLotIdsByCategoryIds(@Param("categoryIds") List<Long> categoryIds);
+}

+ 16 - 0
lot/src/main/java/cn/hobbystocks/auc/request/CategoryQueryRequest.java

@@ -0,0 +1,16 @@
+package cn.hobbystocks.auc.request;
+
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel("分类菜单查询条件对象")
+public class CategoryQueryRequest extends BaseEntity{
+
+
+    @ApiModelProperty("状态:0-禁用,1-启用")
+    private Integer status;
+
+}

+ 26 - 0
lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionPageRequest.java

@@ -0,0 +1,26 @@
+package cn.hobbystocks.auc.request;
+
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import cn.hobbystocks.auc.domain.Lot;
+import cn.hobbystocks.auc.vo.InData;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@ApiModel("金刚位分页对象")
+public class DiamondPositionPageRequest extends BaseEntity{
+
+    @ApiModelProperty("金刚位名称")
+    private String name;
+
+    @ApiModelProperty("类型:home_ad-首页横屏异形banner图、home_alien_banner-首页新版异形轮播图")
+    private String type;
+
+    @ApiModelProperty("状态:0-禁用,1-启用")
+    private Integer status;
+
+}

+ 19 - 0
lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionQueryRequest.java

@@ -0,0 +1,19 @@
+package cn.hobbystocks.auc.request;
+
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel("金刚位查询条件对象")
+public class DiamondPositionQueryRequest extends BaseEntity{
+
+
+    @ApiModelProperty("类型:home_ad-首页横屏异形banner图、home_alien_banner-首页新版异形轮播图")
+    private String type;
+
+    @ApiModelProperty("业务模块(如HOME-首页,ORDER-订单,USER-用户中心)")
+    private String businessModule;
+
+}

+ 57 - 0
lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionRequest.java

@@ -0,0 +1,57 @@
+package cn.hobbystocks.auc.request;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@ApiModel("金刚位创建/更新请求对象")
+public class DiamondPositionRequest {
+
+    @ApiModelProperty("主键ID(更新时必填)")
+    private Long id;
+
+    @ApiModelProperty("金刚位名称")
+    private String name;
+
+    @ApiModelProperty("图标URL")
+    private String iconUrl;
+
+    @ApiModelProperty("类型:home_ad-首页横屏异形banner图、home_alien_banner-首页新版异形轮播图")
+    private String type;
+
+    @ApiModelProperty("跳转地址/路径")
+    private String jumpUrl;
+
+    @ApiModelProperty("跳转参数(JSON格式)")
+    private String jumpParams;
+
+    @ApiModelProperty("描述")
+    private String description;
+
+    @ApiModelProperty("业务模块(如HOME-首页,ORDER-订单,USER-用户中心)")
+    private String businessModule;
+
+    @ApiModelProperty("展示版本(适配不同版本页面)")
+    private String version;
+
+    @ApiModelProperty("状态:0-禁用,1-启用")
+    private Integer status;
+
+    @ApiModelProperty("备注说明")
+    private String remark;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("生效开始时间")
+    private Date effectiveStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("生效结束时间")
+    private Date effectiveEndTime;
+
+    @ApiModelProperty("排序(数字越小越靠前)")
+    private Integer sort;
+}

+ 52 - 0
lot/src/main/java/cn/hobbystocks/auc/request/DiamondPositionSaveRequest.java

@@ -0,0 +1,52 @@
+package cn.hobbystocks.auc.request;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@ApiModel("金刚位创建/更新请求对象")
+public class DiamondPositionSaveRequest {
+
+    @ApiModelProperty("主键ID(更新时必填)")
+    private Long id;
+
+    @ApiModelProperty("金刚位名称")
+    private String name;
+
+    @ApiModelProperty("图标URL")
+    private String iconUrl;
+
+    @ApiModelProperty("类型:home_ad-首页横屏异形banner图、home_alien_banner-首页新版异形轮播图")
+    private String type;
+
+    @ApiModelProperty("跳转地址/路径")
+    private String jumpUrl;
+
+    @ApiModelProperty("描述")
+    private String description;
+
+    @ApiModelProperty("业务模块(如HOME-首页,ORDER-订单,USER-用户中心)")
+    private String businessModule;
+
+    @ApiModelProperty("状态:0-禁用,1-启用")
+    private Integer status;
+
+    @ApiModelProperty("备注说明")
+    private String remark;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("生效开始时间")
+    private String effectiveStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("生效结束时间")
+    private String effectiveEndTime;
+
+    @ApiModelProperty("排序(数字越小越靠前)")
+    private Integer sort;
+}

+ 16 - 0
lot/src/main/java/cn/hobbystocks/auc/request/LotFansTogglePageRequest.java

@@ -0,0 +1,16 @@
+package cn.hobbystocks.auc.request;
+
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@ApiModel("收藏拍品请求对象")
+public class LotFansTogglePageRequest extends BaseEntity {
+
+
+}

+ 23 - 0
lot/src/main/java/cn/hobbystocks/auc/request/LotFansToggleRequest.java

@@ -0,0 +1,23 @@
+package cn.hobbystocks.auc.request;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("收藏拍品请求对象")
+public class LotFansToggleRequest {
+
+    @ApiModelProperty("是否收藏:true-收藏,false-取消收藏")
+    private Boolean isLike;
+
+    @ApiModelProperty("拍品ID")
+    private Long lotId;
+
+}

+ 68 - 0
lot/src/main/java/cn/hobbystocks/auc/request/LotQueryRequest.java

@@ -0,0 +1,68 @@
+package cn.hobbystocks.auc.request;
+
+import cn.hobbystocks.auc.annotation.Sensitive;
+import cn.hobbystocks.auc.annotation.View;
+import cn.hobbystocks.auc.common.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+import nonapi.io.github.classgraph.json.Id;
+import org.apache.ibatis.type.Alias;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.validation.constraints.NotBlank;
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class LotQueryRequest extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /** 主分类id */
+    @ApiModelProperty("主分类id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long mainCategoryId;
+
+
+    /** 子分类id */
+    @ApiModelProperty("子分类id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long childCategoryId;
+
+    /** 拍品名称 */
+    @ApiModelProperty("拍品名称")
+    private String name;
+
+    /** 是否发布(0:未发布;1:已发布) */
+    @ApiModelProperty("是否发布(1已上架  2已下架  0未审核)")
+    private Integer pubStatus;
+
+
+    /** 拍卖状态(Waiting:未开始;Starting:开启中;Bidding:进行中;Finished:拍卖结束;Cancelled:撤拍;Pass:流拍;Sold:成交) */
+    @ApiModelProperty("拍卖状态(Waiting:未开始;Starting:开启中;Bidding:进行中;Finished:拍卖结束;Cancelled:撤拍;Pass:流拍;Sold:成交)")
+    private String status;
+
+    /** 拍卖开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("拍卖开始时间")
+    private Date startTime;
+
+    /** 拍卖结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("拍卖结束时间")
+    private Date endTime;
+
+    /** 实际结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("实际结束时间")
+    private Date realEndTime;
+
+}

+ 66 - 0
lot/src/main/java/cn/hobbystocks/auc/response/DiamondPositionResponse.java

@@ -0,0 +1,66 @@
+package cn.hobbystocks.auc.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@ApiModel("金刚位响应对象")
+public class DiamondPositionResponse {
+
+    @ApiModelProperty("主键ID")
+    private Long id;
+
+    @ApiModelProperty("金刚位名称")
+    private String name;
+
+    @ApiModelProperty("图标URL")
+    private String iconUrl;
+
+    @ApiModelProperty("类型:home_ad-首页横屏异形banner图、home_alien_banner-首页新版异形轮播图")
+    private String type;
+
+    @ApiModelProperty("跳转地址/路径")
+    private String jumpUrl;
+
+    @ApiModelProperty("描述")
+    private String description;
+
+    @ApiModelProperty("业务模块(如HOME-首页,ORDER-订单,USER-用户中心)")
+    private String businessModule;
+
+    @ApiModelProperty("状态:0-禁用,1-启用")
+    private Integer status;
+
+    @ApiModelProperty("备注说明")
+    private String remark;
+
+    @ApiModelProperty("创建id")
+    private String createUser;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("更新id")
+    private String updateUser;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("更新时间")
+    private LocalDateTime updateTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("生效开始时间")
+    private LocalDateTime effectiveStartTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("生效结束时间")
+    private LocalDateTime effectiveEndTime;
+
+    @ApiModelProperty("排序(数字越小越靠前)")
+    private Integer sort;
+}

+ 25 - 0
lot/src/main/java/cn/hobbystocks/auc/response/FavoriteOperationResponse.java

@@ -0,0 +1,25 @@
+package cn.hobbystocks.auc.response;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("收藏操作响应对象")
+public class FavoriteOperationResponse {
+
+    @ApiModelProperty("是否操作成功")
+    private Boolean success;
+
+    @ApiModelProperty("操作结果:true-已收藏,false-已取消收藏")
+    private Boolean isLiked;
+
+    @ApiModelProperty("提示信息")
+    private String message;
+}

+ 88 - 0
lot/src/main/java/cn/hobbystocks/auc/response/LotFansResponse.java

@@ -0,0 +1,88 @@
+package cn.hobbystocks.auc.response;
+
+import cn.hobbystocks.auc.annotation.View;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("收藏拍品响应对象")
+public class LotFansResponse {
+
+    @ApiModelProperty("收藏ID")
+    private Long id;
+
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    @ApiModelProperty("拍品ID")
+    private Long lotId;
+
+    @ApiModelProperty("商品ID")
+    private String goodsId;
+
+    @ApiModelProperty("商品名称")
+    private String goodsName;
+
+    @ApiModelProperty("拍品名称")
+    private String name;
+
+    @ApiModelProperty("拍品图片")
+    private String imgs;
+
+    @ApiModelProperty("轮播图片")
+    private String carouselImgs;
+
+    @ApiModelProperty("商家ID")
+    private Long merchantId;
+
+    @ApiModelProperty("商家名称")
+    private String merchantName;
+
+    @ApiModelProperty("商家头像")
+    private String merchantAvatar;
+
+    @ApiModelProperty("拍卖会ID")
+    private Long auctionId;
+
+    @ApiModelProperty("起拍价")
+    private String startPrice;
+
+    @ApiModelProperty("当前价")
+    private String currentPrice;
+
+    @ApiModelProperty("拍品数量")
+    private Long num;
+
+    @ApiModelProperty("数量单位")
+    private String unit;
+
+    @ApiModelProperty("拍卖状态")
+    private String status;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("拍卖开始时间")
+    private Date startTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("拍卖结束时间")
+    private Date endTime;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @ApiModelProperty("收藏时间")
+    private Date createTime;
+
+    /** 规则内容 */
+    @ApiModelProperty("规则内容")
+    private String ruleContent;
+}

+ 34 - 0
lot/src/main/java/cn/hobbystocks/auc/response/SpuChildCategoryResponse.java

@@ -0,0 +1,34 @@
+package cn.hobbystocks.auc.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@ApiModel("子分类VO")
+public class SpuChildCategoryResponse {
+
+    /**
+     * 子分类ID
+     */
+    @ApiModelProperty("子分类ID")
+    private Long categoryId; // 子分类ID
+    /**
+     * 子分类名称
+     */
+    @ApiModelProperty("子分类名称")
+    private String categoryName; // 子分类名称
+    /**
+     * 子分类图标
+     */
+    @ApiModelProperty("子分类图标")
+    private String iconUrl; // 子分类图标
+    /**
+     * 排序号
+     */
+    @ApiModelProperty("排序号")
+    private Integer sort; // 排序号
+}

+ 40 - 0
lot/src/main/java/cn/hobbystocks/auc/response/SpuMainCategoryResponse.java

@@ -0,0 +1,40 @@
+package cn.hobbystocks.auc.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+@ApiModel("主分类VO")
+public class SpuMainCategoryResponse {
+
+    /**
+     * 主分类ID
+     */
+    @ApiModelProperty("主分类ID")
+    private Long categoryId; // 主分类ID
+    /**
+     * 主分类名称
+     */
+    @ApiModelProperty("主分类名称")
+    private String categoryName; // 主分类名称
+    /**
+     * 主分类图标
+     */
+    @ApiModelProperty("主分类图标")
+    private String iconUrl; // 主分类图标
+    /**
+     * 排序号
+     */
+    @ApiModelProperty("排序号")
+    private Integer sort; // 排序号
+    /**
+     * 子分类列表
+     */
+    @ApiModelProperty("子分类列表")
+    private List<SpuChildCategoryResponse> childCategoryList;
+}

+ 53 - 0
lot/src/main/java/cn/hobbystocks/auc/service/IDiamondPositionService.java

@@ -0,0 +1,53 @@
+package cn.hobbystocks.auc.service;
+
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.request.DiamondPositionPageRequest;
+import cn.hobbystocks.auc.request.DiamondPositionSaveRequest;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface IDiamondPositionService extends IService<DiamondPosition> {
+
+    /**
+     * 根据ID查询金刚位
+     * @param id 主键ID
+     * @return 金刚位信息
+     */
+    DiamondPosition selectDiamondPositionById(Long id);
+
+    /**
+     * 分页查询金刚位列表
+     * @param request 查询条件
+     * @return 金刚位列表
+     */
+    List<DiamondPositionResponse> selectDiamondPositionPageList(DiamondPositionPageRequest request);
+
+
+    /**
+     * 查询有效的金刚位列表
+     * @param businessModule 业务模块
+     * @param version 版本
+     * @return 有效的金刚位列表
+     */
+    List<DiamondPosition> selectActiveDiamondPositions(String businessModule, String version);
+
+
+    /**
+     * 删除金刚位(逻辑删除)
+     * @param id 主键ID
+     * @param updateUser 更新用户
+     * @return 结果
+     */
+    int deleteDiamondPositionById(Long id, String updateUser);
+
+
+    /**
+     * 新增金刚位\更新金刚位
+     * @param request 金刚位信息
+     * @return 结果
+     */
+    int saveOrUpdate(DiamondPositionSaveRequest request);
+}

+ 0 - 26
lot/src/main/java/cn/hobbystocks/auc/service/ILotFansService.java

@@ -1,26 +0,0 @@
-package cn.hobbystocks.auc.service;
-
-
-import cn.hobbystocks.auc.domain.LotFans;
-import cn.hobbystocks.auc.vo.FansVO;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-import java.util.List;
-
-public interface ILotFansService extends IService<LotFans> {
-    public LotFans selectLotFansById(Long id);
-
-    public List<LotFans> selectLotFansList(LotFans lotFans);
-
-    public int insertLotFans(LotFans lotFans);
-
-    public int updateLotFans(LotFans lotFans);
-
-    public int deleteLotFansById(Long id);
-
-    void fans(FansVO fansVO);
-
-    int updateLotFansDel(Long id);
-
-    LotFans selectLotFansByLotIdAndType(Long lotId, String type);
-}

+ 17 - 1
lot/src/main/java/cn/hobbystocks/auc/service/ILotService.java

@@ -6,7 +6,9 @@ import cn.hobbystocks.auc.domain.LotFans;
 import cn.hobbystocks.auc.domain.LotGroup;
 import cn.hobbystocks.auc.dto.LotExportDTO;
 import cn.hobbystocks.auc.handle.context.Live;
+import cn.hobbystocks.auc.request.LotQueryRequest;
 import cn.hobbystocks.auc.request.LotRequest;
+import cn.hobbystocks.auc.response.LotFansResponse;
 import cn.hobbystocks.auc.vo.LiveVO;
 import cn.hobbystocks.auc.vo.LotVO;
 import cn.hobbystocks.auc.vo.SelfVO;
@@ -117,11 +119,25 @@ public interface ILotService extends IService<Lot> {
 
     List<Lot> selectBiddingLotList();
 
-    List<Lot> queryLotByCategory(Lot lot);
+    /**
+     * 资产-珍品搜索查询-根据分类查询拍品
+     * @param request
+     * @return
+     */
+    List<LotFansResponse> queryLotByCategory(LotQueryRequest request);
 
     /**
      * 导出拍品列表信息
      * @param request
      */
     List<LotExportDTO> exportLotList(LotRequest request);
+
+    /**
+     * 根据拍品id数组查询拍品列表
+     * @param lotIds 拍品id数组
+     * @return 拍品列表
+     */
+    List<Lot> selectLotListByLotIds(List<Long> lotIds);
+
+
 }

+ 42 - 0
lot/src/main/java/cn/hobbystocks/auc/service/LotFansService.java

@@ -0,0 +1,42 @@
+package cn.hobbystocks.auc.service;
+
+
+import cn.hobbystocks.auc.domain.LotFans;
+import cn.hobbystocks.auc.request.LotFansTogglePageRequest;
+import cn.hobbystocks.auc.request.LotFansToggleRequest;
+import cn.hobbystocks.auc.response.LotFansResponse;
+import cn.hobbystocks.auc.vo.FansVO;
+
+import java.util.List;
+
+public interface LotFansService {
+    LotFans selectLotFansById(Long id);
+
+    List<LotFans> selectLotFansList(LotFans lotFans);
+
+    int insertLotFans(LotFans lotFans);
+
+    int updateLotFans(LotFans lotFans);
+
+    int deleteLotFansById(Long id);
+
+    void fans(FansVO fansVO);
+
+    int updateLotFansDel(Long id);
+
+    LotFans selectLotFansByLotIdAndType(Long lotId, String type);
+
+    /**
+     * 收藏/取消收藏拍品
+     * @param request
+     * @return
+     */
+    Boolean toggleFavorite(LotFansToggleRequest request);
+
+    /**
+     * 分页查询用户收藏的拍品列表
+     * @param request
+     * @return
+     */
+    List<LotFansResponse> page(LotFansTogglePageRequest request);
+}

+ 22 - 0
lot/src/main/java/cn/hobbystocks/auc/service/SpuCategoryService.java

@@ -0,0 +1,22 @@
+package cn.hobbystocks.auc.service;
+
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.domain.SpuCategory;
+import cn.hobbystocks.auc.request.CategoryQueryRequest;
+import cn.hobbystocks.auc.request.DiamondPositionPageRequest;
+import cn.hobbystocks.auc.request.DiamondPositionSaveRequest;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import cn.hobbystocks.auc.response.SpuMainCategoryResponse;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface SpuCategoryService {
+
+    /**
+     * 查询所有分类
+     * @param request
+     * @return
+     */
+    List<SpuMainCategoryResponse> queryAllCategory(CategoryQueryRequest request);
+}

+ 95 - 0
lot/src/main/java/cn/hobbystocks/auc/service/impl/DiamondPositionServiceImpl.java

@@ -0,0 +1,95 @@
+package cn.hobbystocks.auc.service.impl;
+
+import cn.hobbystocks.auc.common.constant.Constants;
+import cn.hobbystocks.auc.common.core.domain.AjaxResult;
+import cn.hobbystocks.auc.common.utils.DateUtils;
+import cn.hobbystocks.auc.convert.DiamondPositionConvert;
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.domain.Lot;
+import cn.hobbystocks.auc.mapper.DiamondPositionMapper;
+import cn.hobbystocks.auc.request.DiamondPositionPageRequest;
+import cn.hobbystocks.auc.request.DiamondPositionSaveRequest;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import cn.hobbystocks.auc.service.IDiamondPositionService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class DiamondPositionServiceImpl extends ServiceImpl<DiamondPositionMapper, DiamondPosition> implements IDiamondPositionService {
+
+    @Autowired
+    private DiamondPositionMapper diamondPositionMapper;
+
+    @Override
+    public DiamondPosition selectDiamondPositionById(Long id) {
+        return diamondPositionMapper.selectDiamondPositionById(id);
+    }
+
+    @Override
+    public List<DiamondPositionResponse> selectDiamondPositionPageList(DiamondPositionPageRequest request) {
+
+        IPage<DiamondPosition> diamondPositionIPage =new Page<>(request.getPageNum(),request.getPageSize());
+        List<DiamondPosition> diamondPositions = diamondPositionMapper.selectDiamondPositionList(diamondPositionIPage, request);
+        List<DiamondPositionResponse> collect = diamondPositions.stream().map(DiamondPositionConvert.INSTANCE::toDiamondPositionResponse).collect(Collectors.toList());
+        return collect;
+    }
+
+    @Override
+    public List<DiamondPosition> selectActiveDiamondPositions(String businessModule, String version) {
+        return diamondPositionMapper.selectActiveDiamondPositions(businessModule, version);
+    }
+
+    @Override
+    public int deleteDiamondPositionById(Long id, String updateUser) {
+        DiamondPosition existing = diamondPositionMapper.selectDiamondPositionById(id);
+        if (Objects.isNull( existing)) {
+            return 0;
+        }
+        return diamondPositionMapper.deleteDiamondPositionById(id, updateUser);
+    }
+
+    @Override
+    public int saveOrUpdate(DiamondPositionSaveRequest request) {
+        if (Objects.isNull(request)) {
+            return 0;
+        }
+
+        DiamondPosition diamondPosition = new DiamondPosition();
+        diamondPosition.setName(request.getName());
+        diamondPosition.setIconUrl(request.getIconUrl());
+        diamondPosition.setType(request.getType());
+        diamondPosition.setJumpUrl(request.getJumpUrl());
+//        diamondPosition.setJumpParams(request.getJumpParams());
+        diamondPosition.setDescription(request.getDescription());
+        diamondPosition.setBusinessModule(request.getBusinessModule());
+        diamondPosition.setStatus(request.getStatus());
+        diamondPosition.setRemark(request.getRemark());
+
+        diamondPosition.setEffectiveStartTime(DateUtils.parseStringToLocalDateTime(request.getEffectiveStartTime()));
+        diamondPosition.setEffectiveEndTime(DateUtils.parseStringToLocalDateTime(request.getEffectiveEndTime()));
+        diamondPosition.setSort(request.getSort());
+        diamondPosition.setCreateUser("admin");
+        diamondPosition.setCreateTime(LocalDateTime.now());
+        diamondPosition.setUpdateUser("admin");
+        diamondPosition.setUpdateTime(LocalDateTime.now());
+        if (Objects.nonNull(request.getId())) {
+            diamondPosition.setId(request.getId());
+            return diamondPositionMapper.updateDiamondPosition(diamondPosition);
+        } else {
+            return diamondPositionMapper.insertDiamondPosition(diamondPosition);
+        }
+    }
+}

+ 110 - 10
lot/src/main/java/cn/hobbystocks/auc/service/impl/LotFansServiceImpl.java

@@ -1,27 +1,48 @@
 package cn.hobbystocks.auc.service.impl;
 
+import cn.hobbystocks.auc.common.exception.ServiceException;
+import cn.hobbystocks.auc.common.user.UserInfo;
 import cn.hobbystocks.auc.common.user.UserUtils;
 import cn.hobbystocks.auc.common.utils.DateUtils;
+import cn.hobbystocks.auc.common.utils.StringUtils;
+import cn.hobbystocks.auc.convert.LotConvert;
+import cn.hobbystocks.auc.domain.Lot;
 import cn.hobbystocks.auc.domain.LotFans;
+import cn.hobbystocks.auc.handle.context.tradition.TraditionRule;
 import cn.hobbystocks.auc.mapper.LotFansMapper;
-import cn.hobbystocks.auc.service.ILotFansService;
+import cn.hobbystocks.auc.request.LotFansTogglePageRequest;
+import cn.hobbystocks.auc.request.LotFansToggleRequest;
+import cn.hobbystocks.auc.response.LotFansResponse;
+import cn.hobbystocks.auc.service.ILotService;
+import cn.hobbystocks.auc.service.LotFansService;
 import cn.hobbystocks.auc.vo.FansVO;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
+import lombok.extern.log4j.Log4j2;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
-
+@Log4j2
 @Service
-public class LotFansServiceImpl extends ServiceImpl<LotFansMapper,LotFans> implements ILotFansService
-{
-    @Autowired
-    private LotFansMapper lotFansMapper;
+public class LotFansServiceImpl  implements LotFansService {
+    @Resource
+    LotFansMapper lotFansMapper;
+
+    @Resource
+    ILotService lotService;
+
+
 
     @Override
     public LotFans selectLotFansById(Long id)
@@ -38,7 +59,7 @@ public class LotFansServiceImpl extends ServiceImpl<LotFansMapper,LotFans> imple
     @Override
     public int insertLotFans(LotFans lotFans)
     {
-        lotFans.setCreateTime(DateUtils.getNowDate());
+        lotFans.setCreateTime(LocalDateTime.now());
         return lotFansMapper.insertLotFans(lotFans);
     }
 
@@ -63,7 +84,7 @@ public class LotFansServiceImpl extends ServiceImpl<LotFansMapper,LotFans> imple
             List<LotFans> lotFansList =
                     lotFansMapper.selectLotFansList(lotFans);
             if (CollectionUtils.isEmpty(lotFansList)) {
-                lotFans.setCreateTime(new Date());
+                lotFans.setCreateTime(LocalDateTime.now());
                 lotFansMapper.insertLotFans(lotFans);
             }
         }else {
@@ -80,4 +101,83 @@ public class LotFansServiceImpl extends ServiceImpl<LotFansMapper,LotFans> imple
     public LotFans selectLotFansByLotIdAndType(Long lotId, String type) {
         return lotFansMapper.selectLotFansByLotIdAndType(lotId, type);
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean toggleFavorite(LotFansToggleRequest request) {
+        UserInfo userInfo = UserUtils.getSimpleUserInfo();
+        if (Objects.isNull(userInfo) || userInfo.getId() == -1) {
+            throw new ServiceException("用户未登录",-1);
+        }
+        // 获取用户ID
+        long userId = userInfo.getId().longValue();
+
+        if (request.getLotId() == null) {
+            log.error("lotId不能为空");
+            return Boolean.FALSE;
+        }
+
+        String type = "user_like";
+        Boolean isLike = request.getIsLike();
+        // 收藏
+        if (Boolean.TRUE.equals(isLike)) {
+            List<LotFans> lotFansList = lotFansMapper.selectLotFansList(LotFans.builder()
+                    .lotId(request.getLotId())
+                    .userId(userId)
+                    .type(type)
+                    .build()
+            );
+            if (CollectionUtils.isEmpty(lotFansList)) {
+                LotFans lotFans = LotFans.builder()
+                    .lotId(request.getLotId())
+                    .userId(userId)
+                    .type(type)
+                    // 过期时间往后退30天
+                    .expire(DateUtils.addDays(30))
+                    .createTime(LocalDateTime.now())
+                    .updateTime(LocalDateTime.now())
+                    .createUser(String.valueOf(userId))
+                    .updateUser(String.valueOf(userId))
+                    .build();
+                lotFansMapper.insertLotFans(lotFans);
+            }
+        } else { // 取消收藏
+            lotFansMapper.deleteLotFans(userId, request.getLotId(), type);
+        }
+        return true;
+    }
+
+    @Override
+    public List<LotFansResponse> page(LotFansTogglePageRequest request) {
+        Long userId = UserUtils.getSimpleUserInfo().getId().longValue();
+        if (Objects.isNull(userId) || userId == -1) {
+            throw new ServiceException("用户未登录",-1);
+        }
+        // 查询当前用户关注的拍品
+        LotFans lotFans = LotFans.builder()
+            .userId(userId)
+            .type("user_like")
+            .build();
+        IPage<LotFans> lotFansIPage =new Page<>(request.getPageNum(),request.getPageSize());
+        List<LotFans> lotFansList = lotFansMapper.selectLotFansPageList(lotFansIPage,lotFans);
+        if (CollectionUtils.isEmpty(lotFansList)) {
+            return Lists.newArrayList();
+        }
+        // 收集关注表中所有lotId,查询拍品信息
+        List<Long> lotIdList = lotFansList.stream().map(LotFans::getLotId).collect(Collectors.toList());
+        List<Lot> lotList = lotService.selectLotListByLotIds(lotIdList);
+        if (CollectionUtils.isEmpty(lotList)) {
+            return Lists.newArrayList();
+        }
+
+        List<LotFansResponse> lotFansResponses = lotList.stream().map(LotConvert.INSTANCE::toLotFansResponse).collect(Collectors.toList());
+        for (LotFansResponse lotFansRespons : lotFansResponses) {
+            // 起拍价
+            if (StringUtils.isNotEmpty(lotFansRespons.getRuleContent())) {
+                TraditionRule traditionRule = JSON.parseObject(lotFansRespons.getRuleContent(), TraditionRule.class);
+                lotFansRespons.setStartPrice(String.valueOf(traditionRule.getStartPrice()));
+            }
+        }
+        return lotFansResponses;
+    }
 }

+ 53 - 7
lot/src/main/java/cn/hobbystocks/auc/service/impl/LotServiceImpl.java

@@ -2,6 +2,7 @@ package cn.hobbystocks.auc.service.impl;
 
 import cn.hobbystocks.auc.cache.CacheMap;
 import cn.hobbystocks.auc.common.constant.Constants;
+import cn.hobbystocks.auc.common.core.domain.AjaxResult;
 import cn.hobbystocks.auc.common.core.redis.Locker;
 import cn.hobbystocks.auc.common.core.redis.RedisCache;
 import cn.hobbystocks.auc.common.core.text.Convert;
@@ -13,6 +14,7 @@ import cn.hobbystocks.auc.common.utils.CloneUtils;
 import cn.hobbystocks.auc.common.utils.DateUtils;
 import cn.hobbystocks.auc.common.utils.SensitiveDataUtils;
 import cn.hobbystocks.auc.common.utils.StringUtils;
+import cn.hobbystocks.auc.convert.LotConvert;
 import cn.hobbystocks.auc.domain.*;
 import cn.hobbystocks.auc.dto.LotExportDTO;
 import cn.hobbystocks.auc.event.ChangeEvent;
@@ -24,7 +26,9 @@ import cn.hobbystocks.auc.handle.context.Live;
 import cn.hobbystocks.auc.handle.context.LiveContext;
 import cn.hobbystocks.auc.handle.context.tradition.TraditionRule;
 import cn.hobbystocks.auc.mapper.*;
+import cn.hobbystocks.auc.request.LotQueryRequest;
 import cn.hobbystocks.auc.request.LotRequest;
+import cn.hobbystocks.auc.response.LotFansResponse;
 import cn.hobbystocks.auc.service.ILotService;
 import cn.hobbystocks.auc.task.DynamicTaskService;
 import cn.hobbystocks.auc.vo.LiveVO;
@@ -36,6 +40,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import lombok.extern.slf4j.Slf4j;
 
 import org.springframework.beans.BeanUtils;
@@ -80,6 +85,8 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
     private LotGroupMapper lotGroupMapper;
     @Autowired
     private LotFansMapper lotFansMapper;
+    @Autowired
+    private SpuCategoryMapper spuCategoryMapper;
 
     @Override
     public Lot selectLotById(Long id) {
@@ -210,7 +217,7 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
                 LotFans.builder()
                         .id(fans.getId())
                         .type("pay_expire")
-                        .expire(DateUtils.addDays(fans.getCreateTime(), 1))
+                        .expire(DateUtils.addDays(DateUtils.toDate(fans.getCreateTime()), 1))
                         .build());
         lotMapper.updateLot(Lot.builder().id(fans.getLotId()).status(Constants.LOT_STATUS_PASS).build());
     }
@@ -646,8 +653,42 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
     }
 
     @Override
-    public List<Lot> queryLotByCategory(Lot lot) {
-        return baseMapper.queryLotListByCategory(lot);
+    public List<LotFansResponse> queryLotByCategory(LotQueryRequest request) {
+        // 1. 构建最终要查询的分类ID
+        List<Long> categoryIds = Lists.newArrayList();
+
+        if (Objects.nonNull(request.getChildCategoryId())) {
+            // 传了二级分类 → 直接用
+            categoryIds.add(request.getChildCategoryId());
+        } else if (Objects.nonNull(request.getMainCategoryId())) {
+            // 只传一级 → 查询该一级下所有二级ID(单表查询)
+            categoryIds = spuCategoryMapper.listChildByParentId(request.getMainCategoryId());
+        }
+
+        // 2. 没有分类 → 返回空
+        if (CollectionUtils.isEmpty(categoryIds)) {
+            return Lists.newArrayList();
+        }
+
+        // 3. 查询拍品ID(单表)
+        List<Long> lotIds = spuCategoryMapper.listLotIdsByCategoryIds(categoryIds);
+
+        if (CollectionUtils.isEmpty(lotIds)) {
+            return Lists.newArrayList();
+        }
+
+        IPage<Lot> lotIPage =new Page<>(request.getPageNum(),request.getPageSize());
+        Lot lot = new Lot();
+        lot.setIds(lotIds);
+        lot.setName(request.getName());
+        lot.setPubStatus(request.getPubStatus());
+        lot.setStatus(request.getStatus());
+        lot.setStartTime(request.getStartTime());
+        lot.setEndTime(request.getEndTime());
+        lot.setRealEndTime(request.getRealEndTime());
+        List<Lot> diamondPositions = baseMapper.selectLotList(lotIPage, lot);
+        List<LotFansResponse> lotFansResponses = diamondPositions.stream().map(LotConvert.INSTANCE::toLotFansResponse).collect(Collectors.toList());
+        return lotFansResponses;
     }
 
     @Override
@@ -672,10 +713,10 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
             lotExportDTO.setBidCount(String.valueOf(l.getBidCount()));
             lotExportDTO.setPubStatus(PubStatusEnum.of(l.getPubStatus()).getDesc());
             lotExportDTO.setStatus(LotStatusEnum.of(l.getStatus()).getDesc());
-            lotExportDTO.setCreateTime(l.getCreateTime());
-            lotExportDTO.setStartTime(l.getStartTime());
-            lotExportDTO.setEndTime(l.getEndTime());
-            lotExportDTO.setDeposit(String.valueOf(l.getDeposit()));
+            lotExportDTO.setCreateTime(DateUtils.parseDateToStr(l.getCreateTime()));
+            lotExportDTO.setStartTime(DateUtils.parseDateToStr(l.getStartTime()));
+            lotExportDTO.setEndTime(DateUtils.parseDateToStr(l.getEndTime()));
+            lotExportDTO.setDeposit(String.valueOf(l.getDeposit() == null ? 0 : l.getDeposit()));
             lotExportDTO.setServiceTariff(String.valueOf(l.getServiceTariff()));
             lotExportDTO.setRuleType(RuleTypeEnum.getByCode(l.getRuleType()).getDesc());
             // 起拍价
@@ -688,4 +729,9 @@ public class LotServiceImpl extends ServiceImpl<LotMapper,Lot> implements ILotSe
 
         return lotExportDTOS;
     }
+
+    @Override
+    public List<Lot> selectLotListByLotIds(List<Long> lotIds) {
+        return baseMapper.selectLotListByLotIds(lotIds);
+    }
 }

+ 76 - 0
lot/src/main/java/cn/hobbystocks/auc/service/impl/SpuCategoryServiceImpl.java

@@ -0,0 +1,76 @@
+package cn.hobbystocks.auc.service.impl;
+
+import cn.hobbystocks.auc.common.utils.DateUtils;
+import cn.hobbystocks.auc.convert.DiamondPositionConvert;
+import cn.hobbystocks.auc.convert.SpuCategoryConvert;
+import cn.hobbystocks.auc.domain.DiamondPosition;
+import cn.hobbystocks.auc.domain.SpuCategory;
+import cn.hobbystocks.auc.mapper.DiamondPositionMapper;
+import cn.hobbystocks.auc.mapper.SpuCategoryMapper;
+import cn.hobbystocks.auc.request.CategoryQueryRequest;
+import cn.hobbystocks.auc.request.DiamondPositionPageRequest;
+import cn.hobbystocks.auc.request.DiamondPositionSaveRequest;
+import cn.hobbystocks.auc.response.DiamondPositionResponse;
+import cn.hobbystocks.auc.response.SpuChildCategoryResponse;
+import cn.hobbystocks.auc.response.SpuMainCategoryResponse;
+import cn.hobbystocks.auc.service.IDiamondPositionService;
+import cn.hobbystocks.auc.service.SpuCategoryService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Service
+@Slf4j
+public class SpuCategoryServiceImpl implements SpuCategoryService {
+
+    @Resource
+    private DiamondPositionMapper diamondPositionMapper;
+
+    @Resource
+    private SpuCategoryMapper spuCategoryMapper;
+
+    @Override
+    public List<SpuMainCategoryResponse> queryAllCategory(CategoryQueryRequest request) {
+        // 1. 查询所有启用的主分类
+        List<SpuCategory> mainCategoryList = spuCategoryMapper.selectAllMainCategory();
+        if (CollectionUtils.isEmpty(mainCategoryList)) {
+            return Lists.newArrayList();
+        }
+        List<SpuMainCategoryResponse> spuMainCategoryResponses = mainCategoryList.stream().map(SpuCategoryConvert.INSTANCE::toSpuMainCategoryResponse).collect(Collectors.toList());
+
+        // 2. 提取所有主分类ID,批量查询子分类
+        List<Long> mainCategoryIds = spuMainCategoryResponses.stream()
+            .map(SpuMainCategoryResponse::getCategoryId)
+            .collect(Collectors.toList());
+        List<SpuCategory> allChildCategoryList = spuCategoryMapper.selectChildCategoryByParentIds(mainCategoryIds);
+
+        // 3. 按主分类ID分组子分类
+        Map<Long, List<SpuCategory>> childCategoryMap = allChildCategoryList.stream()
+            .collect(Collectors.groupingBy(SpuCategory::getParentId)); // 注意:子分类VO需加parentId字段
+
+        // 4. 嵌套子分类到对应主分类
+        spuMainCategoryResponses.forEach(main -> {
+            List<SpuCategory> childList = childCategoryMap.getOrDefault(main.getCategoryId(), Lists.newArrayList());
+            // 子分类按排序号升序
+            childList.sort(Comparator.comparingInt(SpuCategory::getSort));
+            List<SpuChildCategoryResponse> spuChildCategoryResponses = childList.stream().map(SpuCategoryConvert.INSTANCE::toSpuChildCategoryResponse).collect(Collectors.toList());
+
+            main.setChildCategoryList(spuChildCategoryResponses);
+        });
+
+        // 5. 主分类按排序号升序
+        spuMainCategoryResponses.sort(Comparator.comparingInt(SpuMainCategoryResponse::getSort));
+        return spuMainCategoryResponses;
+    }
+}

+ 146 - 0
lot/src/main/resources/mapper/DiamondPositionMapper.xml

@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.hobbystocks.auc.mapper.DiamondPositionMapper">
+
+    <resultMap type="cn.hobbystocks.auc.domain.DiamondPosition" id="BaseResultMap">
+        <id     property="id"                   column="id"                   />
+        <result property="name"                 column="name"                 />
+        <result property="iconUrl"              column="icon_url"             />
+        <result property="type"                 column="type"                 />
+        <result property="jumpUrl"              column="jump_url"             />
+        <result property="jumpParams"           column="jump_params"          />
+        <result property="description"          column="description"          />
+        <result property="businessModule"       column="business_module"      />
+        <result property="version"              column="version"              />
+        <result property="status"               column="status"               />
+        <result property="remark"               column="remark"               />
+        <result property="createUser"           column="create_user"          />
+        <result property="createTime"           column="create_time"          />
+        <result property="updateUser"           column="update_user"          />
+        <result property="updateTime"           column="update_time"          />
+        <result property="delFlag"              column="del_flag"             />
+        <result property="effectiveStartTime"   column="effective_start_time"  />
+        <result property="effectiveEndTime"     column="effective_end_time"    />
+        <result property="sort"                 column="sort"                 />
+    </resultMap>
+
+    <sql id="baseColumnList">
+        select id, name, icon_url, type, jump_url, jump_params, description,
+               business_module, version, status, remark, create_user, create_time,
+               update_user, update_time, del_flag, effective_start_time, effective_end_time, sort
+        from t_diamond_position
+    </sql>
+
+
+
+    <select id="selectDiamondPositionById" parameterType="Long" resultMap="BaseResultMap">
+        <include refid="baseColumnList"/>
+        where id = #{id} and del_flag = 0
+    </select>
+
+    <select id="selectDiamondPositionList" parameterType="cn.hobbystocks.auc.domain.DiamondPosition" resultMap="BaseResultMap">
+        <include refid="baseColumnList"/>
+        <where>
+            del_flag = 0
+            <if test="request.name != null and request.name != ''">
+                AND name like concat('%', #{request.name}, '%')
+            </if>
+            <if test="request.type != null and request.type != ''">
+                AND type = #{request.type}
+            </if>
+            <if test="request.status != null">
+                AND status = #{request.status}
+            </if>
+        </where>
+        order by sort asc, create_time desc
+    </select>
+
+    <select id="selectActiveDiamondPositions" resultMap="BaseResultMap">
+        <include refid="baseColumnList"/>
+        <where>
+            del_flag = 0
+            AND status = 1
+            <if test="businessModule != null and businessModule != ''">
+                AND business_module = #{businessModule}
+            </if>
+            <if test="version != null and version != ''">
+                AND version = #{version}
+            </if>
+            AND (effective_start_time is null OR effective_start_time &lt;= CURRENT_TIMESTAMP)
+            AND (effective_end_time is null OR effective_end_time &gt;= CURRENT_TIMESTAMP)
+        </where>
+        order by sort asc
+    </select>
+
+    <insert id="insertDiamondPosition" parameterType="cn.hobbystocks.auc.domain.DiamondPosition" useGeneratedKeys="true" keyProperty="id">
+        insert into t_diamond_position
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="name != null and name != ''">name,</if>
+            <if test="iconUrl != null and iconUrl != ''">icon_url,</if>
+            <if test="type != null and type != ''">type,</if>
+            <if test="jumpUrl != null and jumpUrl != ''">jump_url,</if>
+            <if test="jumpParams != null and jumpParams != ''">jump_params,</if>
+            <if test="description != null and description != ''">description,</if>
+            <if test="businessModule != null and businessModule != ''">business_module,</if>
+            <if test="version != null and version != ''">version,</if>
+            <if test="status != null">status,</if>
+            <if test="remark != null and remark != ''">remark,</if>
+            <if test="createUser != null and createUser != ''">create_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateUser != null and updateUser != ''">update_user,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="delFlag != null">del_flag,</if>
+            <if test="effectiveStartTime != null">effective_start_time,</if>
+            <if test="effectiveEndTime != null">effective_end_time,</if>
+            <if test="sort != null">sort,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="name != null and name != ''">#{name},</if>
+            <if test="iconUrl != null and iconUrl != ''">#{iconUrl},</if>
+            <if test="type != null and type != ''">#{type},</if>
+            <if test="jumpUrl != null and jumpUrl != ''">#{jumpUrl},</if>
+            <if test="jumpParams != null and jumpParams != ''">#{jumpParams},</if>
+            <if test="description != null and description != ''">#{description},</if>
+            <if test="businessModule != null and businessModule != ''">#{businessModule},</if>
+            <if test="version != null and version != ''">#{version},</if>
+            <if test="status != null">#{status},</if>
+            <if test="remark != null and remark != ''">#{remark},</if>
+            <if test="createUser != null and createUser != ''">#{createUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateUser != null and updateUser != ''">#{updateUser},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="delFlag != null">#{delFlag},</if>
+            <if test="effectiveStartTime != null">#{effectiveStartTime},</if>
+            <if test="effectiveEndTime != null">#{effectiveEndTime},</if>
+            <if test="sort != null">#{sort},</if>
+        </trim>
+    </insert>
+
+    <update id="updateDiamondPosition" parameterType="cn.hobbystocks.auc.domain.DiamondPosition">
+        update t_diamond_position
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="name != null and name != ''">name = #{name},</if>
+            <if test="iconUrl != null">icon_url = #{iconUrl},</if>
+            <if test="type != null and type != ''">type = #{type},</if>
+            <if test="jumpUrl != null">jump_url = #{jumpUrl},</if>
+            <if test="jumpParams != null">jump_params = #{jumpParams},</if>
+            <if test="description != null">description = #{description},</if>
+            <if test="businessModule != null and businessModule != ''">business_module = #{businessModule},</if>
+            <if test="version != null and version != ''">version = #{version},</if>
+            <if test="status != null">status = #{status},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="updateUser != null and updateUser != ''">update_user = #{updateUser},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="effectiveStartTime != null">effective_start_time = #{effectiveStartTime},</if>
+            <if test="effectiveEndTime != null">effective_end_time = #{effectiveEndTime},</if>
+            <if test="sort != null">sort = #{sort},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <update id="deleteDiamondPositionById">
+        update t_diamond_position set del_flag = 1, update_user = #{updateUser}, update_time = CURRENT_TIMESTAMP
+        where id = #{id}
+    </update>
+
+</mapper>

+ 48 - 15
lot/src/main/resources/mapper/LotFansMapper.xml

@@ -4,35 +4,44 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="cn.hobbystocks.auc.mapper.LotFansMapper">
 
-    <resultMap type="LotFans" id="LotFansResult">
+    <resultMap type="LotFans" id="BaseResultMap">
         <result property="id"    column="id"    />
         <result property="userId"    column="user_id"    />
         <result property="lotId"    column="lot_id"    />
-        <result property="createTime"    column="create_time"    />
         <result property="type"    column="type"    />
         <result property="expire" column="expire"/>
         <result property="merchantId" column="merchant_id"/>
+        <result property="createUser" column="create_user"/>
+        <result property="updateUser" column="update_user"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
     </resultMap>
 
     <sql id="selectLotFansVo">
-        select id, user_id, lot_id, create_time, type, expire,merchant_id  from lot_fans
+        select id, user_id, lot_id, create_time, type, expire,merchant_id,update_time,create_user,update_user
     </sql>
 
-    <select id="selectLotFansList" parameterType="LotFans" resultMap="LotFansResult">
+    <select id="selectLotFansList" parameterType="LotFans" resultMap="BaseResultMap">
         <include refid="selectLotFansVo"/>
-        where del_flag = 0
-        <if test="lotId != null"> and lot_id = #{lotId}</if>
-        <if test="userId != null"> and user_id = #{userId}</if>
-        <if test="type != null"> and type = #{type}</if>
-        <if test="merchantId != null"> and merchant_id = #{merchantId}</if>
+        from
+            lot_fans
+        <where>
+            del_flag = 0
+            <if test="lotId != null"> and lot_id = #{lotId}</if>
+            <if test="userId != null"> and user_id = #{userId}</if>
+            <if test="type != null"> and type = #{type}</if>
+            <if test="merchantId != null"> and merchant_id = #{merchantId}</if>
+        </where>
     </select>
 
     <delete id="lotFansListCheck">
         delete from lot_fans where type = 'pay_expire' and expire &lt; NOW()
     </delete>
 
-    <select id="selectLotFansById" parameterType="Long" resultMap="LotFansResult">
+    <select id="selectLotFansById" parameterType="Long" resultMap="BaseResultMap">
         <include refid="selectLotFansVo"/>
+        from
+            lot_fans
         where id = #{id}
     </select>
 
@@ -42,19 +51,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="id != null">id,</if>
             <if test="userId != null">user_id,</if>
             <if test="lotId != null">lot_id,</if>
-            <if test="createTime != null">create_time,</if>
             <if test="type != null and type != ''">type,</if>
             <if test="expire != null">expire,</if>
             <if test="merchantId != null">merchant_id,</if>
+            <if test="createUser != null">create_user,</if>
+            <if test="updateUser != null">update_user,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateTime != null">update_time,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="userId != null">#{userId},</if>
             <if test="lotId != null">#{lotId},</if>
-            <if test="createTime != null">#{createTime},</if>
             <if test="type != null and type != ''">#{type},</if>
             <if test="expire != null">#{expire},</if>
             <if test="merchantId != null">#{merchantId},</if>
+            <if test="createUser != null">#{createUser},</if>
+            <if test="updateUser != null">#{updateUser},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateTime != null">#{updateTime},</if>
          </trim>
     </insert>
 
@@ -82,9 +97,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </delete>
 
-    <delete id="deleteLotFans">
-        delete from lot_fans where user_id = #{userId} and lot_id = #{lotId} and type = #{type}
-    </delete>
+    <update id="deleteLotFans">
+        update lot_fans set del_flag = 1 ,update_time = now() where user_id = #{userId} and lot_id = #{lotId} and type = #{type}
+    </update>
 
     <update id="updateLotFansDel">
         update lot_fans set del_flag = 1 where id = #{id}
@@ -92,6 +107,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectLotFansByLotIdAndType" resultType="cn.hobbystocks.auc.domain.LotFans">
         <include refid="selectLotFansVo"/>
+        from
+            lot_fans
         where lot_id = #{lotId} and type = #{type} and del_flag = 0
     </select>
+
+
+    <select id="selectLotFansPageList" parameterType="cn.hobbystocks.auc.domain.LotFans" resultMap="BaseResultMap">
+        <include refid="selectLotFansVo"/>
+        from
+            lot_fans
+        <where>
+            del_flag = 0
+            <if test="request.lotId != null"> and lot_id = #{request.lotId}</if>
+            <if test="request.userId != null"> and user_id = #{request.userId}</if>
+            <if test="request.type != null"> and type = #{request.type}</if>
+            <if test="request.merchantId != null"> and merchant_id = #{request.merchantId}</if>
+        </where>
+        order by create_time desc
+    </select>
+
 </mapper>

+ 20 - 0
lot/src/main/resources/mapper/LotMapper.xml

@@ -76,6 +76,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="lot.name != null  and lot.name != ''"> and name like concat('%', #{lot.name}, '%')</if>
             <if test="lot.pubStatus != null "> and pub_status  = #{lot.pubStatus}</if>
             <if test="lot.auctionId!=null">and auction_id=#{lot.auctionId}</if>
+            <if test="lot.ids != null and lot.ids.size() > 0">
+                and id in
+                <foreach item="id" collection="lot.ids" open="(" separator="," close=")">
+                    #{id}
+                </foreach>
+            </if>
+
         </where>
         order by sort desc,id desc
     </select>
@@ -513,4 +520,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             </if>
         </where>
     </select>
+    <select id="selectLotListByLotIds" resultType="cn.hobbystocks.auc.domain.Lot">
+        <include refid="selectLotVo"/>
+        <where>
+            del_flag = 0
+            <if test="lotIds != null and lotIds.size() > 0">
+                and id in
+                <foreach item="id" collection="lotIds" open="(" separator="," close=")">
+                    #{id}
+                </foreach>
+            </if>
+        </where>
+
+    </select>
 </mapper>

+ 118 - 0
lot/src/main/resources/mapper/SpuCategoryMapper.xml

@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.hobbystocks.auc.mapper.SpuCategoryMapper">
+
+    <resultMap type="cn.hobbystocks.auc.domain.SpuCategory" id="BaseResultMap">
+        <id     property="id"                   column="id"                   />
+        <result property="categoryName"                 column="category_name"                 />
+        <result property="isCascade"              column="is_cascade"             />
+        <result property="subLabel"                 column="sub_label"                 />
+        <result property="sort"              column="sort"             />
+        <result property="parentId"           column="parent_id"          />
+        <result property="iconUrl"          column="icon_url"          />
+        <result property="status"       column="status"      />
+        <result property="createTime"              column="create_time"              />
+        <result property="updateTime"               column="update_time"               />
+    </resultMap>
+
+
+    <sql id="baseColumnList">
+        select id,category_name,is_cascade, sub_label,sort,parent_id,icon_url,status,create_time,update_time from spu_category
+    </sql>
+
+
+    <select id="querySpuCategory" resultMap="BaseResultMap">
+        <include refid="baseColumnList"/>
+    </select>
+    <select id="getSpuSubCategory" resultMap="BaseResultMap">
+        <include refid="baseColumnList"/>
+        <where>
+            parent_id=#{id}
+        </where>
+    </select>
+
+
+    <select id="selectAllMainCategory" resultMap="BaseResultMap">
+
+        <include refid="baseColumnList"/>
+        <where>
+            AND parent_id = 0
+            AND status = 1
+            AND del_flag = 0
+        </where>
+    </select>
+
+    <select id="listChildByParentId" resultType="java.lang.Long">
+        SELECT id FROM spu_category
+        WHERE parent_id = #{mainCategoryId}
+        AND del_flag = 0
+        AND status = 1
+    </select>
+
+
+    <select id="selectChildCategoryByParentIds" resultType="cn.hobbystocks.auc.domain.SpuCategory">
+        <include refid="baseColumnList"/>
+        <where>
+            AND status = 1
+            AND del_flag = 0
+            AND parent_id IN
+            <foreach collection="list" item="parentId" open="(" separator="," close=")">
+                #{parentId}
+            </foreach>
+        </where>
+    </select>
+
+    <select id="listLotIdsByCategoryIds" resultType="java.lang.Long">
+        SELECT DISTINCT lot_id
+            FROM lot_category_relation
+        <where>
+            category_id IN
+            <foreach collection="categoryIds" item="categoryId" open="(" separator="," close=")">
+                #{categoryId}
+            </foreach>
+            AND del_flag = 0
+        </where>
+
+
+    </select>
+
+
+    <insert id="createCategory" parameterType="cn.hobbystocks.auc.domain.SpuCategory">
+        insert into spu_category (category_name,is_cascade,sub_label,sort,parent_id,icon_url,status,create_time,update_time)
+        values (#{categoryName},#{isCascade},#{subLabel},#{sort},#{parentId},#{iconUrl},#{status},#{createTime},#{updateTime})
+    </insert>
+
+    <update id="updateCategory">
+        update spu_category
+        <trim prefix="set" suffixOverrides=",">
+            <if test="categoryName!=null and categoryName!=''">
+                category_name=#{categoryName},
+            </if>
+            <if test="isCascade!=null">
+                is_cascade=#{isCascade},
+            </if>
+            <if test="subLabel!=null and subLabel!=''">
+                sub_label=#{subLabel},
+            </if>
+            <if test="sort!=null">
+                sort=#{sort},
+            </if>
+            <if test="parentId!=null">
+                parent_id=#{parentId},
+            </if>
+            <if test="iconUrl!=null and iconUrl!=''">
+                icon_url=#{iconUrl},
+            </if>
+            <if test="status!=null">
+                status=#{status},
+            </if>
+            <if test="updateTime!=null">
+                update_time=#{updateTime},
+            </if>
+
+        </trim>
+        where id=#{id}
+    </update>
+</mapper>