From c40d7aabcbba7aa5f20d4f067b04d59a8e02d0f9 Mon Sep 17 00:00:00 2001 From: cst61 Date: Wed, 3 Jun 2026 12:43:07 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=89=E4=B8=9D=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FanManagementController.java | 89 +++++++ .../java/com/rj/entity/FanManagement.java | 59 +++++ .../com/rj/mapper/FanManagementMapper.java | 12 + .../com/rj/service/IFanManagementService.java | 27 +++ .../java/com/rj/service/ILbGoodsService.java | 2 +- .../impl/FanManagementServiceImpl.java | 223 ++++++++++++++++++ .../rj/service/impl/LbGoodsServiceImpl.java | 4 +- src/main/sql/fan_management.sql | 22 ++ 8 files changed, 435 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/rj/controller/FanManagementController.java create mode 100644 src/main/java/com/rj/entity/FanManagement.java create mode 100644 src/main/java/com/rj/mapper/FanManagementMapper.java create mode 100644 src/main/java/com/rj/service/IFanManagementService.java create mode 100644 src/main/java/com/rj/service/impl/FanManagementServiceImpl.java create mode 100644 src/main/sql/fan_management.sql diff --git a/src/main/java/com/rj/controller/FanManagementController.java b/src/main/java/com/rj/controller/FanManagementController.java new file mode 100644 index 0000000..8370ed1 --- /dev/null +++ b/src/main/java/com/rj/controller/FanManagementController.java @@ -0,0 +1,89 @@ +package com.rj.controller; + +import com.rj.entity.FanManagement; +import com.rj.service.IFanManagementService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +/** + * 粉丝管理(fan_management)前端控制器 + */ +@RestController +@RequestMapping("/api/fanManagement") +@Tag(name = "粉丝管理", description = "fan_management 增删改查与分页") +public class FanManagementController { + + @Autowired + private IFanManagementService fanManagementService; + + @PostMapping("/add") + @Operation(summary = "新增粉丝") + public ResponseEntity> add( + @Parameter(description = "粉丝实体(id 必填)", required = true) + @RequestBody FanManagement entity) { + Map result = fanManagementService.add(entity); + return toResponse(result); + } + + @PutMapping("/update") + @Operation(summary = "修改粉丝") + public ResponseEntity> update( + @Parameter(description = "粉丝实体(id 必填)", required = true) + @RequestBody FanManagement entity) { + Map result = fanManagementService.update(entity); + return toResponse(result); + } + + @DeleteMapping("/delete/{id}") + @Operation(summary = "删除粉丝") + public ResponseEntity> delete( + @Parameter(description = "粉丝ID", required = true) @PathVariable Long id) { + Map result = fanManagementService.deleteById(id); + return toResponse(result); + } + + @GetMapping("/list") + @Operation(summary = "分页查询粉丝") + public ResponseEntity> list( + @RequestParam(defaultValue = "1") Integer current, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String nickname, + @RequestParam(required = false) String mobile, + @RequestParam(required = false) Integer shareNumMin, + @RequestParam(required = false) Integer shareNumMax, + @Parameter(description = "创建时间起,格式 yyyy-MM-dd HH:mm:ss") + @RequestParam(required = false) String createdAtStart, + @Parameter(description = "创建时间止,格式 yyyy-MM-dd HH:mm:ss") + @RequestParam(required = false) String createdAtEnd) { + Map result = fanManagementService.pageQuery( + current, size, nickname, mobile, shareNumMin, shareNumMax, + createdAtStart, createdAtEnd); + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + if (result.get("message") != null + && result.get("message").toString().contains("格式错误")) { + return ResponseEntity.badRequest().body(result); + } + return ResponseEntity.internalServerError().body(result); + } + + private ResponseEntity> toResponse(Map result) { + Boolean success = (Boolean) result.get("success"); + if (success != null && success) { + return ResponseEntity.ok(result); + } + String message = result.get("message") != null ? result.get("message").toString() : ""; + if (message.contains("不能为空") || message.contains("格式错误")) { + return ResponseEntity.badRequest().body(result); + } + return ResponseEntity.badRequest().body(result); + } +} diff --git a/src/main/java/com/rj/entity/FanManagement.java b/src/main/java/com/rj/entity/FanManagement.java new file mode 100644 index 0000000..9a598d5 --- /dev/null +++ b/src/main/java/com/rj/entity/FanManagement.java @@ -0,0 +1,59 @@ +package com.rj.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 粉丝管理表 fan_management + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("fan_management") +@Schema(description = "粉丝管理") +@JsonIgnoreProperties(ignoreUnknown = true) +public class FanManagement implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 粉丝 id(与 {@link #tenantId} 组成复合主键 {@code (tenant_id, id)})。 + */ + @TableId(value = "id", type = IdType.INPUT) + @Schema(description = "粉丝ID(复合主键之一,须与 tenantId 一起使用)") + private Long id; + + @TableField("tenant_id") + @Schema(description = "租户ID") + private String tenantId; + + @TableField("avatar") + @Schema(description = "头像路径") + private String avatar; + + @TableField("nickname") + @Schema(description = "昵称") + private String nickname; + + @TableField("mobile") + @Schema(description = "手机号") + private String mobile; + + @TableField("created_at") + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createdAt; + + @TableField("share_num") + @Schema(description = "分享次数") + private Integer shareNum; +} diff --git a/src/main/java/com/rj/mapper/FanManagementMapper.java b/src/main/java/com/rj/mapper/FanManagementMapper.java new file mode 100644 index 0000000..7a00d67 --- /dev/null +++ b/src/main/java/com/rj/mapper/FanManagementMapper.java @@ -0,0 +1,12 @@ +package com.rj.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.rj.entity.FanManagement; +import org.apache.ibatis.annotations.Mapper; + +/** + * 粉丝管理表 Mapper + */ +@Mapper +public interface FanManagementMapper extends BaseMapper { +} diff --git a/src/main/java/com/rj/service/IFanManagementService.java b/src/main/java/com/rj/service/IFanManagementService.java new file mode 100644 index 0000000..005ab72 --- /dev/null +++ b/src/main/java/com/rj/service/IFanManagementService.java @@ -0,0 +1,27 @@ +package com.rj.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.rj.entity.FanManagement; + +import java.util.Map; + +/** + * 粉丝管理服务 + */ +public interface IFanManagementService extends IService { + + Map add(FanManagement entity); + + Map update(FanManagement entity); + + Map deleteById(Long id); + + Map pageQuery(Integer current, + Integer size, + String nickname, + String mobile, + Integer shareNumMin, + Integer shareNumMax, + String createdAtStart, + String createdAtEnd); +} diff --git a/src/main/java/com/rj/service/ILbGoodsService.java b/src/main/java/com/rj/service/ILbGoodsService.java index 13e9f93..d602be6 100644 --- a/src/main/java/com/rj/service/ILbGoodsService.java +++ b/src/main/java/com/rj/service/ILbGoodsService.java @@ -48,7 +48,7 @@ public interface ILbGoodsService extends IService { * 成功笔数达到 {@code maxBuyCount} 后停止,且循环抢购总次数不超过 {@code maxBuyCount} 的5倍。 * * @param token 可选;非空时作为请求头 token,否则使用 {@code lb_third_integration_config} 中的 goodsApiToken - * @param rushBuyAccountLabel 可选;批量账号抢单时传入,用于日志标识当前抢单账号 + * @param ;批量账号抢单时传入,用于日志标识当前抢单账号 */ default Map rushBuy(String tenantId, String token, Integer maxBuyCount) { return rushBuy(tenantId, token, maxBuyCount, null); diff --git a/src/main/java/com/rj/service/impl/FanManagementServiceImpl.java b/src/main/java/com/rj/service/impl/FanManagementServiceImpl.java new file mode 100644 index 0000000..16d8de5 --- /dev/null +++ b/src/main/java/com/rj/service/impl/FanManagementServiceImpl.java @@ -0,0 +1,223 @@ +package com.rj.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.rj.entity.FanManagement; +import com.rj.mapper.FanManagementMapper; +import com.rj.service.IFanManagementService; +import com.rj.tenant.TenantContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; + +/** + * 粉丝管理服务实现 + */ +@Slf4j +@Service +public class FanManagementServiceImpl + extends ServiceImpl + implements IFanManagementService { + + private static final DateTimeFormatter DATE_TIME_FORMATTER = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + @Override + public Map add(FanManagement entity) { + Map result = new HashMap<>(); + try { + if (entity.getId() == null) { + result.put("success", false); + result.put("message", "粉丝ID不能为空"); + return result; + } + trimStringFields(entity); + if (entity.getShareNum() == null) { + entity.setShareNum(0); + } + if (entity.getCreatedAt() == null) { + entity.setCreatedAt(LocalDateTime.now()); + } + fillTenantIdIfAbsent(entity); + + boolean ok = this.save(entity); + result.put("success", ok); + result.put("message", ok ? "新增成功" : "新增失败"); + if (ok) { + result.put("data", entity); + } + return result; + } catch (Exception e) { + log.error("粉丝管理新增异常", e); + result.put("success", false); + result.put("message", "新增异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map update(FanManagement entity) { + Map result = new HashMap<>(); + try { + if (entity.getId() == null) { + result.put("success", false); + result.put("message", "粉丝ID不能为空"); + return result; + } + trimStringFields(entity); + fillTenantIdIfAbsent(entity); + + boolean ok = this.updateById(entity); + result.put("success", ok); + result.put("message", ok ? "修改成功" : "修改失败,记录可能不存在"); + if (ok) { + result.put("data", getOneByIdAndTenant(entity.getId(), entity.getTenantId())); + } + return result; + } catch (Exception e) { + log.error("粉丝管理修改异常", e); + result.put("success", false); + result.put("message", "修改异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map deleteById(Long id) { + Map result = new HashMap<>(); + try { + if (id == null) { + result.put("success", false); + result.put("message", "粉丝ID不能为空"); + return result; + } + boolean ok = this.removeById(id); + result.put("success", ok); + result.put("message", ok ? "删除成功" : "删除失败,记录可能不存在"); + return result; + } catch (Exception e) { + log.error("粉丝管理删除异常, id={}", id, e); + result.put("success", false); + result.put("message", "删除异常:" + e.getMessage()); + return result; + } + } + + @Override + public Map pageQuery(Integer current, + Integer size, + String nickname, + String mobile, + Integer shareNumMin, + Integer shareNumMax, + String createdAtStart, + String createdAtEnd) { + Map result = new HashMap<>(); + try { + if (current == null || current < 1) { + current = 1; + } + if (size == null || size < 1) { + size = 10; + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (nickname != null && !nickname.trim().isEmpty()) { + queryWrapper.like(FanManagement::getNickname, nickname.trim()); + } + if (mobile != null && !mobile.trim().isEmpty()) { + queryWrapper.like(FanManagement::getMobile, mobile.trim()); + } + if (shareNumMin != null) { + queryWrapper.ge(FanManagement::getShareNum, shareNumMin); + } + if (shareNumMax != null) { + queryWrapper.le(FanManagement::getShareNum, shareNumMax); + } + + LocalDateTime start = parseDateTime(createdAtStart); + if (createdAtStart != null && !createdAtStart.trim().isEmpty() && start == null) { + result.put("success", false); + result.put("message", "createdAtStart 格式错误,请使用 yyyy-MM-dd HH:mm:ss"); + return result; + } + LocalDateTime end = parseDateTime(createdAtEnd); + if (createdAtEnd != null && !createdAtEnd.trim().isEmpty() && end == null) { + result.put("success", false); + result.put("message", "createdAtEnd 格式错误,请使用 yyyy-MM-dd HH:mm:ss"); + return result; + } + if (start != null) { + queryWrapper.ge(FanManagement::getCreatedAt, start); + } + if (end != null) { + queryWrapper.le(FanManagement::getCreatedAt, end); + } + queryWrapper.orderByDesc(FanManagement::getCreatedAt); + + Page page = this.page(new Page<>(current, size), queryWrapper); + result.put("success", true); + result.put("message", "查询成功"); + result.put("data", page.getRecords()); + result.put("total", page.getTotal()); + result.put("current", page.getCurrent()); + result.put("size", page.getSize()); + result.put("pages", page.getPages()); + return result; + } catch (Exception e) { + log.error("粉丝管理分页查询异常", e); + result.put("success", false); + result.put("message", "查询异常:" + e.getMessage()); + return result; + } + } + + private FanManagement getOneByIdAndTenant(Long id, String tenantId) { + LambdaQueryWrapper q = new LambdaQueryWrapper<>(); + q.eq(FanManagement::getId, id); + if (tenantId != null && !tenantId.trim().isEmpty()) { + q.eq(FanManagement::getTenantId, tenantId.trim()); + } + return this.getOne(q, false); + } + + private void fillTenantIdIfAbsent(FanManagement entity) { + if (entity.getTenantId() == null || entity.getTenantId().trim().isEmpty()) { + String tenantId = TenantContextHolder.getTenantId(); + if (tenantId != null && !tenantId.trim().isEmpty()) { + entity.setTenantId(tenantId.trim()); + } + } + } + + private void trimStringFields(FanManagement entity) { + if (entity.getTenantId() != null) { + entity.setTenantId(entity.getTenantId().trim()); + } + if (entity.getAvatar() != null) { + entity.setAvatar(entity.getAvatar().trim()); + } + if (entity.getNickname() != null) { + entity.setNickname(entity.getNickname().trim()); + } + if (entity.getMobile() != null) { + entity.setMobile(entity.getMobile().trim()); + } + } + + private LocalDateTime parseDateTime(String text) { + if (text == null || text.trim().isEmpty()) { + return null; + } + try { + return LocalDateTime.parse(text.trim(), DATE_TIME_FORMATTER); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/com/rj/service/impl/LbGoodsServiceImpl.java b/src/main/java/com/rj/service/impl/LbGoodsServiceImpl.java index 264ce06..6d9a89a 100644 --- a/src/main/java/com/rj/service/impl/LbGoodsServiceImpl.java +++ b/src/main/java/com/rj/service/impl/LbGoodsServiceImpl.java @@ -34,7 +34,7 @@ import java.util.Optional; @RequiredArgsConstructor public class LbGoodsServiceImpl extends ServiceImpl implements ILbGoodsService { - private static final BigDecimal RUSH_BUY_MIN_TOTAL_MONEY = new BigDecimal("29000"); + private static final BigDecimal RUSH_BUY_MIN_TOTAL_MONEY = new BigDecimal("26000"); private static final DateTimeFormatter DATETIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @@ -551,7 +551,7 @@ public class LbGoodsServiceImpl extends ServiceImpl impl w.isNotNull(LbGoods::getSellerId); w.gt(LbGoods::getTotalMoney, RUSH_BUY_MIN_TOTAL_MONEY); w.ge(LbGoods::getUpdatedAt, updatedAfter); - w.orderByDesc(LbGoods::getUpdatedAt); + w.orderByDesc(LbGoods::getTotalMoney); List goodsList = this.list(w); if (goodsList.isEmpty()) { result.put("success", false); diff --git a/src/main/sql/fan_management.sql b/src/main/sql/fan_management.sql new file mode 100644 index 0000000..3b7482c --- /dev/null +++ b/src/main/sql/fan_management.sql @@ -0,0 +1,22 @@ +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +DROP TABLE IF EXISTS `fan_management`; +CREATE TABLE `fan_management` ( + `id` BIGINT NOT NULL COMMENT '粉丝ID(外部系统主键,如 98817)', + `tenant_id` VARCHAR(36) NULL DEFAULT NULL COMMENT '租户ID,关联 tenant.id', + `avatar` VARCHAR(512) NULL DEFAULT NULL COMMENT '头像路径', + `nickname` VARCHAR(100) NULL DEFAULT NULL COMMENT '昵称(可为脱敏手机号,如 137****6199)', + `mobile` VARCHAR(32) NULL DEFAULT NULL COMMENT '手机号', + `created_at` DATETIME NULL DEFAULT NULL COMMENT '创建时间', + `share_num` INT NOT NULL DEFAULT 0 COMMENT '分享次数', + PRIMARY KEY (`tenant_id`, `id`) USING BTREE, + KEY `idx_fm_mobile` (`tenant_id`, `mobile`) USING BTREE, + KEY `idx_fm_created_at` (`tenant_id`, `created_at`) USING BTREE +) ENGINE=InnoDB + DEFAULT CHARSET=utf8mb4 + COLLATE=utf8mb4_0900_ai_ci + COMMENT='粉丝管理' + ROW_FORMAT=DYNAMIC; + +SET FOREIGN_KEY_CHECKS = 1;