规范化类的名称

This commit is contained in:
2026-06-03 13:04:26 +08:00
parent c40d7aabcb
commit 6ce698eecc
8 changed files with 183 additions and 105 deletions

View File

@@ -1,7 +1,7 @@
package com.rj.controller;
import com.rj.entity.FanManagement;
import com.rj.service.IFanManagementService;
import com.rj.entity.LbFanManagement;
import com.rj.service.ILbFanManagementService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -12,39 +12,40 @@ import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 粉丝管理fan_management前端控制器
* 粉丝管理lb_fan_management前端控制器
*/
@RestController
@RequestMapping("/api/fanManagement")
@Tag(name = "粉丝管理", description = "fan_management 增删改查与分页")
public class FanManagementController {
@RequestMapping("/api/lbFanManagement")
@Tag(name = "粉丝管理", description = "lb_fan_management 增删改查与分页")
public class LbFanManagementController {
@Autowired
private IFanManagementService fanManagementService;
private ILbFanManagementService lbFanManagementService;
@PostMapping("/add")
@Operation(summary = "新增粉丝")
public ResponseEntity<Map<String, Object>> add(
@Parameter(description = "粉丝实体(id 必填", required = true)
@RequestBody FanManagement entity) {
Map<String, Object> result = fanManagementService.add(entity);
@Parameter(description = "粉丝实体(tenant_id、id 必填id_tenant_id 可省略,自动生成 id_tenantId", required = true)
@RequestBody LbFanManagement entity) {
Map<String, Object> result = lbFanManagementService.add(entity);
return toResponse(result);
}
@PutMapping("/update")
@Operation(summary = "修改粉丝")
public ResponseEntity<Map<String, Object>> update(
@Parameter(description = "粉丝实体(id 必填", required = true)
@RequestBody FanManagement entity) {
Map<String, Object> result = fanManagementService.update(entity);
@Parameter(description = "粉丝实体(tenant_id、id 必填;也可用 id_tenant_id 定位", required = true)
@RequestBody LbFanManagement entity) {
Map<String, Object> result = lbFanManagementService.update(entity);
return toResponse(result);
}
@DeleteMapping("/delete/{id}")
@DeleteMapping("/delete")
@Operation(summary = "删除粉丝")
public ResponseEntity<Map<String, Object>> delete(
@Parameter(description = "粉丝ID", required = true) @PathVariable Long id) {
Map<String, Object> result = fanManagementService.deleteById(id);
@Parameter(description = "唯一IDid_tenant_id格式 id_tenantId", required = true)
@RequestParam String idTenantId) {
Map<String, Object> result = lbFanManagementService.deleteByIdTenantId(idTenantId);
return toResponse(result);
}
@@ -61,7 +62,7 @@ public class FanManagementController {
@RequestParam(required = false) String createdAtStart,
@Parameter(description = "创建时间止,格式 yyyy-MM-dd HH:mm:ss")
@RequestParam(required = false) String createdAtEnd) {
Map<String, Object> result = fanManagementService.pageQuery(
Map<String, Object> result = lbFanManagementService.pageQuery(
current, size, nickname, mobile, shareNumMin, shareNumMax,
createdAtStart, createdAtEnd);
Boolean success = (Boolean) result.get("success");

View File

@@ -14,28 +14,32 @@ import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 粉丝管理表 fan_management
* 粉丝管理表 lb_fan_management
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("fan_management")
@TableName("lb_fan_management")
@Schema(description = "粉丝管理")
@JsonIgnoreProperties(ignoreUnknown = true)
public class FanManagement implements Serializable {
public class LbFanManagement implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 粉丝 id {@link #tenantId} 组成复合主键 {@code (tenant_id, id)}
* 唯一主键格式{@code {id}_{tenantId}} {@code 98817_xxx-tenant-uuid}
*/
@TableId(value = "id", type = IdType.INPUT)
@Schema(description = "粉丝ID复合主键之一,须与 tenantId 一起使用")
private Long id;
@TableId(value = "id_tenant_id", type = IdType.INPUT)
@Schema(description = "唯一IDid_tenantId新增时可不传由服务端生成")
private String idTenantId;
@TableField("tenant_id")
@Schema(description = "租户ID")
private String tenantId;
@TableField("id")
@Schema(description = "粉丝ID可跨租户重复")
private Long id;
@TableField("avatar")
@Schema(description = "头像路径")
private String avatar;

View File

@@ -1,12 +0,0 @@
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<FanManagement> {
}

View File

@@ -0,0 +1,12 @@
package com.rj.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.rj.entity.LbFanManagement;
import org.apache.ibatis.annotations.Mapper;
/**
* 粉丝管理表 lb_fan_management Mapper
*/
@Mapper
public interface LbFanManagementMapper extends BaseMapper<LbFanManagement> {
}

View File

@@ -1,20 +1,20 @@
package com.rj.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.rj.entity.FanManagement;
import com.rj.entity.LbFanManagement;
import java.util.Map;
/**
* 粉丝管理服务
*/
public interface IFanManagementService extends IService<FanManagement> {
public interface ILbFanManagementService extends IService<LbFanManagement> {
Map<String, Object> add(FanManagement entity);
Map<String, Object> add(LbFanManagement entity);
Map<String, Object> update(FanManagement entity);
Map<String, Object> update(LbFanManagement entity);
Map<String, Object> deleteById(Long id);
Map<String, Object> deleteByIdTenantId(String idTenantId);
Map<String, Object> pageQuery(Integer current,
Integer size,

View File

@@ -3,11 +3,12 @@ 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.entity.LbFanManagement;
import com.rj.mapper.LbFanManagementMapper;
import com.rj.service.ILbFanManagementService;
import com.rj.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
@@ -20,30 +21,38 @@ import java.util.Map;
*/
@Slf4j
@Service
public class FanManagementServiceImpl
extends ServiceImpl<FanManagementMapper, FanManagement>
implements IFanManagementService {
public class LbFanManagementServiceImpl
extends ServiceImpl<LbFanManagementMapper, LbFanManagement>
implements ILbFanManagementService {
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public Map<String, Object> add(FanManagement entity) {
public Map<String, Object> add(LbFanManagement entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
trimStringFields(entity);
fillTenantIdIfAbsent(entity);
Map<String, Object> keyError = validateCompositeKey(entity);
if (keyError != null) {
return keyError;
}
Map<String, Object> idTenantError = fillAndValidateIdTenantId(entity);
if (idTenantError != null) {
return idTenantError;
}
if (existsByIdTenantId(entity.getIdTenantId())) {
result.put("success", false);
result.put("message", "粉丝ID不能为空");
result.put("message", "唯一ID已存在" + entity.getIdTenantId());
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);
@@ -52,6 +61,11 @@ public class FanManagementServiceImpl
result.put("data", entity);
}
return result;
} catch (DuplicateKeyException e) {
log.warn("粉丝管理新增重复键, idTenantId={}", entity.getIdTenantId());
result.put("success", false);
result.put("message", "唯一ID已存在" + entity.getIdTenantId());
return result;
} catch (Exception e) {
log.error("粉丝管理新增异常", e);
result.put("success", false);
@@ -61,22 +75,38 @@ public class FanManagementServiceImpl
}
@Override
public Map<String, Object> update(FanManagement entity) {
public Map<String, Object> update(LbFanManagement entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
result.put("success", false);
result.put("message", "粉丝ID不能为空");
return result;
}
trimStringFields(entity);
fillTenantIdIfAbsent(entity);
Map<String, Object> keyError = validateCompositeKey(entity);
if (keyError != null) {
return keyError;
}
Map<String, Object> idTenantError = fillAndValidateIdTenantId(entity);
if (idTenantError != null) {
return idTenantError;
}
LbFanManagement existing = this.getById(entity.getIdTenantId());
if (existing == null) {
result.put("success", false);
result.put("message", "记录不存在id_tenant_id=" + entity.getIdTenantId());
return result;
}
if (entity.getCreatedAt() == null) {
entity.setCreatedAt(existing.getCreatedAt());
}
// 唯一主键与联合键字段不可变更
entity.setIdTenantId(existing.getIdTenantId());
entity.setTenantId(existing.getTenantId());
entity.setId(existing.getId());
boolean ok = this.updateById(entity);
result.put("success", ok);
result.put("message", ok ? "修改成功" : "修改失败,记录可能不存在");
result.put("message", ok ? "修改成功" : "修改失败");
if (ok) {
result.put("data", getOneByIdAndTenant(entity.getId(), entity.getTenantId()));
result.put("data", this.getById(entity.getIdTenantId()));
}
return result;
} catch (Exception e) {
@@ -88,20 +118,21 @@ public class FanManagementServiceImpl
}
@Override
public Map<String, Object> deleteById(Long id) {
public Map<String, Object> deleteByIdTenantId(String idTenantId) {
Map<String, Object> result = new HashMap<>();
try {
if (id == null) {
if (idTenantId == null || idTenantId.trim().isEmpty()) {
result.put("success", false);
result.put("message", "粉丝ID不能为空");
result.put("message", "唯一IDid_tenant_id不能为空");
return result;
}
boolean ok = this.removeById(id);
String key = idTenantId.trim();
boolean ok = this.removeById(key);
result.put("success", ok);
result.put("message", ok ? "删除成功" : "删除失败,记录可能不存在");
return result;
} catch (Exception e) {
log.error("粉丝管理删除异常, id={}", id, e);
log.error("粉丝管理删除异常, idTenantId={}", idTenantId, e);
result.put("success", false);
result.put("message", "删除异常:" + e.getMessage());
return result;
@@ -126,18 +157,18 @@ public class FanManagementServiceImpl
size = 10;
}
LambdaQueryWrapper<FanManagement> queryWrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper<LbFanManagement> queryWrapper = new LambdaQueryWrapper<>();
if (nickname != null && !nickname.trim().isEmpty()) {
queryWrapper.like(FanManagement::getNickname, nickname.trim());
queryWrapper.like(LbFanManagement::getNickname, nickname.trim());
}
if (mobile != null && !mobile.trim().isEmpty()) {
queryWrapper.like(FanManagement::getMobile, mobile.trim());
queryWrapper.like(LbFanManagement::getMobile, mobile.trim());
}
if (shareNumMin != null) {
queryWrapper.ge(FanManagement::getShareNum, shareNumMin);
queryWrapper.ge(LbFanManagement::getShareNum, shareNumMin);
}
if (shareNumMax != null) {
queryWrapper.le(FanManagement::getShareNum, shareNumMax);
queryWrapper.le(LbFanManagement::getShareNum, shareNumMax);
}
LocalDateTime start = parseDateTime(createdAtStart);
@@ -153,14 +184,14 @@ public class FanManagementServiceImpl
return result;
}
if (start != null) {
queryWrapper.ge(FanManagement::getCreatedAt, start);
queryWrapper.ge(LbFanManagement::getCreatedAt, start);
}
if (end != null) {
queryWrapper.le(FanManagement::getCreatedAt, end);
queryWrapper.le(LbFanManagement::getCreatedAt, end);
}
queryWrapper.orderByDesc(FanManagement::getCreatedAt);
queryWrapper.orderByDesc(LbFanManagement::getCreatedAt);
Page<FanManagement> page = this.page(new Page<>(current, size), queryWrapper);
Page<LbFanManagement> page = this.page(new Page<>(current, size), queryWrapper);
result.put("success", true);
result.put("message", "查询成功");
result.put("data", page.getRecords());
@@ -177,16 +208,53 @@ public class FanManagementServiceImpl
}
}
private FanManagement getOneByIdAndTenant(Long id, String tenantId) {
LambdaQueryWrapper<FanManagement> 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);
/**
* 生成唯一IDid + '_' + tenant_id
*/
public static String buildIdTenantId(Long id, String tenantId) {
return id + "_" + tenantId;
}
private void fillTenantIdIfAbsent(FanManagement entity) {
private Map<String, Object> validateCompositeKey(LbFanManagement entity) {
Map<String, Object> result = new HashMap<>();
if (entity.getTenantId() == null || entity.getTenantId().trim().isEmpty()) {
result.put("success", false);
result.put("message", "租户ID不能为空");
return result;
}
if (entity.getId() == null) {
result.put("success", false);
result.put("message", "粉丝ID不能为空");
return result;
}
return null;
}
/**
* 填充 id_tenant_id并与传入值校验一致
*/
private Map<String, Object> fillAndValidateIdTenantId(LbFanManagement entity) {
Map<String, Object> result = new HashMap<>();
String expected = buildIdTenantId(entity.getId(), entity.getTenantId());
if (entity.getIdTenantId() == null || entity.getIdTenantId().trim().isEmpty()) {
entity.setIdTenantId(expected);
return null;
}
String actual = entity.getIdTenantId().trim();
if (!expected.equals(actual)) {
result.put("success", false);
result.put("message", "id_tenant_id 与 id、tenant_id 不一致,应为:" + expected);
return result;
}
entity.setIdTenantId(actual);
return null;
}
private boolean existsByIdTenantId(String idTenantId) {
return this.getById(idTenantId) != null;
}
private void fillTenantIdIfAbsent(LbFanManagement entity) {
if (entity.getTenantId() == null || entity.getTenantId().trim().isEmpty()) {
String tenantId = TenantContextHolder.getTenantId();
if (tenantId != null && !tenantId.trim().isEmpty()) {
@@ -195,7 +263,10 @@ public class FanManagementServiceImpl
}
}
private void trimStringFields(FanManagement entity) {
private void trimStringFields(LbFanManagement entity) {
if (entity.getIdTenantId() != null) {
entity.setIdTenantId(entity.getIdTenantId().trim());
}
if (entity.getTenantId() != null) {
entity.setTenantId(entity.getTenantId().trim());
}

View File

@@ -1,22 +0,0 @@
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;

View File

@@ -0,0 +1,24 @@
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `lb_fan_management`;
CREATE TABLE `lb_fan_management` (
`id_tenant_id` VARCHAR(128) NOT NULL COMMENT '唯一ID格式id_tenantId如 98817_xxx-tenant-uuid',
`tenant_id` VARCHAR(36) NOT NULL COMMENT '租户ID',
`id` BIGINT NOT NULL COMMENT '粉丝ID外部业务ID仅 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 (`id_tenant_id`) USING BTREE,
UNIQUE KEY `uk_lfm_tenant_id` (`tenant_id`, `id`) USING BTREE,
KEY `idx_lfm_mobile` (`tenant_id`, `mobile`) USING BTREE,
KEY `idx_lfm_created_at` (`tenant_id`, `created_at`) USING BTREE
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci
COMMENT='粉丝管理(唯一主键 id_tenant_id = id + _ + tenant_id'
ROW_FORMAT=DYNAMIC;
SET FOREIGN_KEY_CHECKS = 1;