diff --git a/src/main/java/com/aida/seller/common/config/WatermarkProperties.java b/src/main/java/com/aida/seller/common/config/WatermarkProperties.java index 04d97f1..04b31a5 100644 --- a/src/main/java/com/aida/seller/common/config/WatermarkProperties.java +++ b/src/main/java/com/aida/seller/common/config/WatermarkProperties.java @@ -17,7 +17,9 @@ public class WatermarkProperties { private int rotationDegrees = -30; - private float spacingRatio = 1.5f; + private float spacingRatioX = 1.67f; + + private float spacingRatioY = 0.9f; private int ttlDays = 30; diff --git a/src/main/java/com/aida/seller/common/context/UserContext.java b/src/main/java/com/aida/seller/common/context/UserContext.java index 2290cd8..3b54b47 100644 --- a/src/main/java/com/aida/seller/common/context/UserContext.java +++ b/src/main/java/com/aida/seller/common/context/UserContext.java @@ -52,4 +52,15 @@ public class UserContext { } return holder.getId(); } + + public static Long getBuyerIdSafely() { + AuthPrincipalVo holder = userHolder.get(); + if (holder == null) { + return null; + } + if (!"BUYER".equals(holder.getSource())) { + return null; + } + return holder.getId(); + } } diff --git a/src/main/java/com/aida/seller/module/listing/service/ListingServiceImpl.java b/src/main/java/com/aida/seller/module/listing/service/ListingServiceImpl.java index ad6ac0c..5bdab78 100644 --- a/src/main/java/com/aida/seller/module/listing/service/ListingServiceImpl.java +++ b/src/main/java/com/aida/seller/module/listing/service/ListingServiceImpl.java @@ -13,6 +13,8 @@ import com.aida.seller.module.listing.enums.ProductCategoryEnum; import com.aida.seller.module.listing.mapper.ListingImageMapper; import com.aida.seller.module.listing.mapper.ListingMapper; import com.aida.seller.module.listing.vo.ListingPageVO; +import com.aida.seller.module.order.mapper.OrderItemMapper; +import com.aida.seller.module.order.entity.OrderItemEntity; import com.aida.seller.util.MinioUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -27,6 +29,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -41,6 +44,7 @@ import java.util.stream.Collectors; public class ListingServiceImpl extends ServiceImpl implements ListingService { private final ListingImageMapper listingImageMapper; + private final OrderItemMapper orderItemMapper; private final RedisTemplate redisTemplate; private final MinioUtil minioUtil; @@ -323,6 +327,51 @@ public class ListingServiceImpl extends ServiceImpl vo.setProductStatus(2)); + return result; + } + Map orderStatusMap = getListingOrderStatusMap( + result.getRecords().stream().map(ListingPageVO::getId).collect(Collectors.toList()), + buyerId + ); + for (ListingPageVO vo : result.getRecords()) { + Integer orderStatus = orderStatusMap.get(vo.getId()); + if (orderStatus == null) { + vo.setProductStatus(2); + } else if (orderStatus == 1) { + vo.setProductStatus(1); + } else if (orderStatus == 0) { + vo.setProductStatus(0); + } else { + vo.setProductStatus(2); + } + } + + return result; + } + + private Map getListingOrderStatusMap(List listingIds, Long buyerId) { + if (CollectionUtils.isEmpty(listingIds) || buyerId == null) { + return Collections.emptyMap(); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(OrderItemEntity::getListingId, listingIds); + queryWrapper.eq(OrderItemEntity::getBuyerId, buyerId); + queryWrapper.eq(OrderItemEntity::getDeleted, 0); + List items = orderItemMapper.selectList(queryWrapper); + if (CollectionUtils.isEmpty(items)) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + for (OrderItemEntity item : items) { + Integer current = result.get(item.getListingId()); + if (current == null || (item.getStatus() == 1 && current != 1)) { + result.put(item.getListingId(), item.getStatus()); + } + } return result; } } diff --git a/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java b/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java index e9fa2d9..03fc7bd 100644 --- a/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java +++ b/src/main/java/com/aida/seller/module/listing/service/impl/ListingMallServiceImpl.java @@ -1,6 +1,7 @@ package com.aida.seller.module.listing.service.impl; import com.aida.seller.common.constants.CommonConstants; +import com.aida.seller.common.context.UserContext; import com.aida.seller.common.exception.BusinessException; import com.aida.seller.module.designer.entity.DesignerEntity; import com.aida.seller.module.designer.mapper.DesignerMapper; @@ -13,8 +14,10 @@ import com.aida.seller.module.listing.mapper.ListingImageMapper; import com.aida.seller.module.listing.mapper.ListingMallMapper; import com.aida.seller.module.listing.vo.ListingDetailVO; import com.aida.seller.module.listing.vo.ListingMallVO; +import com.aida.seller.module.order.entity.OrderItemEntity; import com.aida.seller.module.order.entity.OrderItemImageEntity; import com.aida.seller.module.order.mapper.OrderItemImageMapper; +import com.aida.seller.module.order.mapper.OrderItemMapper; import com.aida.seller.util.ImageWatermarkUtil; import com.aida.seller.util.MinioUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -26,8 +29,10 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Collections; import java.util.stream.Collectors; import com.aida.seller.module.listing.vo.ListingMallVO; @@ -43,14 +48,16 @@ public class ListingMallServiceImpl extends ServiceImpl result = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); - result.setRecords(records.stream().map(entity -> { + List voList = records.stream().map(entity -> { DesignerEntity designer = designerMap.get(entity.getSellerId()); ListingMallVO vo = new ListingMallVO(); vo.setId(entity.getId()); @@ -123,10 +130,54 @@ public class ListingMallServiceImpl extends ServiceImpl listingIds = voList.stream().map(ListingMallVO::getId).collect(Collectors.toList()); + Map orderStatusMap = getListingOrderStatusMap(listingIds, buyerId); + for (ListingMallVO vo : voList) { + Integer orderStatus = orderStatusMap.get(vo.getId()); + if (orderStatus == null) { + vo.setProductStatus(2); + } else if (orderStatus == 1) { + vo.setProductStatus(1); + } else if (orderStatus == 0) { + vo.setProductStatus(0); + } else { + vo.setProductStatus(2); + } + } + } else { + voList.forEach(vo -> vo.setProductStatus(2)); + } + + result.setRecords(voList); return result; } + private Map getListingOrderStatusMap(List listingIds, Long buyerId) { + if (CollectionUtils.isEmpty(listingIds) || buyerId == null) { + return Collections.emptyMap(); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(OrderItemEntity::getListingId, listingIds); + queryWrapper.eq(OrderItemEntity::getBuyerId, buyerId); + queryWrapper.eq(OrderItemEntity::getDeleted, 0); + List items = orderItemMapper.selectList(queryWrapper); + if (CollectionUtils.isEmpty(items)) { + return Collections.emptyMap(); + } + Map resultMap = new HashMap<>(); + for (OrderItemEntity item : items) { + Integer current = resultMap.get(item.getListingId()); + if (current == null || (item.getStatus() == 1 && current != 1)) { + resultMap.put(item.getListingId(), item.getStatus()); + } + } + return resultMap; + } + private void applySorting(LambdaQueryWrapper queryWrapper, String sortField, String sortOrder) { if (!StringUtils.hasText(sortField)) { queryWrapper.orderByDesc(ListingEntity::getUpdateTime); @@ -219,6 +270,28 @@ public class ListingMallServiceImpl extends ServiceImpl() + .eq(OrderItemEntity::getListingId, id) + .eq(OrderItemEntity::getBuyerId, buyerId) + .eq(OrderItemEntity::getDeleted, 0) + .last("LIMIT 1")); + Integer orderStatus = orderItem != null ? orderItem.getStatus() : null; + if (orderStatus == null) { + vo.setProductStatus(2); + } else if (orderStatus == 1) { + vo.setProductStatus(1); + } else if (orderStatus == 0) { + vo.setProductStatus(0); + } else { + vo.setProductStatus(2); + } + } + List apparelUrls = imageMap.get("apparel"); if (!CollectionUtils.isEmpty(apparelUrls)) { List watermarkedUrls = apparelUrls.parallelStream() diff --git a/src/main/java/com/aida/seller/module/listing/vo/ListingDetailVO.java b/src/main/java/com/aida/seller/module/listing/vo/ListingDetailVO.java index ccab649..97baab4 100644 --- a/src/main/java/com/aida/seller/module/listing/vo/ListingDetailVO.java +++ b/src/main/java/com/aida/seller/module/listing/vo/ListingDetailVO.java @@ -55,4 +55,7 @@ public class ListingDetailVO implements Serializable { /** 卖家ID */ private Long sellerId; + + /** 商品状态:0-已下单未付款,1-已购买,2-未下单 */ + private Integer productStatus; } diff --git a/src/main/java/com/aida/seller/module/listing/vo/ListingMallVO.java b/src/main/java/com/aida/seller/module/listing/vo/ListingMallVO.java index 3fa568e..c460bca 100644 --- a/src/main/java/com/aida/seller/module/listing/vo/ListingMallVO.java +++ b/src/main/java/com/aida/seller/module/listing/vo/ListingMallVO.java @@ -39,4 +39,7 @@ public class ListingMallVO implements Serializable { /** 销量 */ private Integer salesVolume; + + /** 商品状态:0-已下单未付款,1-已购买,2-未下单 */ + private Integer productStatus; } diff --git a/src/main/java/com/aida/seller/module/listing/vo/ListingPageVO.java b/src/main/java/com/aida/seller/module/listing/vo/ListingPageVO.java index cd905da..9e2f290 100644 --- a/src/main/java/com/aida/seller/module/listing/vo/ListingPageVO.java +++ b/src/main/java/com/aida/seller/module/listing/vo/ListingPageVO.java @@ -37,4 +37,7 @@ public class ListingPageVO implements Serializable { /** 浏览量 */ private Integer viewCount; + + /** 商品状态:0-已下单未付款,1-已购买,2-未下单 */ + private Integer productStatus; } diff --git a/src/main/java/com/aida/seller/module/order/entity/OrderItemEntity.java b/src/main/java/com/aida/seller/module/order/entity/OrderItemEntity.java index 7afe2d0..fc1df75 100644 --- a/src/main/java/com/aida/seller/module/order/entity/OrderItemEntity.java +++ b/src/main/java/com/aida/seller/module/order/entity/OrderItemEntity.java @@ -59,4 +59,7 @@ public class OrderItemEntity implements Serializable { /** 商品分类列表 */ @TableField(typeHandler = JacksonTypeHandler.class) private List productCategory; + + /** 商品状态:0-未支付,1-已支付,2-已取消 */ + private Integer status; } diff --git a/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java b/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java index 22555b8..3a58610 100644 --- a/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java +++ b/src/main/java/com/aida/seller/module/order/service/OrderServiceImpl.java @@ -106,7 +106,7 @@ public class OrderServiceImpl extends ServiceImpl images = listingImageMapper.selectList( @@ -357,24 +358,30 @@ public class OrderServiceImpl extends ServiceImpl targetOrderIds; - if (dto.getOrderIds() != null && !dto.getOrderIds().isEmpty()) { - targetOrderIds = dto.getOrderIds(); - } else if (dto.getPaymentId() != null) { - LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); - qw.eq(OrderInfoEntity::getPaymentId, dto.getPaymentId()); - targetOrderIds = this.list(qw).stream() - .map(OrderInfoEntity::getId) - .collect(Collectors.toList()); - } else { - targetOrderIds = Collections.emptyList(); - } + List targetOrderIds; + if (dto.getOrderIds() != null && !dto.getOrderIds().isEmpty()) { + targetOrderIds = dto.getOrderIds(); + } else if (dto.getPaymentId() != null) { + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(OrderInfoEntity::getPaymentId, dto.getPaymentId()); + targetOrderIds = this.list(qw).stream() + .map(OrderInfoEntity::getId) + .collect(Collectors.toList()); + } else { + targetOrderIds = Collections.emptyList(); + } - if (!targetOrderIds.isEmpty()) { - orderItemMapper.incrementSalesVolumeByOrderIds(targetOrderIds); - log.info("[Order] SalesVolume incremented for orderIds: {}", targetOrderIds); - } + if (!targetOrderIds.isEmpty()) { + LambdaUpdateWrapper itemUpdateWrapper = new LambdaUpdateWrapper<>(); + itemUpdateWrapper.in(OrderItemEntity::getOrderId, targetOrderIds) + .set(OrderItemEntity::getStatus, dto.getStatus()); + orderItemMapper.update(null, itemUpdateWrapper); + log.info("[Order] Item status synced for orderIds: {}", targetOrderIds); + } + + if (dto.getStatus() != null && dto.getStatus() == 1) { + orderItemMapper.incrementSalesVolumeByOrderIds(targetOrderIds); + log.info("[Order] SalesVolume incremented for orderIds: {}", targetOrderIds); } } } diff --git a/src/main/java/com/aida/seller/util/ImageWatermarkUtil.java b/src/main/java/com/aida/seller/util/ImageWatermarkUtil.java index f370e56..f98ba9f 100644 --- a/src/main/java/com/aida/seller/util/ImageWatermarkUtil.java +++ b/src/main/java/com/aida/seller/util/ImageWatermarkUtil.java @@ -83,7 +83,7 @@ public class ImageWatermarkUtil { g2d.drawImage(original, 0, 0, width, height, null); int baseFontSize = Math.max(12, (int) (Math.min(width, height) * watermarkProperties.getFontSizeRatio())); - Font font = new Font("Arial", Font.BOLD, baseFontSize); + Font font = new Font("Arial", Font.PLAIN, baseFontSize); g2d.setFont(font); int[] rgba = watermarkProperties.getColorComponents(); @@ -92,8 +92,8 @@ public class ImageWatermarkUtil { g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); double radians = Math.toRadians(watermarkProperties.getRotationDegrees()); - int stepX = (int) (baseFontSize * watermarkProperties.getSpacingRatio()); - int stepY = (int) (baseFontSize * watermarkProperties.getSpacingRatio()); + int stepX = (int) (baseFontSize * watermarkProperties.getSpacingRatioX()); + int stepY = (int) (baseFontSize * watermarkProperties.getSpacingRatioY()); AffineTransform rotateTransform = new AffineTransform(); rotateTransform.translate(width / 2.0, height / 2.0); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e157c97..005c032 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -33,10 +33,11 @@ minio: watermark: apparel: text: "AiDA" - font-size-ratio: 0.05 - color: "80,80,80,180" - rotation-degrees: -30 - spacing-ratio: 3.0 + font-size-ratio: 0.053 + color: "194,194,194,107" + rotation-degrees: 45 + spacing-ratio-x: 3.6 + spacing-ratio-y: 2.5 ttl-days: 30 bucket-name: "aida-user" diff --git a/src/main/resources/db/schema.sql b/src/main/resources/db/schema.sql index 8bf0b16..d3ed906 100644 --- a/src/main/resources/db/schema.sql +++ b/src/main/resources/db/schema.sql @@ -93,6 +93,7 @@ CREATE TABLE seller_order_item ( create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', deleted INT(1) DEFAULT 0 COMMENT '是否删除:0-否,1-是', product_category JSON COMMENT '商品分类列表', + status TINYINT DEFAULT 0 COMMENT '商品状态:0-未支付,1-已支付,2-已取消', INDEX idx_order_id (order_id), INDEX idx_listing_id (listing_id), INDEX idx_deleted (deleted) diff --git a/src/main/resources/mapper/OrderItemImageMapper.xml b/src/main/resources/mapper/OrderItemImageMapper.xml index 3c3c46f..5b42f8b 100644 --- a/src/main/resources/mapper/OrderItemImageMapper.xml +++ b/src/main/resources/mapper/OrderItemImageMapper.xml @@ -12,12 +12,12 @@ soi.listing_id AS listingId, soi.buyer_id AS buyerId FROM seller_order_item_image soi - INNER JOIN seller_orders so ON soi.order_id = so.id + INNER JOIN seller_order_item oi ON soi.order_item_id = oi.id WHERE soi.listing_id = #{listingId} AND soi.buyer_id = #{buyerId} AND soi.deleted = 0 - AND so.deleted = 0 - AND so.status = 1 + AND oi.deleted = 0 + AND oi.status = 1 ORDER BY soi.sort_order ASC diff --git a/src/main/resources/mapper/OrderItemMapper.xml b/src/main/resources/mapper/OrderItemMapper.xml index e13b2d5..18d7669 100644 --- a/src/main/resources/mapper/OrderItemMapper.xml +++ b/src/main/resources/mapper/OrderItemMapper.xml @@ -15,7 +15,7 @@ WHERE soi.deleted = 0 AND so.deleted = 0 AND so.buyer_id = #{dto.buyerId} - AND so.status = 1 + AND soi.status = 1 AND ( @@ -38,7 +38,7 @@ WHERE soi.deleted = 0 AND so.deleted = 0 AND so.buyer_id = #{dto.buyerId} - AND so.status = 1 + AND soi.status = 1 AND (