Browse Source

feat(system): 新增线下盲注等级管理模块

- 添加线下盲注等级实体类及对应BO、VO类- 实现线下盲注等级的增删改查接口和服务实现- 配置MyBatis映射文件和Mapper接口
- 提供Excel导入导出支持和数据校验工具类
- 完善控制器层API接口和权限控制
- 添加盲注结构主表相关实体和服务接口定义
fugui001 2 months ago
parent
commit
47841b9963
19 changed files with 1912 additions and 0 deletions
  1. 3 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/BlindLevelsImportVo.java
  2. 98 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/BlindLevelsValidatorUtils.java
  3. 105 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/controller/PhysicalBlindLevelsController.java
  4. 138 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/controller/PhysicalBlindStructuresController.java
  5. 102 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/PhysicalBlindLevels.java
  6. 62 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/PhysicalBlindStructures.java
  7. 109 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/bo/PhysicalBlindLevelsBo.java
  8. 62 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/bo/PhysicalBlindStructuresBo.java
  9. 86 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/vo/PhysicalBlindLevelsImportVo.java
  10. 122 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/vo/PhysicalBlindLevelsVo.java
  11. 83 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/vo/PhysicalBlindStructuresVo.java
  12. 45 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/mapper/PhysicalBlindLevelsMapper.java
  13. 47 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/mapper/PhysicalBlindStructuresMapper.java
  14. 68 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/IPhysicalBlindLevelsService.java
  15. 70 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/IPhysicalBlindStructuresService.java
  16. 152 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/impl/PhysicalBlindLevelsServiceImpl.java
  17. 313 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/impl/PhysicalBlindStructuresServiceImpl.java
  18. 146 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/physical/PhysicalBlindLevelsMapper.xml
  19. 101 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/physical/PhysicalBlindStructuresMapper.xml

+ 3 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/domain/vo/BlindLevelsImportVo.java

@@ -56,4 +56,7 @@ public class BlindLevelsImportVo implements Serializable {
     @ExcelProperty(value = "升级时间")
     private Long durationMinutes;
 
+
+
+
 }

+ 98 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/business/utils/BlindLevelsValidatorUtils.java

@@ -1,6 +1,7 @@
 package org.dromara.business.utils;
 
 import org.dromara.business.domain.vo.BlindLevelsImportVo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsImportVo;
 
 import java.util.List;
 
@@ -86,11 +87,108 @@ public class BlindLevelsValidatorUtils {
             if (vo.getDurationMinutes() <= 0) {
                 result.addError("第 " + level + " 行:持续时间必须大于 0 分钟");
             }
+
+
         }
 
         return result;
     }
 
 
+    /**
+     * 线下赛事专用
+     * @param dataList
+     * @return
+     */
+    public static ValidationResult validateBlindLevelsPhysical(List<PhysicalBlindLevelsImportVo> dataList) {
+        ValidationResult result = new ValidationResult();
+
+        if (dataList == null || dataList.isEmpty()) {
+            result.addError("数据为空");
+            return result;
+        }
+
+        boolean anteStarted = false;
+        int expectedLevel = 1;
+
+        for (int i = 0; i < dataList.size(); i++) {
+            PhysicalBlindLevelsImportVo vo = dataList.get(i);
+            int level = i + 1;
+
+            // 校验 isBreak 字段
+            if (vo.getIsBreak() == null) {
+                result.addError("第 " + level + " 行是否休息字段不能为空");
+            } else if (vo.getIsBreak() != 0 && vo.getIsBreak() != 1) {
+                result.addError("第 " + level + " 行是否休息字段只能为 1 或 0");
+            }
+
+            // 如果是休息行,跳过常规校验
+            if (vo.getIsBreak() != null && vo.getIsBreak() == 1) {
+                // 只校验休息行的基本信息
+                if (vo.getBreakDurationMinutes() == null || vo.getBreakDurationMinutes() <= 0) {
+                    result.addError("第 " + level + " 行休息时长必须大于0");
+                }
+                continue; // 跳过后续常规校验
+            }
+
+            // 检查字段是否为空
+            if (vo.getLevelNumber() == null || vo.getSmallBlind() == null ||
+                vo.getBigBlind() == null || vo.getDurationMinutes() == null) {
+                result.addError("第 " + level + " 行存在空字段");
+                continue;
+            }
+
+            // 级别编号是否连续(只对非休息行校验)
+            if (!vo.getLevelNumber().equals((long) expectedLevel)) {
+                result.addError("第 " + level + " 行级别编号不正确,应为 " + expectedLevel);
+            }
+
+            // 更新期望级别
+            expectedLevel++;
+
+            // 大盲是否是小盲的两倍
+            if (!vo.getBigBlind().equals(vo.getSmallBlind() * 2)) {
+                result.addError("第 " + level + " 行:大盲金额应为小盲金额的两倍");
+            }
+
+            // 小盲和大盲是否递增
+            if (i > 0) {
+                PhysicalBlindLevelsImportVo prev = dataList.get(i - 1);
+                // 只比较非休息行
+                if (prev.getIsBreak() == null || prev.getIsBreak() != 1) {
+                    if (vo.getSmallBlind() <= prev.getSmallBlind() || vo.getBigBlind() <= prev.getBigBlind()) {
+                        result.addError("第 " + level + " 行:小盲或大盲金额未递增");
+                    }
+                }
+            }
+
+            // 底注校验
+            if (vo.getAnte() != null) {
+                if (vo.getAnte() < 0) {
+                    result.addError("第 " + level + " 行:底注金额不能为负数");
+                }
+                if (vo.getAnte() > vo.getSmallBlind() / 2) {
+                    result.addError("第 " + level + " 行:底注金额不应超过小盲金额的一半");
+                }
+                anteStarted = true;
+            } else if (anteStarted) {
+                // 如果前面已经有底注,后面不应突然消失(可选)
+                // result.addError("第 " + level + " 行:底注在前面已出现,不应突然消失");
+            }
+
+            // 持续时间校验
+            if (vo.getDurationMinutes() <= 0) {
+                result.addError("第 " + level + " 行:持续时间必须大于 0 分钟");
+            }
+
+            // 展示顺序校验
+            if (vo.getDisplayOrder() == null || vo.getDisplayOrder() <= 0) {
+                result.addError("第 " + level + " 行展示顺序必须大于0");
+            }
+        }
+
+        return result;
+    }
+
 
 }

+ 105 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/controller/PhysicalBlindLevelsController.java

@@ -0,0 +1,105 @@
+package org.dromara.physical.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.physical.domain.bo.PhysicalBlindLevelsBo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsVo;
+import org.dromara.physical.service.IPhysicalBlindLevelsService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 线下盲注等级
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/physical/blindLevels")
+public class PhysicalBlindLevelsController extends BaseController {
+
+    private final IPhysicalBlindLevelsService physicalBlindLevelsService;
+
+    /**
+     * 查询线下盲注等级列表
+     */
+    @SaCheckPermission("physical:blindLevels:list")
+    @GetMapping("/list")
+    public TableDataInfo<PhysicalBlindLevelsVo> list(PhysicalBlindLevelsBo bo, PageQuery pageQuery) {
+        return physicalBlindLevelsService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出线下盲注等级列表
+     */
+    @SaCheckPermission("physical:blindLevels:export")
+    @Log(title = "线下盲注等级", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(PhysicalBlindLevelsBo bo, HttpServletResponse response) {
+        List<PhysicalBlindLevelsVo> list = physicalBlindLevelsService.queryList(bo);
+        ExcelUtil.exportExcel(list, "线下盲注等级", PhysicalBlindLevelsVo.class, response);
+    }
+
+    /**
+     * 获取线下盲注等级详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("physical:blindLevels:query")
+    @GetMapping("/{id}")
+    public R<PhysicalBlindLevelsVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable Long id) {
+        return R.ok(physicalBlindLevelsService.queryById(id));
+    }
+
+    /**
+     * 新增线下盲注等级
+     */
+    @SaCheckPermission("physical:blindLevels:add")
+    @Log(title = "线下盲注等级", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody PhysicalBlindLevelsBo bo) {
+        return toAjax(physicalBlindLevelsService.insertByBo(bo));
+    }
+
+    /**
+     * 修改线下盲注等级
+     */
+    @SaCheckPermission("physical:blindLevels:edit")
+    @Log(title = "线下盲注等级", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody PhysicalBlindLevelsBo bo) {
+        return toAjax(physicalBlindLevelsService.updateByBo(bo));
+    }
+
+    /**
+     * 删除线下盲注等级
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("physical:blindLevels:remove")
+    @Log(title = "线下盲注等级", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(physicalBlindLevelsService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 138 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/controller/PhysicalBlindStructuresController.java

@@ -0,0 +1,138 @@
+package org.dromara.physical.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.physical.domain.bo.PhysicalBlindStructuresBo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsImportVo;
+import org.dromara.physical.domain.vo.PhysicalBlindStructuresVo;
+import org.dromara.physical.service.IPhysicalBlindStructuresService;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 线下盲注等级主名
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/physical/blindStructures")
+public class PhysicalBlindStructuresController extends BaseController {
+
+    private final IPhysicalBlindStructuresService physicalBlindStructuresService;
+
+    /**
+     * 查询线下盲注等级主名列表
+     */
+    @SaCheckPermission("physical:blindStructures:list")
+    @GetMapping("/list")
+    public TableDataInfo<PhysicalBlindStructuresVo> list(PhysicalBlindStructuresBo bo, PageQuery pageQuery) {
+        return physicalBlindStructuresService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出线下盲注等级主名列表
+     */
+    @SaCheckPermission("physical:blindStructures:export")
+    @Log(title = "线下盲注等级主名", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(PhysicalBlindStructuresBo bo, HttpServletResponse response) {
+        List<PhysicalBlindStructuresVo> list = physicalBlindStructuresService.queryList(bo);
+        ExcelUtil.exportExcel(list, "线下盲注等级主名", PhysicalBlindStructuresVo.class, response);
+    }
+
+    /**
+     * 获取线下盲注等级主名详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("physical:blindStructures:query")
+    @GetMapping("/{id}")
+    public R<PhysicalBlindStructuresVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable Long id) {
+        return R.ok(physicalBlindStructuresService.queryById(id));
+    }
+
+    /**
+     * 新增线下盲注等级主名
+     */
+    @SaCheckPermission("physical:blindStructures:add")
+    @Log(title = "【盲注结构】", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping(path = "", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Boolean> add(
+        @RequestPart("name") String name,
+        @RequestPart(value = "description", required = false) String description,
+        @RequestParam("file") MultipartFile file
+    ) {
+        // 构造 BO 对象
+        PhysicalBlindStructuresBo bo = new PhysicalBlindStructuresBo();
+        bo.setName(name);
+        bo.setDescription(description);
+
+        // 处理文件上传逻辑
+        if (file == null && file.isEmpty()) {
+            // TODO: 文件处理逻辑,比如保存到服务器或存储路径
+        /*    String filePath = uploadService.saveFile(file); // 示例方法
+            bo.setFilePath(filePath); // 假设 BO 中有字段记录文件路径*/
+            return R.fail();
+        }
+
+        return physicalBlindStructuresService.insertByBo(bo,file);
+    }
+
+
+    /**
+     * 修改线下盲注等级主名
+     */
+    @SaCheckPermission("physical:blindStructures:edit")
+    @Log(title = "【盲注结构】", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PostMapping(value = "/edit")
+    public R<Boolean> edit(
+        @RequestPart(name = "BlindStructuresBo") PhysicalBlindStructuresBo bo,
+        @RequestPart(name = "file", required = false) MultipartFile file
+    ) {
+       return physicalBlindStructuresService.updateByBo(bo,file);
+    }
+
+    /**
+     * 删除线下盲注等级主名
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("physical:blindStructures:remove")
+    @Log(title = "线下盲注等级主名", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(physicalBlindStructuresService.deleteWithValidByIds(List.of(ids), true));
+    }
+
+
+    /**
+     * 获取导入模板
+     */
+    @PostMapping("/importPhysicalTemplate")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil.exportExcel(new ArrayList<>(), "盲注表模版", PhysicalBlindLevelsImportVo.class, response);
+    }
+
+}

+ 102 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/PhysicalBlindLevels.java

@@ -0,0 +1,102 @@
+package org.dromara.physical.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+
+import java.io.Serial;
+
+/**
+ * 线下盲注等级对象 physical_blind_levels
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("physical_blind_levels")
+public class PhysicalBlindLevels extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 所属盲注结构
+     */
+    private Long blindStructureId;
+
+    /**
+     * 级别编号,如第1级、第2级
+     */
+    private Long levelNumber;
+
+    /**
+     * 小盲金额
+     */
+    private Long smallBlind;
+
+    /**
+     * 大盲金额
+     */
+    private Long bigBlind;
+
+    /**
+     * 底注(可选)
+     */
+    private Long ante;
+
+    /**
+     * 本级别持续时间(分钟)
+     */
+    private Long durationMinutes;
+
+    /**
+     *
+     */
+    private String createdAt;
+
+    /**
+     *
+     */
+    private String updatedAt;
+
+    /**
+     * 创建人
+     */
+    private Long createUserId;
+
+    /**
+     * 修改人
+     */
+    private Long updateUserId;
+
+    /**
+     * 是否休息  true 1 是  false  0  否
+     */
+    private Long isBreak;
+
+    /**
+     * 休息时长
+     */
+    private Long breakDurationMinutes;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 展示顺序
+     */
+    private Long displayOrder;
+
+
+}

+ 62 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/PhysicalBlindStructures.java

@@ -0,0 +1,62 @@
+package org.dromara.physical.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+
+import java.io.Serial;
+
+/**
+ * 线下盲注等级主名对象 physical_blind_structures
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("physical_blind_structures")
+public class PhysicalBlindStructures extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 盲注结构名称,如:Standard, Turbo
+     */
+    private String name;
+
+    /**
+     * 描述信息
+     */
+    private String description;
+
+    /**
+     *
+     */
+    private Date createdAt;
+
+    /**
+     *
+     */
+    private Date updatedAt;
+
+    /**
+     * 创建人
+     */
+    private Long createUserId;
+
+    /**
+     * 修改人
+     */
+    private Long updateUserId;
+
+
+}

+ 109 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/bo/PhysicalBlindLevelsBo.java

@@ -0,0 +1,109 @@
+package org.dromara.physical.domain.bo;
+
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import org.dromara.physical.domain.PhysicalBlindLevels;
+
+import java.util.Date;
+
+/**
+ * 线下盲注等级业务对象 physical_blind_levels
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = PhysicalBlindLevels.class, reverseConvertGenerate = false)
+public class PhysicalBlindLevelsBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 所属盲注结构
+     */
+    @NotNull(message = "所属盲注结构不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long blindStructureId;
+
+    /**
+     * 级别编号,如第1级、第2级
+     */
+    @NotNull(message = "级别编号,如第1级、第2级不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long levelNumber;
+
+    /**
+     * 小盲金额
+     */
+    @NotNull(message = "小盲金额不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long smallBlind;
+
+    /**
+     * 大盲金额
+     */
+    @NotNull(message = "大盲金额不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long bigBlind;
+
+    /**
+     * 底注(可选)
+     */
+    private Long ante;
+
+    /**
+     * 本级别持续时间(分钟)
+     */
+    @NotNull(message = "本级别持续时间(分钟)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long durationMinutes;
+
+    /**
+     *
+     */
+    private String createdAt;
+
+    /**
+     *
+     */
+    private String updatedAt;
+
+    /**
+     * 创建人
+     */
+    private Long createUserId;
+
+    /**
+     * 修改人
+     */
+    private Long updateUserId;
+
+    /**
+     * 是否休息  true 1 是  false  0  否
+     */
+    private Long isBreak;
+
+    /**
+     * 休息时长
+     */
+    private Long breakDurationMinutes;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 展示顺序
+     */
+    private Long displayOrder;
+
+    @ExcelProperty(value = "创建人")
+    private String createName;
+}

+ 62 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/bo/PhysicalBlindStructuresBo.java

@@ -0,0 +1,62 @@
+package org.dromara.physical.domain.bo;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import org.dromara.physical.domain.PhysicalBlindStructures;
+
+/**
+ * 线下盲注等级主名业务对象 physical_blind_structures
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = PhysicalBlindStructures.class, reverseConvertGenerate = false)
+public class PhysicalBlindStructuresBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 盲注结构名称,如:Standard, Turbo
+     */
+    @NotBlank(message = "盲注结构名称,如:Standard, Turbo不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String name;
+
+    /**
+     * 描述信息
+     */
+    private String description;
+
+    /**
+     *
+     */
+    private Date createdAt;
+
+    /**
+     *
+     */
+    private Date updatedAt;
+
+    /**
+     * 创建人
+     */
+    private Long createUserId;
+
+    /**
+     * 修改人
+     */
+    private Long updateUserId;
+
+
+}

+ 86 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/vo/PhysicalBlindLevelsImportVo.java

@@ -0,0 +1,86 @@
+package org.dromara.physical.domain.vo;
+
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 盲注导入VO
+ *
+ * @author Lion Li
+ */
+
+@Data
+@NoArgsConstructor
+// @Accessors(chain = true) // 导入不允许使用 会找不到set方法
+public class PhysicalBlindLevelsImportVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 级别编号,如第1级、第2级
+     */
+    @ExcelProperty(value = "等级")
+    private Long levelNumber;
+
+    /**
+     * 小盲金额
+     */
+    @ExcelProperty(value = "小盲预置分")
+    private Long smallBlind;
+
+
+    /**
+     * 大盲金额
+     */
+    @ExcelProperty(value = "大盲预置分")
+    private Long bigBlind;
+
+
+
+    /**
+     * 底注(可选)
+     */
+    @ExcelProperty(value = "前置预置分")
+    private Long ante;
+
+
+
+    /**
+     * 本级别持续时间(分钟)
+     */
+    @ExcelProperty(value = "升级时间")
+    private Long durationMinutes;
+
+
+    /**
+     * 是否休息  true 1 是  false  0  否
+     */
+    @ExcelProperty(value = "是否休息   1 是  0  否")
+    private Long isBreak;
+
+    /**
+     * 休息时长
+     */
+    @ExcelProperty(value = "休息时长")
+    private Long breakDurationMinutes;
+
+
+    /**
+     * 展示顺序
+     */
+    @ExcelProperty(value = "展示顺序")
+    private Long displayOrder;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 122 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/vo/PhysicalBlindLevelsVo.java

@@ -0,0 +1,122 @@
+package org.dromara.physical.domain.vo;
+
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import org.dromara.physical.domain.PhysicalBlindLevels;
+import java.io.Serial;
+import java.io.Serializable;
+
+
+
+/**
+ * 线下盲注等级视图对象 physical_blind_levels
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = PhysicalBlindLevels.class)
+public class PhysicalBlindLevelsVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "编号")
+    private Long id;
+
+    /**
+     * 所属盲注结构
+     */
+    private Long blindStructureId;
+
+    /**
+     * 级别编号,如第1级、第2级
+     */
+    @ExcelProperty(value = "等级")
+    private Long levelNumber;
+
+    /**
+     * 小盲金额
+     */
+    @ExcelProperty(value = "小盲预置分")
+    private Long smallBlind;
+
+    /**
+     * 大盲金额
+     */
+    @ExcelProperty(value = "大盲预置分")
+    private Long bigBlind;
+
+    /**
+     * 底注(可选)
+     */
+    @ExcelProperty(value = "前置分")
+    private Long ante;
+
+    /**
+     * 本级别持续时间(分钟)
+     */
+    @ExcelProperty(value = "升级时间")
+    private Long durationMinutes;
+
+    /**
+     * 展示顺序
+     */
+    @ExcelProperty(value = "展示顺序")
+    private Long displayOrder;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "创建时间")
+    private String createdAt;
+
+    /**
+     *
+     */
+    //@ExcelProperty(value = "")
+    private String updatedAt;
+
+    /**
+     * 创建人
+     */
+    //@ExcelProperty(value = "创建人")
+    private Long createUserId;
+
+    /**
+     * 修改人
+     */
+    // @ExcelProperty(value = "修改人")
+    private Long updateUserId;
+
+    /**
+     * 是否休息  true 1 是  false  0  否
+     */
+    //@ExcelProperty(value = "是否休息")
+    private Long isBreak;
+
+
+    @ExcelProperty(value = "是否休息")
+    private String isBreakName;
+
+    /**
+     * 休息时长
+     */
+    @ExcelProperty(value = "休息时长")
+    private Long breakDurationMinutes;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 83 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/domain/vo/PhysicalBlindStructuresVo.java

@@ -0,0 +1,83 @@
+package org.dromara.physical.domain.vo;
+
+import java.util.Date;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import org.dromara.physical.domain.PhysicalBlindStructures;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+
+/**
+ * 线下盲注等级主名视图对象 physical_blind_structures
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = PhysicalBlindStructures.class)
+public class PhysicalBlindStructuresVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "编号")
+    private Long id;
+
+    /**
+     * 盲注结构名称,如:Standard, Turbo
+     */
+    @ExcelProperty(value = "名称")
+    private String name;
+
+    /**
+     * 预览
+     */
+    @ExcelProperty(value = "预览")
+    private String parseBlindsInfo;
+
+    /**
+     * 描述信息
+     */
+    @ExcelProperty(value = "备注")
+    private String description;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "创建时间")
+    private Date createdAt;
+
+    /**
+     *
+     */
+    //@ExcelProperty(value = "")
+    private Date updatedAt;
+
+    /**
+     * 创建人
+     */
+   // @ExcelProperty(value = "创建人")
+    private Long createUserId;
+
+    /**
+     * 修改人
+     */
+    //@ExcelProperty(value = "修改人")
+    private Long updateUserId;
+
+    private List<PhysicalBlindLevelsVo> blindLevels;
+
+    @ExcelProperty(value = "创建人")
+    private String createName;
+
+
+}

+ 45 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/mapper/PhysicalBlindLevelsMapper.java

@@ -0,0 +1,45 @@
+package org.dromara.physical.mapper;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.physical.domain.PhysicalBlindLevels;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 线下盲注等级Mapper接口
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@DS("mysql2")
+public interface PhysicalBlindLevelsMapper extends BaseMapperPlus<PhysicalBlindLevels, PhysicalBlindLevelsVo> {
+
+    @InterceptorIgnore(tenantLine = "true")
+    Page<PhysicalBlindLevelsVo> selectPhysicalBlindLevelPage(@Param("page") Page<PhysicalBlindLevels> page, @Param("ew") Wrapper<PhysicalBlindLevels> wrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
+    PhysicalBlindLevelsVo selectPhysicalBlindLevelById(Long id);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int updatePhysicalBlindLevel(PhysicalBlindLevels update);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int insertPhysicalBlindLevel(PhysicalBlindLevels insert);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int deletePhysicalBlindLevelById(@Param("ids") Collection<Long> ids);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<PhysicalBlindLevelsVo> selectPhysicalBlindLevelList(@Param("ew") Wrapper<PhysicalBlindLevels> wrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int deletePhysicalBlindLevelByBlindStructureId(Long blindStructureId);
+
+}

+ 47 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/mapper/PhysicalBlindStructuresMapper.java

@@ -0,0 +1,47 @@
+package org.dromara.physical.mapper;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.physical.domain.PhysicalBlindLevels;
+import org.dromara.physical.domain.PhysicalBlindStructures;
+import org.dromara.physical.domain.vo.PhysicalBlindStructuresVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 线下盲注等级主名Mapper接口
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@DS("mysql2")
+public interface PhysicalBlindStructuresMapper extends BaseMapperPlus<PhysicalBlindStructures, PhysicalBlindStructuresVo> {
+
+    @InterceptorIgnore(tenantLine = "true")
+    Page<PhysicalBlindStructuresVo> selectPhysicalBlindStructureAllPage(@Param("page") Page<PhysicalBlindStructures> page, @Param("ew") Wrapper<PhysicalBlindStructures> wrapper);
+
+    @InterceptorIgnore(tenantLine = "true")
+    PhysicalBlindStructuresVo selectPhysicalBlindStructureById(Long id);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int updatePhysicalBlindStructure(PhysicalBlindStructures update);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int insertPhysicalBlindStructure(PhysicalBlindStructures insert);
+
+    @InterceptorIgnore(tenantLine = "true")
+    int deletePhysicalBlindStructure(@Param("ids") Collection<Long> ids);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<PhysicalBlindStructuresVo> selectPhysicalBlindStructureList(@Param("ew") Wrapper<PhysicalBlindStructures> wrapper);
+
+
+
+
+
+}

+ 68 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/IPhysicalBlindLevelsService.java

@@ -0,0 +1,68 @@
+package org.dromara.physical.service;
+
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.physical.domain.bo.PhysicalBlindLevelsBo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 线下盲注等级Service接口
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+public interface IPhysicalBlindLevelsService {
+
+    /**
+     * 查询线下盲注等级
+     *
+     * @param id 主键
+     * @return 线下盲注等级
+     */
+    PhysicalBlindLevelsVo queryById(Long id);
+
+    /**
+     * 分页查询线下盲注等级列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 线下盲注等级分页列表
+     */
+    TableDataInfo<PhysicalBlindLevelsVo> queryPageList(PhysicalBlindLevelsBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的线下盲注等级列表
+     *
+     * @param bo 查询条件
+     * @return 线下盲注等级列表
+     */
+    List<PhysicalBlindLevelsVo> queryList(PhysicalBlindLevelsBo bo);
+
+    /**
+     * 新增线下盲注等级
+     *
+     * @param bo 线下盲注等级
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(PhysicalBlindLevelsBo bo);
+
+    /**
+     * 修改线下盲注等级
+     *
+     * @param bo 线下盲注等级
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(PhysicalBlindLevelsBo bo);
+
+    /**
+     * 校验并批量删除线下盲注等级信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 70 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/IPhysicalBlindStructuresService.java

@@ -0,0 +1,70 @@
+package org.dromara.physical.service;
+
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.physical.domain.bo.PhysicalBlindStructuresBo;
+import org.dromara.physical.domain.vo.PhysicalBlindStructuresVo;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 线下盲注等级主名Service接口
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+public interface IPhysicalBlindStructuresService {
+
+    /**
+     * 查询线下盲注等级主名
+     *
+     * @param id 主键
+     * @return 线下盲注等级主名
+     */
+    PhysicalBlindStructuresVo queryById(Long id);
+
+    /**
+     * 分页查询线下盲注等级主名列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 线下盲注等级主名分页列表
+     */
+    TableDataInfo<PhysicalBlindStructuresVo> queryPageList(PhysicalBlindStructuresBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的线下盲注等级主名列表
+     *
+     * @param bo 查询条件
+     * @return 线下盲注等级主名列表
+     */
+    List<PhysicalBlindStructuresVo> queryList(PhysicalBlindStructuresBo bo);
+
+    /**
+     * 新增线下盲注等级主名
+     *
+     * @param bo 线下盲注等级主名
+     * @return 是否新增成功
+     */
+    R<Boolean> insertByBo(PhysicalBlindStructuresBo bo, MultipartFile file);
+
+    /**
+     * 修改线下盲注等级主名
+     *
+     * @param bo 线下盲注等级主名
+     * @return 是否修改成功
+     */
+    R<Boolean> updateByBo(PhysicalBlindStructuresBo bo, MultipartFile file);
+
+    /**
+     * 校验并批量删除线下盲注等级主名信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 152 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/impl/PhysicalBlindLevelsServiceImpl.java

@@ -0,0 +1,152 @@
+package org.dromara.physical.service.impl;
+
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.physical.domain.PhysicalBlindLevels;
+import org.dromara.physical.domain.bo.PhysicalBlindLevelsBo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsVo;
+import org.dromara.physical.mapper.PhysicalBlindLevelsMapper;
+import org.dromara.physical.service.IPhysicalBlindLevelsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 线下盲注等级Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class PhysicalBlindLevelsServiceImpl implements IPhysicalBlindLevelsService {
+
+    private final PhysicalBlindLevelsMapper baseMapper;
+
+    /**
+     * 查询线下盲注等级
+     *
+     * @param id 主键
+     * @return 线下盲注等级
+     */
+    @Override
+    public PhysicalBlindLevelsVo queryById(Long id){
+        return baseMapper.selectPhysicalBlindLevelById(id);
+    }
+
+    /**
+     * 分页查询线下盲注等级列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 线下盲注等级分页列表
+     */
+    @Override
+    public TableDataInfo<PhysicalBlindLevelsVo> queryPageList(PhysicalBlindLevelsBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<PhysicalBlindLevels> lqw = buildQueryWrapper(bo);
+        Page<PhysicalBlindLevelsVo> result = baseMapper.selectPhysicalBlindLevelPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的线下盲注等级列表
+     *
+     * @param bo 查询条件
+     * @return 线下盲注等级列表
+     */
+    @Override
+    public List<PhysicalBlindLevelsVo> queryList(PhysicalBlindLevelsBo bo) {
+        LambdaQueryWrapper<PhysicalBlindLevels> lqw = buildQueryWrapper(bo);
+        List<PhysicalBlindLevelsVo> physicalBlindLevelsVoList = baseMapper.selectPhysicalBlindLevelList(lqw);
+        for (PhysicalBlindLevelsVo physicalBlindLevelsVo : physicalBlindLevelsVoList) {
+            Long isBreak = physicalBlindLevelsVo.getIsBreak();
+            if (isBreak == 1L) {
+                physicalBlindLevelsVo.setIsBreakName("是");
+            } else {
+                physicalBlindLevelsVo.setIsBreakName("否");
+            }
+        }
+        return physicalBlindLevelsVoList;
+    }
+
+    private LambdaQueryWrapper<PhysicalBlindLevels> buildQueryWrapper(PhysicalBlindLevelsBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<PhysicalBlindLevels> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(PhysicalBlindLevels::getId);
+        lqw.eq(bo.getBlindStructureId() != null, PhysicalBlindLevels::getBlindStructureId, bo.getBlindStructureId());
+        lqw.eq(bo.getLevelNumber() != null, PhysicalBlindLevels::getLevelNumber, bo.getLevelNumber());
+        lqw.eq(bo.getSmallBlind() != null, PhysicalBlindLevels::getSmallBlind, bo.getSmallBlind());
+        lqw.eq(bo.getBigBlind() != null, PhysicalBlindLevels::getBigBlind, bo.getBigBlind());
+        lqw.eq(bo.getAnte() != null, PhysicalBlindLevels::getAnte, bo.getAnte());
+        lqw.eq(bo.getDurationMinutes() != null, PhysicalBlindLevels::getDurationMinutes, bo.getDurationMinutes());
+        lqw.eq(bo.getCreatedAt() != null, PhysicalBlindLevels::getCreatedAt, bo.getCreatedAt());
+        lqw.eq(bo.getUpdatedAt() != null, PhysicalBlindLevels::getUpdatedAt, bo.getUpdatedAt());
+        lqw.eq(bo.getCreateUserId() != null, PhysicalBlindLevels::getCreateUserId, bo.getCreateUserId());
+        lqw.eq(bo.getUpdateUserId() != null, PhysicalBlindLevels::getUpdateUserId, bo.getUpdateUserId());
+        lqw.eq(bo.getIsBreak() != null, PhysicalBlindLevels::getIsBreak, bo.getIsBreak());
+        lqw.eq(bo.getBreakDurationMinutes() != null, PhysicalBlindLevels::getBreakDurationMinutes, bo.getBreakDurationMinutes());
+        lqw.eq(bo.getDisplayOrder() != null, PhysicalBlindLevels::getDisplayOrder, bo.getDisplayOrder());
+        return lqw;
+    }
+
+    /**
+     * 新增线下盲注等级
+     *
+     * @param bo 线下盲注等级
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(PhysicalBlindLevelsBo bo) {
+        PhysicalBlindLevels add = MapstructUtils.convert(bo, PhysicalBlindLevels.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insertPhysicalBlindLevel(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改线下盲注等级
+     *
+     * @param bo 线下盲注等级
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(PhysicalBlindLevelsBo bo) {
+        PhysicalBlindLevels update = MapstructUtils.convert(bo, PhysicalBlindLevels.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updatePhysicalBlindLevel(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(PhysicalBlindLevels entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除线下盲注等级信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deletePhysicalBlindLevelById(ids) > 0;
+    }
+}

+ 313 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/physical/service/impl/PhysicalBlindStructuresServiceImpl.java

@@ -0,0 +1,313 @@
+package org.dromara.physical.service.impl;
+
+import cn.idev.excel.EasyExcel;
+import cn.idev.excel.context.AnalysisContext;
+import cn.idev.excel.event.AnalysisEventListener;
+import org.apache.commons.collections4.CollectionUtils;
+import org.dromara.business.utils.BlindLevelsValidatorUtils;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.service.UserService;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.physical.domain.PhysicalBlindStructures;
+import org.dromara.physical.domain.bo.PhysicalBlindLevelsBo;
+import org.dromara.physical.domain.bo.PhysicalBlindStructuresBo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsImportVo;
+import org.dromara.physical.domain.vo.PhysicalBlindLevelsVo;
+import org.dromara.physical.domain.vo.PhysicalBlindStructuresVo;
+import org.dromara.physical.mapper.PhysicalBlindLevelsMapper;
+import org.dromara.physical.mapper.PhysicalBlindStructuresMapper;
+import org.dromara.physical.service.IPhysicalBlindStructuresService;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 线下盲注等级主名Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2025-11-19
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class PhysicalBlindStructuresServiceImpl implements IPhysicalBlindStructuresService {
+
+    private final PhysicalBlindStructuresMapper baseMapper;
+
+    private final PhysicalBlindLevelsServiceImpl physicalBlindLevelsService;
+
+    private final PhysicalBlindLevelsMapper physicalBlindLevelsMapper;
+
+    private final UserService userService;
+
+    /**
+     * 查询线下盲注等级主名
+     *
+     * @param id 主键
+     * @return 线下盲注等级主名
+     */
+    @Override
+    public PhysicalBlindStructuresVo queryById(Long id){
+        return baseMapper.selectPhysicalBlindStructureById(id);
+    }
+
+    /**
+     * 分页查询线下盲注等级主名列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 线下盲注等级主名分页列表
+     */
+    @Override
+    public TableDataInfo<PhysicalBlindStructuresVo> queryPageList(PhysicalBlindStructuresBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<PhysicalBlindStructures> lqw = buildQueryWrapper(bo);
+        Page<PhysicalBlindStructuresVo> result = baseMapper.selectPhysicalBlindStructureAllPage(pageQuery.build(), lqw);
+        for (PhysicalBlindStructuresVo record : result.getRecords()) {
+            PhysicalBlindLevelsBo blindLevelsBo=new PhysicalBlindLevelsBo();
+            blindLevelsBo.setBlindStructureId(record.getId());
+            record.setBlindLevels(physicalBlindLevelsService.queryList(blindLevelsBo));
+            if(record.getCreateUserId()!=null){
+                String createName = userService.selectUserNameById(record.getCreateUserId());
+                record.setCreateName(createName);
+            }
+        }
+       return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的线下盲注等级主名列表
+     *
+     * @param bo 查询条件
+     * @return 线下盲注等级主名列表
+     */
+    @Override
+    public List<PhysicalBlindStructuresVo> queryList(PhysicalBlindStructuresBo bo) {
+        LambdaQueryWrapper<PhysicalBlindStructures> lqw = buildQueryWrapper(bo);
+        List<PhysicalBlindStructuresVo> blindStructuresVoList = baseMapper.selectPhysicalBlindStructureList(lqw);
+
+        for (PhysicalBlindStructuresVo blindStructuresVo : blindStructuresVoList) {
+            if(blindStructuresVo.getCreateUserId()!=null){
+                String createName = userService.selectUserNameById(blindStructuresVo.getCreateUserId());
+                blindStructuresVo.setCreateName(createName);
+                PhysicalBlindLevelsBo blindLevelsBo=new PhysicalBlindLevelsBo();
+                blindLevelsBo.setBlindStructureId(blindStructuresVo.getId());
+                List<PhysicalBlindLevelsVo> blindLevelsVos = physicalBlindLevelsService.queryList(blindLevelsBo);
+                if(blindLevelsVos.size()>0){
+                    Long smallBlind = blindLevelsVos.get(0).getSmallBlind();
+                    Long bigBlind = blindLevelsVos.get(0).getBigBlind();
+                    Long ante = blindLevelsVos.get(0).getAnte();
+                    String parseBlindsInfo = smallBlind+"/"+bigBlind+" "+ante;
+                    blindStructuresVo.setParseBlindsInfo(parseBlindsInfo);
+                }
+            }
+        }
+        return blindStructuresVoList;
+    }
+
+    private LambdaQueryWrapper<PhysicalBlindStructures> buildQueryWrapper(PhysicalBlindStructuresBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<PhysicalBlindStructures> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(PhysicalBlindStructures::getId);
+        lqw.like(StringUtils.isNotBlank(bo.getName()), PhysicalBlindStructures::getName, bo.getName());
+        lqw.eq(StringUtils.isNotBlank(bo.getDescription()), PhysicalBlindStructures::getDescription, bo.getDescription());
+        lqw.eq(bo.getCreatedAt() != null, PhysicalBlindStructures::getCreatedAt, bo.getCreatedAt());
+        lqw.eq(bo.getUpdatedAt() != null, PhysicalBlindStructures::getUpdatedAt, bo.getUpdatedAt());
+        lqw.eq(bo.getCreateUserId() != null, PhysicalBlindStructures::getCreateUserId, bo.getCreateUserId());
+        lqw.eq(bo.getUpdateUserId() != null, PhysicalBlindStructures::getUpdateUserId, bo.getUpdateUserId());
+        return lqw;
+    }
+
+    /**
+     * 新增线下盲注等级主名
+     *
+     * @param bo 线下盲注等级主名
+     * @return 是否新增成功
+     */
+    @Override
+    public R<Boolean> insertByBo(PhysicalBlindStructuresBo bo, MultipartFile file) {
+        PhysicalBlindStructures add = MapstructUtils.convert(bo, PhysicalBlindStructures.class);
+        validEntityBeforeSave(add);
+
+        // 2. 解析 Excel 文件
+        List<PhysicalBlindLevelsImportVo> dataList;
+        try (InputStream inputStream = file.getInputStream()) {
+            dataList = parseExcel(inputStream);
+        } catch (IOException e) {
+            log.error("读取文件失败", e);
+            return R.fail("读取文件失败");
+        }
+
+        if (CollectionUtils.isEmpty(dataList)) {
+            return R.fail("导入数据为空");
+        }
+
+        // 3. 校验数据逻辑(可选)
+        BlindLevelsValidatorUtils.ValidationResult validationResult = BlindLevelsValidatorUtils.validateBlindLevelsPhysical(dataList);
+        if (validationResult.isValid()) {
+            System.out.println("数据校验通过");
+        } else {
+            return R.fail(validationResult.getErrorMessage());
+        }
+
+        Long userId = LoginHelper.getUserId();
+        add.setCreateUserId(userId);
+        boolean flag = baseMapper.insertPhysicalBlindStructure(add) > 0;
+        if (!flag) {
+            return R.fail("插入主表失败");
+        }
+
+        bo.setId(add.getId());
+        // 5. 插入子表数据
+        for (PhysicalBlindLevelsImportVo vo : dataList) {
+            PhysicalBlindLevelsBo levelBo = new PhysicalBlindLevelsBo();
+            levelBo.setBlindStructureId(add.getId());
+            levelBo.setLevelNumber(vo.getLevelNumber());
+            levelBo.setSmallBlind(vo.getSmallBlind());
+            levelBo.setBigBlind(vo.getBigBlind());
+            levelBo.setAnte(vo.getAnte());
+            levelBo.setDurationMinutes(vo.getDurationMinutes());
+            levelBo.setCreateUserId(userId);
+            levelBo.setDisplayOrder(vo.getDisplayOrder());
+            levelBo.setIsBreak(vo.getIsBreak());
+            levelBo.setBreakDurationMinutes(vo.getBreakDurationMinutes());
+            physicalBlindLevelsService.insertByBo(levelBo);
+        }
+
+        return R.ok(true); // 成功返回
+    }
+
+
+
+    /**
+     * 修改线下盲注等级主名
+     *
+     * @param bo 线下盲注等级主名
+     * @return 是否修改成功
+     */
+    @Override
+    public R<Boolean> updateByBo(PhysicalBlindStructuresBo bo, MultipartFile file) {
+        //todo 1. 检查是否正在使用中
+
+        PhysicalBlindStructures update = MapstructUtils.convert(bo, PhysicalBlindStructures.class);
+        validEntityBeforeSave(update);
+
+        Long userId = LoginHelper.getUserId();
+        update.setUpdateUserId(userId);
+        log.info("准备更新盲注结构,用户ID: {}", userId);
+
+        // 3. 解析 Excel 文件
+        List<PhysicalBlindLevelsImportVo> dataList = List.of();
+        if (file != null) {
+            log.info("开始解析上传的Excel文件");
+            try (InputStream inputStream = file.getInputStream()) {
+                dataList = parseExcel(inputStream);
+            } catch (IOException e) {
+                log.error("读取文件失败", e);
+                return R.fail("读取文件失败");
+            }
+
+            if (CollectionUtils.isEmpty(dataList)) {
+                log.warn("导入数据为空");
+                return R.fail("导入数据为空");
+            }
+
+            // 4. 校验数据逻辑(可选)
+            BlindLevelsValidatorUtils.ValidationResult validationResult = BlindLevelsValidatorUtils.validateBlindLevelsPhysical(dataList);
+            if (validationResult.isValid()) {
+                log.info("数据校验通过,共{}条数据", dataList.size());
+            } else {
+                log.warn("数据校验失败: {}", validationResult.getErrorMessage());
+                return R.fail(validationResult.getErrorMessage());
+            }
+        }
+
+        int i = baseMapper.updatePhysicalBlindStructure(update);
+        if (i <= 0) {
+            log.error("更新主表失败");
+            return R.fail("更新失败");
+        }
+        log.info("主表更新成功");
+        // 6. 处理等级数据
+        if (file != null) {
+            log.info("开始处理等级数据,删除原有数据");
+            physicalBlindLevelsMapper.deletePhysicalBlindLevelByBlindStructureId(update.getId());
+
+            log.info("开始插入新等级数据,共{}条", dataList.size());
+            for (PhysicalBlindLevelsImportVo vo : dataList) {
+                PhysicalBlindLevelsBo levelBo = new PhysicalBlindLevelsBo();
+                levelBo.setBlindStructureId(update.getId());
+                levelBo.setLevelNumber(vo.getLevelNumber());
+                levelBo.setSmallBlind(vo.getSmallBlind());
+                levelBo.setBigBlind(vo.getBigBlind());
+                levelBo.setAnte(vo.getAnte());
+                levelBo.setDurationMinutes(vo.getDurationMinutes());
+                levelBo.setCreateUserId(userId);
+                physicalBlindLevelsService.insertByBo(levelBo);
+            }
+            log.info("等级数据处理完成");
+        }
+
+        log.info("盲注结构更新成功,ID: {}", bo.getId());
+        return R.ok(true); // 成功返回 true
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(PhysicalBlindStructures entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除线下盲注等级主名信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        //TODO已经在比赛中使用的盲注禁止删除和修改
+
+        return baseMapper.deletePhysicalBlindStructure(ids) > 0;
+    }
+
+
+
+
+    // 解析 Excel 方法
+    private List<PhysicalBlindLevelsImportVo> parseExcel(InputStream inputStream) {
+        List<PhysicalBlindLevelsImportVo> list = new ArrayList<>();
+        EasyExcel.read(inputStream, PhysicalBlindLevelsImportVo.class, new AnalysisEventListener<PhysicalBlindLevelsImportVo>() {
+            @Override
+            public void invoke(PhysicalBlindLevelsImportVo data, AnalysisContext context) {
+                list.add(data);
+            }
+
+            @Override
+            public void doAfterAllAnalysed(AnalysisContext context) {
+                // 解析完成
+            }
+        }).sheet().doRead();
+
+        return list;
+    }
+}

+ 146 - 0
ruoyi-modules/ruoyi-system/src/main/resources/mapper/physical/PhysicalBlindLevelsMapper.xml

@@ -0,0 +1,146 @@
+<?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="org.dromara.physical.mapper.PhysicalBlindLevelsMapper">
+
+
+    <!-- 按 ID 查询(显式列出所有字段) -->
+    <select id="selectPhysicalBlindLevelById" resultType="org.dromara.physical.domain.vo.PhysicalBlindLevelsVo">
+        SELECT
+            id,
+            blind_structure_id,
+            level_number,
+            small_blind,
+            big_blind,
+            ante,
+            duration_minutes,
+            created_at,
+            updated_at,
+            create_user_id,
+            update_user_id,
+            is_break,
+            break_duration_minutes,
+            remark,
+            display_order
+        FROM physical_blind_levels
+        WHERE id = #{id}
+    </select>
+
+    <select id="selectPhysicalBlindLevelPage" resultType="org.dromara.physical.domain.vo.PhysicalBlindLevelsVo">
+        SELECT
+            id,
+            blind_structure_id,
+            level_number,
+            small_blind,
+            big_blind,
+            ante,
+            duration_minutes,
+            created_at,
+            updated_at,
+            create_user_id,
+            update_user_id,
+            is_break,
+            break_duration_minutes,
+            remark,
+            display_order
+        FROM physical_blind_levels ${ew.customSqlSegment}
+    </select>
+
+
+    <select id="selectPhysicalBlindLevelList" resultType="org.dromara.physical.domain.vo.PhysicalBlindLevelsVo">
+        SELECT
+            id,
+            blind_structure_id,
+            level_number,
+            small_blind,
+            big_blind,
+            ante,
+            duration_minutes,
+            created_at,
+            updated_at,
+            create_user_id,
+            update_user_id,
+            is_break,
+            break_duration_minutes,
+            remark,
+            display_order
+        FROM physical_blind_levels ${ew.customSqlSegment}
+    </select>
+
+    <!-- 插入(动态非空字段) -->
+    <insert id="insertPhysicalBlindLevel" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO physical_blind_levels (
+        <trim suffixOverrides=",">
+            <if test="blindStructureId != null">blind_structure_id,</if>
+            <if test="levelNumber != null">level_number,</if>
+            <if test="smallBlind != null">small_blind,</if>
+            <if test="bigBlind != null">big_blind,</if>
+            <if test="ante != null">ante,</if>
+            <if test="durationMinutes != null">duration_minutes,</if>
+            <if test="createUserId != null">create_user_id,</if>
+            <if test="updateUserId != null">update_user_id,</if>
+            <if test="isBreak != null">is_break,</if>
+            <if test="breakDurationMinutes != null">break_duration_minutes,</if>
+            <if test="remark != null and remark != ''">remark,</if>
+            <if test="displayOrder != null">display_order,</if>
+            created_at,
+            updated_at
+        </trim>
+        ) VALUES (
+        <trim suffixOverrides=",">
+            <if test="blindStructureId != null">#{blindStructureId},</if>
+            <if test="levelNumber != null">#{levelNumber},</if>
+            <if test="smallBlind != null">#{smallBlind},</if>
+            <if test="bigBlind != null">#{bigBlind},</if>
+            <if test="ante != null">#{ante},</if>
+            <if test="durationMinutes != null">#{durationMinutes},</if>
+            <if test="createUserId != null">#{createUserId},</if>
+            <if test="updateUserId != null">#{updateUserId},</if>
+            <if test="isBreak != null">#{isBreak, jdbcType=TINYINT},</if>
+            <if test="breakDurationMinutes != null">#{breakDurationMinutes},</if>
+            <if test="remark != null and remark != ''">#{remark},</if>
+            <if test="displayOrder != null">#{displayOrder},</if>
+            NOW(),
+            NOW()
+        </trim>
+        )
+    </insert>
+
+    <!-- 更新(动态非空字段) -->
+    <update id="updatePhysicalBlindLevel">
+        UPDATE physical_blind_levels
+        <set>
+            <if test="blindStructureId != null">blind_structure_id = #{blindStructureId},</if>
+            <if test="levelNumber != null">level_number = #{levelNumber},</if>
+            <if test="smallBlind != null">small_blind = #{smallBlind},</if>
+            <if test="bigBlind != null">big_blind = #{bigBlind},</if>
+            <if test="ante != null">ante = #{ante},</if>
+            <if test="durationMinutes != null">duration_minutes = #{durationMinutes},</if>
+            <if test="updateUserId != null">update_user_id = #{updateUserId},</if>
+            <if test="isBreak != null">is_break = #{isBreak, jdbcType=TINYINT},</if>
+            <if test="breakDurationMinutes != null">break_duration_minutes = #{breakDurationMinutes},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            <if test="displayOrder != null">display_order = #{displayOrder},</if>
+            updated_at = NOW()
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <delete id="deletePhysicalBlindLevelById">
+        DELETE FROM physical_blind_levels
+        <where>
+            id IN
+            <foreach item="id" collection="ids" open="(" separator="," close=")">
+                <if test="id > 0">
+                    #{id}
+                </if>
+            </foreach>
+        </where>
+    </delete>
+
+    <delete id="deletePhysicalBlindLevelByBlindStructureId">
+        DELETE FROM physical_blind_levels where  blind_structure_id=#{blindStructureId}
+    </delete>
+
+</mapper>

+ 101 - 0
ruoyi-modules/ruoyi-system/src/main/resources/mapper/physical/PhysicalBlindStructuresMapper.xml

@@ -0,0 +1,101 @@
+<?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="org.dromara.physical.mapper.PhysicalBlindStructuresMapper">
+
+
+
+
+    <!-- 查询所有(可选分页) -->
+    <select id="selectPhysicalBlindStructureAllPage" resultType="org.dromara.physical.domain.vo.PhysicalBlindStructuresVo">
+        SELECT
+            id,
+            name,
+            description,
+            created_at,
+            updated_at,
+            create_user_id,
+            update_user_id
+        FROM physical_blind_structures  ${ew.customSqlSegment}
+    </select>
+
+
+
+    <!-- 查询所有(可选分页) -->
+    <select id="selectPhysicalBlindStructureList" resultType="org.dromara.physical.domain.vo.PhysicalBlindStructuresVo">
+        SELECT
+            id,
+            name,
+            description,
+            created_at,
+            updated_at,
+            create_user_id,
+            update_user_id
+        FROM physical_blind_structures  ${ew.customSqlSegment}
+    </select>
+
+
+    <!-- 查询所有(可选分页) -->
+    <select id="selectPhysicalBlindStructureById" resultType="org.dromara.physical.domain.vo.PhysicalBlindStructuresVo">
+        SELECT
+            id,
+            name,
+            description,
+            created_at,
+            updated_at,
+            create_user_id,
+            update_user_id
+        FROM physical_blind_structures    WHERE id = #{id}
+    </select>
+
+    <!-- 插入(动态非空字段) -->
+    <insert id="insertPhysicalBlindStructure" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO physical_blind_structures (
+        <trim suffixOverrides=",">
+            <if test="name != null and name != ''">name,</if>
+            <if test="description != null and description != ''">description,</if>
+            <if test="createUserId != null">create_user_id,</if>
+            <if test="updateUserId != null">update_user_id,</if>
+            created_at,
+            updated_at
+        </trim>
+        ) VALUES (
+        <trim suffixOverrides=",">
+            <if test="name != null and name != ''">#{name},</if>
+            <if test="description != null and description != ''">#{description},</if>
+            <if test="createUserId != null">#{createUserId},</if>
+            <if test="updateUserId != null">#{updateUserId},</if>
+            NOW(),
+            NOW()
+        </trim>
+        )
+    </insert>
+
+
+    <!-- 更新(动态非空字段) -->
+    <update id="updatePhysicalBlindStructure">
+        UPDATE physical_blind_structures
+        <set>
+            <if test="name != null and name != ''">name = #{name},</if>
+            <if test="description != null">description = #{description},</if>
+            <if test="updateUserId != null">update_user_id = #{updateUserId},</if>
+            updated_at = NOW()
+        </set>
+        WHERE id = #{id}
+    </update>
+
+    <delete id="deletePhysicalBlindStructure">
+        DELETE FROM physical_blind_structures
+        <where>
+            id IN
+            <foreach item="id" collection="ids" open="(" separator="," close=")">
+                <if test="id > 0">
+                    #{id}
+                </if>
+            </foreach>
+        </where>
+    </delete>
+
+
+</mapper>