fix(food-encyclopedia): 后台食物百科列表/编辑页接入并修复图片URL双前缀
- 新增 FoodEncyclopediaController 及 ToolFoodAdminService,提供 /api/admin/tool/food/* CRUD - ToolFoodAdminServiceImpl 在保存前 clearPrefix 并正则修复历史脏数据中的多层 host 前缀 - 前端 list.vue/edit.vue 修复二次解包导致 listData.list 渲染崩溃 - edit.vue 加载详情时兜底归一化 image 字段,处理 https://host//https://host//crmebimage/... 形式 - content.js 注册 foodManager / foodEdit 路由 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package com.zbkj.service.service.impl.tool;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.zbkj.common.model.tool.V2Food;
|
||||
import com.zbkj.common.request.PageParamRequest;
|
||||
import com.zbkj.service.dao.tool.V2FoodDao;
|
||||
import com.zbkj.service.service.SystemAttachmentService;
|
||||
import com.zbkj.service.service.tool.ToolFoodAdminService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 食物百科管理后台服务实现类
|
||||
* +----------------------------------------------------------------------
|
||||
* | 提供后台 CRUD 操作,图片维护等功能
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ToolFoodAdminServiceImpl implements ToolFoodAdminService {
|
||||
|
||||
@Resource
|
||||
private V2FoodDao v2FoodDao;
|
||||
|
||||
@Resource
|
||||
private SystemAttachmentService systemAttachmentService;
|
||||
|
||||
@Override
|
||||
public List<V2Food> getAdminList(String keyword, String category, String status,
|
||||
PageParamRequest pageParamRequest) {
|
||||
PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
|
||||
LambdaQueryWrapper<V2Food> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 关键词搜索(名称或别名)
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
wrapper.and(w -> w.like(V2Food::getName, keyword)
|
||||
.or().like(V2Food::getAlias, keyword));
|
||||
}
|
||||
// 分类筛选
|
||||
if (StrUtil.isNotBlank(category)) {
|
||||
wrapper.eq(V2Food::getCategory, category);
|
||||
}
|
||||
// 状态筛选
|
||||
if (StrUtil.isNotBlank(status)) {
|
||||
wrapper.eq(V2Food::getStatus, status);
|
||||
}
|
||||
|
||||
wrapper.orderByDesc(V2Food::getSortOrder)
|
||||
.orderByDesc(V2Food::getUpdatedAt);
|
||||
|
||||
return v2FoodDao.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V2Food getById(Long id) {
|
||||
return v2FoodDao.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(V2Food food) {
|
||||
Date now = new Date();
|
||||
food.setImage(normalizeImage(food.getImage()));
|
||||
food.setCreatedAt(now);
|
||||
food.setUpdatedAt(now);
|
||||
if (food.getStatus() == null) {
|
||||
food.setStatus("active");
|
||||
}
|
||||
if (food.getSortOrder() == null) {
|
||||
food.setSortOrder(0);
|
||||
}
|
||||
if (food.getViewCount() == null) {
|
||||
food.setViewCount(0);
|
||||
}
|
||||
return v2FoodDao.insert(food) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateFood(V2Food food) {
|
||||
food.setImage(normalizeImage(food.getImage()));
|
||||
food.setUpdatedAt(new Date());
|
||||
return v2FoodDao.updateById(food) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化图片字段:
|
||||
* 1. 先 clearPrefix 剥掉单层 CDN 前缀
|
||||
* 2. 再用正则去掉残留的「http(s)://xxx/」段,修复历史脏数据中的双前缀
|
||||
*/
|
||||
private String normalizeImage(String image) {
|
||||
if (StrUtil.isBlank(image)) {
|
||||
return image;
|
||||
}
|
||||
String cleaned = systemAttachmentService.clearPrefix(image);
|
||||
// 处理历史脏数据:形如 "https://.../crmebimage/..." 或 "https://.../https://.../crmebimage/..."
|
||||
// 去除 "crmebimage/" 之前的所有 "http(s)://...//?" 段
|
||||
return cleaned.replaceAll("^(https?://[^/]+/+)+(?=crmebimage/)", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteById(Long id) {
|
||||
return v2FoodDao.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeStatus(Long id, String status) {
|
||||
V2Food food = new V2Food();
|
||||
food.setFoodId(id);
|
||||
food.setStatus(status);
|
||||
food.setUpdatedAt(new Date());
|
||||
return v2FoodDao.updateById(food) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAllCategories() {
|
||||
LambdaQueryWrapper<V2Food> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.select(V2Food::getCategory)
|
||||
.isNotNull(V2Food::getCategory)
|
||||
.ne(V2Food::getCategory, "")
|
||||
.groupBy(V2Food::getCategory);
|
||||
return v2FoodDao.selectList(wrapper).stream()
|
||||
.map(V2Food::getCategory)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.zbkj.service.service.tool;
|
||||
|
||||
import com.zbkj.common.model.tool.V2Food;
|
||||
import com.zbkj.common.request.PageParamRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 食物百科管理后台服务接口
|
||||
* +----------------------------------------------------------------------
|
||||
* | 提供后台 CRUD 操作,图片维护等功能
|
||||
* +----------------------------------------------------------------------
|
||||
*/
|
||||
public interface ToolFoodAdminService {
|
||||
|
||||
/**
|
||||
* 后台分页列表(支持关键词、分类、状态筛选)
|
||||
*/
|
||||
List<V2Food> getAdminList(String keyword, String category, String status,
|
||||
PageParamRequest pageParamRequest);
|
||||
|
||||
/**
|
||||
* 根据ID获取食物<E9A39F><E789A9><EFBFBD>情
|
||||
*/
|
||||
V2Food getById(Long id);
|
||||
|
||||
/**
|
||||
* 新增食物
|
||||
*/
|
||||
boolean create(V2Food food);
|
||||
|
||||
/**
|
||||
* 修改食物
|
||||
*/
|
||||
boolean updateFood(V2Food food);
|
||||
|
||||
/**
|
||||
* 删除食物
|
||||
*/
|
||||
boolean deleteById(Long id);
|
||||
|
||||
/**
|
||||
* 修改状态(上架/下架)
|
||||
*/
|
||||
boolean changeStatus(Long id, String status);
|
||||
|
||||
/**
|
||||
* 获取所有分类列表
|
||||
*/
|
||||
List<String> getAllCategories();
|
||||
}
|
||||
Reference in New Issue
Block a user