|
@@ -225,6 +225,10 @@ wrapper.in(Product::getId, productIds)
|
|
|
if (query.getKeyword() != null && !query.getKeyword().isEmpty()) {
|
|
if (query.getKeyword() != null && !query.getKeyword().isEmpty()) {
|
|
|
wrapper.like(Product::getName, query.getKeyword());
|
|
wrapper.like(Product::getName, query.getKeyword());
|
|
|
}
|
|
}
|
|
|
|
|
+ // 营养标签筛选:逗号分隔标签中任一命中即返回(NULL/空=不限)
|
|
|
|
|
+ if (query.getNutritionTag() != null && !query.getNutritionTag().trim().isEmpty()) {
|
|
|
|
|
+ wrapper.like(Product::getNutritionTags, query.getNutritionTag().trim());
|
|
|
|
|
+ }
|
|
|
SortUtil.applySort(wrapper);
|
|
SortUtil.applySort(wrapper);
|
|
|
IPage<Product> result = productMapper.selectPage(page, wrapper);
|
|
IPage<Product> result = productMapper.selectPage(page, wrapper);
|
|
|
boolean isGuest = (userId == null);
|
|
boolean isGuest = (userId == null);
|
|
@@ -619,9 +623,23 @@ wrapper.in(Product::getId, productIds)
|
|
|
// updateById 默认忽略 null 字段:clearable 下拉清空后需显式置 NULL
|
|
// updateById 默认忽略 null 字段:clearable 下拉清空后需显式置 NULL
|
|
|
boolean clearCategory = product.getCategoryId() == null;
|
|
boolean clearCategory = product.getCategoryId() == null;
|
|
|
boolean clearDistributionSystem = product.getDistributionSystemId() == null;
|
|
boolean clearDistributionSystem = product.getDistributionSystemId() == null;
|
|
|
|
|
+ // 营养数据字段为 nullable 且允许清空:管理端清空输入框后需显式置 NULL,
|
|
|
|
|
+ // 否则 updateById 忽略 null 会残留旧值;空串营养标签同样规整为 NULL。
|
|
|
|
|
+ // 仅当原记录确实有值时才需要清空,避免每次编辑都多打一条无意义的 UPDATE。
|
|
|
|
|
+ boolean clearCalories = existing.getCaloriesKcal() != null && product.getCaloriesKcal() == null;
|
|
|
|
|
+ boolean clearProtein = existing.getProteinG() != null && product.getProteinG() == null;
|
|
|
|
|
+ boolean clearFat = existing.getFatG() != null && product.getFatG() == null;
|
|
|
|
|
+ boolean clearCarb = existing.getCarbG() != null && product.getCarbG() == null;
|
|
|
|
|
+ boolean clearFiber = existing.getFiberG() != null && product.getFiberG() == null;
|
|
|
|
|
+ if (product.getNutritionTags() != null && product.getNutritionTags().trim().isEmpty()) {
|
|
|
|
|
+ product.setNutritionTags(null);
|
|
|
|
|
+ }
|
|
|
|
|
+ boolean clearNutritionTags = existing.getNutritionTags() != null && product.getNutritionTags() == null;
|
|
|
productMapper.updateById(product);
|
|
productMapper.updateById(product);
|
|
|
nutritionProductService.syncFromProduct(product);
|
|
nutritionProductService.syncFromProduct(product);
|
|
|
- if (clearMinVisibleLevel || clearCategory || clearDistributionSystem) {
|
|
|
|
|
|
|
+ if (clearMinVisibleLevel || clearCategory || clearDistributionSystem
|
|
|
|
|
+ || clearCalories || clearProtein || clearFat || clearCarb || clearFiber
|
|
|
|
|
+ || clearNutritionTags) {
|
|
|
LambdaUpdateWrapper<Product> clearWrapper = new LambdaUpdateWrapper<Product>()
|
|
LambdaUpdateWrapper<Product> clearWrapper = new LambdaUpdateWrapper<Product>()
|
|
|
.eq(Product::getId, product.getId());
|
|
.eq(Product::getId, product.getId());
|
|
|
if (clearMinVisibleLevel) {
|
|
if (clearMinVisibleLevel) {
|
|
@@ -633,6 +651,24 @@ wrapper.in(Product::getId, productIds)
|
|
|
if (clearDistributionSystem) {
|
|
if (clearDistributionSystem) {
|
|
|
clearWrapper.set(Product::getDistributionSystemId, null);
|
|
clearWrapper.set(Product::getDistributionSystemId, null);
|
|
|
}
|
|
}
|
|
|
|
|
+ if (clearCalories) {
|
|
|
|
|
+ clearWrapper.set(Product::getCaloriesKcal, null);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (clearProtein) {
|
|
|
|
|
+ clearWrapper.set(Product::getProteinG, null);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (clearFat) {
|
|
|
|
|
+ clearWrapper.set(Product::getFatG, null);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (clearCarb) {
|
|
|
|
|
+ clearWrapper.set(Product::getCarbG, null);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (clearFiber) {
|
|
|
|
|
+ clearWrapper.set(Product::getFiberG, null);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (clearNutritionTags) {
|
|
|
|
|
+ clearWrapper.set(Product::getNutritionTags, null);
|
|
|
|
|
+ }
|
|
|
productMapper.update(null, clearWrapper);
|
|
productMapper.update(null, clearWrapper);
|
|
|
}
|
|
}
|
|
|
return Result.success(ProductDTO.from(productMapper.selectById(product.getId())));
|
|
return Result.success(ProductDTO.from(productMapper.selectById(product.getId())));
|
|
@@ -731,6 +767,12 @@ wrapper.in(Product::getId, productIds)
|
|
|
copy.setSortOrder(original.getSortOrder());
|
|
copy.setSortOrder(original.getSortOrder());
|
|
|
copy.setVisibleRoles(original.getVisibleRoles());
|
|
copy.setVisibleRoles(original.getVisibleRoles());
|
|
|
copy.setMinVisibleLevel(original.getMinVisibleLevel());
|
|
copy.setMinVisibleLevel(original.getMinVisibleLevel());
|
|
|
|
|
+ copy.setCaloriesKcal(original.getCaloriesKcal());
|
|
|
|
|
+ copy.setProteinG(original.getProteinG());
|
|
|
|
|
+ copy.setFatG(original.getFatG());
|
|
|
|
|
+ copy.setCarbG(original.getCarbG());
|
|
|
|
|
+ copy.setFiberG(original.getFiberG());
|
|
|
|
|
+ copy.setNutritionTags(original.getNutritionTags());
|
|
|
copy.setCreatedAt(new Date());
|
|
copy.setCreatedAt(new Date());
|
|
|
copy.setUpdatedAt(new Date());
|
|
copy.setUpdatedAt(new Date());
|
|
|
productMapper.insert(copy);
|
|
productMapper.insert(copy);
|