Skip to content

Commit 03de3d8

Browse files
committed
feat(client): 实现商品详情页用户收藏状态展示与收藏功能迁移
- 在商品详情接口中增加用户收藏状态的返回字段 - 从 ClientProductFavoriteController 迁移商品收藏接口至 ClientUserController - 优化文件服务图片上传逻辑,支持非JPG格式自动转换 - 调整管理员登录密码校验规则,允许6-20位字母数字组合 - 修复商品服务库存缓存后错误抛出问题 - 增加根据用户ID查询商品收藏状态的临时方案实现
1 parent cc50ca3 commit 03de3d8

9 files changed

Lines changed: 89 additions & 43 deletions

File tree

common/src/main/java/com/ligg/common/module/vo/ProductDetailVo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ public class ProductDetailVo extends ProductVo {
1919
private String description;
2020
private List<ProductImageVo> detailImages;
2121
private List<SpecVo> specs;
22+
private User user;
23+
24+
@Getter
25+
@Setter
26+
public static class User {
27+
private boolean favorite;
28+
}
2229
// private List<Images> images;
2330

2431
// @Getter

common/src/main/java/com/ligg/common/service/UserService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,9 @@ public interface UserService extends IService<UserEntity> {
5656
*/
5757
int productFavorite(Long productId, boolean isFavorite);
5858

59-
59+
/**
60+
* 根据用户id查询商品收藏是否已存在
61+
* 临时方案
62+
*/
63+
boolean isProductFavoriteByUserId(String productId, String userId);
6064
}

common/src/main/java/com/ligg/common/service/impl/FileServiceImpl.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public String uploadImage(MultipartFile imageFile, String path) {
5050
String originalFilename = imageFile.getOriginalFilename();
5151

5252
// 生成唯一文件名
53-
String uniqueFileName = UUID.randomUUID().toString().substring(0, 8) + '-' + originalFilename;
53+
String uniqueFileName = UUID.randomUUID().toString().substring(0, 8) + ".jpg";
5454

5555
//创建目录
5656
String datePath = java.time.LocalDate.now().toString();
@@ -62,8 +62,13 @@ public String uploadImage(MultipartFile imageFile, String path) {
6262
//构建文件完整路径
6363
Path filePath = directoryPath.resolve(uniqueFileName);
6464

65-
// 保存文件
66-
imageFile.transferTo(filePath);
65+
// 如果是JPG格式直接保存,否则进行转换
66+
if (isJpegImage(contentType, originalFilename)) {
67+
imageFile.transferTo(filePath);
68+
} else {
69+
// 转换为JPG格式
70+
convertToJpeg(imageFile, filePath);
71+
}
6772

6873
return Constant.IMAGE_RELATIVE_PATH + typePath + '/' + datePath + '/' + uniqueFileName;
6974
} catch (IOException e) {
@@ -97,6 +102,26 @@ public StreamingResponseBody getImageInputStream(String path, String type, Strin
97102
};
98103
}
99104

105+
/**
106+
* 判断是否为JPEG图片
107+
*/
108+
private boolean isJpegImage(String contentType, String filename) {
109+
return "image/jpeg".equals(contentType) ||
110+
(filename != null && (filename.toLowerCase().endsWith(".jpg") || filename.toLowerCase().endsWith(".jpeg")));
111+
}
112+
113+
/**
114+
* 转换图片为JPG格式
115+
*/
116+
private void convertToJpeg(MultipartFile imageFile, Path targetPath) throws IOException {
117+
try (InputStream inputStream = imageFile.getInputStream()) {
118+
Thumbnails.of(inputStream)
119+
.scale(1.0) // 保持原尺寸
120+
.outputFormat("jpg")
121+
.toFile(targetPath.toFile());
122+
}
123+
}
124+
100125
/**
101126
* 获取图片输入流
102127
*

common/src/main/java/com/ligg/common/service/impl/UserServiceImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,21 @@ public int productFavorite(Long productId, boolean isFavorite) {
215215
}
216216
}
217217

218+
/**
219+
* 根据用户id查询商品收藏是否已存在
220+
* 临时方案
221+
*/
222+
@Override
223+
public boolean isProductFavoriteByUserId(String productId, String userId) {
224+
return productFavoriteMapper.selectOne(new LambdaQueryWrapper<ProductFavoriteEntity>()
225+
.eq(ProductFavoriteEntity::getProductId, productId)
226+
.eq(ProductFavoriteEntity::getUserId, userId)) != null;
227+
}
228+
218229

219230
private UserEntity getRedisUserInfo(String userId) {
220231
return (UserEntity) redisUtil.get(UserConstant.USER_INFO + ":" + userId);
221232
}
233+
234+
222235
}

common/src/main/java/com/ligg/common/service/impl/product/ProductServiceImpl.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public void saveFeatured(ProductEntity product) {
3535
//商品库存缓存没有过期时间
3636
redisUtil.set(ProductConstant.STOCK_KEY_PREFIX + product.getId(), product.getStock());
3737
}
38-
throw new RuntimeException(String.valueOf(BusinessStates.INTERNAL_SERVER_ERROR));
3938
}
4039

4140
/**

web/api-admin/src/main/java/com/ligg/apiadmin/controller/AdminAuthController.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
import com.ligg.common.utils.Response;
1313
import io.swagger.v3.oas.annotations.media.Schema;
1414
import io.swagger.v3.oas.annotations.tags.Tag;
15+
import jakarta.validation.Valid;
1516
import jakarta.validation.constraints.Email;
1617
import jakarta.validation.constraints.NotNull;
1718
import jakarta.validation.constraints.Pattern;
1819
import lombok.RequiredArgsConstructor;
20+
import org.springframework.validation.annotation.Validated;
1921
import org.springframework.web.bind.annotation.PostMapping;
2022
import org.springframework.web.bind.annotation.RequestMapping;
2123
import org.springframework.web.bind.annotation.RequestParam;
@@ -24,6 +26,7 @@
2426
/**
2527
* 账户接口
2628
*/
29+
@Validated
2730
@Tag(name = "账户接口")
2831
@RestController
2932
@RequestMapping("/api/admin/auth")
@@ -56,7 +59,7 @@ public Response<String> register(@Schema(description = "账号") @NotNull String
5659
*/
5760
@PostMapping("/login")
5861
public Response<String> login(@Schema(description = "邮箱") @RequestParam @NotNull @Email(message = "邮箱格式错误") String email,
59-
@Schema(description = "密码") @Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z\\d]{6,30}$", message = "密码格式错误") @RequestParam @NotNull String password) {
62+
@Schema(description = "密码") @Pattern(regexp = "^[a-zA-Z0-9]{6,20}$", message = "密码格式错误") @RequestParam @NotNull String password) {
6063
UserEntity userInfo = userService.getUserInfoByEmail(email);
6164
if (userInfo == null || !BCryptUtil.verify(password, userInfo.getPassword())) {
6265
return Response.error(BusinessStates.FORBIDDEN, "账号或密码错误");

web/api-client/src/main/java/com/ligg/apiclient/controller/ClientProductController.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66

77
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
88
import com.ligg.apiclient.pojo.vo.TagVo;
9+
import com.ligg.common.constants.UserConstant;
910
import com.ligg.common.enums.SearchSorting;
11+
import com.ligg.common.mapper.UserMapper;
1012
import com.ligg.common.module.entity.ProductEntity;
1113
import com.ligg.common.module.entity.ProductDetailEntity;
1214
import com.ligg.common.module.entity.ProductImageEntity;
1315
import com.ligg.common.module.vo.*;
1416
import com.ligg.common.module.vo.search.SearchVo;
17+
import com.ligg.common.service.UserService;
1518
import com.ligg.common.service.product.ProductCommentService;
1619
import com.ligg.common.service.product.ProductImageService;
1720
import com.ligg.common.service.product.ProductService;
@@ -20,10 +23,12 @@
2023
import com.ligg.common.service.SpecService;
2124
import com.ligg.common.utils.DiscountUtil;
2225
import com.ligg.common.utils.ImageUtil;
26+
import com.ligg.common.utils.JWTUtil;
2327
import com.ligg.common.utils.Response;
2428
import io.swagger.v3.oas.annotations.Operation;
2529
import io.swagger.v3.oas.annotations.media.Schema;
2630
import io.swagger.v3.oas.annotations.tags.Tag;
31+
import jakarta.servlet.http.HttpServletRequest;
2732
import jakarta.validation.constraints.Max;
2833
import jakarta.validation.constraints.Min;
2934
import jakarta.validation.constraints.NotNull;
@@ -33,6 +38,7 @@
3338
import org.springframework.web.bind.annotation.*;
3439

3540
import java.util.List;
41+
import java.util.Map;
3642
import java.util.concurrent.ThreadLocalRandom;
3743

3844
/**
@@ -54,6 +60,9 @@ public class ClientProductController {
5460

5561
private final ProductImageService productImageService;
5662

63+
private final HttpServletRequest request;
64+
private final UserService userService;
65+
5766
/**
5867
* 获取商品分页列表
5968
*/
@@ -118,10 +127,23 @@ public Response<ProductDetailVo> getFeaturedDetail(@Schema(description = "商品
118127
List<SpecVo> specVoList = specService.getSpecDetailByProductId(productId);
119128
featuredDetailVo.setSpecs(specVoList);
120129

130+
/*
131+
* 用户信息
132+
* 临时方案
133+
*/
134+
String authorization = request.getHeader("Authorization");
135+
if (authorization != null) {
136+
Map<String, Object> userInfo = JWTUtil.parseToken(authorization);
137+
String userId = (String) userInfo.get(UserConstant.USER_ID);
138+
ProductDetailVo.User user = new ProductDetailVo.User();
139+
user.setFavorite(userService.isProductFavoriteByUserId(productId, userId));
140+
featuredDetailVo.setUser(user);
141+
}
142+
121143
//阅览数++
122144
productService.lambdaUpdate()
123145
.eq(ProductEntity::getId, productId)
124-
.setIncrBy(ProductEntity::getViews, ThreadLocalRandom.current().nextInt(10,21))
146+
.setIncrBy(ProductEntity::getViews, ThreadLocalRandom.current().nextInt(10, 21))
125147
.update();
126148
return Response.success(BusinessStates.SUCCESS, featuredDetailVo);
127149
}

web/api-client/src/main/java/com/ligg/apiclient/controller/ClientProductFavoriteController.java

Lines changed: 0 additions & 36 deletions
This file was deleted.

web/api-client/src/main/java/com/ligg/apiclient/controller/ClientUserController.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.ligg.common.module.vo.UserInfoVo;
1717
import io.swagger.v3.oas.annotations.Operation;
1818
import io.swagger.v3.oas.annotations.tags.Tag;
19+
import jakarta.validation.constraints.NotNull;
1920
import lombok.RequiredArgsConstructor;
2021
import lombok.extern.slf4j.Slf4j;
2122
import org.springframework.beans.BeanUtils;
@@ -120,4 +121,12 @@ public Response<String> recharge(@RequestBody PaymentDto payment) {
120121
? Response.error(BusinessStates.INTERNAL_SERVER_ERROR)
121122
: Response.success(BusinessStates.SUCCESS);
122123
}
124+
125+
@Operation(summary = "商品收藏")
126+
@PostMapping("/favorite")
127+
public Response<String> productFavorite(@NotNull Long productId, @NotNull boolean isFavorite) {
128+
return userService.productFavorite(productId, isFavorite) < 1
129+
? Response.error(BusinessStates.INTERNAL_SERVER_ERROR)
130+
: Response.success(BusinessStates.SUCCESS);
131+
}
123132
}

0 commit comments

Comments
 (0)