diff --git a/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java b/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java new file mode 100644 index 0000000..171f3ec --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java @@ -0,0 +1,162 @@ +package com.yfd.platform.data.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.data.domain.ImportTask; +import com.yfd.platform.data.service.IImportTaskService; +import com.yfd.platform.utils.KendoUtil; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 导入任务表 前端控制器 + *

+ */ +@RestController +@RequestMapping("/data/importTask") +@Tag(name = "导入任务管理") +public class ImportTaskController { + + @Resource + private IImportTaskService importTaskService; + +// @GetMapping("/page") +// @Operation(summary = "分页查询导入任务") +// public ResponseResult queryPageList( +// @RequestParam(defaultValue = "1") Integer current, +// @RequestParam(defaultValue = "10") Integer size, +// @RequestParam(required = false) String bizType, +// @RequestParam(required = false) String status, +// @RequestParam(required = false) Long uploadUserId) { +// Page page = new Page<>(current, size); +// Page result = importTaskService.queryPageList(page, bizType, status, uploadUserId); +// return ResponseResult.successData(result); +// } + @PostMapping("/page") + @Operation(summary = "分页查询导入任务") + public ResponseResult queryPageList(@RequestBody DataSourceRequest dataSourceRequest) { + Page page = KendoUtil.getPage(dataSourceRequest); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String bizType = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "bizType"); + String status = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "status"); + String uploadUserId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "uploadUserId"); + Page result = importTaskService.queryPageList(page, bizType, status, uploadUserId); + return ResponseResult.successData(result); + } + + @GetMapping("/list") + @Operation(summary = "查询导入任务列表") + public ResponseResult list() { + List list = importTaskService.list(); + return ResponseResult.successData(list); + } + + @GetMapping("/getById") + @Operation(summary = "根据ID查询") + public ResponseResult getById(@RequestParam Long id) { + ImportTask importTask = importTaskService.getById(id); + return ResponseResult.successData(importTask); + } + + @GetMapping("/getByImportNo") + @Operation(summary = "根据任务编号查询") + public ResponseResult getByImportNo(@RequestParam String importNo) { + ImportTask importTask = importTaskService.getByImportNo(importNo); + return ResponseResult.successData(importTask); + } + + @GetMapping("/getByBizType") + @Operation(summary = "根据业务类型查询") + public ResponseResult getByBizType(@RequestParam String bizType) { + List list = importTaskService.getByBizType(bizType); + return ResponseResult.successData(list); + } + + @GetMapping("/getByStatus") + @Operation(summary = "根据状态查询") + public ResponseResult getByStatus(@RequestParam String status) { + List list = importTaskService.getByStatus(status); + return ResponseResult.successData(list); + } + + @PostMapping("/createTask") + @Operation(summary = "创建导入任务") + public ResponseResult createTask(@RequestBody ImportTask importTask) { + boolean result = importTaskService.createTask(importTask); + return result ? ResponseResult.success("创建成功") : ResponseResult.error("创建失败"); + } + + @PostMapping("/updateStatus") + @Operation(summary = "更新任务状态") + public ResponseResult updateStatus(@RequestParam String id, + @RequestParam String status, + @RequestParam(required = false) String errorMsg) { + boolean result = importTaskService.updateStatus(id, status, errorMsg); + return result ? ResponseResult.success("更新成功") : ResponseResult.error("更新失败"); + } + + @PostMapping("/updateProgress") + @Operation(summary = "更新解析进度") + public ResponseResult updateProgress(@RequestParam String id, + @RequestParam(required = false) Integer totalCount, + @RequestParam(required = false) Integer successCount, + @RequestParam(required = false) Integer failCount) { + boolean result = importTaskService.updateProgress(id, totalCount, successCount, failCount); + return result ? ResponseResult.success("更新成功") : ResponseResult.error("更新失败"); + } + + @PostMapping("/markFailed") + @Operation(summary = "标记任务失败") + public ResponseResult markFailed(@RequestParam String id, + @RequestParam String errorMsg) { + boolean result = importTaskService.markFailed(id, errorMsg); + return result ? ResponseResult.success("标记失败") : ResponseResult.error("标记失败"); + } + + @PostMapping("/markSuccess") + @Operation(summary = "标记任务成功") + public ResponseResult markSuccess(@RequestParam String id) { + boolean result = importTaskService.markSuccess(id); + return result ? ResponseResult.success("标记成功") : ResponseResult.error("标记失败"); + } + + @PostMapping("/deleteExpired") + @Operation(summary = "删除过期任务") + public ResponseResult deleteExpired() { + boolean result = importTaskService.deleteExpiredTasks(); + return result ? ResponseResult.success("清理完成") : ResponseResult.error("清理失败"); + } + + @PostMapping("/add") + @Operation(summary = "新增导入任务") + public ResponseResult add(@RequestBody ImportTask importTask) { + importTask.setCreatedAt(new Date()); + importTask.setUpdatedAt(new Date()); + boolean result = importTaskService.save(importTask); + return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); + } + + @PostMapping("/update") + @Operation(summary = "修改导入任务") + public ResponseResult update(@RequestBody ImportTask importTask) { + importTask.setUpdatedAt(new Date()); + boolean result = importTaskService.updateById(importTask); + return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); + } + + @PostMapping("/delete") + @Operation(summary = "删除导入任务") + public ResponseResult delete(@RequestParam Long id) { + boolean result = importTaskService.removeById(id); + return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/controller/SysUserDataScopeController.java b/backend/src/main/java/com/yfd/platform/data/controller/SysUserDataScopeController.java index c02ee7d..6858f42 100644 --- a/backend/src/main/java/com/yfd/platform/data/controller/SysUserDataScopeController.java +++ b/backend/src/main/java/com/yfd/platform/data/controller/SysUserDataScopeController.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.annotation.Log; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.data.domain.SysUserDataScope; +import com.yfd.platform.data.domain.bo.EditUserDataScopeBo; +import com.yfd.platform.data.domain.vo.SysUserDataScopeVO; import com.yfd.platform.data.service.ISysUserDataScopeService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -53,6 +55,13 @@ public class SysUserDataScopeController { return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); } + @PostMapping("/batchAdd") + @Operation(summary = "新增数据填报权限") + public ResponseResult batchAdd(@RequestBody EditUserDataScopeBo editUserDataScopeBo) { + boolean result = dataScopeService.batchAddDataScope(editUserDataScopeBo); + return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); + } + /** * 修改数据填报权限 */ @@ -118,7 +127,7 @@ public class SysUserDataScopeController { @GetMapping("/getValidPermissions") @Operation(summary = "查询用户有效权限") public ResponseResult getValidPermissions(@RequestParam String userId) { - List list = dataScopeService.getValidPermissions(userId); + List list = dataScopeService.getValidPermissionsWithOrgName(userId); return ResponseResult.successData(list); } } diff --git a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalChangeLog.java b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalChangeLog.java index b7e1af8..ddc9c05 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalChangeLog.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalChangeLog.java @@ -1,8 +1,6 @@ package com.yfd.platform.data.domain; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; @@ -65,5 +63,6 @@ public class ApprovalChangeLog implements Serializable { /** * 创建时间 */ + @TableField(fill = FieldFill.INSERT) private Date createdAt; } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalLog.java b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalLog.java index bb20c64..b8d4e3e 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalLog.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalLog.java @@ -1,8 +1,6 @@ package com.yfd.platform.data.domain; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; @@ -55,5 +53,7 @@ public class ApprovalLog implements Serializable { /** * 创建时间 */ + + @TableField(fill = FieldFill.INSERT) private Date createdAt; } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java index 950200f..9989f93 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java @@ -1,8 +1,6 @@ package com.yfd.platform.data.domain; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; @@ -75,10 +73,12 @@ public class ApprovalMain implements Serializable { /** * 创建时间 */ + @TableField(fill = FieldFill.INSERT) private Date createdAt; /** * 更新时间 */ + @TableField(fill = FieldFill.INSERT_UPDATE) private Date updatedAt; } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java b/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java index f602b9f..383f3ad 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java @@ -1,13 +1,11 @@ package com.yfd.platform.data.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.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; +import java.math.BigDecimal; import java.util.Date; /** @@ -124,6 +122,32 @@ public class FishDraftData implements Serializable { */ private Date submitTime; + /** + * 水温 + */ + @TableField(exist = false) + private BigDecimal wt; + + + /** + * 电站名称 + */ + @TableField(exist = false) + private String engName; + + /** + * 基地名称 + */ + @TableField(exist = false) + private String baseName; + + /** + * 设施名称 + */ + @TableField(exist = false) + private String fPname; + + /** * 审批完成时间 */ @@ -147,6 +171,7 @@ public class FishDraftData implements Serializable { /** * 创建时间 */ + @TableField(fill = FieldFill.INSERT) private Date createdAt; /** @@ -157,6 +182,7 @@ public class FishDraftData implements Serializable { /** * 更新时间 */ + @TableField(fill = FieldFill.INSERT_UPDATE) private Date updatedAt; /** diff --git a/backend/src/main/java/com/yfd/platform/data/domain/ImportTask.java b/backend/src/main/java/com/yfd/platform/data/domain/ImportTask.java new file mode 100644 index 0000000..1e4e645 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/domain/ImportTask.java @@ -0,0 +1,109 @@ +package com.yfd.platform.data.domain; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 导入任务表(ZIP导入全过程管理) + *

+ */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("IMPORT_TASK") +public class ImportTask implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 导入任务编号(唯一) + */ + private String importNo; + + /** + * 业务类型(FISH过鱼数据) + */ + private String bizType; + + /** + * 上传压缩包文件名 + */ + private String fileName; + + /** + * 文件大小(字节) + */ + private Long fileSize; + + /** + * 原始压缩包存储路径 + */ + private String filePath; + + /** + * 解压后的临时目录路径 + */ + private String tempDir; + + /** + * 总数据条数 + */ + private Integer totalCount; + + /** + * 校验通过条数 + */ + private Integer successCount; + + /** + * 校验失败条数 + */ + private Integer failCount; + + /** + * 任务状态(UPLOADED已上传 / PARSING解析中 / VALIDATED已校验 / FAILED失败 / CONFIRMED已入库) + */ + private String status; + + /** + * 错误信息(异常时记录) + */ + private String errorMsg; + + /** + * 上传人ID + */ + private Long uploadUserId; + + /** + * 上传时间 + */ + private Date uploadTime; + + /** + * 过期时间(用于清理临时文件) + */ + private Date expireTime; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createdAt; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updatedAt; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/domain/bo/EditUserDataScopeBo.java b/backend/src/main/java/com/yfd/platform/data/domain/bo/EditUserDataScopeBo.java new file mode 100644 index 0000000..db27b4f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/domain/bo/EditUserDataScopeBo.java @@ -0,0 +1,13 @@ +package com.yfd.platform.data.domain.bo; + +import com.yfd.platform.data.domain.SysUserDataScope; +import lombok.Data; + +import java.util.List; + + +@Data +public class EditUserDataScopeBo { + private String userId; + List dataScopeList; +} diff --git a/backend/src/main/java/com/yfd/platform/data/domain/vo/SysUserDataScopeVO.java b/backend/src/main/java/com/yfd/platform/data/domain/vo/SysUserDataScopeVO.java new file mode 100644 index 0000000..b630477 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/domain/vo/SysUserDataScopeVO.java @@ -0,0 +1,84 @@ +package com.yfd.platform.data.domain.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 用户数据权限VO(包含关联的资源名称) + *

+ */ +@Data +@Schema(description = "用户数据权限VO") +public class SysUserDataScopeVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "主键ID") + private String id; + + @Schema(description = "用户ID") + private String userId; + + @Schema(description = "资源类型(BASIN/BASE/COMPANY/STATION)") + private String orgType; + + @Schema(description = "资源编码") + private String orgId; + + @Schema(description = "资源名称(流域名称/基地名称/公司名称/电站名称)") + private String orgName; + + @Schema(description = "上级资源编码") + private String parentId; + + @Schema(description = "所属站层级") + private Long orgLevel; + + @Schema(description = "所属站全路径") + private String path; + + @Schema(description = "权限类型(READ/WRITE/ADMIN)") + private String permissionType; + + @Schema(description = "角色标识") + private String roleCode; + + @Schema(description = "数据范围(ALL/SELF/CUSTOM)") + private String dataScope; + + @Schema(description = "状态(1有效 0无效)") + private Integer status; + + @Schema(description = "生效时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date startTime; + + @Schema(description = "失效时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date endTime; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createdAt; + + @Schema(description = "创建人") + private String createdBy; + + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updatedAt; + + @Schema(description = "更新人") + private String updatedBy; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "是否全选(0:非全选 1:全选)") + private Integer isAllChildren; +} diff --git a/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java b/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java new file mode 100644 index 0000000..dbc74bc --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java @@ -0,0 +1,46 @@ +package com.yfd.platform.data.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.data.domain.ImportTask; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + *

+ * 导入任务表 Mapper 接口 + *

+ */ +public interface ImportTaskMapper extends BaseMapper { + + /** + * 根据任务编号查询 + */ + @Select("SELECT * FROM IMPORT_TASK WHERE IMPORT_NO = #{importNo}") + ImportTask selectByImportNo(@Param("importNo") String importNo); + + /** + * 根据业务类型查询 + */ + @Select("SELECT * FROM IMPORT_TASK WHERE BIZ_TYPE = #{bizType} ORDER BY CREATED_AT DESC") + List selectByBizType(@Param("bizType") String bizType); + + /** + * 根据状态查询 + */ + @Select("SELECT * FROM IMPORT_TASK WHERE STATUS = #{status} ORDER BY CREATED_AT DESC") + List selectByStatus(@Param("status") String status); + + /** + * 根据上传人查询 + */ + @Select("SELECT * FROM IMPORT_TASK WHERE UPLOAD_USER_ID = #{uploadUserId} ORDER BY CREATED_AT DESC") + List selectByUploadUserId(@Param("uploadUserId") Long uploadUserId); + + /** + * 查询过期的任务 + */ + @Select("SELECT * FROM IMPORT_TASK WHERE EXPIRE_TIME < SYSDATE AND EXPIRE_TIME IS NOT NULL") + List selectExpiredTasks(); +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java b/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java new file mode 100644 index 0000000..7b305bd --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java @@ -0,0 +1,65 @@ +package com.yfd.platform.data.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.data.domain.ImportTask; + +import java.util.List; + +/** + *

+ * 导入任务表 服务类 + *

+ */ +public interface IImportTaskService extends IService { + + /** + * 分页查询导入任务 + */ + Page queryPageList(Page page, String bizType, String status, String uploadUserId); + + /** + * 根据任务编号查询 + */ + ImportTask getByImportNo(String importNo); + + /** + * 根据业务类型查询 + */ + List getByBizType(String bizType); + + /** + * 根据状态查询 + */ + List getByStatus(String status); + + /** + * 创建导入任务 + */ + boolean createTask(ImportTask importTask); + + /** + * 更新任务状态 + */ + boolean updateStatus(String id, String status, String errorMsg); + + /** + * 更新解析进度 + */ + boolean updateProgress(String id, Integer totalCount, Integer successCount, Integer failCount); + + /** + * 标记任务失败 + */ + boolean markFailed(String id, String errorMsg); + + /** + * 标记任务成功 + */ + boolean markSuccess(String id); + + /** + * 删除过期任务 + */ + boolean deleteExpiredTasks(); +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/ISysUserDataScopeService.java b/backend/src/main/java/com/yfd/platform/data/service/ISysUserDataScopeService.java index 92a2393..a4f75d3 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/ISysUserDataScopeService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/ISysUserDataScopeService.java @@ -3,6 +3,8 @@ package com.yfd.platform.data.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.yfd.platform.data.domain.SysUserDataScope; +import com.yfd.platform.data.domain.bo.EditUserDataScopeBo; +import com.yfd.platform.data.domain.vo.SysUserDataScopeVO; import java.util.List; @@ -52,4 +54,19 @@ public interface ISysUserDataScopeService extends IService { * 查询用户有效权限(状态=1且在有效期内的) */ List getValidPermissions(String userId); + + boolean batchAddDataScope(EditUserDataScopeBo editUserDataScopeBo); + + /** + * 查询用户有效权限(包含关联的资源名称)- 扩展版本 + * 根据 orgType 自动关联查询: + * - BASIN: 关联 SD_RVCD_DIC 获取流域名称 + * - BASE: 关联 SD_HYDROBASE 获取基地名称 + * - COMPANY: 关联 SD_HYCD_DIC 获取公司名称 + * - STATION: 关联 SD_ENGINFO_B_H 获取电站名称 + * + * @param userId 用户ID + * @return 包含资源名称的权限列表 + */ + List getValidPermissionsWithOrgName(String userId); } diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java new file mode 100644 index 0000000..0e31749 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java @@ -0,0 +1,140 @@ +package com.yfd.platform.data.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.data.domain.ImportTask; +import com.yfd.platform.data.mapper.ImportTaskMapper; +import com.yfd.platform.data.service.IImportTaskService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.util.Date; +import java.util.List; + +/** + *

+ * 导入任务表 服务实现类 + *

+ */ +@Service +public class ImportTaskServiceImpl extends ServiceImpl implements IImportTaskService { + + @Resource + private ImportTaskMapper importTaskMapper; + + @Override + public Page queryPageList(Page page, String bizType, String status, String uploadUserId) { + return this.page(page, this.lambdaQuery() + .eq(StringUtils.hasText(bizType), ImportTask::getBizType, bizType) + .eq(StringUtils.hasText(status), ImportTask::getStatus, status) + .eq(uploadUserId != null, ImportTask::getUploadUserId, uploadUserId) + .orderByDesc(ImportTask::getCreatedAt) + .getWrapper()); + } + + @Override + public ImportTask getByImportNo(String importNo) { + return importTaskMapper.selectByImportNo(importNo); + } + + @Override + public List getByBizType(String bizType) { + return importTaskMapper.selectByBizType(bizType); + } + + @Override + public List getByStatus(String status) { + return importTaskMapper.selectByStatus(status); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean createTask(ImportTask importTask) { + importTask.setStatus("UPLOADED"); + importTask.setCreatedAt(new Date()); + importTask.setUpdatedAt(new Date()); + if (importTask.getTotalCount() == null) { + importTask.setTotalCount(0); + } + if (importTask.getSuccessCount() == null) { + importTask.setSuccessCount(0); + } + if (importTask.getFailCount() == null) { + importTask.setFailCount(0); + } + return this.save(importTask); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateStatus(String id, String status, String errorMsg) { + ImportTask importTask = this.getById(id); + if (importTask == null) { + return false; + } + importTask.setStatus(status); + if (StringUtils.hasText(errorMsg)) { + importTask.setErrorMsg(errorMsg); + } + importTask.setUpdatedAt(new Date()); + return this.updateById(importTask); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateProgress(String id, Integer totalCount, Integer successCount, Integer failCount) { + ImportTask importTask = this.getById(id); + if (importTask == null) { + return false; + } + if (totalCount != null) { + importTask.setTotalCount(totalCount); + } + if (successCount != null) { + importTask.setSuccessCount(successCount); + } + if (failCount != null) { + importTask.setFailCount(failCount); + } + importTask.setUpdatedAt(new Date()); + return this.updateById(importTask); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean markFailed(String id, String errorMsg) { + ImportTask importTask = this.getById(id); + if (importTask == null) { + return false; + } + importTask.setStatus("FAILED"); + importTask.setErrorMsg(errorMsg); + importTask.setUpdatedAt(new Date()); + return this.updateById(importTask); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean markSuccess(String id) { + ImportTask importTask = this.getById(id); + if (importTask == null) { + return false; + } + importTask.setStatus("CONFIRMED"); + importTask.setUpdatedAt(new Date()); + return this.updateById(importTask); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteExpiredTasks() { + List expiredTasks = importTaskMapper.selectExpiredTasks(); + if (expiredTasks == null || expiredTasks.isEmpty()) { + return true; + } + List ids = expiredTasks.stream().map(ImportTask::getId).toList(); + return this.removeByIds(ids); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/SysUserDataScopeServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/SysUserDataScopeServiceImpl.java index 3dd6828..7492688 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/impl/SysUserDataScopeServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/SysUserDataScopeServiceImpl.java @@ -1,13 +1,29 @@ package com.yfd.platform.data.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.data.domain.SysUserDataScope; +import com.yfd.platform.data.domain.bo.EditUserDataScopeBo; +import com.yfd.platform.data.domain.vo.SysUserDataScopeVO; import com.yfd.platform.data.mapper.SysUserDataScopeMapper; import com.yfd.platform.data.service.ISysUserDataScopeService; +import com.yfd.platform.env.domain.SdEngInfoBH; +import com.yfd.platform.env.domain.SdHycdDic; +import com.yfd.platform.env.domain.SdHydrobase; +import com.yfd.platform.env.domain.SdRvcdDic; +import com.yfd.platform.env.mapper.SdEngInfoBHMapper; +import com.yfd.platform.env.mapper.SdHycdDicMapper; +import com.yfd.platform.env.mapper.SdHydrobaseMapper; +import com.yfd.platform.env.mapper.SdRvcdDicMapper; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; /** *

@@ -16,6 +32,17 @@ import java.util.List; */ @Service public class SysUserDataScopeServiceImpl extends ServiceImpl implements ISysUserDataScopeService { + @Resource + private SdRvcdDicMapper rvcdDicMapper; + + @Resource + private SdHydrobaseMapper hydrobaseMapper; + + @Resource + private SdHycdDicMapper hycdDicMapper; + + @Resource + private SdEngInfoBHMapper engInfoBHMapper; @Override public Page queryPageList(Page page, String userId, String orgType, String orgId, Integer status) { @@ -73,4 +100,174 @@ public class SysUserDataScopeServiceImpl extends ServiceImpl getValidPermissionsWithOrgName(String userId) { + // 1. 查询用户的有效权限 + List permissions = this.getValidPermissions(userId); + + if (CollUtil.isEmpty(permissions)) { + return Collections.emptyList(); + } + + // 2. 按 orgType 分组 + Map> groupedByType = permissions.stream() + .collect(Collectors.groupingBy(SysUserDataScope::getOrgType)); + + // 3. 批量查询各类资源的名称 + Map orgNameMap = new HashMap<>(); + + // 3.1 查询流域名称 (BASIN) + if (groupedByType.containsKey("BASIN")) { + Set rvcds = groupedByType.get("BASIN").stream() + .map(SysUserDataScope::getOrgId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + if (CollUtil.isNotEmpty(rvcds)) { + List basins = rvcdDicMapper.selectBatchIds(rvcds); + basins.forEach(basin -> orgNameMap.put(basin.getRvcd(), basin.getRvnm())); + } + } + + // 3.2 查询基地名称 (BASE) + if (groupedByType.containsKey("BASE")) { + Set baseIds = groupedByType.get("BASE").stream() + .map(SysUserDataScope::getOrgId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + if (CollUtil.isNotEmpty(baseIds)) { + List bases = hydrobaseMapper.selectBatchIds(baseIds); + bases.forEach(base -> orgNameMap.put(base.getBaseid(), base.getBasename())); + } + } + + // 3.3 查询公司名称 (COMPANY) + if (groupedByType.containsKey("COMPANY")) { + Set hycds = groupedByType.get("COMPANY").stream() + .map(SysUserDataScope::getOrgId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + if (CollUtil.isNotEmpty(hycds)) { + List companies = hycdDicMapper.selectBatchIds(hycds); + companies.forEach(company -> orgNameMap.put(company.getHycd(), company.getHynm())); + } + } + + // 3.4 查询电站名称 (STATION) + if (groupedByType.containsKey("STATION")) { + Set stcds = groupedByType.get("STATION").stream() + .map(SysUserDataScope::getOrgId) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + + if (CollUtil.isNotEmpty(stcds)) { + List stations = engInfoBHMapper.selectBatchIds(stcds); + stations.forEach(station -> orgNameMap.put(station.getStcd(), station.getEnnm())); + } + } + + // 4. 组装 VO 对象 + List voList = new ArrayList<>(); + for (SysUserDataScope permission : permissions) { + SysUserDataScopeVO vo = new SysUserDataScopeVO(); + BeanUtils.copyProperties(permission, vo); + + // 设置资源名称 + String orgName = orgNameMap.get(permission.getOrgId()); + vo.setOrgName(StrUtil.blankToDefault(orgName, "未知")); + + voList.add(vo); + } + + return voList; + } + + @Override + public boolean batchAddDataScope(EditUserDataScopeBo editUserDataScopeBo) { + List dataScopeList = editUserDataScopeBo.getDataScopeList(); + if (CollUtil.isEmpty(dataScopeList)) { + String userId = editUserDataScopeBo.getUserId(); + // 删除旧数据 + this.remove(new LambdaQueryWrapper().eq(SysUserDataScope::getUserId, userId)); + return true; + } + // 1. 去重:基于 userId + orgType + orgId 去除传入列表中的重复数据 + List uniqueList = dataScopeList.stream() + .collect(Collectors.toMap( + scope -> buildUniqueKey(scope.getUserId(), scope.getOrgType(), scope.getOrgId()), + scope -> scope, + (existing, replacement) -> replacement // 如果有重复,保留后者 + )) + .values() + .stream() + .collect(Collectors.toList()); + + // 2. 提取所有需要处理的唯一键 + Set targetKeys = uniqueList.stream() + .map(scope -> buildUniqueKey(scope.getUserId(), scope.getOrgType(), scope.getOrgId())) + .collect(Collectors.toSet()); + + // 3. 查询数据库中已存在的记录 + List existingRecords = this.lambdaQuery() + .in(SysUserDataScope::getUserId, + uniqueList.stream().map(SysUserDataScope::getUserId).collect(Collectors.toSet())) + .list(); + + // 4. 找出需要删除的记录(数据库中存在但新列表中不存在的) + Set existingKeys = existingRecords.stream() + .map(record -> buildUniqueKey(record.getUserId(), record.getOrgType(), record.getOrgId())) + .collect(Collectors.toSet()); + + List idsToDelete = existingRecords.stream() + .filter(record -> !targetKeys.contains( + buildUniqueKey(record.getUserId(), record.getOrgType(), record.getOrgId()) + )) + .map(SysUserDataScope::getId) + .collect(Collectors.toList()); + + // 5. 找出需要更新的记录(数据库和新列表中都存在的) + List toUpdate = uniqueList.stream() + .filter(scope -> existingKeys.contains( + buildUniqueKey(scope.getUserId(), scope.getOrgType(), scope.getOrgId()) + )) + .peek(scope -> { + // 设置已存在记录的ID + existingRecords.stream() + .filter(existing -> buildUniqueKey(existing.getUserId(), existing.getOrgType(), existing.getOrgId()) + .equals(buildUniqueKey(scope.getUserId(), scope.getOrgType(), scope.getOrgId()))) + .findFirst() + .ifPresent(existing -> scope.setId(existing.getId())); + }) + .collect(Collectors.toList()); + + // 6. 找出需要新增的记录(数据库中不存在的) + List toInsert = uniqueList.stream() + .filter(scope -> !existingKeys.contains( + buildUniqueKey(scope.getUserId(), scope.getOrgType(), scope.getOrgId()) + )) + .collect(Collectors.toList()); + + // 7. 执行删除操作 + if (CollUtil.isNotEmpty(idsToDelete)) { + this.removeByIds(idsToDelete); + } + + // 8. 执行批量新增和更新 + boolean insertResult = CollUtil.isEmpty(toInsert) || this.saveBatch(toInsert); + boolean updateResult = CollUtil.isEmpty(toUpdate) || this.updateBatchById(toUpdate); + return insertResult && updateResult; + } + + /** + * 构建唯一键(userId + orgType + orgId) + */ + private String buildUniqueKey(String userId, String orgType, String orgId) { + return String.format("%s_%s_%s", + StrUtil.blankToDefault(userId, ""), + StrUtil.blankToDefault(orgType, ""), + StrUtil.blankToDefault(orgId, "")); + } } diff --git a/backend/src/main/java/com/yfd/platform/env/controller/TreeStructureController.java b/backend/src/main/java/com/yfd/platform/env/controller/TreeStructureController.java index 4286e1d..f1c4b4b 100644 --- a/backend/src/main/java/com/yfd/platform/env/controller/TreeStructureController.java +++ b/backend/src/main/java/com/yfd/platform/env/controller/TreeStructureController.java @@ -10,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import jakarta.annotation.Resource; + +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -26,20 +28,45 @@ public class TreeStructureController { @Resource private ITreeStructureService treeStructureService; + @GetMapping("/rvcdEng") + @Operation(summary = "获取流域-电站树形结构") + public ResponseResult getRvcdEngTree( + @RequestParam(required = false) String rvcd, + @RequestParam(required = false) String engName) { + List> result = treeStructureService.getRvcdEngTree(rvcd, engName); + return ResponseResult.successData(result); + } + + @GetMapping("/rvcdBaseEng") @Operation(summary = "获取流域-基地-电站树形结构") - public ResponseResult getRvcdBaseEngTree(@RequestParam(required = false) String rvcd) { - List> result = treeStructureService.getRvcdBaseEngTree(rvcd); + public ResponseResult getRvcdBaseEngTree(@RequestParam(required = false) String rvcd, @RequestParam(required = false) String engName) { + List> result = treeStructureService.getRvcdBaseEngTree(rvcd, engName); return ResponseResult.successData(result); } @GetMapping("/rvcdCompanyEng") @Operation(summary = "获取流域-公司-电站树形结构") - public ResponseResult getRvcdCompanyEngTree(@RequestParam(required = false) String rvcd) { - List> result = treeStructureService.getRvcdCompanyEngTree(rvcd); + public ResponseResult getRvcdCompanyEngTree( + @RequestParam(required = false) String rvcd, + @RequestParam(required = false) String engName) { + List> result = treeStructureService.getRvcdCompanyEngTree(rvcd, engName); return ResponseResult.successData(result); } + @GetMapping("/getRvcdBaseOrCompanyEngTree") + @Operation(summary = "获取流域-基地-电站树形结构") + public ResponseResult getRvcdBaseOrCompanyEngTree(@RequestParam(required = false) String rvcd, @RequestParam(required = false) String engName, @RequestParam(required = false) String type) { + if ("1".equals(type)) { + List> result = treeStructureService.getRvcdBaseEngTree(rvcd, engName); + return ResponseResult.successData(result); + } else if ("2".equals(type)) { + List> rvcdCompanyEngTree = treeStructureService.getRvcdCompanyEngTree(rvcd, engName); + return ResponseResult.successData(rvcdCompanyEngTree); + } + return ResponseResult.successData(new ArrayList<>()); + } + @GetMapping("/rvcd") @Operation(summary = "获取流域树") public ResponseResult getRvcdTree(@RequestParam(required = false) String prvcd) { diff --git a/backend/src/main/java/com/yfd/platform/env/service/ITreeStructureService.java b/backend/src/main/java/com/yfd/platform/env/service/ITreeStructureService.java index 8d669d1..360f88d 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/ITreeStructureService.java +++ b/backend/src/main/java/com/yfd/platform/env/service/ITreeStructureService.java @@ -16,13 +16,13 @@ public interface ITreeStructureService { * 获取流域-基地-电站树形结构 * @param rvcd 流域编码(可选,为空则返回全部) */ - List> getRvcdBaseEngTree(String rvcd); + List> getRvcdBaseEngTree(String rvcd, String engName); /** * 获取流域-公司-电站树形结构 * @param rvcd 流域编码(可选,为空则返回全部) */ - List> getRvcdCompanyEngTree(String rvcd); + List> getRvcdCompanyEngTree(String rvcd, String engName); /** * 获取流域树(带子节点标记) @@ -38,4 +38,11 @@ public interface ITreeStructureService { * 获取公司树(带子节点标记) */ List> getHycdTree(String phycd); + + /** + * 获取流域-电站树形结构(二级树) + * @param rvcd 流域编码(可选,为空则返回全部) + * @param engName 电站名称(可选,用于模糊筛选电站) + */ + List> getRvcdEngTree(String rvcd, String engName); } diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/TreeStructureServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/TreeStructureServiceImpl.java index 9ca2266..440687a 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/impl/TreeStructureServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/TreeStructureServiceImpl.java @@ -42,7 +42,7 @@ public class TreeStructureServiceImpl implements ITreeStructureService { private SdPrhyrltnBMapper prhyrltnBMapper; @Override - public List> getRvcdBaseEngTree(String rvcd) { + public List> getRvcdBaseEngTree(String rvcd, String engName) { List> result = new ArrayList<>(); List rvcdList; @@ -60,16 +60,26 @@ public class TreeStructureServiceImpl implements ITreeStructureService { Map> rvcdEngMap = new HashMap<>(); for (SdRvcdDic rvcdDic : rvcdList) { List engList = engInfoBHMapper.selectByRvcd(rvcdDic.getRvcd()); + + // 如果提供了电站名称参数,进行模糊匹配筛选 + if (StringUtils.hasText(engName) && engList != null) { + engList = engList.stream() + .filter(eng -> eng.getEnnm() != null && eng.getEnnm().contains(engName)) + .collect(Collectors.toList()); + } + if (engList != null && !engList.isEmpty()) { rvcdEngMap.put(rvcdDic.getRvcd(), engList); } } + for (SdRvcdDic rvcdDic : rvcdList) { Map rvcdNode = new LinkedHashMap<>(); rvcdNode.put("type", "BASIN"); rvcdNode.put("code", rvcdDic.getRvcd()); rvcdNode.put("name", rvcdDic.getRvnm()); rvcdNode.put("path", rvcdDic.getPath()); + rvcdNode.put("orgLevel", 0); rvcdNode.put("grd", rvcdDic.getGrd()); rvcdNode.put("lgtd", rvcdDic.getLgtd()); rvcdNode.put("lttd", rvcdDic.getLttd()); @@ -102,6 +112,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { baseNode.put("shortname", base.getShortname()); baseNode.put("grd", base.getGrd()); baseNode.put("parentId", rvcdDic.getRvcd()); + baseNode.put("orgLevel", 1); + List> engChildren = new ArrayList<>(); for (SdEngInfoBH eng : baseEngList) { Map engNode = new LinkedHashMap<>(); @@ -115,71 +127,140 @@ public class TreeStructureServiceImpl implements ITreeStructureService { engNode.put("bldstt", eng.getBldstt()); engNode.put("engtp", eng.getEngtp()); engNode.put("parentId", base.getBaseid()); + engNode.put("orgLevel", 2); engChildren.add(engNode); } - baseNode.put("children", engChildren); - baseChildren.add(baseNode); + + // 只有当该基地下有电站时才添加该基地节点 + if (!engChildren.isEmpty()) { + baseNode.put("children", engChildren); + baseChildren.add(baseNode); + } } } - rvcdNode.put("children", baseChildren); - result.add(rvcdNode); + // 只有当该流域下有基地(进而有电站)时才添加该流域节点 + if (!baseChildren.isEmpty()) { + rvcdNode.put("children", baseChildren); + result.add(rvcdNode); + } } return result; } + @Override - public List> getRvcdCompanyEngTree(String rvcd) { + public List> getRvcdCompanyEngTree(String rvcd, String engName) { List> result = new ArrayList<>(); + // 1. 查询流域列表 List rvcdList; if (StringUtils.hasText(rvcd)) { rvcdList = rvcdDicMapper.selectByPrvcd(rvcd); + SdRvcdDic singleRvcd = rvcdDicMapper.selectById(rvcd); + if (singleRvcd != null && !rvcdList.contains(singleRvcd)) { + rvcdList = new ArrayList<>(); + rvcdList.add(singleRvcd); + } } else { rvcdList = rvcdDicMapper.selectRootList(); } + // 2. 预加载所有流域下的电站(按流域分组) + Map> rvcdEngMap = new HashMap<>(); + for (SdRvcdDic rvcdDic : rvcdList) { + List engList = engInfoBHMapper.selectByRvcd(rvcdDic.getRvcd()); + + // 如果提供了电站名称参数,进行模糊匹配筛选 + if (StringUtils.hasText(engName) && engList != null) { + engList = engList.stream() + .filter(eng -> eng.getEnnm() != null && eng.getEnnm().contains(engName)) + .collect(Collectors.toList()); + } + + if (engList != null && !engList.isEmpty()) { + rvcdEngMap.put(rvcdDic.getRvcd(), engList); + } + } + + // 3. 构建树形结构 for (SdRvcdDic rvcdDic : rvcdList) { Map rvcdNode = new LinkedHashMap<>(); - rvcdNode.put("type", "RVCD"); + rvcdNode.put("type", "BASIN"); rvcdNode.put("code", rvcdDic.getRvcd()); rvcdNode.put("name", rvcdDic.getRvnm()); rvcdNode.put("path", rvcdDic.getPath()); + rvcdNode.put("orgLevel", 0); rvcdNode.put("grd", rvcdDic.getGrd()); + rvcdNode.put("lgtd", rvcdDic.getLgtd()); + rvcdNode.put("lttd", rvcdDic.getLttd()); + rvcdNode.put("parentId", "0"); - List companyList = hycdDicMapper.selectRootList(); List> companyChildren = new ArrayList<>(); - for (SdHycdDic company : companyList) { - Map companyNode = new LinkedHashMap<>(); - companyNode.put("type", "COMPANY"); - companyNode.put("code", company.getHycd()); - companyNode.put("name", company.getHynm()); - companyNode.put("shortname", company.getShortname()); + // 获取该流域下的所有电站 + List engList = rvcdEngMap.get(rvcdDic.getRvcd()); + if (engList != null && !engList.isEmpty()) { + // 按公司编码分组(直接使用电站表中的 HYCD 字段) + Map> companyEngMap = engList.stream() + .filter(eng -> StringUtils.hasText(eng.getHycd())) + .collect(Collectors.groupingBy(SdEngInfoBH::getHycd)); - List stcdList = prhyrltnBMapper.selectStcdListByHycd(company.getHycd()); - List> engChildren = new ArrayList<>(); + // 遍历每个公司,构建公司节点 + for (Map.Entry> entry : companyEngMap.entrySet()) { + String hycd = entry.getKey(); + List companyEngList = entry.getValue(); - for (String stcd : stcdList) { - SdEngInfoBH eng = engInfoBHMapper.selectById(stcd); - if (eng != null) { + // 查询公司信息 + SdHycdDic company = hycdDicMapper.selectById(hycd); + if (company == null) { + company = new SdHycdDic(); + company.setHycd(hycd); + company.setHynm("未知公司"); + company.setShortname("未知"); + } + + Map companyNode = new LinkedHashMap<>(); + companyNode.put("type", "COMPANY"); + companyNode.put("code", company.getHycd()); + companyNode.put("name", company.getHynm()); + companyNode.put("shortname", company.getShortname()); + companyNode.put("grd", company.getGrd()); + companyNode.put("parentId", rvcdDic.getRvcd()); + companyNode.put("orgLevel", 1); + + // 构建电站子节点 + List> engChildren = new ArrayList<>(); + for (SdEngInfoBH eng : companyEngList) { Map engNode = new LinkedHashMap<>(); - engNode.put("type", "ENG"); + engNode.put("type", "STATION"); engNode.put("code", eng.getStcd()); engNode.put("name", eng.getEnnm()); engNode.put("lgtd", eng.getLgtd()); engNode.put("lttd", eng.getLttd()); + engNode.put("elev", eng.getElev()); + engNode.put("usfl", eng.getUsfl()); + engNode.put("bldstt", eng.getBldstt()); + engNode.put("engtp", eng.getEngtp()); + engNode.put("parentId", company.getHycd()); + engNode.put("orgLevel", 2); engChildren.add(engNode); } - } - companyNode.put("children", engChildren); - companyChildren.add(companyNode); + // 只有当该公司下有电站时才添加该公司节点 + if (!engChildren.isEmpty()) { + companyNode.put("children", engChildren); + companyChildren.add(companyNode); + } + } } - rvcdNode.put("children", companyChildren); - result.add(rvcdNode); + // 只有当该流域下有公司(进而有电站)时才添加该流域节点 + if (!companyChildren.isEmpty()) { + rvcdNode.put("children", companyChildren); + result.add(rvcdNode); + } } return result; @@ -265,4 +346,85 @@ public class TreeStructureServiceImpl implements ITreeStructureService { return result; } + + @Override + public List> getRvcdEngTree(String rvcd, String engName) { + List> result = new ArrayList<>(); + + // 1. 查询流域列表 + List rvcdList; + if (StringUtils.hasText(rvcd)) { + rvcdList = rvcdDicMapper.selectByPrvcd(rvcd); + SdRvcdDic singleRvcd = rvcdDicMapper.selectById(rvcd); + if (singleRvcd != null && !rvcdList.contains(singleRvcd)) { + rvcdList = new ArrayList<>(); + rvcdList.add(singleRvcd); + } + } else { + rvcdList = rvcdDicMapper.selectRootList(); + } + + // 2. 预加载所有流域下的电站(按流域分组) + Map> rvcdEngMap = new HashMap<>(); + for (SdRvcdDic rvcdDic : rvcdList) { + List engList = engInfoBHMapper.selectByRvcd(rvcdDic.getRvcd()); + + // 如果提供了电站名称参数,进行模糊匹配筛选 + if (StringUtils.hasText(engName) && engList != null) { + engList = engList.stream() + .filter(eng -> eng.getEnnm() != null && eng.getEnnm().contains(engName)) + .collect(Collectors.toList()); + } + + if (engList != null && !engList.isEmpty()) { + rvcdEngMap.put(rvcdDic.getRvcd(), engList); + } + } + + // 3. 构建二级树形结构(流域 -> 电站) + for (SdRvcdDic rvcdDic : rvcdList) { + Map rvcdNode = new LinkedHashMap<>(); + rvcdNode.put("type", "BASIN"); + rvcdNode.put("code", rvcdDic.getRvcd()); + rvcdNode.put("name", rvcdDic.getRvnm()); + rvcdNode.put("path", rvcdDic.getPath()); + rvcdNode.put("orgLevel", 0); + rvcdNode.put("grd", rvcdDic.getGrd()); + rvcdNode.put("lgtd", rvcdDic.getLgtd()); + rvcdNode.put("lttd", rvcdDic.getLttd()); + rvcdNode.put("parentId", "0"); + + // 获取该流域下的所有电站 + List engList = rvcdEngMap.get(rvcdDic.getRvcd()); + List> engChildren = new ArrayList<>(); + + if (engList != null && !engList.isEmpty()) { + for (SdEngInfoBH eng : engList) { + Map engNode = new LinkedHashMap<>(); + engNode.put("type", "STATION"); + engNode.put("code", eng.getStcd()); + engNode.put("name", eng.getEnnm()); + engNode.put("lgtd", eng.getLgtd()); + engNode.put("lttd", eng.getLttd()); + engNode.put("elev", eng.getElev()); + engNode.put("usfl", eng.getUsfl()); + engNode.put("bldstt", eng.getBldstt()); + engNode.put("engtp", eng.getEngtp()); + engNode.put("parentId", rvcdDic.getRvcd()); + engNode.put("orgLevel", 1); + engChildren.add(engNode); + } + } + + // 只有当该流域下有电站时才添加该流域节点 + if (!engChildren.isEmpty()) { + rvcdNode.put("children", engChildren); + result.add(rvcdNode); + } + } + + return result; + } + + }