瀏覽代碼

运营活动

zjy 2 周之前
父節點
當前提交
1cc3089c27

+ 101 - 0
alien-entity/src/main/java/shop/alien/entity/storePlatform/StoreOperationalActivity.java

@@ -0,0 +1,101 @@
+package shop.alien.entity.storePlatform;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 运营活动表
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Data
+@JsonInclude
+@TableName("store_operational_activity")
+@ApiModel(value = "StoreOperationalActivity对象", description = "运营活动表")
+public class StoreOperationalActivity {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "商户ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "活动名称")
+    @TableField("activity_name")
+    private String activityName;
+
+    @ApiModelProperty(value = "活动宣传图URL")
+    @TableField("promotional_image")
+    private String promotionalImage;
+
+    @ApiModelProperty(value = "活动开始时间")
+    @TableField("start_time")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date startTime;
+
+    @ApiModelProperty(value = "活动结束时间")
+    @TableField("end_time")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date endTime;
+
+    @ApiModelProperty(value = "用户可参与次数,0表示不限制")
+    @TableField("participation_limit")
+    private Integer participationLimit;
+
+    @ApiModelProperty(value = "活动规则:VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡")
+    @TableField("activity_rule")
+    private String activityRule;
+
+    @ApiModelProperty(value = "奖励类型:COUPON-优惠券, RED_PACKET-红包")
+    @TableField("reward_type")
+    private String rewardType;
+
+    @ApiModelProperty(value = "优惠券ID,关联优惠券表")
+    @TableField("coupon_id")
+    private Integer couponId;
+
+    @ApiModelProperty(value = "优惠券发放数量")
+    @TableField("coupon_quantity")
+    private Integer couponQuantity;
+
+    @ApiModelProperty(value = "状态:0-禁用, 1-启用")
+    @TableField("status")
+    private Integer status;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+
+    @ApiModelProperty(value = "拒绝原因")
+    @TableField("approval_comments")
+    private String approvalComments;
+}
+

+ 77 - 0
alien-entity/src/main/java/shop/alien/entity/storePlatform/vo/StoreOperationalActivityDTO.java

@@ -0,0 +1,77 @@
+package shop.alien.entity.storePlatform.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.StoreImg;
+
+import java.util.Date;
+
+/**
+ * 运营活动 DTO
+ * 用于接收前端请求参数
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Data
+@ApiModel(value = "StoreOperationalActivityDTO", description = "运营活动传输对象")
+public class StoreOperationalActivityDTO {
+
+    @ApiModelProperty(value = "主键ID(更新时必填)")
+    private Integer id;
+
+    @ApiModelProperty(value = "商户ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "活动名称", required = true)
+    private String activityName;
+
+    @ApiModelProperty(value = "活动宣传图URL")
+    private String promotionalImage;
+
+    @ApiModelProperty(value = "活动开始时间", required = true)
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date startTime;
+
+    @ApiModelProperty(value = "活动结束时间", required = true)
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date endTime;
+
+    @ApiModelProperty(value = "用户可参与次数,0表示不限制")
+    private Integer participationLimit;
+
+    @ApiModelProperty(value = "活动规则:VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡", required = true)
+    private String activityRule;
+
+    @ApiModelProperty(value = "奖励类型:COUPON-优惠券, RED_PACKET-红包")
+    private String rewardType;
+
+    @ApiModelProperty(value = "优惠券ID")
+    private Integer couponId;
+
+    @ApiModelProperty(value = "优惠券发放数量")
+    private Integer couponQuantity;
+
+    @ApiModelProperty(value = "状态:0-禁用, 1-启用")
+    private Integer status;
+
+    @ApiModelProperty(value = "拒绝原因")
+    private String approvalComments;
+
+    @ApiModelProperty(value = "活动标题图片")
+    private StoreImg activityTitleImg;
+
+    @ApiModelProperty(value = "活动详情图片")
+    private StoreImg activityDetailImg;
+
+    @ApiModelProperty(value = "页码")
+    private Integer pageNum;
+
+    @ApiModelProperty(value = "页数")
+    private Integer pageSize;
+
+}
+

+ 58 - 0
alien-entity/src/main/java/shop/alien/entity/storePlatform/vo/StoreOperationalActivityVO.java

@@ -0,0 +1,58 @@
+package shop.alien.entity.storePlatform.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.entity.storePlatform.StoreOperationalActivity;
+
+/**
+ * 运营活动 VO
+ * 用于返回给前端的数据对象
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreOperationalActivityVO", description = "运营活动返回对象")
+public class StoreOperationalActivityVO extends StoreOperationalActivity {
+
+    @ApiModelProperty(value = "活动状态名称")
+    private String statusName;
+
+    @ApiModelProperty(value = "活动规则名称")
+    private String activityRuleName;
+
+    @ApiModelProperty(value = "奖励类型名称")
+    private String rewardTypeName;
+
+    @ApiModelProperty(value = "优惠券名称")
+    private String couponName;
+
+    @ApiModelProperty(value = "商户名称")
+    private String storeName;
+
+    @ApiModelProperty(value = "活动状态:0-未开始, 1-进行中, 2-已结束")
+    private Integer activityStatus;
+
+    @ApiModelProperty(value = "已参与人数")
+    private Integer participationCount;
+
+    @ApiModelProperty(value = "剩余优惠券数量")
+    private Integer remainingCouponQuantity;
+
+    @ApiModelProperty(value = "活动标题图片")
+    private StoreImg activityTitleImg;
+
+    @ApiModelProperty(value = "活动详情图片")
+    private StoreImg activityDetailImg;
+
+    @ApiModelProperty(value = "活动标题图片")
+    private String activityTitleImgUrl;
+
+    @ApiModelProperty(value = "活动详情图片")
+    private String activityDetailImgUrl;
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/storePlantform/StoreOperationalActivityMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper.storePlantform;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.storePlatform.StoreOperationalActivity;
+
+/**
+ * 运营活动 Mapper 接口
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Mapper
+public interface StoreOperationalActivityMapper extends BaseMapper<StoreOperationalActivity> {
+
+}
+

+ 32 - 0
alien-entity/src/main/resources/mapper/storePlatform/StoreOperationalActivityMapper.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="shop.alien.mapper.storePlantform.StoreOperationalActivityMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="shop.alien.entity.storePlatform.StoreOperationalActivity">
+        <id column="id" property="id" />
+        <result column="store_id" property="storeId" />
+        <result column="activity_name" property="activityName" />
+        <result column="promotional_image" property="promotionalImage" />
+        <result column="start_time" property="startTime" />
+        <result column="end_time" property="endTime" />
+        <result column="participation_limit" property="participationLimit" />
+        <result column="activity_rule" property="activityRule" />
+        <result column="reward_type" property="rewardType" />
+        <result column="coupon_id" property="couponId" />
+        <result column="coupon_quantity" property="couponQuantity" />
+        <result column="status" property="status" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="created_time" property="createdTime" />
+        <result column="created_user_id" property="createdUserId" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="updated_user_id" property="updatedUserId" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, store_id, activity_name, promotional_image, start_time, end_time, participation_limit, activity_rule, reward_type, coupon_id, coupon_quantity, status, delete_flag, created_time, created_user_id, updated_time, updated_user_id
+    </sql>
+
+</mapper>
+

+ 285 - 0
alien-store-platform/doc/OPERATIONAL_ACTIVITY_README.md

@@ -0,0 +1,285 @@
+# 运营活动管理模块
+
+## 功能说明
+
+本模块用于管理商户的运营活动,支持活动的创建、查询、更新和删除操作。活动可以设置参与规则、奖励类型、优惠券等信息。
+
+---
+
+## 数据库表结构
+
+### store_operational_activity 表
+
+```sql
+CREATE TABLE `store_operational_activity` (
+    `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `store_id` int NULL COMMENT '商户ID',
+    `activity_name` VARCHAR(100) NOT NULL COMMENT '活动名称',
+    `promotional_image` VARCHAR(500) DEFAULT NULL COMMENT '活动宣传图URL',
+    `start_time` DATETIME NOT NULL COMMENT '活动开始时间',
+    `end_time` DATETIME NOT NULL COMMENT '活动结束时间',
+    `participation_limit` int DEFAULT 0 COMMENT '用户可参与次数,0表示不限制',
+    `activity_rule` VARCHAR(50) NOT NULL COMMENT '活动规则:VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡',
+    `reward_type` VARCHAR(50) DEFAULT NULL COMMENT '奖励类型:COUPON-优惠券, RED_PACKET-红包',
+    `coupon_id` int DEFAULT NULL COMMENT '优惠券ID,关联优惠券表',
+    `coupon_quantity` int DEFAULT NULL COMMENT '优惠券发放数量',
+    `status` int DEFAULT 1 COMMENT '状态:0-禁用, 1-启用',
+    `delete_flag` int NOT NULL DEFAULT '0' COMMENT '删除标记, 0:未删除, 1:已删除',
+    `created_time` datetime(1) NOT NULL COMMENT '创建时间',
+    `created_user_id` int DEFAULT NULL COMMENT '创建人ID',
+    `updated_time` datetime DEFAULT NULL COMMENT '修改时间',
+    `updated_user_id` int DEFAULT NULL COMMENT '修改人ID',
+    PRIMARY KEY (`id`),
+    INDEX `idx_activity_time` (`start_time`, `end_time`),
+    INDEX `idx_status` (`status`, `delete_flag`),
+    INDEX `idx_coupon_id` (`coupon_id`),
+    INDEX `idx_create_time` (`created_time`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='运营活动表';
+```
+
+---
+
+## 文件清单
+
+### 1. Entity(实体类)
+**路径**: `alien-entity/src/main/java/shop/alien/entity/store/StoreOperationalActivity.java`
+
+**功能**: 运营活动实体类,对应数据库表 `store_operational_activity`
+
+**主要字段**:
+- `id`: 主键
+- `storeId`: 商户ID
+- `activityName`: 活动名称
+- `promotionalImage`: 活动宣传图URL
+- `startTime`: 活动开始时间
+- `endTime`: 活动结束时间
+- `participationLimit`: 用户可参与次数(0表示不限制)
+- `activityRule`: 活动规则(VERIFY_AND_COMMENT-核销并评论, VERIFY-核销, CHECK_IN-打卡)
+- `rewardType`: 奖励类型(COUPON-优惠券, RED_PACKET-红包)
+- `couponId`: 优惠券ID
+- `couponQuantity`: 优惠券发放数量
+- `status`: 状态(0-禁用, 1-启用)
+- `deleteFlag`: 删除标记(逻辑删除)
+- `createdTime`: 创建时间(自动填充)
+- `createdUserId`: 创建人ID
+- `updatedTime`: 修改时间(自动填充)
+- `updatedUserId`: 修改人ID
+
+---
+
+### 2. DTO(数据传输对象)
+**路径**: `alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOperationalActivityDTO.java`
+
+**功能**: 用于接收前端请求参数,包含参数校验
+
+**校验规则**:
+- `activityName`: 必填,不能为空
+- `startTime`: 必填,不能为空
+- `endTime`: 必填,不能为空
+- `activityRule`: 必填,不能为空
+- 其他字段可选
+
+---
+
+### 3. VO(视图对象)
+**路径**: `alien-entity/src/main/java/shop/alien/entity/store/vo/StoreOperationalActivityVO.java`
+
+**功能**: 用于返回给前端的数据对象,继承自实体类并扩展了额外字段
+
+**扩展字段**:
+- `statusName`: 状态名称
+- `activityRuleName`: 活动规则名称
+- `rewardTypeName`: 奖励类型名称
+- `couponName`: 优惠券名称
+- `storeName`: 商户名称
+- `activityStatus`: 活动状态(0-未开始, 1-进行中, 2-已结束)
+- `participationCount`: 已参与人数
+- `remainingCouponQuantity`: 剩余优惠券数量
+
+---
+
+### 4. Mapper(数据访问层)
+**路径**: `alien-entity/src/main/java/shop/alien/mapper/StoreOperationalActivityMapper.java`
+
+**功能**: 继承 MyBatis-Plus 的 `BaseMapper`,提供基础 CRUD 操作
+
+---
+
+### 5. Mapper XML(映射文件)
+**路径**: `alien-entity/src/main/resources/mapper/StoreOperationalActivityMapper.xml`
+
+**功能**: MyBatis 映射配置文件,定义结果集映射和通用 SQL
+
+---
+
+### 6. Service(服务接口)
+**路径**: `alien-store-platform/src/main/java/shop/alien/storeplatform/service/OperationalActivityService.java`
+
+**功能**: 定义运营活动业务逻辑接口
+
+**方法列表**:
+- `createActivity(StoreOperationalActivityDTO dto)`: 创建运营活动
+- `updateActivity(StoreOperationalActivityDTO dto)`: 更新运营活动
+- `deleteActivity(Integer id)`: 删除运营活动(逻辑删除)
+- `getActivityById(Integer id)`: 根据ID获取活动详情
+- `getActivityListByStoreId(Integer storeId)`: 根据商户ID获取活动列表
+- `getActivityPage(Integer current, Integer size, Integer storeId, Integer status)`: 分页查询活动列表
+- `updateActivityStatus(Integer id, Integer status)`: 启用/禁用活动
+- `getOngoingActivities(Integer storeId)`: 获取进行中的活动列表
+
+---
+
+### 7. ServiceImpl(服务实现类)
+**路径**: `alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/OperationalActivityServiceImpl.java`
+
+**功能**: 实现运营活动业务逻辑
+
+**核心功能**:
+- 活动的增删改查
+- 实体与VO对象的转换
+- 活动状态的自动判断(未开始/进行中/已结束)
+- 活动规则和奖励类型的中文名称转换
+
+---
+
+### 8. Controller(控制器)
+**路径**: `alien-store-platform/src/main/java/shop/alien/storeplatform/controller/OperationalActivityController.java`
+
+**功能**: 提供运营活动管理的 REST API 接口
+
+**API 列表**:
+
+#### 8.1 创建运营活动
+- **接口**: `POST /operationalActivity/create`
+- **参数**: StoreOperationalActivityDTO(JSON)
+- **返回**: R<String>
+
+#### 8.2 更新运营活动
+- **接口**: `POST /operationalActivity/update`
+- **参数**: StoreOperationalActivityDTO(JSON)
+- **返回**: R<String>
+
+#### 8.3 删除运营活动
+- **接口**: `DELETE /operationalActivity/delete`
+- **参数**: id(活动ID)
+- **返回**: R<String>
+
+#### 8.4 根据ID获取活动详情
+- **接口**: `GET /operationalActivity/detail`
+- **参数**: id(活动ID)
+- **返回**: R<StoreOperationalActivityVO>
+
+#### 8.5 根据商户ID获取活动列表
+- **接口**: `GET /operationalActivity/list`
+- **参数**: storeId(商户ID)
+- **返回**: R<List<StoreOperationalActivityVO>>
+
+#### 8.6 分页查询活动列表
+- **接口**: `GET /operationalActivity/page`
+- **参数**: 
+  - current(当前页,默认1)
+  - size(每页大小,默认10)
+  - storeId(商户ID,可选)
+  - status(状态,可选)
+- **返回**: R<IPage<StoreOperationalActivityVO>>
+
+#### 8.7 启用/禁用活动
+- **接口**: `POST /operationalActivity/updateStatus`
+- **参数**: 
+  - id(活动ID)
+  - status(状态:0-禁用, 1-启用)
+- **返回**: R<String>
+
+#### 8.8 获取进行中的活动列表
+- **接口**: `GET /operationalActivity/ongoing`
+- **参数**: storeId(商户ID)
+- **返回**: R<List<StoreOperationalActivityVO>>
+
+---
+
+## 使用示例
+
+### 创建活动
+
+```json
+POST /operationalActivity/create
+
+{
+  "storeId": 1,
+  "activityName": "双十一优惠活动",
+  "promotionalImage": "https://example.com/image.jpg",
+  "startTime": "2025-11-11 00:00:00",
+  "endTime": "2025-11-11 23:59:59",
+  "participationLimit": 1,
+  "activityRule": "VERIFY_AND_COMMENT",
+  "rewardType": "COUPON",
+  "couponId": 100,
+  "couponQuantity": 1000,
+  "status": 1
+}
+```
+
+### 查询活动列表
+
+```
+GET /operationalActivity/list?storeId=1
+```
+
+### 分页查询
+
+```
+GET /operationalActivity/page?current=1&size=10&storeId=1&status=1
+```
+
+---
+
+## 数据字典
+
+### 活动规则(activity_rule)
+- `VERIFY_AND_COMMENT`: 核销并评论
+- `VERIFY`: 核销
+- `CHECK_IN`: 打卡
+
+### 奖励类型(reward_type)
+- `COUPON`: 优惠券
+- `RED_PACKET`: 红包
+
+### 活动状态(status)
+- `0`: 禁用
+- `1`: 启用
+
+### 活动进行状态(activityStatus)
+- `0`: 未开始
+- `1`: 进行中
+- `2`: 已结束
+
+---
+
+## 注意事项
+
+1. **时间校验**: 创建活动时,需要确保结束时间晚于开始时间
+2. **逻辑删除**: 删除操作为逻辑删除,不会真正删除数据
+3. **状态管理**: 活动状态由系统根据当前时间自动判断
+4. **参数校验**: DTO 中包含必填项校验,需要确保必填字段不为空
+5. **优惠券关联**: 如果奖励类型为优惠券,需要填写 couponId 和 couponQuantity
+
+---
+
+## 扩展建议
+
+1. **用户参与记录**: 可以创建用户参与活动记录表,跟踪用户参与情况
+2. **活动统计**: 添加活动效果统计功能,如参与人数、发放优惠券数量等
+3. **活动审核**: 添加活动审核流程,确保活动内容合规
+4. **活动推送**: 集成消息推送功能,在活动开始时通知用户
+5. **活动模板**: 提供常用活动模板,简化活动创建流程
+
+---
+
+## 更新日志
+
+### 2025-11-26
+- 初始版本发布
+- 实现基础的增删改查功能
+- 支持活动状态管理
+- 支持分页查询
+

+ 145 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/OperationalActivityController.java

@@ -0,0 +1,145 @@
+package shop.alien.storeplatform.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityDTO;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+import shop.alien.storeplatform.service.OperationalActivityService;
+
+import java.util.List;
+
+/**
+ * 运营活动管理控制器
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Slf4j
+@Api(tags = {"商家端-运营活动管理"})
+@ApiSort(10)
+@CrossOrigin
+@RestController
+@RequestMapping("/operationalActivity")
+@RequiredArgsConstructor
+public class OperationalActivityController {
+
+    private final OperationalActivityService activityService;
+
+    @ApiOperation("创建运营活动")
+    @ApiOperationSupport(order = 1)
+    @PostMapping("/create")
+    public R<String> createActivity(@RequestBody StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityController.createActivity: dto={}", dto);
+        try {
+            int result = activityService.createActivity(dto);
+            if (result > 0) {
+                return R.success("活动创建成功");
+            }
+            return R.fail("活动创建失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.createActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("更新运营活动")
+    @ApiOperationSupport(order = 2)
+    @PostMapping("/update")
+    public R<String> updateActivity(@RequestBody StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityController.updateActivity: dto={}", dto);
+        try {
+            int result = activityService.updateActivity(dto);
+            if (result > 0) {
+                return R.success("活动更新成功");
+            }
+            return R.fail("活动更新失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.updateActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("删除运营活动")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "活动ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> deleteActivity(@RequestParam("id") Integer id) {
+        log.info("OperationalActivityController.deleteActivity: id={}", id);
+        try {
+            int result = activityService.deleteActivity(id);
+            if (result > 0) {
+                return R.success("活动删除成功");
+            }
+            return R.fail("活动删除失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.deleteActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("根据ID获取活动详情")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "活动ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/queryActivityById")
+    public R<StoreOperationalActivityVO> queryActivityById(@RequestParam("id") Integer id) {
+        log.info("OperationalActivityController.getActivityById: id={}", id);
+        try {
+            StoreOperationalActivityVO result = activityService.queryActivityById(id);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("OperationalActivityController.getActivityById ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("根据商户ID获取活动列表")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "商户ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/queryActivityList")
+    public R<IPage<StoreOperationalActivityVO>> queryActivityList(@RequestBody StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityController.queryActivityList: storeId={}, status={}, activityName={}", dto.getStoreId(), dto.getStatus(), dto.getActivityName());
+        try {
+            IPage<StoreOperationalActivityVO> result = activityService.queryActivityList( dto.getStoreId(), dto.getStatus(), dto.getActivityName(), dto.getPageNum(), dto.getPageSize());
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("OperationalActivityController.qeryActivityList ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+
+    @ApiOperation("启用/禁用活动")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "活动ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "status", value = "状态:0-禁用, 1-启用", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/updateStatus")
+    public R<String> updateActivityStatus(
+            @RequestParam("id") Integer id,
+            @RequestParam("status") Integer status) {
+        log.info("OperationalActivityController.updateActivityStatus: id={}, status={}", id, status);
+        try {
+            int result = activityService.updateActivityStatus(id, status);
+            if (result > 0) {
+                return R.success("状态更新成功");
+            }
+            return R.fail("状态更新失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.updateActivityStatus ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+}
+

+ 71 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/OperationalActivityService.java

@@ -0,0 +1,71 @@
+package shop.alien.storeplatform.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityDTO;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+
+import java.util.List;
+
+/**
+ * 运营活动服务接口
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+public interface OperationalActivityService {
+
+    /**
+     * 创建运营活动
+     *
+     * @param dto 活动信息
+     * @return 创建结果
+     */
+    int createActivity(StoreOperationalActivityDTO dto);
+
+    /**
+     * 更新运营活动
+     *
+     * @param dto 活动信息
+     * @return 更新结果
+     */
+    int updateActivity(StoreOperationalActivityDTO dto);
+
+    /**
+     * 删除运营活动(逻辑删除)
+     *
+     * @param id 活动ID
+     * @return 删除结果
+     */
+    int deleteActivity(Integer id);
+
+    /**
+     * 根据ID获取活动详情
+     *
+     * @param id 活动ID
+     * @return 活动详情
+     */
+    StoreOperationalActivityVO queryActivityById(Integer id);
+
+    /**
+     * 分页查询活动列表
+     *
+     * @param storeId      商户ID
+     * @param status       状态
+     * @param activityName 活动名称
+     * @param pageNum      页码
+     * @param pageSize     每页大小
+     * @return 分页结果
+     */
+    IPage<StoreOperationalActivityVO> queryActivityList(Integer storeId, Integer status, String activityName, Integer pageNum, Integer pageSize);
+
+    /**
+     * 启用/禁用活动
+     *
+     * @param id     活动ID
+     * @param status 状态:0-禁用, 1-启用
+     * @return 更新结果
+     */
+    int updateActivityStatus(Integer id, Integer status);
+
+}
+

+ 300 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/OperationalActivityServiceImpl.java

@@ -0,0 +1,300 @@
+package shop.alien.storeplatform.service.impl;
+
+import com.alibaba.excel.util.StringUtils;
+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 lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.LifeDiscountCoupon;
+import shop.alien.entity.store.LifeUser;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.entity.store.StoreUser;
+import shop.alien.entity.storePlatform.StoreOperationalActivity;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityDTO;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+import shop.alien.mapper.LifeDiscountCouponMapper;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
+import shop.alien.storeplatform.service.OperationalActivityService;
+
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 运营活动服务实现类
+ * <p>
+ * 提供运营活动的增删改查功能,包括:
+ * 1. 活动的创建、更新、删除
+ * 2. 活动列表查询、分页查询
+ * 3. 活动状态管理
+ * </p>
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class OperationalActivityServiceImpl implements OperationalActivityService {
+
+    private final StoreOperationalActivityMapper activityMapper;
+
+    private final StoreImgMapper imgMapper;
+
+    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
+
+    @Override
+    public int createActivity(StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityServiceImpl.createActivity: dto={}", dto);
+        
+        StoreOperationalActivity activity = new StoreOperationalActivity();
+        BeanUtils.copyProperties(dto, activity);
+        
+        // 设置默认值
+        if (activity.getParticipationLimit() == null) {
+            activity.setParticipationLimit(0);
+        }
+        if (activity.getStatus() == null) {
+            activity.setStatus(1);
+        }
+        Integer result = activityMapper.insert(activity);
+        if (result > 0) {
+            dto.getActivityTitleImg().setBusinessId(activity.getId());
+            dto.getActivityTitleImg().setImgType(26);
+            imgMapper.insert(dto.getActivityTitleImg());
+
+            dto.getActivityDetailImg().setBusinessId(activity.getId());
+            dto.getActivityDetailImg().setImgType(27);
+            imgMapper.insert(dto.getActivityDetailImg());
+        }
+        
+        return result;
+    }
+
+    @Override
+    public int updateActivity(StoreOperationalActivityDTO dto) {
+        log.info("OperationalActivityServiceImpl.updateActivity: dto={}", dto);
+        
+        if (dto.getId() == null) {
+            throw new IllegalArgumentException("活动ID不能为空");
+        }
+        
+        StoreOperationalActivity activity = new StoreOperationalActivity();
+        BeanUtils.copyProperties(dto, activity);
+        Integer result = activityMapper.updateById(activity);
+
+        // 添加
+        if (result > 0) {
+            // 删除原本的图片
+            LambdaUpdateWrapper<StoreImg> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(StoreImg::getBusinessId, dto.getId())
+                    .eq(StoreImg::getStoreId, dto.getStoreId())
+                    .set(StoreImg::getDeleteFlag, 1);
+            imgMapper.update(null, wrapper);
+
+
+
+            // 插入新图片
+            StoreImg activityTitleImg = new StoreImg();
+            activityTitleImg.setStoreId(dto.getStoreId());
+            activityTitleImg.setImgType(26);
+            activityTitleImg.setImgSort(dto.getActivityTitleImg().getImgSort());
+            activityTitleImg.setImgUrl(dto.getActivityTitleImg().getImgUrl());
+            activityTitleImg.setBusinessId(dto.getId());
+            imgMapper.insert(activityTitleImg);
+
+            // 插入新图片
+            StoreImg activityDetailImg = new StoreImg();
+            activityDetailImg.setStoreId(dto.getStoreId());
+            activityDetailImg.setImgType(27);
+            activityDetailImg.setImgSort(dto.getActivityDetailImg().getImgSort());
+            activityDetailImg.setImgUrl(dto.getActivityDetailImg().getImgUrl());
+            activityDetailImg.setBusinessId(dto.getId());
+            imgMapper.insert(activityDetailImg);
+        }
+        return result;
+    }
+
+    @Override
+    public int deleteActivity(Integer id) {
+        log.info("OperationalActivityServiceImpl.deleteActivity: id={}", id);
+        
+        if (id == null) {
+            throw new IllegalArgumentException("活动ID不能为空");
+        }
+        
+        // 逻辑删除
+        return activityMapper.deleteById(id);
+    }
+
+    @Override
+    public StoreOperationalActivityVO queryActivityById(Integer id) {
+        log.info("OperationalActivityServiceImpl.getActivityById: id={}", id);
+        
+        if (id == null) {
+            throw new IllegalArgumentException("活动ID不能为空");
+        }
+        
+        StoreOperationalActivity activity = activityMapper.selectById(id);
+
+        if (activity == null) {
+            return null;
+        }
+
+        // 创建实体类
+        StoreOperationalActivityVO vo = new StoreOperationalActivityVO();
+        BeanUtils.copyProperties(activity, vo);
+
+        if (activity.getStatus() == 1) {
+            vo.setStatusName("待审核");
+        } else if (activity.getStatus() == 2) {
+            vo.setStatusName("未开始");
+        } else if (activity.getStatus() == 3) {
+            vo.setStatusName("审核拒绝");
+        } else if (activity.getStatus() == 4) {
+            vo.setStatusName("已售罄");
+        } else if (activity.getStatus() == 5) {
+            vo.setStatusName("进行中");
+        } else if (activity.getStatus() == 6) {
+            vo.setStatusName("已下架");
+        } else if (activity.getStatus() == 7) {
+            vo.setStatusName("已结束");
+        }
+        
+        // 设置优惠券名称(判空处理)
+        if (activity.getCouponId() != null) {
+            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(activity.getCouponId());
+            if (coupon != null) {
+                vo.setCouponName(coupon.getName());
+            }
+        }
+
+        StoreImg activityTitleImg = imgMapper.selectOne(new LambdaQueryWrapper<StoreImg>()
+                .eq(StoreImg::getStoreId, vo.getStoreId())
+                .eq(StoreImg::getImgType, 26)
+                .eq(StoreImg::getDeleteFlag, 0)
+                .eq(StoreImg::getBusinessId, activity.getId()));
+        if (activityTitleImg != null) {
+            vo.setActivityTitleImgUrl(activityTitleImg.getImgUrl());
+        }
+
+
+        StoreImg activityDetailImg = imgMapper.selectOne(new LambdaQueryWrapper<StoreImg>()
+                .eq(StoreImg::getStoreId, vo.getStoreId())
+                .eq(StoreImg::getImgType, 27)
+                .eq(StoreImg::getDeleteFlag, 0)
+                .eq(StoreImg::getBusinessId, activity.getId()));
+        if (activityDetailImg != null) {
+            vo.setActivityDetailImgUrl(activityDetailImg.getImgUrl());
+        }
+
+        return vo;
+    }
+
+
+    @Override
+    public IPage<StoreOperationalActivityVO> queryActivityList(Integer storeId, Integer status, String activityName, Integer pageNum, Integer pageSize) {
+        log.info("OperationalActivityServiceImpl.queryActivityList: storeId={}, status={}, activityName={}, pageNum={}, pageSize={}", 
+                storeId, status, activityName, pageNum, pageSize);
+        
+        LambdaQueryWrapper<StoreOperationalActivity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(storeId != null, StoreOperationalActivity::getStoreId, storeId);
+        wrapper.like(activityName != null && activityName != "", StoreOperationalActivity::getActivityName, activityName);
+        wrapper.eq(status != null, StoreOperationalActivity::getStatus, status);
+
+        IPage<StoreOperationalActivity> list = activityMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
+        
+        // 将list复制到vo
+        List<StoreOperationalActivityVO> voRecords = new ArrayList<>();
+        
+        for (StoreOperationalActivity activity : list.getRecords()) {
+            // 创建实体类
+            StoreOperationalActivityVO vo = new StoreOperationalActivityVO();
+            BeanUtils.copyProperties(activity, vo);
+
+            if (activity.getStatus() == 1) {
+                vo.setStatusName("待审核");
+            } else if (activity.getStatus() == 2) {
+                vo.setStatusName("未开始");
+            } else if (activity.getStatus() == 3) {
+                vo.setStatusName("审核拒绝");
+            } else if (activity.getStatus() == 4) {
+                vo.setStatusName("已售罄");
+            } else if (activity.getStatus() == 5) {
+                vo.setStatusName("进行中");
+            } else if (activity.getStatus() == 6) {
+                vo.setStatusName("已下架");
+            } else if (activity.getStatus() == 7) {
+                vo.setStatusName("已结束");
+            }
+
+            vo.setCouponName(lifeDiscountCouponMapper.selectById(activity.getCouponId()).getName());
+
+            voRecords.add(vo);
+        }
+        
+        // 创建分页结果对象
+        Page<StoreOperationalActivityVO> voList = new Page<>(list.getCurrent(), list.getSize(), list.getTotal());
+        voList.setRecords(voRecords);
+        
+        return voList;
+    }
+
+    public static void main(String[] args) {
+        // 时间格式化
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+        Date now = new Date();
+        System.out.println("当前时间: " + sdf.format(now));
+        
+        // 获取当天零点零分零秒时间
+        Calendar todayStart = Calendar.getInstance();
+        todayStart.setTime(now);
+        todayStart.set(Calendar.HOUR_OF_DAY, 0);
+        todayStart.set(Calendar.MINUTE, 0);
+        todayStart.set(Calendar.SECOND, 0);
+        todayStart.set(Calendar.MILLISECOND, 0);
+        Date todayZero = todayStart.getTime();
+        System.out.println("当天零点时间: " + sdf.format(todayZero));
+        
+        // now + 1天(零点)
+        Calendar calendarPlus = Calendar.getInstance();
+        calendarPlus.setTime(now);
+        calendarPlus.add(Calendar.DAY_OF_MONTH, 1);
+        calendarPlus.set(Calendar.HOUR_OF_DAY, 0);
+        calendarPlus.set(Calendar.MINUTE, 0);
+        calendarPlus.set(Calendar.SECOND, 0);
+        calendarPlus.set(Calendar.MILLISECOND, 0);
+        Date nowPlusOneDay = calendarPlus.getTime();
+        System.out.println("当前时间+1天(零点): " + sdf.format(nowPlusOneDay));
+
+    }
+
+    @Override
+    public int updateActivityStatus(Integer id, Integer status) {
+        log.info("OperationalActivityServiceImpl.updateActivityStatus: id={}, status={}", id, status);
+        
+        if (id == null) {
+            throw new IllegalArgumentException("活动ID不能为空");
+        }
+        
+        StoreOperationalActivity activity = new StoreOperationalActivity();
+        activity.setId(id);
+        activity.setStatus(status);
+        
+        return activityMapper.updateById(activity);
+    }
+}
+