13 changed files with 1046 additions and 50 deletions
@ -1,22 +1,23 @@ |
|||
create table efcode_virtual_unit |
|||
( |
|||
vir_id varchar(100) not null comment '虚拟单位ID' primary key, |
|||
vir_is_virtual varchar(20) null comment '是否是虚拟节点', |
|||
vir_tenant_id varchar(20) default '000000' null comment '租户编号', |
|||
vir_parent_id varchar(100) default '0' null comment '父部门id', |
|||
vir_zone tinyint null comment '类型', |
|||
vir_ancestors varchar(500) default '' null comment '虚拟单位祖级ID列表:包含自身', |
|||
vir_display_path varchar(1000) null comment '虚拟单位节点的单位路径:包含自身', |
|||
vir_include_type varchar(20) null comment '包含类型:查询/统计,查询,统计', |
|||
vir_domain varchar(40) null comment '域', |
|||
vir_status varchar(40) null comment '状态', |
|||
vir_remark varchar(500) null comment '备注', |
|||
sys_dept_id varchar(100) null comment '部门id', |
|||
srz_organization_id varchar(100) null comment '市认证的组织ID', |
|||
order_num int default 0 null comment '显示顺序', |
|||
create_dept varchar(100) null comment '创建部门', |
|||
create_by bigint null comment '创建者', |
|||
create_time datetime null comment '创建时间', |
|||
update_by bigint null comment '更新者', |
|||
update_time datetime null comment '更新时间' |
|||
vir_id varchar(100) not null comment '虚拟单位ID' primary key, |
|||
vir_is_virtual varchar(20) null comment '是否是虚拟节点', |
|||
vir_parent_id varchar(100) default '0' null comment '父部门id', |
|||
vir_name varchar(100) null comment '名称', |
|||
vir_zone tinyint null comment '类型', |
|||
vir_ancestors varchar(500) default '' null comment '虚拟单位祖级ID列表:包含自身', |
|||
vir_display_path varchar(1000) null comment '虚拟单位节点的单位路径:包含自身', |
|||
vir_include_type varchar(20) null comment '包含类型:查询/统计,查询,统计', |
|||
vir_domain varchar(40) null comment '域', |
|||
vir_status varchar(40) null comment '状态', |
|||
vir_show_at_business varchar(40) null comment '是否在业务中显示', |
|||
vir_remark varchar(500) null comment '备注', |
|||
sys_dept_id varchar(100) null comment '部门id', |
|||
srz_organization_id varchar(100) null comment '市认证的组织ID', |
|||
order_num int default 0 null comment '显示顺序', |
|||
create_dept varchar(100) null comment '创建部门', |
|||
create_by bigint null comment '创建者', |
|||
create_time datetime null comment '创建时间', |
|||
update_by bigint null comment '更新者', |
|||
update_time datetime null comment '更新时间' |
|||
) comment '虚拟单位树' row_format = DYNAMIC; |
|||
|
|||
@ -0,0 +1,105 @@ |
|||
package com.zdxt.enforcementcode.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.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 com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo; |
|||
import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo; |
|||
import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService; |
|||
import org.dromara.common.mybatis.core.page.TableDataInfo; |
|||
|
|||
/** |
|||
* 虚拟单位树 |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
@Validated |
|||
@RequiredArgsConstructor |
|||
@RestController |
|||
@RequestMapping("/enforcementcode/virtualUnit") |
|||
public class EfcodeVirtualUnitController extends BaseController { |
|||
|
|||
private final IEfcodeVirtualUnitService efcodeVirtualUnitService; |
|||
|
|||
/** |
|||
* 查询虚拟单位树列表 |
|||
*/ |
|||
@SaCheckPermission("enforcementcode:virtualUnit:list") |
|||
@GetMapping("/list") |
|||
public TableDataInfo<EfcodeVirtualUnitVo> list(EfcodeVirtualUnitBo bo, PageQuery pageQuery) { |
|||
return efcodeVirtualUnitService.queryPageList(bo, pageQuery); |
|||
} |
|||
|
|||
/** |
|||
* 导出虚拟单位树列表 |
|||
*/ |
|||
@SaCheckPermission("enforcementcode:virtualUnit:export") |
|||
@Log(title = "虚拟单位树", businessType = BusinessType.EXPORT) |
|||
@PostMapping("/export") |
|||
public void export(EfcodeVirtualUnitBo bo, HttpServletResponse response) { |
|||
List<EfcodeVirtualUnitVo> list = efcodeVirtualUnitService.queryList(bo); |
|||
ExcelUtil.exportExcel(list, "虚拟单位树", EfcodeVirtualUnitVo.class, response); |
|||
} |
|||
|
|||
/** |
|||
* 获取虚拟单位树详细信息 |
|||
* |
|||
* @param virId 主键 |
|||
*/ |
|||
@SaCheckPermission("enforcementcode:virtualUnit:query") |
|||
@GetMapping("/{virId}") |
|||
public R<EfcodeVirtualUnitVo> getInfo(@NotNull(message = "主键不能为空") |
|||
@PathVariable String virId) { |
|||
return R.ok(efcodeVirtualUnitService.queryById(virId)); |
|||
} |
|||
|
|||
/** |
|||
* 新增虚拟单位树 |
|||
*/ |
|||
@SaCheckPermission("enforcementcode:virtualUnit:add") |
|||
@Log(title = "虚拟单位树", businessType = BusinessType.INSERT) |
|||
@RepeatSubmit() |
|||
@PostMapping() |
|||
public R<Void> add(@Validated(AddGroup.class) @RequestBody EfcodeVirtualUnitBo bo) { |
|||
return toAjax(efcodeVirtualUnitService.insertByBo(bo)); |
|||
} |
|||
|
|||
/** |
|||
* 修改虚拟单位树 |
|||
*/ |
|||
@SaCheckPermission("enforcementcode:virtualUnit:edit") |
|||
@Log(title = "虚拟单位树", businessType = BusinessType.UPDATE) |
|||
@RepeatSubmit() |
|||
@PutMapping() |
|||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody EfcodeVirtualUnitBo bo) { |
|||
return toAjax(efcodeVirtualUnitService.updateByBo(bo)); |
|||
} |
|||
|
|||
/** |
|||
* 删除虚拟单位树 |
|||
* |
|||
* @param virIds 主键串 |
|||
*/ |
|||
@SaCheckPermission("enforcementcode:virtualUnit:remove") |
|||
@Log(title = "虚拟单位树", businessType = BusinessType.DELETE) |
|||
@DeleteMapping("/{virIds}") |
|||
public R<Void> remove(@NotEmpty(message = "主键不能为空") |
|||
@PathVariable String[] virIds) { |
|||
return toAjax(efcodeVirtualUnitService.deleteWithValidByIds(List.of(virIds), true)); |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
package com.zdxt.enforcementcode.domain; |
|||
|
|||
import org.dromara.common.mybatis.core.domain.BaseEntity; |
|||
import com.baomidou.mybatisplus.annotation.*; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
import java.io.Serial; |
|||
|
|||
/** |
|||
* 虚拟单位树对象 efcode_virtual_unit |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@TableName("efcode_virtual_unit") |
|||
public class EfcodeVirtualUnit extends BaseEntity { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 虚拟单位ID |
|||
*/ |
|||
@TableId(value = "vir_id") |
|||
private String virId; |
|||
|
|||
/** |
|||
* 是否是虚拟节点 |
|||
*/ |
|||
private String virIsVirtual; |
|||
|
|||
|
|||
/** |
|||
* 父部门id |
|||
*/ |
|||
private String virParentId; |
|||
|
|||
/** |
|||
* 名称 |
|||
*/ |
|||
private String virName; |
|||
|
|||
/** |
|||
* 类型 |
|||
*/ |
|||
private Long virZone; |
|||
|
|||
/** |
|||
* 虚拟单位祖级ID列表:包含自身 |
|||
*/ |
|||
private String virAncestors; |
|||
|
|||
/** |
|||
* 虚拟单位节点的单位路径:包含自身 |
|||
*/ |
|||
private String virDisplayPath; |
|||
|
|||
/** |
|||
* 包含类型:查询/统计,查询,统计 |
|||
*/ |
|||
private String virIncludeType; |
|||
|
|||
/** |
|||
* 域 |
|||
*/ |
|||
private String virDomain; |
|||
|
|||
/** |
|||
* 状态 |
|||
*/ |
|||
private String virStatus; |
|||
|
|||
/** |
|||
* 是否在业务中显示 |
|||
*/ |
|||
private String virShowAtBusiness; |
|||
|
|||
/** |
|||
* 备注 |
|||
*/ |
|||
private String virRemark; |
|||
|
|||
/** |
|||
* 部门id |
|||
*/ |
|||
private String sysDeptId; |
|||
|
|||
/** |
|||
* 市认证的组织ID |
|||
*/ |
|||
private String srzOrganizationId; |
|||
|
|||
/** |
|||
* 显示顺序 |
|||
*/ |
|||
private Long orderNum; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,105 @@ |
|||
package com.zdxt.enforcementcode.domain.bo; |
|||
|
|||
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit; |
|||
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.*; |
|||
|
|||
/** |
|||
* 虚拟单位树业务对象 efcode_virtual_unit |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@AutoMapper(target = EfcodeVirtualUnit.class, reverseConvertGenerate = false) |
|||
public class EfcodeVirtualUnitBo extends BaseEntity { |
|||
|
|||
/** |
|||
* 虚拟单位ID |
|||
*/ |
|||
@NotBlank(message = "虚拟单位ID不能为空", groups = { EditGroup.class }) |
|||
private String virId; |
|||
|
|||
/** |
|||
* 是否是虚拟节点 |
|||
*/ |
|||
private String virIsVirtual; |
|||
|
|||
/** |
|||
* 租户编号 |
|||
*/ |
|||
private String virTenantId; |
|||
|
|||
/** |
|||
* 父部门id |
|||
*/ |
|||
private String virParentId; |
|||
|
|||
/** |
|||
* 名称 |
|||
*/ |
|||
private String virName; |
|||
|
|||
/** |
|||
* 类型 |
|||
*/ |
|||
private Long virZone; |
|||
|
|||
/** |
|||
* 虚拟单位祖级ID列表:包含自身 |
|||
*/ |
|||
private String virAncestors; |
|||
|
|||
/** |
|||
* 虚拟单位节点的单位路径:包含自身 |
|||
*/ |
|||
private String virDisplayPath; |
|||
|
|||
/** |
|||
* 包含类型:查询/统计,查询,统计 |
|||
*/ |
|||
private String virIncludeType; |
|||
|
|||
/** |
|||
* 域 |
|||
*/ |
|||
private String virDomain; |
|||
|
|||
/** |
|||
* 状态 |
|||
*/ |
|||
private String virStatus; |
|||
|
|||
/** |
|||
* 是否在业务中显示 |
|||
*/ |
|||
private String virShowAtBusiness; |
|||
|
|||
/** |
|||
* 备注 |
|||
*/ |
|||
private String virRemark; |
|||
|
|||
/** |
|||
* 部门id |
|||
*/ |
|||
private String sysDeptId; |
|||
|
|||
/** |
|||
* 市认证的组织ID |
|||
*/ |
|||
private String srzOrganizationId; |
|||
|
|||
/** |
|||
* 显示顺序 |
|||
*/ |
|||
private Long orderNum; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,128 @@ |
|||
package com.zdxt.enforcementcode.domain.vo; |
|||
|
|||
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit; |
|||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
|||
import cn.idev.excel.annotation.ExcelProperty; |
|||
import org.dromara.common.excel.annotation.ExcelDictFormat; |
|||
import org.dromara.common.excel.convert.ExcelDictConvert; |
|||
import io.github.linpeilie.annotations.AutoMapper; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serial; |
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
|
|||
|
|||
|
|||
/** |
|||
* 虚拟单位树视图对象 efcode_virtual_unit |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
@Data |
|||
@ExcelIgnoreUnannotated |
|||
@AutoMapper(target = EfcodeVirtualUnit.class) |
|||
public class EfcodeVirtualUnitVo implements Serializable { |
|||
|
|||
@Serial |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
/** |
|||
* 虚拟单位ID |
|||
*/ |
|||
@ExcelProperty(value = "虚拟单位ID") |
|||
private String virId; |
|||
|
|||
/** |
|||
* 是否是虚拟节点 |
|||
*/ |
|||
@ExcelProperty(value = "是否是虚拟节点") |
|||
private String virIsVirtual; |
|||
|
|||
/** |
|||
* 租户编号 |
|||
*/ |
|||
@ExcelProperty(value = "租户编号") |
|||
private String virTenantId; |
|||
|
|||
/** |
|||
* 父部门id |
|||
*/ |
|||
@ExcelProperty(value = "父部门id") |
|||
private String virParentId; |
|||
|
|||
/** |
|||
* 名称 |
|||
*/ |
|||
@ExcelProperty(value = "名称") |
|||
private String virName; |
|||
|
|||
/** |
|||
* 类型 |
|||
*/ |
|||
@ExcelProperty(value = "类型") |
|||
private Long virZone; |
|||
|
|||
/** |
|||
* 虚拟单位祖级ID列表:包含自身 |
|||
*/ |
|||
@ExcelProperty(value = "虚拟单位祖级ID列表:包含自身") |
|||
private String virAncestors; |
|||
|
|||
/** |
|||
* 虚拟单位节点的单位路径:包含自身 |
|||
*/ |
|||
@ExcelProperty(value = "虚拟单位节点的单位路径:包含自身") |
|||
private String virDisplayPath; |
|||
|
|||
/** |
|||
* 包含类型:查询/统计,查询,统计 |
|||
*/ |
|||
@ExcelProperty(value = "包含类型:查询/统计,查询,统计") |
|||
private String virIncludeType; |
|||
|
|||
/** |
|||
* 域 |
|||
*/ |
|||
@ExcelProperty(value = "域") |
|||
private String virDomain; |
|||
|
|||
/** |
|||
* 状态 |
|||
*/ |
|||
@ExcelProperty(value = "状态") |
|||
private String virStatus; |
|||
|
|||
/** |
|||
* 是否在业务中显示 |
|||
*/ |
|||
@ExcelProperty(value = "是否在业务中显示") |
|||
private String virShowAtBusiness; |
|||
|
|||
/** |
|||
* 备注 |
|||
*/ |
|||
@ExcelProperty(value = "备注") |
|||
private String virRemark; |
|||
|
|||
/** |
|||
* 部门id |
|||
*/ |
|||
@ExcelProperty(value = "部门id") |
|||
private String sysDeptId; |
|||
|
|||
/** |
|||
* 市认证的组织ID |
|||
*/ |
|||
@ExcelProperty(value = "市认证的组织ID") |
|||
private String srzOrganizationId; |
|||
|
|||
/** |
|||
* 显示顺序 |
|||
*/ |
|||
@ExcelProperty(value = "显示顺序") |
|||
private Long orderNum; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.zdxt.enforcementcode.mapper; |
|||
|
|||
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit; |
|||
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo; |
|||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; |
|||
|
|||
/** |
|||
* 虚拟单位树Mapper接口 |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
public interface EfcodeVirtualUnitMapper extends BaseMapperPlus<EfcodeVirtualUnit, EfcodeVirtualUnitVo> { |
|||
|
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
package com.zdxt.enforcementcode.service; |
|||
|
|||
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo; |
|||
import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo; |
|||
import org.dromara.common.mybatis.core.page.TableDataInfo; |
|||
import org.dromara.common.mybatis.core.page.PageQuery; |
|||
|
|||
import java.util.Collection; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 虚拟单位树Service接口 |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
public interface IEfcodeVirtualUnitService { |
|||
|
|||
/** |
|||
* 查询虚拟单位树 |
|||
* |
|||
* @param virId 主键 |
|||
* @return 虚拟单位树 |
|||
*/ |
|||
EfcodeVirtualUnitVo queryById(String virId); |
|||
|
|||
/** |
|||
* 分页查询虚拟单位树列表 |
|||
* |
|||
* @param bo 查询条件 |
|||
* @param pageQuery 分页参数 |
|||
* @return 虚拟单位树分页列表 |
|||
*/ |
|||
TableDataInfo<EfcodeVirtualUnitVo> queryPageList(EfcodeVirtualUnitBo bo, PageQuery pageQuery); |
|||
|
|||
/** |
|||
* 查询符合条件的虚拟单位树列表 |
|||
* |
|||
* @param bo 查询条件 |
|||
* @return 虚拟单位树列表 |
|||
*/ |
|||
List<EfcodeVirtualUnitVo> queryList(EfcodeVirtualUnitBo bo); |
|||
|
|||
/** |
|||
* 新增虚拟单位树 |
|||
* |
|||
* @param bo 虚拟单位树 |
|||
* @return 是否新增成功 |
|||
*/ |
|||
Boolean insertByBo(EfcodeVirtualUnitBo bo); |
|||
|
|||
/** |
|||
* 修改虚拟单位树 |
|||
* |
|||
* @param bo 虚拟单位树 |
|||
* @return 是否修改成功 |
|||
*/ |
|||
Boolean updateByBo(EfcodeVirtualUnitBo bo); |
|||
|
|||
/** |
|||
* 校验并批量删除虚拟单位树信息 |
|||
* |
|||
* @param ids 待删除的主键集合 |
|||
* @param isValid 是否进行有效性校验 |
|||
* @return 是否删除成功 |
|||
*/ |
|||
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid); |
|||
} |
|||
@ -0,0 +1,144 @@ |
|||
package com.zdxt.enforcementcode.service.impl; |
|||
|
|||
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.springframework.stereotype.Service; |
|||
import com.zdxt.enforcementcode.domain.bo.EfcodeVirtualUnitBo; |
|||
import com.zdxt.enforcementcode.domain.vo.EfcodeVirtualUnitVo; |
|||
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit; |
|||
import com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitMapper; |
|||
import com.zdxt.enforcementcode.service.IEfcodeVirtualUnitService; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Collection; |
|||
|
|||
/** |
|||
* 虚拟单位树Service业务层处理 |
|||
* |
|||
* @author Lion Li |
|||
* @date 2026-05-07 |
|||
*/ |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
@Service |
|||
public class EfcodeVirtualUnitServiceImpl implements IEfcodeVirtualUnitService { |
|||
|
|||
private final EfcodeVirtualUnitMapper baseMapper; |
|||
|
|||
/** |
|||
* 查询虚拟单位树 |
|||
* |
|||
* @param virId 主键 |
|||
* @return 虚拟单位树 |
|||
*/ |
|||
@Override |
|||
public EfcodeVirtualUnitVo queryById(String virId){ |
|||
return baseMapper.selectVoById(virId); |
|||
} |
|||
|
|||
/** |
|||
* 分页查询虚拟单位树列表 |
|||
* |
|||
* @param bo 查询条件 |
|||
* @param pageQuery 分页参数 |
|||
* @return 虚拟单位树分页列表 |
|||
*/ |
|||
@Override |
|||
public TableDataInfo<EfcodeVirtualUnitVo> queryPageList(EfcodeVirtualUnitBo bo, PageQuery pageQuery) { |
|||
LambdaQueryWrapper<EfcodeVirtualUnit> lqw = buildQueryWrapper(bo); |
|||
Page<EfcodeVirtualUnitVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); |
|||
return TableDataInfo.build(result); |
|||
} |
|||
|
|||
/** |
|||
* 查询符合条件的虚拟单位树列表 |
|||
* |
|||
* @param bo 查询条件 |
|||
* @return 虚拟单位树列表 |
|||
*/ |
|||
@Override |
|||
public List<EfcodeVirtualUnitVo> queryList(EfcodeVirtualUnitBo bo) { |
|||
LambdaQueryWrapper<EfcodeVirtualUnit> lqw = buildQueryWrapper(bo); |
|||
return baseMapper.selectVoList(lqw); |
|||
} |
|||
|
|||
private LambdaQueryWrapper<EfcodeVirtualUnit> buildQueryWrapper(EfcodeVirtualUnitBo bo) { |
|||
Map<String, Object> params = bo.getParams(); |
|||
LambdaQueryWrapper<EfcodeVirtualUnit> lqw = Wrappers.lambdaQuery(); |
|||
lqw.orderByAsc(EfcodeVirtualUnit::getVirId); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirIsVirtual()), EfcodeVirtualUnit::getVirIsVirtual, bo.getVirIsVirtual()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirParentId()), EfcodeVirtualUnit::getVirParentId, bo.getVirParentId()); |
|||
lqw.eq(bo.getVirZone() != null, EfcodeVirtualUnit::getVirZone, bo.getVirZone()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirAncestors()), EfcodeVirtualUnit::getVirAncestors, bo.getVirAncestors()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirDisplayPath()), EfcodeVirtualUnit::getVirDisplayPath, bo.getVirDisplayPath()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirIncludeType()), EfcodeVirtualUnit::getVirIncludeType, bo.getVirIncludeType()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirDomain()), EfcodeVirtualUnit::getVirDomain, bo.getVirDomain()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirStatus()), EfcodeVirtualUnit::getVirStatus, bo.getVirStatus()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirShowAtBusiness()), EfcodeVirtualUnit::getVirShowAtBusiness, bo.getVirShowAtBusiness()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getVirRemark()), EfcodeVirtualUnit::getVirRemark, bo.getVirRemark()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getSysDeptId()), EfcodeVirtualUnit::getSysDeptId, bo.getSysDeptId()); |
|||
lqw.eq(StringUtils.isNotBlank(bo.getSrzOrganizationId()), EfcodeVirtualUnit::getSrzOrganizationId, bo.getSrzOrganizationId()); |
|||
lqw.eq(bo.getOrderNum() != null, EfcodeVirtualUnit::getOrderNum, bo.getOrderNum()); |
|||
return lqw; |
|||
} |
|||
|
|||
/** |
|||
* 新增虚拟单位树 |
|||
* |
|||
* @param bo 虚拟单位树 |
|||
* @return 是否新增成功 |
|||
*/ |
|||
@Override |
|||
public Boolean insertByBo(EfcodeVirtualUnitBo bo) { |
|||
EfcodeVirtualUnit add = MapstructUtils.convert(bo, EfcodeVirtualUnit.class); |
|||
validEntityBeforeSave(add); |
|||
boolean flag = baseMapper.insert(add) > 0; |
|||
if (flag) { |
|||
bo.setVirId(add.getVirId()); |
|||
} |
|||
return flag; |
|||
} |
|||
|
|||
/** |
|||
* 修改虚拟单位树 |
|||
* |
|||
* @param bo 虚拟单位树 |
|||
* @return 是否修改成功 |
|||
*/ |
|||
@Override |
|||
public Boolean updateByBo(EfcodeVirtualUnitBo bo) { |
|||
EfcodeVirtualUnit update = MapstructUtils.convert(bo, EfcodeVirtualUnit.class); |
|||
validEntityBeforeSave(update); |
|||
return baseMapper.updateById(update) > 0; |
|||
} |
|||
|
|||
/** |
|||
* 保存前的数据校验 |
|||
*/ |
|||
private void validEntityBeforeSave(EfcodeVirtualUnit entity){ |
|||
//TODO 做一些数据校验,如唯一约束
|
|||
} |
|||
|
|||
/** |
|||
* 校验并批量删除虚拟单位树信息 |
|||
* |
|||
* @param ids 待删除的主键集合 |
|||
* @param isValid 是否进行有效性校验 |
|||
* @return 是否删除成功 |
|||
*/ |
|||
@Override |
|||
public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) { |
|||
if(isValid){ |
|||
//TODO 做一些业务上的校验,判断是否需要校验
|
|||
} |
|||
return baseMapper.deleteByIds(ids) > 0; |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
<?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="com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitMapper"> |
|||
</mapper> |
|||
@ -0,0 +1,344 @@ |
|||
package com.zdxt.service.test; |
|||
|
|||
import cn.dev33.satoken.context.mock.SaTokenContextMockUtil; |
|||
import cn.dev33.satoken.stp.StpUtil; |
|||
import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
|||
import cn.hutool.core.collection.CollUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|||
import com.zdxt.enforcementcode.domain.EfcodeVirtualUnit; |
|||
import com.zdxt.enforcementcode.mapper.EfcodeVirtualUnitMapper; |
|||
import org.dromara.ZdxtAdminApplication; |
|||
import org.dromara.common.core.constant.SystemConstants; |
|||
import org.dromara.common.core.domain.model.LoginUser; |
|||
import org.dromara.common.core.utils.StringUtils; |
|||
import org.dromara.common.satoken.utils.LoginHelper; |
|||
import org.dromara.system.domain.SysDept; |
|||
import org.dromara.system.domain.vo.SysDeptVo; |
|||
import org.dromara.system.domain.vo.SysDictDataVo; |
|||
import org.dromara.system.mapper.SysDeptMapper; |
|||
import org.dromara.system.service.ISysDictTypeService; |
|||
import org.junit.jupiter.api.*; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; |
|||
import org.springframework.boot.test.context.SpringBootTest; |
|||
import org.springframework.mock.web.MockHttpServletRequest; |
|||
import org.springframework.test.context.ActiveProfiles; |
|||
import org.springframework.web.context.request.RequestContextHolder; |
|||
import org.springframework.web.context.request.ServletRequestAttributes; |
|||
|
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
/** |
|||
* 初始化虚拟单位树 |
|||
* <p> |
|||
* 将 selectDeptTreeListReBuildByZone 中的虚拟化节点转为实际节点, |
|||
* 连同真实部门节点一起存入 efcode_virtual_unit 表。 |
|||
* </p> |
|||
*/ |
|||
@SpringBootTest(classes = ZdxtAdminApplication.class) |
|||
@ActiveProfiles({"dev", "dev-cust-zrb"}) |
|||
@AutoConfigureMockMvc |
|||
@DisplayName("初始化虚拟单位树") |
|||
public class InitVirtualUnitTest { |
|||
|
|||
@Autowired |
|||
private SysDeptMapper sysDeptMapper; |
|||
|
|||
@Autowired |
|||
private ISysDictTypeService dictTypeService; |
|||
|
|||
@Autowired |
|||
private EfcodeVirtualUnitMapper efcodeVirtualUnitMapper; |
|||
|
|||
private static final String TEST_CLIENT_ID = "e5cd7e4891bf95d1d19206ce24a7b32e"; |
|||
private static final String TENANT_ID = "000000"; |
|||
|
|||
@BeforeEach |
|||
public void setUp() { |
|||
SaTokenContextMockUtil.setMockContext(); |
|||
|
|||
MockHttpServletRequest mockRequest = new MockHttpServletRequest(); |
|||
mockRequest.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); |
|||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest)); |
|||
|
|||
LoginUser loginUser = new LoginUser(); |
|||
loginUser.setUserId(1L); |
|||
loginUser.setUserType("sys_user"); |
|||
loginUser.setTenantId(TENANT_ID); |
|||
loginUser.setUsername("test_admin"); |
|||
loginUser.setNickname("测试管理员"); |
|||
loginUser.setDeptId("103"); |
|||
loginUser.setDeptName("测试部门"); |
|||
loginUser.setRolePermission(new HashSet<>()); |
|||
loginUser.setMenuPermission(new HashSet<>()); |
|||
|
|||
SaLoginParameter param = new SaLoginParameter(); |
|||
param.setExtra(LoginHelper.CLIENT_KEY, TEST_CLIENT_ID); |
|||
LoginHelper.login(loginUser, param); |
|||
} |
|||
|
|||
@AfterEach |
|||
public void tearDown() { |
|||
try { |
|||
StpUtil.logout(); |
|||
} catch (Exception ignored) { |
|||
} |
|||
RequestContextHolder.resetRequestAttributes(); |
|||
SaTokenContextMockUtil.clearContext(); |
|||
} |
|||
|
|||
@DisplayName("初始化虚拟单位树数据到 efcode_virtual_unit 表") |
|||
@Test |
|||
public void initVirtualUnitTree() { |
|||
// 与 SysUserController.deptTreeReBuildByZone 使用相同的 zone 列表
|
|||
List<Integer> zones = Arrays.asList(1, 2, 3, 4, 5, 6, 16, 15); |
|||
|
|||
// 1. 查询所有部门(按zone过滤)
|
|||
LambdaQueryWrapper<SysDept> lqw = Wrappers.lambdaQuery(); |
|||
lqw.eq(SysDept::getDelFlag, SystemConstants.NORMAL); |
|||
lqw.orderByAsc(SysDept::getParentId); |
|||
lqw.orderByAsc(SysDept::getOrderNum); |
|||
lqw.orderByAsc(SysDept::getDeptId); |
|||
lqw.in(SysDept::getZone, zones); |
|||
List<SysDeptVo> depts = new ArrayList<>(sysDeptMapper.selectVoList(lqw)); |
|||
|
|||
if (CollUtil.isEmpty(depts)) { |
|||
System.out.println("未查询到任何部门数据,退出"); |
|||
return; |
|||
} |
|||
System.out.println("查询到部门总数: " + depts.size()); |
|||
|
|||
// 构建 deptId -> organizationId 映射(用于设置 srz_organization_id)
|
|||
Map<String, String> deptOrgIdMap = sysDeptMapper.selectList(Wrappers.<SysDept>lambdaQuery() |
|||
.select(SysDept::getDeptId, SysDept::getOrganizationId) |
|||
.in(SysDept::getZone, zones) |
|||
.eq(SysDept::getDelFlag, SystemConstants.NORMAL) |
|||
).stream().collect(Collectors.toMap( |
|||
SysDept::getDeptId, |
|||
d -> d.getOrganizationId() != null ? d.getOrganizationId() : "", |
|||
(a, b) -> a |
|||
)); |
|||
|
|||
// 用于收集所有待插入的虚拟单位节点
|
|||
List<EfcodeVirtualUnit> allUnits = new ArrayList<>(); |
|||
// id -> name 映射,用于构建 displayPath
|
|||
Map<String, String> idNameMap = new LinkedHashMap<>(); |
|||
|
|||
// 2. 构建虚拟根节点 "深圳市"
|
|||
EfcodeVirtualUnit rootUnit = buildVirtualUnit("_root_", "深圳市", null, 0L); |
|||
allUnits.add(rootUnit); |
|||
idNameMap.put(rootUnit.getVirId(), "深圳市"); |
|||
|
|||
// 3. 获取字典数据 role_tree_zone
|
|||
List<SysDictDataVo> dictDataList = dictTypeService.selectDictDataByType("role_tree_zone"); |
|||
if (CollUtil.isEmpty(dictDataList)) { |
|||
System.out.println("未获取到 role_tree_zone 字典数据,退出"); |
|||
return; |
|||
} |
|||
|
|||
// 3.1 添加 "市直"(dictValue=1) 和 "区"(dictValue=2) 虚拟节点
|
|||
// dictValue -> 虚拟节点virId 的映射,用于后续绑定父节点
|
|||
Map<String, String> zoneVirIdMap = new HashMap<>(); |
|||
for (SysDictDataVo dict : dictDataList) { |
|||
if ("1".equals(dict.getDictValue()) || "2".equals(dict.getDictValue())) { |
|||
EfcodeVirtualUnit zoneUnit = buildVirtualUnit( |
|||
rootUnit.getVirId(), dict.getDictLabel(), |
|||
Long.parseLong(dict.getDictValue()), Long.parseLong(dict.getDictValue())); |
|||
allUnits.add(zoneUnit); |
|||
zoneVirIdMap.put(dict.getDictValue(), zoneUnit.getVirId()); |
|||
idNameMap.put(zoneUnit.getVirId(), dict.getDictLabel()); |
|||
} |
|||
} |
|||
|
|||
// 4. 按 zone 重新绑定部门的父节点(同 selectDeptTreeListReBuildByZone 逻辑)
|
|||
String shizhiVirId = zoneVirIdMap.get("1"); |
|||
String quVirId = zoneVirIdMap.get("2"); |
|||
depts.forEach(d -> { |
|||
if (Objects.equals(d.getZone(), 1)) { |
|||
d.setParentId(shizhiVirId); |
|||
} |
|||
if (Objects.equals(d.getZone(), 2)) { |
|||
d.setParentId(quVirId); |
|||
} |
|||
if (Objects.equals(d.getZone(), 15) || Objects.equals(d.getZone(), 16)) { |
|||
d.setParentId(shizhiVirId); |
|||
} |
|||
}); |
|||
|
|||
// 5. 收集区(zone=2)的 id->name 映射
|
|||
Map<String, String> districtMap = depts.stream() |
|||
.filter(d -> Objects.equals(d.getZone(), 2)) |
|||
.collect(Collectors.toMap(SysDeptVo::getDeptId, SysDeptVo::getDeptName)); |
|||
|
|||
// 收集 zone=3/5/6 的部门ID
|
|||
List<String> checkDeptIds = depts.stream() |
|||
.filter(d -> Objects.equals(d.getZone(), 3) || Objects.equals(d.getZone(), 5) || Objects.equals(d.getZone(), 6)) |
|||
.map(SysDeptVo::getDeptId) |
|||
.collect(Collectors.toList()); |
|||
|
|||
// 6. 为每个区创建 "区直" 虚拟节点,并将 zone=3/5/6 的部门挂到对应区直下
|
|||
districtMap.forEach((pid, districtName) -> { |
|||
EfcodeVirtualUnit quzhiUnit = buildVirtualUnit(pid, "区直", null, 0L); |
|||
String quzhiId = quzhiUnit.getVirId(); |
|||
allUnits.add(quzhiUnit); |
|||
idNameMap.put(quzhiId, "区直"); |
|||
|
|||
for (SysDeptVo dept : depts) { |
|||
if (Objects.equals(dept.getZone(), 3) || Objects.equals(dept.getZone(), 6) || Objects.equals(dept.getZone(), 5)) { |
|||
if (checkDeptIds.contains(dept.getParentId())) { |
|||
// 父部门也是区直类型(zone=3/5/6),保持原有父子关系
|
|||
} else if (StringUtils.isNotEmpty(dept.getAncestors()) && dept.getAncestors().contains(pid)) { |
|||
dept.setParentId(quzhiId); |
|||
} else if (StringUtils.isEmpty(dept.getAncestors()) |
|||
|| districtMap.values().stream().noneMatch(v -> dept.getAncestors().contains(v))) { |
|||
if (dept.getDeptName() != null && districtName.length() >= 2 |
|||
&& dept.getDeptName().contains(districtName.substring(0, 2))) { |
|||
dept.setParentId(quzhiId); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// 7. 将实际部门节点转为 EfcodeVirtualUnit
|
|||
// 7.1 先为每个部门生成 UUID,并建立 deptId -> UUID 映射
|
|||
Map<String, String> deptIdToVirIdMap = new HashMap<>(); |
|||
for (SysDeptVo dept : depts) { |
|||
String virId = UUID.randomUUID().toString().replace("-", ""); |
|||
deptIdToVirIdMap.put(dept.getDeptId(), virId); |
|||
// idNameMap 同时存 deptId 和 virId 两个 key,确保 ancestors/displayPath 构建时能找到名称
|
|||
idNameMap.put(dept.getDeptId(), dept.getDeptName()); |
|||
idNameMap.put(virId, dept.getDeptName()); |
|||
} |
|||
|
|||
// 7.2 更新已有虚拟节点的 parentId(如"区直"节点的 parentId 还是原始 deptId,需替换为 UUID)
|
|||
for (EfcodeVirtualUnit existingUnit : allUnits) { |
|||
String pid = existingUnit.getVirParentId(); |
|||
if (deptIdToVirIdMap.containsKey(pid)) { |
|||
existingUnit.setVirParentId(deptIdToVirIdMap.get(pid)); |
|||
} |
|||
} |
|||
|
|||
// 7.3 构建实际部门节点,parentId 如果指向其他部门则替换为对应 UUID
|
|||
// 收集所有已知的有效 virId(虚拟节点 + 部门映射)
|
|||
Set<String> knownVirIds = allUnits.stream() |
|||
.map(EfcodeVirtualUnit::getVirId) |
|||
.collect(Collectors.toSet()); |
|||
knownVirIds.addAll(deptIdToVirIdMap.values()); |
|||
|
|||
for (SysDeptVo dept : depts) { |
|||
EfcodeVirtualUnit unit = new EfcodeVirtualUnit(); |
|||
unit.setVirId(deptIdToVirIdMap.get(dept.getDeptId())); |
|||
unit.setVirIsVirtual("否"); |
|||
// parentId: 优先映射为对应部门的UUID,否则检查是否为已知虚拟节点virId
|
|||
String parentId = dept.getParentId(); |
|||
if (deptIdToVirIdMap.containsKey(parentId)) { |
|||
parentId = deptIdToVirIdMap.get(parentId); |
|||
} else if (!knownVirIds.contains(parentId)) { |
|||
// parentId 无法映射为有效virId,从原始 ancestors 中查找最近的有效祖级
|
|||
String fallback = null; |
|||
if (StringUtils.isNotEmpty(dept.getAncestors())) { |
|||
String[] ancestorArr = dept.getAncestors().split(","); |
|||
for (int j = ancestorArr.length - 1; j >= 0; j--) { |
|||
String aid = ancestorArr[j].trim(); |
|||
if (deptIdToVirIdMap.containsKey(aid)) { |
|||
fallback = deptIdToVirIdMap.get(aid); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
// 如果仍找不到,按 zone 降级到虚拟父节点
|
|||
if (fallback == null) { |
|||
if (Objects.equals(dept.getZone(), 2)) { |
|||
fallback = quVirId; |
|||
} else if (Objects.equals(dept.getZone(), 1) || Objects.equals(dept.getZone(), 15) || Objects.equals(dept.getZone(), 16)) { |
|||
fallback = shizhiVirId; |
|||
} else { |
|||
fallback = rootUnit.getVirId(); |
|||
} |
|||
} |
|||
parentId = fallback; |
|||
} |
|||
unit.setVirParentId(parentId); |
|||
unit.setVirName(dept.getDeptName()); |
|||
unit.setVirZone(dept.getZone() != null ? Long.valueOf(dept.getZone()) : null); |
|||
unit.setVirStatus("启用"); |
|||
unit.setVirIncludeType("全部"); |
|||
unit.setVirShowAtBusiness("是"); |
|||
unit.setSysDeptId(dept.getDeptId()); |
|||
unit.setSrzOrganizationId(deptOrgIdMap.getOrDefault(dept.getDeptId(), "")); |
|||
unit.setOrderNum(StringUtils.isNotEmpty(dept.getSequence()) ? Long.valueOf(dept.getSequence()) : 0L); |
|||
allUnits.add(unit); |
|||
} |
|||
|
|||
// 8. 构建 ancestors 和 displayPath
|
|||
Map<String, EfcodeVirtualUnit> unitMap = allUnits.stream() |
|||
.collect(Collectors.toMap(EfcodeVirtualUnit::getVirId, u -> u, (a, b) -> a)); |
|||
|
|||
for (EfcodeVirtualUnit unit : allUnits) { |
|||
// 8.1 构建 vir_ancestors:向上追溯所有祖级virId + 自身 virId
|
|||
List<String> ancestorIds = new ArrayList<>(); |
|||
String parentId = unit.getVirParentId(); |
|||
while (parentId != null && !"_root_".equals(parentId)) { |
|||
EfcodeVirtualUnit parentUnit = unitMap.get(parentId); |
|||
if (parentUnit != null) { |
|||
ancestorIds.add(0, parentId); |
|||
parentId = parentUnit.getVirParentId(); |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
ancestorIds.add(unit.getVirId()); |
|||
unit.setVirAncestors(String.join(",", ancestorIds)); |
|||
|
|||
// 8.2 构建 vir_display_path:基于 ancestors 中每个 virId 查找名称
|
|||
String displayPath = ancestorIds.stream() |
|||
.map(id -> idNameMap.getOrDefault(id, "")) |
|||
.collect(Collectors.joining("/")); |
|||
unit.setVirDisplayPath(displayPath); |
|||
} |
|||
|
|||
// 9. 清空旧数据后批量插入
|
|||
long existCount = efcodeVirtualUnitMapper.selectCount(Wrappers.lambdaQuery()); |
|||
if (existCount > 0) { |
|||
System.out.println("清空旧数据,共 " + existCount + " 条"); |
|||
efcodeVirtualUnitMapper.delete(Wrappers.lambdaQuery()); |
|||
} |
|||
|
|||
// 分批插入(每批500条)
|
|||
int batchSize = 500; |
|||
int total = allUnits.size(); |
|||
int inserted = 0; |
|||
for (int i = 0; i < total; i += batchSize) { |
|||
List<EfcodeVirtualUnit> batch = allUnits.subList(i, Math.min(i + batchSize, total)); |
|||
efcodeVirtualUnitMapper.insertBatch(batch); |
|||
inserted += batch.size(); |
|||
} |
|||
|
|||
System.out.println("========== 初始化完成 =========="); |
|||
System.out.println("虚拟节点数: " + allUnits.stream().filter(u -> "1".equals(u.getVirIsVirtual())).count()); |
|||
System.out.println("实际部门节点数: " + allUnits.stream().filter(u -> "0".equals(u.getVirIsVirtual())).count()); |
|||
System.out.println("总插入数: " + inserted); |
|||
} |
|||
|
|||
/** |
|||
* 构建虚拟节点 |
|||
*/ |
|||
private EfcodeVirtualUnit buildVirtualUnit(String parentId, String name, Long zone, Long orderNum) { |
|||
EfcodeVirtualUnit unit = new EfcodeVirtualUnit(); |
|||
unit.setVirId(UUID.randomUUID().toString().replace("-", "")); |
|||
unit.setVirIsVirtual("是"); |
|||
unit.setVirParentId(parentId); |
|||
unit.setVirName(name); |
|||
unit.setVirZone(zone); |
|||
unit.setVirStatus("启用"); |
|||
unit.setVirIncludeType("全部"); |
|||
unit.setVirShowAtBusiness("是"); |
|||
unit.setSysDeptId(null); |
|||
unit.setSrzOrganizationId(null); |
|||
unit.setOrderNum(orderNum != null ? orderNum : 0L); |
|||
return unit; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue