puzhibing
2026-09-22 372107864f52452727ea34125132a33c3f096612
添加集团和分公司部分功能
14个文件已添加
2个文件已修改
639 ■■■■■ 已修改文件
doc/耗时统计.md 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TGroup.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TGroupCompany.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGroupCompanyController.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGroupController.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TGroupCompanyMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TGroupMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TGroupCompanyService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TGroupService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TGroupCompanyServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TGroupServiceImpl.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/GroupCompanyVo.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/GroupTreeVo.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/20260903_complete_database_comments.sql 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/20260922_group_company.sql 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/20260922_group_management.sql 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/耗时统计.md
@@ -12,3 +12,4 @@
| 2026-09-01 13:46:42 | 2026-09-01 14:07:44 | 1262 | 推送代码 | 是:仅提交 VIN 码充电订单功能,精确排除刷卡订单统计未完成改动;隔离暂存快照回归后普通推送前后端分支 | 提交并推送 VIN 独立订单表、列表/汇总/详情/计费明细/导出、菜单权限,以及管理后台 VIN 订单页面;服务端提交 `6cff7f18`,管理后台提交 `50a2bbbd` | 服务端 11 个 VIN 业务、测试及 SQL 文件;管理后台 7 个 VIN 页面、路由与权限文件;本统计文件 | 后端订单模块及依赖 Maven `clean test` BUILD SUCCESS、VIN 聚焦测试 BUILD SUCCESS;前端 `tsc`、Jest 12 套件/44 用例、生产构建、UTF-8、`git diff --cached --check`、远端引用核验全部通过 | 未执行数据库脚本;刷卡订单统计改动继续保留本地;既存 Maven 模型、React act、Jest open handle、Browserslist 警告不影响结果 |
| 2026-09-15 09:41:00(估算) | 2026-09-15 10:33:37 | 3157(估算) | 请继续执行未完成的任务。(续作:VIN 订单首末 SOC 回填) | 是:统一结算首次处理时按监控创建时间升/降序取首末 SOC,空数据或查询异常不阻断,重复账单保持幂等 | 在 VD 正常交易记录及充电超时补偿共用结算入口中回填 `start_soc/end_soc`;增加正常映射、空监控数据及重复账单不查询 Mongo 的回归断言 | `ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TVinChargingOrderServiceImpl.java`;`ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/CardVinSettlementTimeAlignmentTest.java`;`ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/CardVinOrderCompensationTest.java`;`doc/耗时统计.md` | UTF-8、IDE lint、`git diff --check` 通过;reactor `mvn -o -pl ruoyi-service/ruoyi-order -am install -DskipTests` BUILD SUCCESS;定向 20/20、ruoyi-order 全量 178/178 JUnit 5 全部通过;代码走查通过 | 开始时间依据当天分析记录估算,耗时包含方案分析及等待续作;首轮 Maven 在工作区根目录因 reactor 路径错误未执行构建,进入 `ChargingPile` 后重跑通过 |
| 2026-09-15 17:39:31 | 2026-09-15 17:52:02 | 751 | 请继续执行未完成的任务。(续作:SD 已结束未扣款补偿) | 是:账户侧新增批量扣款流水查询接口,订单侧扫描状态5且应扣款的刷卡订单,逐单复核无扣款流水后条件回退为停止中交由既有补偿结算;本轮补齐“已有流水不回退”“账户查询失败不回退”“无候选不远程调用”“未抢到锁不回退”“定时任务异常隔离”5 个回归用例 | 完成 SD 已结束(状态5)订单无充电扣款流水的定时兜底回退,并补齐测试与全量回归;默认 surefire 版本无法执行 JUnit 5,改用本地仓库 surefire 2.22.2 执行 | `ruoyi-api/ruoyi-api-account/.../feignClient/ChargingCardClient.java`;`ruoyi-api/ruoyi-api-account/.../factory/ChargingCardFallbackFactory.java`;`ruoyi-service/ruoyi-account/.../controller/TChargingCardController.java`;`.../mapper/TChargingCardMapper.java`;`.../service/TChargingCardService.java`;`.../service/impl/TChargingCardServiceImpl.java`;`.../resources/mapper/account/TChargingCardMapper.xml`;`.../test/.../TChargingCardControllerTest.java`;`.../test/.../TChargingCardServiceImplTest.java`;`ruoyi-service/ruoyi-order/.../service/TCardChargingOrderService.java`;`.../service/impl/TCardChargingOrderServiceImpl.java`;`.../service/impl/TVinChargingOrderServiceImpl.java`;`.../util/task/TaskUtil.java`;`.../test/.../TCardChargingOrderAmountFieldsTest.java`;`.../test/.../TaskUtilCompensationTest.java`;`doc/耗时统计.md` | `mvn -o -pl ruoyi-api/ruoyi-api-account,ruoyi-service/ruoyi-account,ruoyi-service/ruoyi-order -am test-compile -DskipTests` BUILD SUCCESS;surefire 2.22.2 定向 14/14、ruoyi-order 全量 185/185、ruoyi-account 全量 103/103 全部通过;IDE lint 0 条;`git diff --check` 通过;代码走查通过 | 开始时间取本次续作会话首个命令时间,耗时仅统计续作会话(751 秒);实现主体在当天更早会话完成、时间未记录,故整体任务耗时未合并统计;新增用例首轮因在 thenReturn 参数内调用 Mockito 桩方法触发 UnfinishedStubbing,提取局部变量后修复 |
| 2026-09-21 15:19:30(估算) | 2026-09-21 15:23:29 | 约 240(估算) | 分析代码,汇总下已完成三方对接的品牌:光伏:科士达、华为、隆基、晶科、通威;储能:利普芯储能、华为、宁德时代、阳光电源;监控:海康、萤石、大华;道闸:吉莲、顺捷 | 否(只读分析任务,未涉及代码修改,无需授权口令) | 全项目盘点光伏/储能/视频监控/道闸四类三方对接实现,逐品牌核对真实完成情况,区分「已完成对接 / 仅枚举占位 / 代码中不存在」,并核对数据表品牌字段与同步任务 | `.codebuddy/memory/2026-09-21.md`(新建);`.codebuddy/memory/MEMORY.md`;`doc/耗时统计.md`(未修改任何业务代码) | 只读分析,未执行构建与测试;通过全库关键词检索、类与 SQL 文件走查、调用链核对交叉验证(含 2 个子代理并行探索) | 开始时间因本会话首条命令时间戳不可得而估算;结论:已真实完成对接为科士达、华为(仅光伏)、利普芯(eMind2000)、萤石、通用 HTTP 道闸平台,以及清单外的优旦储能;阳光电源/古瑞瓦特/海康/大华/顺捷、吉联、舜杰、捷联均为枚举占位;隆基、晶科、通威、宁德时代、吉莲在代码中不存在 |
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TGroup.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.other.api.domain;
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.ruoyi.common.core.web.domain.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <p>
 * 集团管理实体(t_group)
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_group")
@ApiModel(value = "TGroup对象", description = "集团管理")
public class TGroup extends BasePojo {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty(value = "集团名称")
    @TableField("group_name")
    private String groupName;
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TGroupCompany.java
New file
@@ -0,0 +1,81 @@
package com.ruoyi.other.api.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
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.ruoyi.common.core.web.domain.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * <p>
 * 公司(企业)管理实体(t_group_company)
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_group_company")
@ApiModel(value = "TGroupCompany对象", description = "公司管理")
public class TGroupCompany extends BasePojo {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @ApiModelProperty(value = "集团ID(关联t_group.id)")
    @TableField("group_id")
    private Integer groupId;
    @ApiModelProperty(value = "公司名称")
    @TableField("name")
    private String name;
    @ApiModelProperty(value = "公司编码")
    @TableField("code")
    private String code;
    @ApiModelProperty(value = "联系人")
    @TableField("contact_name")
    private String contactName;
    @ApiModelProperty(value = "联系人电话")
    @TableField("contact_phone")
    private String contactPhone;
    @ApiModelProperty(value = "账户模式(1=预充值,2=后付费)")
    @TableField("account_mode")
    private Integer accountMode;
    @ApiModelProperty(value = "月充值金额")
    @TableField("month_recharge_amount")
    private BigDecimal monthRechargeAmount;
    @ApiModelProperty(value = "当前可用余额")
    @TableField("available_balance")
    private BigDecimal availableBalance;
    @ApiModelProperty(value = "公司状态(1=启用,0=停用)")
    @TableField("status")
    private Integer status;
    @ApiModelProperty(value = "备注")
    @TableField("remark")
    private String remark;
    @ApiModelProperty(value = "更新时间")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGroupCompanyController.java
New file
@@ -0,0 +1,144 @@
package com.ruoyi.other.controller;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.Logical;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.other.api.domain.TGroupCompany;
import com.ruoyi.other.service.TGroupCompanyService;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * <p>
 * 公司(企业)管理 前端控制器
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@RestController
@RequestMapping("/group-company")
public class TGroupCompanyController {
    @Resource
    private TGroupCompanyService groupCompanyService;
    /**
     * 分页查询公司
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @GetMapping("/page")
    @ApiOperation(value = "分页查询公司", tags = {"管理后台-公司管理"})
    public AjaxResult<PageInfo<TGroupCompany>> page(@RequestParam(value = "current", defaultValue = "1") Integer current,
                                                     @RequestParam(value = "size", defaultValue = "10") Integer size,
                                                     @RequestParam(value = "groupId", required = false) Integer groupId,
                                                     @RequestParam(value = "name", required = false) String name,
                                                     @RequestParam(value = "contactName", required = false) String contactName,
                                                     @RequestParam(value = "contactPhone", required = false) String contactPhone,
                                                     @RequestParam(value = "status", required = false) Integer status) {
        PageInfo<TGroupCompany> page = new PageInfo<>(current, size);
        groupCompanyService.lambdaQuery()
                .eq(groupId != null, TGroupCompany::getGroupId, groupId)
                .like(StringUtils.hasText(name), TGroupCompany::getName, name)
                .like(StringUtils.hasText(contactName), TGroupCompany::getContactName, contactName)
                .like(StringUtils.hasText(contactPhone), TGroupCompany::getContactPhone, contactPhone)
                .eq(status != null, TGroupCompany::getStatus, status)
                .orderByDesc(TGroupCompany::getId)
                .page(page);
        return AjaxResult.success(page);
    }
    /**
     * 公司详情
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @GetMapping("/detail")
    @ApiOperation(value = "公司详情", tags = {"管理后台-公司管理"})
    public AjaxResult<TGroupCompany> detail(@RequestParam("id") Integer id) {
        return AjaxResult.success(groupCompanyService.getById(id));
    }
    /**
     * 添加公司
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @PostMapping("/add")
    @ApiOperation(value = "添加公司", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】添加公司", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody TGroupCompany company) {
        if (company.getGroupId() == null) {
            return AjaxResult.error("所属集团不能为空");
        }
        if (!StringUtils.hasText(company.getName())) {
            return AjaxResult.error("公司名称不能为空");
        }
        company.setId(null);
        company.setDelFlag(false);
        if (company.getStatus() == null) {
            company.setStatus(1);
        }
        groupCompanyService.save(company);
        return AjaxResult.success();
    }
    /**
     * 编辑公司
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @PostMapping("/edit")
    @ApiOperation(value = "编辑公司", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】编辑公司", businessType = BusinessType.UPDATE)
    public AjaxResult edit(@RequestBody TGroupCompany company) {
        if (company.getId() == null) {
            return AjaxResult.error("公司ID不能为空");
        }
        groupCompanyService.updateById(company);
        return AjaxResult.success();
    }
    /**
     * 删除公司
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @DeleteMapping("/del")
    @ApiOperation(value = "删除公司", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】删除公司", businessType = BusinessType.DELETE)
    public AjaxResult del(@RequestParam("id") Integer id) {
        if (id == null) {
            return AjaxResult.error("公司ID不能为空");
        }
        groupCompanyService.removeById(id);
        return AjaxResult.success();
    }
    /**
     * 切换公司启用状态
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @PostMapping("/status")
    @ApiOperation(value = "切换公司启用状态", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】切换公司状态", businessType = BusinessType.UPDATE)
    public AjaxResult status(@RequestParam("id") Integer id, @RequestParam("status") Integer status) {
        if (id == null) {
            return AjaxResult.error("公司ID不能为空");
        }
        TGroupCompany update = new TGroupCompany();
        update.setId(id);
        update.setStatus(status);
        groupCompanyService.updateById(update);
        return AjaxResult.success();
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TGroupController.java
New file
@@ -0,0 +1,125 @@
package com.ruoyi.other.controller;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.Logical;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.other.api.domain.TGroup;
import com.ruoyi.other.api.domain.TGroupCompany;
import com.ruoyi.other.service.TGroupCompanyService;
import com.ruoyi.other.service.TGroupService;
import com.ruoyi.other.vo.GroupTreeVo;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
 * <p>
 * 集团管理 前端控制器
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@RestController
@RequestMapping("/group")
public class TGroupController {
    @Resource
    private TGroupService groupService;
    @Resource
    private TGroupCompanyService groupCompanyService;
    /**
     * 获取组织树(第一层集团,第二层企业)
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @GetMapping("/tree")
    @ApiOperation(value = "获取组织树", tags = {"管理后台-公司管理"})
    public AjaxResult<List<GroupTreeVo>> tree() {
        return AjaxResult.success(groupService.groupTree());
    }
    /**
     * 添加集团
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @PostMapping("/add")
    @ApiOperation(value = "添加集团", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】添加集团", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody TGroup group) {
        if (!StringUtils.hasText(group.getGroupName())) {
            return AjaxResult.error("集团名称不能为空");
        }
        String groupName = group.getGroupName().trim();
        long count = groupService.lambdaQuery().eq(TGroup::getGroupName, groupName).count();
        if (count > 0) {
            return AjaxResult.error("集团名称已存在");
        }
        group.setId(null);
        group.setGroupName(groupName);
        group.setDelFlag(false);
        groupService.save(group);
        return AjaxResult.success();
    }
    /**
     * 编辑集团
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @PostMapping("/edit")
    @ApiOperation(value = "编辑集团", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】编辑集团", businessType = BusinessType.UPDATE)
    public AjaxResult edit(@RequestBody TGroup group) {
        if (group.getId() == null) {
            return AjaxResult.error("集团ID不能为空");
        }
        if (!StringUtils.hasText(group.getGroupName())) {
            return AjaxResult.error("集团名称不能为空");
        }
        String groupName = group.getGroupName().trim();
        long count = groupService.lambdaQuery()
                .eq(TGroup::getGroupName, groupName)
                .ne(TGroup::getId, group.getId())
                .count();
        if (count > 0) {
            return AjaxResult.error("集团名称已存在");
        }
        TGroup update = new TGroup();
        update.setId(group.getId());
        update.setGroupName(groupName);
        groupService.updateById(update);
        return AjaxResult.success();
    }
    /**
     * 删除集团(集团下存在企业时禁止删除)
     */
    @RequiresPermissions(value = {"/companyManagement/list"}, logical = Logical.OR)
    @DeleteMapping("/del")
    @ApiOperation(value = "删除集团", tags = {"管理后台-公司管理"})
    @Log(title = "【公司管理】删除集团", businessType = BusinessType.DELETE)
    public AjaxResult del(@RequestParam("id") Integer id) {
        if (id == null) {
            return AjaxResult.error("集团ID不能为空");
        }
        long companyCount = groupCompanyService.lambdaQuery().eq(TGroupCompany::getGroupId, id).count();
        if (companyCount > 0) {
            return AjaxResult.error("该集团下存在企业,无法删除");
        }
        groupService.removeById(id);
        return AjaxResult.success();
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TGroupCompanyMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.other.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.other.api.domain.TGroupCompany;
/**
 * <p>
 * 公司(企业)管理 Mapper 接口
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
public interface TGroupCompanyMapper extends BaseMapper<TGroupCompany> {
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TGroupMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.other.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.other.api.domain.TGroup;
/**
 * <p>
 * 集团管理 Mapper 接口
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
public interface TGroupMapper extends BaseMapper<TGroup> {
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TGroupCompanyService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.other.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.other.api.domain.TGroupCompany;
/**
 * <p>
 * 公司(企业)管理 服务类
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
public interface TGroupCompanyService extends IService<TGroupCompany> {
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TGroupService.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.other.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.other.api.domain.TGroup;
import com.ruoyi.other.vo.GroupTreeVo;
import java.util.List;
/**
 * <p>
 * 集团管理 服务类
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
public interface TGroupService extends IService<TGroup> {
    /**
     * 查询组织树(第一层集团,第二层企业)
     *
     * @return 组织树
     */
    List<GroupTreeVo> groupTree();
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TGroupCompanyServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.other.api.domain.TGroupCompany;
import com.ruoyi.other.mapper.TGroupCompanyMapper;
import com.ruoyi.other.service.TGroupCompanyService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 公司(企业)管理 服务实现类
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@Service
public class TGroupCompanyServiceImpl extends ServiceImpl<TGroupCompanyMapper, TGroupCompany> implements TGroupCompanyService {
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TGroupServiceImpl.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.other.api.domain.TGroup;
import com.ruoyi.other.api.domain.TGroupCompany;
import com.ruoyi.other.mapper.TGroupMapper;
import com.ruoyi.other.service.TGroupCompanyService;
import com.ruoyi.other.service.TGroupService;
import com.ruoyi.other.vo.GroupCompanyVo;
import com.ruoyi.other.vo.GroupTreeVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
 * 集团管理 服务实现类
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@Service
public class TGroupServiceImpl extends ServiceImpl<TGroupMapper, TGroup> implements TGroupService {
    @Resource
    private TGroupCompanyService groupCompanyService;
    @Override
    public List<GroupTreeVo> groupTree() {
        List<TGroup> groups = lambdaQuery().orderByAsc(TGroup::getId).list();
        if (groups.isEmpty()) {
            return Collections.emptyList();
        }
        List<TGroupCompany> companies = groupCompanyService.lambdaQuery().orderByAsc(TGroupCompany::getId).list();
        return groups.stream().map(group -> {
            GroupTreeVo vo = new GroupTreeVo();
            vo.setId(group.getId());
            vo.setGroupName(group.getGroupName());
            vo.setChildren(companies.stream()
                    .filter(company -> company.getGroupId() != null && company.getGroupId().equals(group.getId()))
                    .map(company -> new GroupCompanyVo(company.getId(), company.getName(), company.getGroupId()))
                    .collect(Collectors.toList()));
            return vo;
        }).collect(Collectors.toList());
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/GroupCompanyVo.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.other.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
 * <p>
 * 组织树-企业节点(第二层)
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "GroupCompanyVo对象", description = "组织树-企业节点")
public class GroupCompanyVo implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "企业ID")
    private Integer id;
    @ApiModelProperty(value = "企业名称")
    private String name;
    @ApiModelProperty(value = "集团ID")
    private Integer groupId;
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/GroupTreeVo.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.other.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * <p>
 * 组织树-集团节点(第一层)
 * </p>
 *
 * @author mxcd
 * @since 2026-09-22
 */
@Data
@ApiModel(value = "GroupTreeVo对象", description = "组织树-集团节点")
public class GroupTreeVo implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "集团ID")
    private Integer id;
    @ApiModelProperty(value = "集团名称")
    private String groupName;
    @ApiModelProperty(value = "企业列表")
    private List<GroupCompanyVo> children;
}
sql/20260903_complete_database_comments.sql
@@ -158,7 +158,7 @@
ALTER TABLE `charging_pile_service`.`t_site` MODIFY COLUMN `venue_partner_id` int NULL DEFAULT NULL COMMENT '场地方合作商ID';
ALTER TABLE `charging_pile_service`.`t_partner` MODIFY COLUMN `partner_type` int NULL DEFAULT NULL COMMENT '合作商类型:1普通合作商,2场地方,3服务商';
ALTER TABLE `charging_pile_service`.`t_partner` MODIFY COLUMN `venue_share_amount` decimal(10,2) NULL DEFAULT NULL COMMENT '场地方合作商分账金额(元)';
ALTER TABLE `charging_pile_service`.`t_parking_lot` MODIFY COLUMN `barrier_brand` int NULL DEFAULT NULL COMMENT '道闸品牌:1舜杰,2捷联';
ALTER TABLE `charging_pile_service`.`t_parking_lot` MODIFY COLUMN `barrier_brand` int NULL DEFAULT NULL COMMENT '道闸品牌:1顺捷,2吉莲';
ALTER TABLE `charging_pile_account`.`t_app_user_car` MODIFY COLUMN `pic` varchar(255) NULL COMMENT '车辆图片';
sql/20260922_group_company.sql
New file
@@ -0,0 +1,23 @@
-- ----------------------------
-- 公司管理表
-- 创建日期: 2026-09-22
-- 库: charging_pile_other
-- ----------------------------
CREATE TABLE `t_group_company` (
  `id`                    int           NOT NULL AUTO_INCREMENT COMMENT '主键',
  `group_id`              int           NULL DEFAULT NULL COMMENT '集团ID(关联t_group.id)',
  `name`                  varchar(255)  NULL DEFAULT NULL COMMENT '公司名称',
  `code`                  varchar(255)  NULL DEFAULT NULL COMMENT '公司编码',
  `contact_name`          varchar(64)   NULL DEFAULT NULL COMMENT '联系人',
  `contact_phone`         varchar(32)   NULL DEFAULT NULL COMMENT '联系人电话',
  `account_mode`          tinyint       NULL DEFAULT NULL COMMENT '账户模式(1=预充值,2=后付费)',
  `month_recharge_amount` decimal(12,2) NULL DEFAULT NULL COMMENT '月充值金额',
  `available_balance`     decimal(12,2) NULL DEFAULT NULL COMMENT '当前可用余额',
  `status`                tinyint       NULL DEFAULT NULL COMMENT '公司状态(1=启用,0=停用)',
  `remark`                varchar(255)  NULL DEFAULT NULL COMMENT '备注',
  `create_time`           datetime(0)   NULL DEFAULT NULL COMMENT '创建时间',
  `update_time`           datetime(0)   NULL DEFAULT NULL COMMENT '更新时间',
  `del_flag`              int           NULL DEFAULT NULL COMMENT '删除(0=否,1=是)',
  PRIMARY KEY (`id`),
  KEY `idx_group_id` (`group_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='公司管理';
sql/20260922_group_management.sql
New file
@@ -0,0 +1,12 @@
-- ----------------------------
-- 集团管理表(2026-09-22)
-- 库:charging_pile_other
-- 仅存储集团名称,业务字段只有 group_name
-- ----------------------------
CREATE TABLE `t_group`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `group_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '集团名称',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `del_flag` int NULL DEFAULT NULL COMMENT '删除(0=否,1=是)',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '集团管理' ROW_FORMAT = DYNAMIC;