diff --git a/diet-core/src/main/java/com/mathvision/diet/service/DishService.java b/diet-core/src/main/java/com/mathvision/diet/service/DishService.java index 35afb05..d55ea87 100644 --- a/diet-core/src/main/java/com/mathvision/diet/service/DishService.java +++ b/diet-core/src/main/java/com/mathvision/diet/service/DishService.java @@ -16,14 +16,19 @@ import org.apache.commons.lang3.tuple.Pair; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.domain.Specification; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.persistence.criteria.Predicate; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; +import java.time.Instant; import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @Slf4j @@ -32,6 +37,9 @@ public class DishService { private static final List MUST_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sodium"); private static final List WANT_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sugar", "sodium"); + private static final Lock UPDATE_LABEL_LOCK = new ReentrantLock(); + private static Instant UPDATE_LABEL_TIME; + @Resource private EnumService enumService; @@ -41,6 +49,41 @@ public class DishService { @Resource private DishRepository dishRepository; + @Scheduled(cron = "0/5 * * * * *") + public void init() { + if (!UPDATE_LABEL_LOCK.tryLock()) { + return; + } + try { + List dishes = UPDATE_LABEL_TIME == null ? dishRepository.findAll() : dishRepository.findByModifyGreaterThan(UPDATE_LABEL_TIME); + Map ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(DishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); + dishes.forEach(dish -> { + Map items = dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())).flatMap(x -> + ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue()).divide(new BigDecimal(100), RoundingMode.HALF_UP))) + ).collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); + items.put("sugar", sugar(dish, ingredientMap)); + + List label = Lists.newArrayList(); + if (items.getOrDefault("sodium", BigDecimal.ZERO).compareTo(new BigDecimal("120")) <= 0) { + label.add("低盐"); + } + if (items.getOrDefault("fat", BigDecimal.ZERO).compareTo(new BigDecimal("3")) <= 0) { + label.add("低脂"); + } + if (items.getOrDefault("sugar", BigDecimal.ZERO).compareTo(new BigDecimal("5")) <= 0) { + label.add("低糖"); + } + dish.setLabel(label); + }); + dishRepository.saveAll(dishes); + } catch (Exception e) { + log.error("[DishService] update label exception : " + e.getMessage(), e); + } finally { + UPDATE_LABEL_TIME = Instant.now(); + UPDATE_LABEL_LOCK.unlock(); + } + } + public void add(List dishes, String operator) { dishRepository.saveAll(dishes); log.info("[DishService] add dishes count = " + dishes.size() + ", operator = " + operator); @@ -85,11 +128,11 @@ public class DishService { return dishRepository.findByNameLikeOrderByIdDesc("%" + keyword + "%"); } - public Page list(Long vender, String name, String mark, String poly, PageRequest pageRequest) { - return dishRepository.findAll(toSpecification(vender, name, mark, poly), pageRequest); + public Page list(Long vender, String name, String mark, String poly, String label, PageRequest pageRequest) { + return dishRepository.findAll(toSpecification(vender, name, mark, poly, label), pageRequest); } - private Specification toSpecification(Long vender, String name, String mark, String poly) { + private Specification toSpecification(Long vender, String name, String mark, String poly, String label) { return (root, query, builder) -> { List predicates = new ArrayList<>(); @@ -109,6 +152,10 @@ public class DishService { predicates.add(builder.like(root.get("name"), "%" + name + "%")); } + if (StringUtils.isNotBlank(label)) { + predicates.add(builder.like(root.get("label"), "%" + label + "%")); + } + if (predicates.size() > 1) { return builder.and(predicates.toArray(new Predicate[0])); } else if (predicates.size() == 1) { @@ -167,9 +214,7 @@ public class DishService { } }, BigDecimal::add)); - items.put("sugar", dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())) - .map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue())) - .filter(x -> StringUtils.equals("糖类", x.getKey().getType())).map(Pair::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO)); + items.put("sugar", sugar(dish, ingredientMap)); MUST_DISPLAY_ITEM.forEach(x -> { if (!items.containsKey(x)) { @@ -201,4 +246,10 @@ public class DishService { return DishLabelDO.builder().name(dish.getName()).ingredients(ingredients).component(component).build(); }).collect(Collectors.toList()); } + + private BigDecimal sugar(Dish dish, Map ingredientMap) { + return dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())) + .map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue())) + .filter(x -> StringUtils.equals("糖类", x.getKey().getType())).map(Pair::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); + } } \ No newline at end of file diff --git a/diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java b/diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java index 4b9e83c..acf82b7 100644 --- a/diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java +++ b/diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java @@ -55,6 +55,10 @@ public class Dish { @Column(name = "marks", nullable = false, length = 45) private String marks; + @Type(type = "json") + @Column(name = "label", columnDefinition = "json", nullable = false) + private List label; + @Column(name = "poly", nullable = false, length = 16) private String poly; diff --git a/diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java b/diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java index ead0c15..63a3dbe 100644 --- a/diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java +++ b/diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java @@ -6,10 +6,12 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; import org.springframework.transaction.annotation.Transactional; +import java.time.Instant; import java.util.Collection; import java.util.List; public interface DishRepository extends JpaRepository, JpaSpecificationExecutor { + List findByModifyGreaterThan(Instant modify); @Transactional long deleteByVender(Long vender); @Query("select new Dish(d.id, d.name, d.marks, d.poly, d.ingredient) from Dish d where d.name like ?1 order by d.id DESC") diff --git a/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java b/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java index 79d895f..aef8f5d 100644 --- a/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java +++ b/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java @@ -121,11 +121,11 @@ public class DishController extends BaseController { @ResponseBody @RequestMapping(method = RequestMethod.GET) - public Object query(@RequestParam(required = false) String keyword, @RequestParam(required = false) Long id, @RequestParam(required = false) Long vendors, @RequestParam(required = false) String mark, @RequestParam(required = false) String poly, @RequestParam(required = false, defaultValue = "0") int pageNo, @RequestParam(required = false, defaultValue = "20") int pageSize) { + public Object query(@RequestParam(required = false) String keyword, @RequestParam(required = false) Long id, @RequestParam(required = false) Long vendors, @RequestParam(required = false) String mark, @RequestParam(required = false) String poly, @RequestParam(required = false) String label, @RequestParam(required = false, defaultValue = "0") int pageNo, @RequestParam(required = false, defaultValue = "20") int pageSize) { if (id != null) { return isAdmin() ? dishService.get(id) : dishService.get(id, getVender()); } - return dishService.list(!isAdmin() || vendors == null ? getVender() : vendors, keyword, mark, poly, PageRequest.of(pageNo, pageSize).withSort(Sort.by(Sort.Direction.DESC, "id"))); + return dishService.list(!isAdmin() || vendors == null ? getVender() : vendors, keyword, mark, poly, label, PageRequest.of(pageNo, pageSize).withSort(Sort.by(Sort.Direction.DESC, "id"))); } @ResponseBody diff --git a/diet-web/src/main/resources/static/change.html b/diet-web/src/main/resources/static/change.html index 78444a2..5f927fe 100644 --- a/diet-web/src/main/resources/static/change.html +++ b/diet-web/src/main/resources/static/change.html @@ -50,4 +50,8 @@
  • ʳ׷: ͷķݽṹ, ǵķӿ, ⿷ʽ;
  • ͼƬӿ: ȡͼƬӿڵ·;
  • +

    12.08

    +
      +
    • Ʒӿ: ֵͱǩ, ֶ-label, -list;
    • +
    diff --git a/doc/change.md b/doc/change.md index f8813e8..e322c7b 100644 --- a/doc/change.md +++ b/doc/change.md @@ -47,4 +47,7 @@ * 食谱接口: 食谱中的状态除草稿和发布状态外屏蔽, 食谱审核协议屏蔽; * 食谱接口: 食谱名称增加了特殊字符的校验; * 食谱分析: 类型分析的返回数据结构变更, 添加油盐糖的分析接口, 添加烹饪方式分析; -* 图片接口: 获取图片接口的路径发生变更; \ No newline at end of file +* 图片接口: 获取图片接口的路径发生变更; + +### 12.08 +* 菜品接口: 返回值增加三低标签, 字段名-label, 类型-list; diff --git a/sql/update.sql b/sql/update.sql new file mode 100644 index 0000000..238ae40 --- /dev/null +++ b/sql/update.sql @@ -0,0 +1,5 @@ +ALTER TABLE `diet`.`ingredient` DROP INDEX `idx_key`; + +ALTER TABLE `diet`.`dish` ADD INDEX `idx_marks`(`marks`); +ALTER TABLE `diet`.`dish` ADD INDEX `idx_modify`(`modify`); +ALTER TABLE `diet`.`dish` ADD COLUMN `label` json NULL COMMENT '标签' AFTER `poly`; \ No newline at end of file