From 85c9929b276b53806a1edcd71afcba254b277fa7 Mon Sep 17 00:00:00 2001 From: OpenCode Date: Tue, 28 Jul 2026 11:55:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=95=86=E5=93=81=E8=A1=8C=E4=B8=BA?= =?UTF-8?q?=E7=AE=A1=E7=90=86=20+=20=E5=B1=9E=E6=80=A7=E7=BC=96=E7=A0=81?= =?UTF-8?q?=20+=20ActionHandler=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ProductActionEntity: 行为管理实体(name/code/description/status) - ProductAttributeEntity: 新增code(属性编码)和action(关联行为)字段 - ActionHandler接口: validate校验 + afterPurchase购买后处理 - StockCheckHandler: 库存校验+扣减 - DatePickHandler: 服务日期校验 - DeliveryRouteHandler: 发货方式校验 - ActionHandlerRegistry: 自动注册所有handler --- .../modules/product/action/ActionHandler.java | 35 ++++++++++++++++++ .../product/action/ActionHandlerRegistry.java | 36 +++++++++++++++++++ .../product/action/DatePickHandler.java | 22 ++++++++++++ .../product/action/DeliveryRouteHandler.java | 22 ++++++++++++ .../product/action/StockCheckHandler.java | 35 ++++++++++++++++++ .../admin/AdminProductActionController.java | 21 +++++++++++ .../app/AppProductActionController.java | 26 ++++++++++++++ .../product/entity/ProductActionEntity.java | 25 +++++++++++++ .../entity/ProductAttributeEntity.java | 6 ++++ .../product/mapper/ProductActionMapper.java | 7 ++++ .../product/service/ProductActionService.java | 7 ++++ .../impl/ProductActionServiceImpl.java | 12 +++++++ 12 files changed, 254 insertions(+) create mode 100644 src/main/java/com/cool/modules/product/action/ActionHandler.java create mode 100644 src/main/java/com/cool/modules/product/action/ActionHandlerRegistry.java create mode 100644 src/main/java/com/cool/modules/product/action/DatePickHandler.java create mode 100644 src/main/java/com/cool/modules/product/action/DeliveryRouteHandler.java create mode 100644 src/main/java/com/cool/modules/product/action/StockCheckHandler.java create mode 100644 src/main/java/com/cool/modules/product/controller/admin/AdminProductActionController.java create mode 100644 src/main/java/com/cool/modules/product/controller/app/AppProductActionController.java create mode 100644 src/main/java/com/cool/modules/product/entity/ProductActionEntity.java create mode 100644 src/main/java/com/cool/modules/product/mapper/ProductActionMapper.java create mode 100644 src/main/java/com/cool/modules/product/service/ProductActionService.java create mode 100644 src/main/java/com/cool/modules/product/service/impl/ProductActionServiceImpl.java diff --git a/src/main/java/com/cool/modules/product/action/ActionHandler.java b/src/main/java/com/cool/modules/product/action/ActionHandler.java new file mode 100644 index 0000000..634b82b --- /dev/null +++ b/src/main/java/com/cool/modules/product/action/ActionHandler.java @@ -0,0 +1,35 @@ +package com.cool.modules.product.action; + +import cn.hutool.json.JSONObject; + +/** + * 商品行为处理器接口 + */ +public interface ActionHandler { + + /** + * 获取行为编码 + */ + String getCode(); + + /** + * 购买时校验 + * + * @param attrCode 属性编码 + * @param attrValue 属性值 + * @param quantity 购买数量 + */ + void validate(String attrCode, String attrValue, int quantity); + + /** + * 购买成功后执行(如扣减库存) + * + * @param attrCode 属性编码 + * @param attrValue 属性值 + * @param quantity 购买数量 + * @return 更新后的属性值 + */ + default String afterPurchase(String attrCode, String attrValue, int quantity) { + return attrValue; + } +} diff --git a/src/main/java/com/cool/modules/product/action/ActionHandlerRegistry.java b/src/main/java/com/cool/modules/product/action/ActionHandlerRegistry.java new file mode 100644 index 0000000..4c71174 --- /dev/null +++ b/src/main/java/com/cool/modules/product/action/ActionHandlerRegistry.java @@ -0,0 +1,36 @@ +package com.cool.modules.product.action; + +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 行为处理器注册中心 + */ +@Component +@RequiredArgsConstructor +public class ActionHandlerRegistry { + + private final List handlers; + + private Map handlerMap; + + @PostConstruct + public void init() { + handlerMap = handlers.stream() + .collect(Collectors.toMap(ActionHandler::getCode, Function.identity())); + } + + public ActionHandler getHandler(String actionCode) { + return handlerMap.get(actionCode); + } + + public boolean hasHandler(String actionCode) { + return handlerMap.containsKey(actionCode); + } +} diff --git a/src/main/java/com/cool/modules/product/action/DatePickHandler.java b/src/main/java/com/cool/modules/product/action/DatePickHandler.java new file mode 100644 index 0000000..eb9fda1 --- /dev/null +++ b/src/main/java/com/cool/modules/product/action/DatePickHandler.java @@ -0,0 +1,22 @@ +package com.cool.modules.product.action; + +import org.springframework.stereotype.Component; + +/** + * 日期选择处理器(服务类商品预约时间) + */ +@Component +public class DatePickHandler implements ActionHandler { + + @Override + public String getCode() { + return "date_pick"; + } + + @Override + public void validate(String attrCode, String attrValue, int quantity) { + if (attrValue == null || attrValue.isEmpty()) { + throw new RuntimeException("请选择服务时间"); + } + } +} diff --git a/src/main/java/com/cool/modules/product/action/DeliveryRouteHandler.java b/src/main/java/com/cool/modules/product/action/DeliveryRouteHandler.java new file mode 100644 index 0000000..15aa078 --- /dev/null +++ b/src/main/java/com/cool/modules/product/action/DeliveryRouteHandler.java @@ -0,0 +1,22 @@ +package com.cool.modules.product.action; + +import org.springframework.stereotype.Component; + +/** + * 发货路由处理器(判断物流/线上交付) + */ +@Component +public class DeliveryRouteHandler implements ActionHandler { + + @Override + public String getCode() { + return "delivery_route"; + } + + @Override + public void validate(String attrCode, String attrValue, int quantity) { + if (attrValue == null || attrValue.isEmpty()) { + throw new RuntimeException("请选择发货方式"); + } + } +} diff --git a/src/main/java/com/cool/modules/product/action/StockCheckHandler.java b/src/main/java/com/cool/modules/product/action/StockCheckHandler.java new file mode 100644 index 0000000..8b922cd --- /dev/null +++ b/src/main/java/com/cool/modules/product/action/StockCheckHandler.java @@ -0,0 +1,35 @@ +package com.cool.modules.product.action; + +import org.springframework.stereotype.Component; + +/** + * 库存校验处理器 + */ +@Component +public class StockCheckHandler implements ActionHandler { + + @Override + public String getCode() { + return "stock_check"; + } + + @Override + public void validate(String attrCode, String attrValue, int quantity) { + if (attrValue == null || attrValue.isEmpty()) { + return; + } + int stock = Integer.parseInt(attrValue); + if (stock < quantity) { + throw new RuntimeException("库存不足,当前库存:" + stock); + } + } + + @Override + public String afterPurchase(String attrCode, String attrValue, int quantity) { + if (attrValue == null || attrValue.isEmpty()) { + return attrValue; + } + int stock = Integer.parseInt(attrValue); + return String.valueOf(stock - quantity); + } +} diff --git a/src/main/java/com/cool/modules/product/controller/admin/AdminProductActionController.java b/src/main/java/com/cool/modules/product/controller/admin/AdminProductActionController.java new file mode 100644 index 0000000..ee98e7a --- /dev/null +++ b/src/main/java/com/cool/modules/product/controller/admin/AdminProductActionController.java @@ -0,0 +1,21 @@ +package com.cool.modules.product.controller.admin; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.base.BaseController; +import com.cool.modules.product.entity.ProductActionEntity; +import com.cool.modules.product.service.ProductActionService; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Tag(name = "商品行为管理", description = "商品行为管理") +@CoolRestController(api = {"add", "delete", "update", "page", "info"}) +public class AdminProductActionController extends BaseController { + + @Override + protected void init(HttpServletRequest request, JSONObject requestParams) { + setPageOption(createOp()); + } +} diff --git a/src/main/java/com/cool/modules/product/controller/app/AppProductActionController.java b/src/main/java/com/cool/modules/product/controller/app/AppProductActionController.java new file mode 100644 index 0000000..b3df5e9 --- /dev/null +++ b/src/main/java/com/cool/modules/product/controller/app/AppProductActionController.java @@ -0,0 +1,26 @@ +package com.cool.modules.product.controller.app; + +import cn.hutool.json.JSONObject; +import com.cool.core.annotation.CoolRestController; +import com.cool.core.request.R; +import com.cool.modules.product.entity.ProductActionEntity; +import com.cool.modules.product.service.ProductActionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestAttribute; + +@RequiredArgsConstructor +@Tag(name = "商品行为", description = "App端商品行为") +@CoolRestController +public class AppProductActionController { + + private final ProductActionService productActionService; + + @Operation(summary = "行为列表") + @GetMapping("/list") + public R list(@RequestAttribute JSONObject requestParams) { + return R.ok(productActionService.list(requestParams, null)); + } +} diff --git a/src/main/java/com/cool/modules/product/entity/ProductActionEntity.java b/src/main/java/com/cool/modules/product/entity/ProductActionEntity.java new file mode 100644 index 0000000..86ad901 --- /dev/null +++ b/src/main/java/com/cool/modules/product/entity/ProductActionEntity.java @@ -0,0 +1,25 @@ +package com.cool.modules.product.entity; + +import com.cool.core.base.TenantEntity; +import com.mybatisflex.annotation.Table; +import com.cool.core.annotation.ColumnDefine; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Table(value = "product_action", comment = "商品行为表") +public class ProductActionEntity extends TenantEntity { + + @ColumnDefine(comment = "行为名称", notNull = true) + private String name; + + @ColumnDefine(comment = "行为编码", notNull = true) + private String code; + + @ColumnDefine(comment = "说明", type = "text") + private String description; + + @ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1") + private Integer status; +} diff --git a/src/main/java/com/cool/modules/product/entity/ProductAttributeEntity.java b/src/main/java/com/cool/modules/product/entity/ProductAttributeEntity.java index 9cd7818..430713e 100644 --- a/src/main/java/com/cool/modules/product/entity/ProductAttributeEntity.java +++ b/src/main/java/com/cool/modules/product/entity/ProductAttributeEntity.java @@ -14,12 +14,18 @@ public class ProductAttributeEntity extends TenantEntity @ColumnDefine(comment = "属性名称", notNull = true) private String name; + @ColumnDefine(comment = "属性编码", notNull = true) + private String code; + @ColumnDefine(comment = "值类型 0:文本 1:数字 2:选择 3:日期", defaultValue = "0") private Integer type; @ColumnDefine(comment = "选项值(type=2时存JSON)", type = "text") private String options; + @ColumnDefine(comment = "关联行为编码") + private String action; + @ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1") private Integer status; } diff --git a/src/main/java/com/cool/modules/product/mapper/ProductActionMapper.java b/src/main/java/com/cool/modules/product/mapper/ProductActionMapper.java new file mode 100644 index 0000000..0aa8f89 --- /dev/null +++ b/src/main/java/com/cool/modules/product/mapper/ProductActionMapper.java @@ -0,0 +1,7 @@ +package com.cool.modules.product.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cool.modules.product.entity.ProductActionEntity; + +public interface ProductActionMapper extends BaseMapper { +} diff --git a/src/main/java/com/cool/modules/product/service/ProductActionService.java b/src/main/java/com/cool/modules/product/service/ProductActionService.java new file mode 100644 index 0000000..26eb651 --- /dev/null +++ b/src/main/java/com/cool/modules/product/service/ProductActionService.java @@ -0,0 +1,7 @@ +package com.cool.modules.product.service; + +import com.cool.core.base.BaseService; +import com.cool.modules.product.entity.ProductActionEntity; + +public interface ProductActionService extends BaseService { +} diff --git a/src/main/java/com/cool/modules/product/service/impl/ProductActionServiceImpl.java b/src/main/java/com/cool/modules/product/service/impl/ProductActionServiceImpl.java new file mode 100644 index 0000000..3791815 --- /dev/null +++ b/src/main/java/com/cool/modules/product/service/impl/ProductActionServiceImpl.java @@ -0,0 +1,12 @@ +package com.cool.modules.product.service.impl; + +import com.cool.core.base.BaseServiceImpl; +import com.cool.modules.product.entity.ProductActionEntity; +import com.cool.modules.product.mapper.ProductActionMapper; +import com.cool.modules.product.service.ProductActionService; +import org.springframework.stereotype.Service; + +@Service +public class ProductActionServiceImpl extends BaseServiceImpl implements + ProductActionService { +}