Просмотр исходного кода

商品表,酒吧,美食,健身模块商家端接口

liyafei 3 дней назад
Родитель
Сommit
7dcb29c0c9

+ 28 - 4
alien-entity/src/main/java/shop/alien/entity/result/CommonEnum.java

@@ -3,12 +3,36 @@ package shop.alien.entity.result;
 
 public interface CommonEnum {
 
-      enum StoreProductItemProdType {
+    /**
+     * 商品所属模块
+     */
+    enum ModelType {
+        BAR(1, "酒吧"),
+        DELICACY(2, "美食"),
+        GYM(3, "运动健身");
+
+        private final int code;
+        private final String desc;
+
+        ModelType(int code, String desc) {
+            this.code = code;
+            this.desc = desc;
+        }
+
+        public int getCode() { return code; }
+        public String getDesc() { return desc; }
+    }
+
+    /**
+     * 商品所属模块,细化
+     */
+    enum StoreProductItemProdType {
         BAR_DRINK(1, "酒吧-酒水"),
         BAR_FOOD(2, "酒吧-餐食"),
-        DELICACY_FOOD(3, "美食-餐食"),
-        GYM_SINGLE(4, "运动健身-单次"),
-        GYM_MULTI(5, "运动健身-多次");
+        BAR_COMBO(3, "酒吧-套餐"),
+        DELICACY_FOOD(4, "美食-餐食"),
+        GYM_SINGLE(5, "运动健身-单次"),
+        GYM_MULTI(6, "运动健身-多次");
 
         private final int code;
         private final String desc;

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreProductGym.java

@@ -37,6 +37,10 @@ public class StoreProductGym implements Serializable {
     @TableField("name")
     private String name;
 
+    @ApiModelProperty(value = "可用/剩余次数")
+    @TableField("usage_count")
+    private Integer usageCount;
+
     @ApiModelProperty(value = "上课形式,如一对一/小班课")
     @TableField("class_mode")
     private String classMode;

+ 0 - 4
alien-entity/src/main/java/shop/alien/entity/store/StoreProductItem.java

@@ -29,10 +29,6 @@ public class StoreProductItem implements Serializable {
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    @ApiModelProperty(value = "父id")
-    @TableField(value = "pid")
-    private Integer pid;
-
     @ApiModelProperty(value = "门店id")
     @TableField("store_id")
     private Integer storeId;

+ 1 - 1
alien-entity/src/main/java/shop/alien/entity/store/dto/StoreProductItemDto.java

@@ -25,7 +25,7 @@ public class StoreProductItemDto implements Serializable {
     @ApiModelProperty("商品名称")
     private String prodName;
 
-    @ApiModelProperty("商品类型,整型枚举:1酒吧-酒水 2酒吧-餐食 3美食-餐食 4运动健身-单次 5运动健身-多次")
+    @ApiModelProperty("商品类型,整型枚举:1酒吧-酒水 2酒吧-餐食 3酒吧-套餐  4美食-餐食 5运动健身-单次 6运动健身-多次")
     private Integer prodType;
 
     @ApiModelProperty("图片列表,最多 9 张 URL")

+ 3 - 5
alien-entity/src/main/resources/mapper/StoreProductItemMapper.xml

@@ -5,7 +5,6 @@
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="shop.alien.entity.store.StoreProductItem">
         <id column="id" property="id" />
-        <result column="pid" property="pid" />
         <result column="store_id" property="storeId" />
         <result column="prod_name" property="prodName" />
         <result column="prod_type" property="prodType" />
@@ -28,7 +27,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, pid, store_id, prod_name, prod_type, images, image_content, detail_content, 
+        id, store_id, prod_name, prod_type, images, image_content, detail_content,
         extra_note, need_reserve, reserve_rule, people_limit, usage_rule, status, 
         rejection_reason, delete_flag, created_user_id, updated_user_id, created_time, updated_time
     </sql>
@@ -69,7 +68,7 @@
         </collection>
     </resultMap>
 
-    <select id="getByPId" resultMap="StoreProductItemDtoMap">
+    <select id="getByExtId" resultMap="StoreProductItemDtoMap">
         SELECT
             spi.id,
             spi.store_id,
@@ -105,8 +104,7 @@
                  LEFT JOIN store_product_bar spb
                            ON spb.ext_id = spi.id
                                AND spb.delete_flag = 0
-        WHERE spi.pid = #{id}
-          AND spi.delete_flag = 0
+        WHERE spi.delete_flag = 0
     </select>
 
 </mapper>

+ 26 - 55
alien-store/src/main/java/shop/alien/store/controller/StoreProductItemController.java

@@ -10,7 +10,6 @@ import shop.alien.entity.store.StoreProductItem;
 import shop.alien.entity.store.dto.StoreProductItemDto;
 import shop.alien.entity.store.vo.StoreProductItemGymVo;
 import shop.alien.store.service.StoreProductItemService;
-import shop.alien.util.myBaticsPlus.QueryBuilder;
 
 import java.util.List;
 
@@ -62,68 +61,40 @@ public class StoreProductItemController {
         return storeProductItemService.getStoreProductItemById(id);
     }
 
-    @ApiOperation("保存或更新商品")
+    @ApiOperation("按商品类型查询列表")
     @ApiOperationSupport(order = 5)
-    @PostMapping("/saveOrUpdate")
-    public R<StoreProductItem> saveOrUpdate(@RequestBody StoreProductItem storeProductItem) {
-        log.info("StoreProductItemController.saveOrUpdate?storeProductItem={}", storeProductItem);
-        boolean result = storeProductItemService.saveOrUpdate(storeProductItem);
-        if (result) {
-            return R.data(storeProductItem);
-        }
-        return R.fail("操作失败");
-    }
-
-    @ApiOperation("通用列表查询")
-    @ApiOperationSupport(order = 6)
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "id", value = "主键", dataType = "Long", paramType = "query"),
-            @ApiImplicitParam(name = "pid", value = "父id", dataType = "Long", paramType = "query"),
-            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "prodName", value = "商品名称", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "prodType", value = "商品类型(1酒吧-酒水 2酒吧-餐食 3美食-餐食 4运动健身-单次 5运动健身-多次)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "needReserve", value = "是否需要预约(0=否,1=是)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "status", value = "状态(0-待审核 1-审核通过 2-审核拒绝)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "rejectionReason", value = "拒绝原因", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "createdTime_Start", value = "创建时间开始(范围查询)", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "createdTime_End", value = "创建时间结束(范围查询)", dataType = "String", paramType = "query")
+            @ApiImplicitParam(name = "prodType", value = "商品类型:1酒吧-酒水 2酒吧-餐食 3美食-餐食 4运动健身-单次 5运动健身-多次", dataType = "Integer", paramType = "query", required = true)
     })
-    @GetMapping("/getList")
-    public R<List<StoreProductItem>> getList(@ModelAttribute StoreProductItem storeProductItem) {
-        log.info("StoreProductItemController.getList?storeProductItem={}", storeProductItem);
-        List<StoreProductItem> list = QueryBuilder.of(storeProductItem)
-                .build()
-                .list(storeProductItemService);
-        return R.data(list);
+    @GetMapping("/listByProdType")
+    public R<List<StoreProductItem>> listByProdType(@RequestParam("prodType") Integer prodType) {
+        log.info("StoreProductItemController.listByProdType?prodType={}", prodType);
+        return storeProductItemService.listByProdType(prodType);
     }
 
-    @ApiOperation("通用分页查询")
+    @ApiOperation("分页查询(按门店/名称/类型/状态/预约筛选)")
     @ApiOperationSupport(order = 7)
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "page", value = "页数(默认1)", dataType = "int", paramType = "query"),
-            @ApiImplicitParam(name = "size", value = "页容(默认10)", dataType = "int", paramType = "query"),
-            @ApiImplicitParam(name = "id", value = "主键", dataType = "Long", paramType = "query"),
-            @ApiImplicitParam(name = "pid", value = "父id", dataType = "Long", paramType = "query"),
-            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "prodName", value = "商品名称", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "prodType", value = "商品类型(1酒吧-酒水 2酒吧-餐食 3美食-餐食 4运动健身-单次 5运动健身-多次)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "needReserve", value = "是否需要预约(0=否,1=是)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "status", value = "状态(0-待审核 1-审核通过 2-审核拒绝)", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "rejectionReason", value = "拒绝原因", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "createdTime_Start", value = "创建时间开始(范围查询)", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "createdTime_End", value = "创建时间结束(范围查询)", dataType = "String", paramType = "query")
+            @ApiImplicitParam(name = "pageNum", value = "页码(默认1)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "pageSize", value = "页容(默认10)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "prodName", value = "商品名称(模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "prodType", value = "商品类型", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "status", value = "状态:0-待审核 1-审核通过 2-审核拒绝", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "needReserve", value = "是否需要预约:0-否 1-是", dataType = "Integer", paramType = "query")
     })
-    @GetMapping("/getPage")
-    public R<IPage<StoreProductItem>> getPage(@ModelAttribute StoreProductItem storeProductItem,
-                                              @RequestParam(defaultValue = "1") int page,
-                                              @RequestParam(defaultValue = "10") int size) {
-        log.info("StoreProductItemController.getPage?storeProductItem={},page={},size={}", storeProductItem, page, size);
-        int pageNum = page > 0 ? page : 1;
-        int pageSize = size > 0 ? size : 10;
-        IPage<StoreProductItem> pageResult = QueryBuilder.of(storeProductItem)
-                .page(pageNum, pageSize)
-                .build()
-                .page(storeProductItemService);
+    @GetMapping("/pageList")
+    public R<IPage<StoreProductItem>> pageList(@RequestParam(defaultValue = "1") int pageNum,
+                                               @RequestParam(defaultValue = "10") int pageSize,
+                                               @RequestParam(required = false) Integer storeId,
+                                               @RequestParam(required = false) String prodName,
+                                               @RequestParam(required = false) Integer prodType,
+                                               @RequestParam(required = false) Integer status,
+                                               @RequestParam(required = false) Integer needReserve) {
+        IPage<StoreProductItem> pageResult = storeProductItemService.pageStoreProductItems(
+                pageNum > 0 ? pageNum : 1,
+                pageSize > 0 ? pageSize : 10,
+                storeId, prodName, prodType, status, needReserve);
         return R.data(pageResult);
     }
 

+ 2 - 1
alien-store/src/main/java/shop/alien/store/service/StoreProductDelicaciesService.java

@@ -1,6 +1,7 @@
 package shop.alien.store.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.store.StoreProductDelicacies;
 
 import java.util.List;
@@ -11,7 +12,7 @@ import java.util.List;
  * @author system
  * @since 2025-01-XX
  */
-public interface StoreProductDelicaciesService {
+public interface StoreProductDelicaciesService extends IService<StoreProductDelicacies> {
 
     /**
      * 分页查询美食商品列表

+ 25 - 0
alien-store/src/main/java/shop/alien/store/service/StoreProductItemService.java

@@ -49,6 +49,15 @@ public interface StoreProductItemService extends IService<StoreProductItem> {
 
 
     /**
+     * 按商品类型查询列表
+     *
+     * @param prodType 商品类型:1酒吧-酒水 2酒吧-餐食 3美食-餐食 4运动健身-单次 5运动健身-多次
+     * @return R<List<StoreProductItem>>
+     */
+    R<List<StoreProductItem>> listByProdType(Integer prodType);
+
+
+    /**
      * 分页查询商品表与运动健身商品表关联数据
      *
      * @param pageNum  页码
@@ -67,5 +76,21 @@ public interface StoreProductItemService extends IService<StoreProductItem> {
      * @return R<StoreProductItemGymVo>
      */
     R<StoreProductItemGymVo> getDetailWithGym(Long id);
+
+    /**
+     * 通用分页查询(支持门店、名称、类型、状态、是否预约筛选)
+     *
+     * @param pageNum     页码
+     * @param pageSize    页容
+     * @param storeId     门店ID
+     * @param prodName    商品名称(模糊)
+     * @param prodType    商品类型
+     * @param status      状态:0-待审核 1-审核通过 2-审核拒绝
+     * @param needReserve 是否需要预约:0-否 1-是
+     * @return IPage<StoreProductItem>
+     */
+    IPage<StoreProductItem> pageStoreProductItems(int pageNum, int pageSize,
+                                                  Integer storeId, String prodName, Integer prodType,
+                                                  Integer status, Integer needReserve);
 }
 

+ 12 - 13
alien-store/src/main/java/shop/alien/store/service/impl/StoreProductDelicaciesServiceImpl.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -25,9 +26,7 @@ import java.util.List;
 @Service
 @RequiredArgsConstructor
 @Transactional
-public class StoreProductDelicaciesServiceImpl implements StoreProductDelicaciesService {
-
-    private final StoreProductDelicaciesMapper storeProductDelicaciesMapper;
+public class StoreProductDelicaciesServiceImpl extends ServiceImpl<StoreProductDelicaciesMapper, StoreProductDelicacies> implements StoreProductDelicaciesService {
 
     @Override
     public IPage<StoreProductDelicacies> getPage(int pageNum, int pageSize, String name, String category, String extGroup, Integer status, Integer extId) {
@@ -61,12 +60,12 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
         // 按创建时间倒序
         queryWrapper.orderByDesc(StoreProductDelicacies::getCreatedTime);
 
-        return storeProductDelicaciesMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
+        return baseMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper);
     }
 
     @Override
     public StoreProductDelicacies getById(Integer id) {
-        return storeProductDelicaciesMapper.selectById(id);
+        return baseMapper.selectById(id);
     }
 
     @Override
@@ -88,7 +87,7 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
             delicacies.setUpdatedUserId(0);
         }
 
-        return storeProductDelicaciesMapper.insert(delicacies) > 0;
+        return baseMapper.insert(delicacies) > 0;
     }
 
     @Override
@@ -103,13 +102,13 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
             delicacies.setUpdatedUserId(0);
         }
 
-        return storeProductDelicaciesMapper.updateById(delicacies) > 0;
+        return baseMapper.updateById(delicacies) > 0;
     }
 
     @Override
     public boolean deleteDelicacies(Integer id) {
         // 逻辑删除,MyBatis-Plus会自动处理
-        return storeProductDelicaciesMapper.deleteById(id) > 0;
+        return baseMapper.deleteById(id) > 0;
     }
 
     @Override
@@ -119,7 +118,7 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
             return false;
         }
         // 逻辑删除,MyBatis-Plus会自动处理
-        return storeProductDelicaciesMapper.deleteBatchIds(ids) > 0;
+        return baseMapper.deleteBatchIds(ids) > 0;
     }
 
     @Override
@@ -137,7 +136,7 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
         updateWrapper.eq(StoreProductDelicacies::getId, id)
                 .set(StoreProductDelicacies::getStatus, status);
 
-        return storeProductDelicaciesMapper.update(null, updateWrapper) > 0;
+        return baseMapper.update(null, updateWrapper) > 0;
     }
 
     @Override
@@ -148,7 +147,7 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
         LambdaQueryWrapper<StoreProductDelicacies> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(StoreProductDelicacies::getExtId, extId)
                 .orderByDesc(StoreProductDelicacies::getCreatedTime);
-        return storeProductDelicaciesMapper.selectList(queryWrapper);
+        return baseMapper.selectList(queryWrapper);
     }
 
     @Override
@@ -159,7 +158,7 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
         LambdaQueryWrapper<StoreProductDelicacies> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(StoreProductDelicacies::getCategory, category)
                 .orderByDesc(StoreProductDelicacies::getCreatedTime);
-        return storeProductDelicaciesMapper.selectList(queryWrapper);
+        return baseMapper.selectList(queryWrapper);
     }
 
     @Override
@@ -170,7 +169,7 @@ public class StoreProductDelicaciesServiceImpl implements StoreProductDelicacies
         LambdaQueryWrapper<StoreProductDelicacies> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(StoreProductDelicacies::getExtGroup, extGroup)
                 .orderByDesc(StoreProductDelicacies::getCreatedTime);
-        return storeProductDelicaciesMapper.selectList(queryWrapper);
+        return baseMapper.selectList(queryWrapper);
     }
 }
 

+ 132 - 40
alien-store/src/main/java/shop/alien/store/service/impl/StoreProductItemServiceImpl.java

@@ -1,5 +1,6 @@
 package shop.alien.store.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -8,19 +9,26 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import shop.alien.entity.result.CommonEnum;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.StoreProductBar;
+import shop.alien.entity.store.StoreProductDelicacies;
+import shop.alien.entity.store.StoreProductGym;
 import shop.alien.entity.store.StoreProductItem;
 import shop.alien.entity.store.vo.StoreProductItemGymVo;
 import shop.alien.entity.store.dto.StoreProductItemDto;
 import shop.alien.mapper.StoreProductItemMapper;
 import shop.alien.store.service.StoreProductBarService;
+import shop.alien.store.service.StoreProductDelicaciesService;
+import shop.alien.store.service.StoreProductGymService;
 import shop.alien.store.service.StoreProductItemService;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -39,29 +47,19 @@ public class StoreProductItemServiceImpl extends ServiceImpl<StoreProductItemMap
 
     private final StoreProductBarService storeProductBarService;
 
+    private final StoreProductDelicaciesService storeProductDelicaciesService;
+
+    private final StoreProductGymService storeProductGymService;
+
     @Override
     public R<StoreProductItem> addStoreProductItemDto(StoreProductItemDto storeProductItemDto) {
         log.info("StoreProductItemServiceImpl.addStoreProductItem?storeProductItem={}", storeProductItemDto);
         StoreProductItem storeProductItem = new StoreProductItem();
-        BeanUtils.copyProperties(storeProductItemDto,storeProductItem);
-        // 设置pid默认值为0
-        storeProductItem.setPid(0);
-        // MySQL 驱动开启 useGeneratedKeys(Spring Boot 默认开启,通常不用改)。
+        BeanUtils.copyProperties(storeProductItemDto, storeProductItem);
+        // 先保存主商品,确保可以拿到自增的 id 作为子表 extId。
         this.save(storeProductItem);
-        // 添加套餐时,需要前端在子集合内元素分别设置type
-        // 处理子项(判空)
-        List<?> rawSubList = storeProductItemDto.getSubList();
-        if (rawSubList != null && !rawSubList.isEmpty()) {
-            List<StoreProductBar> subList = rawSubList.stream()
-                    .map(v -> objectMapper.convertValue(v, StoreProductBar.class))
-                    .collect(Collectors.toList());
-            Integer parentId = storeProductItem.getId();
-            subList.forEach(v -> v.setExtId(parentId));
-            boolean subSaved = storeProductBarService.saveBatch(subList);
-            if (!subSaved) {
-                throw new RuntimeException("子项保存失败");
-            }
-        }
+        // 根据商品类型分发子表保存逻辑。
+        processSubItems(storeProductItemDto, storeProductItem, false);
         return R.data(storeProductItem);
     }
 
@@ -69,29 +67,95 @@ public class StoreProductItemServiceImpl extends ServiceImpl<StoreProductItemMap
     public R<StoreProductItem> editStoreProductItem(StoreProductItemDto storeProductItemDto) {
         log.info("StoreProductItemServiceImpl.editStoreProductItem?storeProductItem={}", storeProductItemDto);
         StoreProductItem storeProductItem = new StoreProductItem();
-        BeanUtils.copyProperties(storeProductItemDto,storeProductItem);
+        BeanUtils.copyProperties(storeProductItemDto, storeProductItem);
         this.updateById(storeProductItem);
-        // 添加套餐时,需要前端在子集合内元素分别设置type
-        // 处理子项(判空)
+        // 统一的子表处理:先清理旧数据,再按商品类型重建。
+        processSubItems(storeProductItemDto, storeProductItem, true);
+        return R.data(storeProductItem);
+    }
+
+    /**
+     * 新增/编辑场景下的子表处理。
+     *
+     * @param storeProductItemDto 前端传入的数据,包含主表和子表信息
+     * @param storeProductItem    已保存/更新的主表实体,需从中读取 id 作为子表 extId
+     * @param replaceExisting     是否需要先删除同 extId 的旧数据(编辑场景)
+     */
+    private void processSubItems(StoreProductItemDto storeProductItemDto,
+                                 StoreProductItem storeProductItem,
+                                 boolean replaceExisting) {
         List<?> rawSubList = storeProductItemDto.getSubList();
-        if (rawSubList != null && !rawSubList.isEmpty()) {
-            List<StoreProductBar> subList = rawSubList.stream()
-                    .map(v -> objectMapper.convertValue(v, StoreProductBar.class))
-                    .collect(Collectors.toList());
-            Integer parentId = storeProductItem.getId();
-            subList.forEach(v -> v.setExtId(parentId));
-            boolean subSaved = storeProductBarService.saveBatch(subList);
-            if (!subSaved) {
-                throw new RuntimeException("子项保存失败");
-            }
+        if (rawSubList == null || rawSubList.isEmpty()) {
+            return;
+        }
+        Integer modelType = storeProductItemDto.getModelType();
+        if (modelType == null) {
+            log.warn("商品缺少 modelType,跳过子项处理");
+            return;
+        }
+        Integer extId = storeProductItem.getId();
+
+        // 编辑场景:删除当前商品 extId 对应的旧子表数据,避免脏数据。
+        if (replaceExisting) {
+            clearSubItemsByModelType(modelType, extId);
+        }
+
+        // 按商品类型把原始子项转换为目标实体并批量入库。
+        if (CommonEnum.ModelType.BAR.getCode() == modelType) {
+            convertAndSave(rawSubList, extId, StoreProductBar.class,
+                    (item, id) -> item.setExtId(id), storeProductBarService::saveBatch);
+        } else if (CommonEnum.ModelType.DELICACY.getCode() == modelType) {
+            convertAndSave(rawSubList, extId, StoreProductDelicacies.class,
+                    (item, id) -> item.setExtId(id), storeProductDelicaciesService::saveBatch);
+        } else if (CommonEnum.ModelType.GYM.getCode() == modelType) {
+            convertAndSave(rawSubList, extId, StoreProductGym.class,
+                    (item, id) -> {
+                        item.setExtId(id);
+                        if (item.getUsageCount() == null) {
+                            item.setUsageCount(0);
+                        }
+                    }, storeProductGymService::saveBatch);
+        } else {
+            log.warn("未知的商品 modelType:{},子项未处理", modelType);
+        }
+    }
+
+    /**
+     * 根据商品模块清理同一个 extId 的旧子表数据,防止编辑后出现重复/脏数据。
+     */
+    private void clearSubItemsByModelType(Integer modelType, Integer extId) {
+        if (CommonEnum.ModelType.BAR.getCode() == modelType) {
+            storeProductBarService.lambdaUpdate().eq(StoreProductBar::getExtId, extId).remove();
+        } else if (CommonEnum.ModelType.DELICACY.getCode() == modelType) {
+            storeProductDelicaciesService.lambdaUpdate().eq(StoreProductDelicacies::getExtId, extId).remove();
+        } else if (CommonEnum.ModelType.GYM.getCode() == modelType) {
+            storeProductGymService.lambdaUpdate().eq(StoreProductGym::getExtId, extId).remove();
+        }
+    }
+
+    /**
+     * 通用转换 + 批量保存,保持原有异常行为。
+     */
+    private <T> void convertAndSave(List<?> rawSubList, Integer extId, Class<T> clazz,
+                                    BiConsumer<T, Integer> extSetter,
+                                    Function<List<T>, Boolean> saveBatchFunc) {
+        List<T> subList = rawSubList.stream()
+                .map(v -> objectMapper.convertValue(v, clazz))
+                .peek(v -> extSetter.accept(v, extId))
+                .collect(Collectors.toList());
+        boolean subSaved = saveBatchFunc.apply(subList);
+        if (!subSaved) {
+            throw new RuntimeException("子项保存失败");
         }
-        return R.data(storeProductItem);
     }
 
     @Override
     public R<Boolean> deleteStoreProductItem(Integer id) {
         log.info("StoreProductItemServiceImpl.deleteStoreProductItem?id={}", id);
         boolean result = this.removeById(id);
+        storeProductBarService.lambdaUpdate().eq(StoreProductBar::getExtId, id).remove();
+        storeProductDelicaciesService.lambdaUpdate().eq(StoreProductDelicacies::getExtId, id).remove();
+        storeProductGymService.lambdaUpdate().eq(StoreProductGym::getExtId, id).remove();
         if (result) {
             return R.success("删除成功");
         }
@@ -102,17 +166,44 @@ public class StoreProductItemServiceImpl extends ServiceImpl<StoreProductItemMap
     public R<List<StoreProductItemDto>> getStoreProductItemById(Integer id) {
         log.info("StoreProductItemServiceImpl.getStoreProductItemById?id={}", id);
         StoreProductItem storeProductItem = this.getById(id);
-        ArrayList<StoreProductItemDto> list = new ArrayList<>();
-        StoreProductItemDto storeProductItemDto = new StoreProductItemDto();
-        list.add(storeProductItemDto);
-        BeanUtils.copyProperties(storeProductItem,storeProductItemDto);
-        if (CommonEnum.StoreProductItemProdType.DELICACY_FOOD.getCode() == storeProductItem.getProdType()) {
-            list = this.getBaseMapper().getByPId(id);
-        }else {
+        if (storeProductItem == null) {
+            ArrayList<StoreProductItemDto> list = new ArrayList<>();
+            StoreProductItemDto storeProductItemDto = new StoreProductItemDto();
+            list.add(storeProductItemDto);
+            BeanUtils.copyProperties(storeProductItem,storeProductItemDto);
             List<StoreProductBar> barList = storeProductBarService.getByExtId(id);
             storeProductItemDto.setSubList(barList);
+            return R.data(list);
         }
-        return R.data(list);
+        return R.fail("未找到数据");
+    }
+
+    @Override
+    public R<List<StoreProductItem>> listByProdType(Integer prodType) {
+        log.info("StoreProductItemServiceImpl.listByProdType?prodType={}", prodType);
+        if (prodType == null) {
+            return R.fail("prodType不能为空");
+        }
+        List<StoreProductItem> result = lambdaQuery().eq(StoreProductItem::getProdType, prodType)
+                .orderByDesc(StoreProductItem::getCreatedTime).list();
+        return R.data(result);
+    }
+
+    @Override
+    public IPage<StoreProductItem> pageStoreProductItems(int pageNum, int pageSize,
+                                                         Integer storeId, String prodName, Integer prodType,
+                                                         Integer status, Integer needReserve) {
+        log.info("StoreProductItemServiceImpl.pageStoreProductItems?pageNum={}, pageSize={}, storeId={}, prodName={}, prodType={}, status={}, needReserve={}",
+                pageNum, pageSize, storeId, prodName, prodType, status, needReserve);
+        Page<StoreProductItem> page = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<StoreProductItem> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(storeId != null, StoreProductItem::getStoreId, storeId)
+                .eq(prodType != null, StoreProductItem::getProdType, prodType)
+                .eq(status != null, StoreProductItem::getStatus, status)
+                .eq(needReserve != null, StoreProductItem::getNeedReserve, needReserve)
+                .like(StringUtils.hasText(prodName), StoreProductItem::getProdName, prodName)
+                .orderByDesc(StoreProductItem::getCreatedTime);
+        return this.page(page, wrapper);
     }
 
     @Override
@@ -139,5 +230,6 @@ public class StoreProductItemServiceImpl extends ServiceImpl<StoreProductItemMap
         }
         return R.fail("查询失败,数据不存在");
     }
+
 }