Merge branch 'main' of http://121.37.111.42:3000/zhengsl/WholeProcessPlatform into main_hzz
This commit is contained in:
commit
57a6cf9e81
@ -15,7 +15,14 @@
|
||||
*/
|
||||
package com.yfd.platform.config;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import com.yfd.platform.qgc_env.wq.service.EnvWqDataService;
|
||||
import com.yfd.platform.qgc_job.service.IDwJobService;
|
||||
import com.yfd.platform.qgc_job.service.IEqJobService;
|
||||
import com.yfd.platform.qgc_job.service.IFhJobService;
|
||||
import com.yfd.platform.system.domain.QuartzJob;
|
||||
import com.yfd.platform.system.mapper.QuartzJobMapper;
|
||||
import com.yfd.platform.utils.QuartzManage;
|
||||
@ -42,6 +49,10 @@ public class JobRunner implements ApplicationRunner {
|
||||
private static final Logger log = LoggerFactory.getLogger(JobRunner.class);
|
||||
private final QuartzJobMapper quartzJobMapper;
|
||||
private final QuartzManage quartzManage;
|
||||
private final EnvWqDataService envWqDataService;
|
||||
private final IEqJobService eqJobService;
|
||||
private final IDwJobService dwJobService;
|
||||
private final IFhJobService fhJobService;
|
||||
|
||||
/**
|
||||
* 项目启动时重新激活启用的定时任务
|
||||
@ -55,5 +66,25 @@ public class JobRunner implements ApplicationRunner {
|
||||
quartzJobMapper.selectList(new LambdaQueryWrapper<QuartzJob>().eq(QuartzJob::getStatus, "1"));
|
||||
quartzJobs.forEach(quartzManage::addJob);
|
||||
log.info("--------------------定时任务注入完成---------------------");
|
||||
JobBaseAo ao = new JobBaseAo();
|
||||
//如果没有传递时间,则默认为上个月的开始到现在
|
||||
if (null == ao.getEndTime()){
|
||||
ao.setEndTime(DateUtil.date());
|
||||
}
|
||||
if (null == ao.getStartTime()){
|
||||
ao.setStartTime(DateUtil.beginOfYear(DateUtil.offset(ao.getEndTime(), DateField.YEAR,-1)));
|
||||
}
|
||||
envWqDataService.wqLastData(ao);
|
||||
log.info("--------------------wq最新一条数据---------------------");
|
||||
eqJobService.eqAnchorPointLastDate(ao);
|
||||
log.info("--------------------eq最新一条数据---------------------");
|
||||
eqJobService.eqAnchorPointLastDate(ao);
|
||||
log.info("--------------------eq最新一条数据---------------------");
|
||||
dwJobService.wtLastData(ao);
|
||||
log.info("--------------------wt最新一条数据---------------------");
|
||||
dwJobService.wtvtPointData(ao);
|
||||
log.info("--------------------wt最新一条数据---------------------");
|
||||
fhJobService.zqLastData(ao);
|
||||
log.info("--------------------fh最新一条数据---------------------");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package com.yfd.platform.config;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springdoc.core.models.GroupedOpenApi;
|
||||
@ -10,15 +13,55 @@ import io.swagger.v3.oas.models.info.Contact;
|
||||
@Configuration
|
||||
public class SwaggerConfig {
|
||||
|
||||
|
||||
// @Bean
|
||||
// public OpenAPI projectOpenAPI() {
|
||||
// return new OpenAPI()
|
||||
// .info(new Info()
|
||||
// .title("项目API 接口文档")
|
||||
// .version("3.0")
|
||||
// .description("")
|
||||
// .contact(new Contact().name("郑顺利").email("13910913995@163.com"))
|
||||
// );
|
||||
// }
|
||||
|
||||
|
||||
@Bean
|
||||
public OpenAPI projectOpenAPI() {
|
||||
// 1. 定义第一个 Header:token
|
||||
SecurityScheme tokenScheme = new SecurityScheme()
|
||||
.type(SecurityScheme.Type.APIKEY)
|
||||
.in(SecurityScheme.In.HEADER)
|
||||
.name("token")
|
||||
.description("用户认证 Token");
|
||||
|
||||
// 2. 定义第二个 Header:租户ID(示例)
|
||||
SecurityScheme tenantScheme = new SecurityScheme()
|
||||
.type(SecurityScheme.Type.APIKEY)
|
||||
.in(SecurityScheme.In.HEADER)
|
||||
.name("Tenant_Id")
|
||||
.description("租户标识");
|
||||
|
||||
// 3. 将两个安全方案注册到 Components
|
||||
Components components = new Components()
|
||||
.addSecuritySchemes("tokenAuth", tokenScheme)
|
||||
.addSecuritySchemes("tenantAuth", tenantScheme);
|
||||
|
||||
// 4. 创建 SecurityRequirement,同时要求两个 Header 都必须提供
|
||||
SecurityRequirement securityRequirement = new SecurityRequirement()
|
||||
.addList("tokenAuth") // 引用 token 方案
|
||||
.addList("tenantAuth"); // 引用 tenant 方案
|
||||
|
||||
|
||||
return new OpenAPI()
|
||||
.info(new Info()
|
||||
.title("项目API 接口文档")
|
||||
.version("3.0")
|
||||
.description("")
|
||||
.contact(new Contact().name("郑顺利").email("13910913995@163.com"))
|
||||
);
|
||||
)
|
||||
.components(components)
|
||||
.addSecurityItem(securityRequirement); // 一次性添加
|
||||
}
|
||||
|
||||
// @Bean
|
||||
|
||||
@ -52,9 +52,27 @@ public class SdEngMonitorController {
|
||||
return ResponseResult.successData(engInfoBHService.getEngPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/alarmPoint/GetKendoListCust")
|
||||
@Operation(summary = "电站告警描点列表")
|
||||
public ResponseResult getAlarmPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(engInfoBHService.getAlarmPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/rsvrcscdb/GetKendoList")
|
||||
@Operation(summary = "条件过滤数据列表")
|
||||
public ResponseResult getRsvrcscdBKendoList(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(engInfoBHService.getRsvrcscdBKendoList(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/rsvrcscdb/rvcd")
|
||||
@Operation(summary = "查询梯级流域")
|
||||
public ResponseResult getRsvrcscdBRvcdList(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(engInfoBHService.getRsvrcscdBRvcdList(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/rsvrcscdb/getQgcRvcd")
|
||||
@Operation(summary = "查询梯级流域图流域")
|
||||
public ResponseResult getQgcRvcdList(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(engInfoBHService.getQgcRvcdList(dataSourceRequest));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package com.yfd.platform.qgc_base.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 当前登录用户的数据权限范围
|
||||
*/
|
||||
@Data
|
||||
public class CurrentUserDataScopeVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 是否为统一管理的超级管理员
|
||||
*/
|
||||
private boolean managedAdmin;
|
||||
|
||||
/**
|
||||
* 当前用户有权限的电站编码
|
||||
*/
|
||||
private Set<String> stationCodes = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* 当前用户有权限的流域编码
|
||||
*/
|
||||
private Set<String> rvcdCodes = new LinkedHashSet<>();
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.yfd.platform.qgc_base.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 数据权限条件应用结果
|
||||
*/
|
||||
@Data
|
||||
public class DataScopeApplyResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 当前用户是否为管理员
|
||||
*/
|
||||
private boolean managedAdmin;
|
||||
|
||||
/**
|
||||
* 当前权限是否命中空结果
|
||||
*/
|
||||
private boolean emptyResult;
|
||||
|
||||
/**
|
||||
* 是否已向查询中追加权限条件
|
||||
*/
|
||||
private boolean conditionApplied;
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
package com.yfd.platform.qgc_base.domain.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Schema(description = "电站告警描点")
|
||||
public class EngAlarmPointVo {
|
||||
|
||||
@Schema(description = "站点类型")
|
||||
private String sttp;
|
||||
|
||||
@Schema(description = "站点编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "经度")
|
||||
private BigDecimal lgtd;
|
||||
|
||||
@Schema(description = "纬度")
|
||||
private BigDecimal lttd;
|
||||
|
||||
@Schema(description = "高程")
|
||||
private BigDecimal dtmel;
|
||||
|
||||
@Schema(description = "描点状态")
|
||||
private String anchoPointState;
|
||||
|
||||
@Schema(description = "锚点类型")
|
||||
private String sttpMap;
|
||||
|
||||
@Schema(description = "弹框站点名称")
|
||||
private String titleName;
|
||||
|
||||
@Schema(description = "地图避让")
|
||||
private Integer distance;
|
||||
|
||||
@Schema(description = "流域编码")
|
||||
private String rvcd;
|
||||
|
||||
@Schema(description = "行政编码")
|
||||
private String addvcd;
|
||||
|
||||
@Schema(description = "基地编码")
|
||||
private String baseId;
|
||||
|
||||
@Schema(description = "关联电站编码")
|
||||
private String rstcds;
|
||||
|
||||
@Schema(description = "设施类型")
|
||||
private String sttpCode;
|
||||
|
||||
@Schema(description = "电站名称")
|
||||
private String ennm;
|
||||
|
||||
@Schema(description = "流域名称")
|
||||
private String rvnm;
|
||||
|
||||
@Schema(description = "电站装机类型")
|
||||
private Integer endInstalledType;
|
||||
|
||||
@Schema(description = "生态流量告警数")
|
||||
private Integer stqCount;
|
||||
|
||||
@Schema(description = "水质告警数")
|
||||
private Integer wqCount;
|
||||
|
||||
@Schema(description = "水位告警数")
|
||||
private Integer zCount;
|
||||
|
||||
@Schema(description = "水温告警数")
|
||||
private Integer wtCount;
|
||||
|
||||
@Schema(description = "年份")
|
||||
private String yyyy;
|
||||
|
||||
@Schema(description = "告警区间范围")
|
||||
private String range;
|
||||
|
||||
@Schema(description = "装机容量")
|
||||
private BigDecimal ttpwr;
|
||||
|
||||
@Schema(description = "基地名称")
|
||||
private String baseName;
|
||||
|
||||
@Schema(description = "电站编码")
|
||||
private String rstcd;
|
||||
|
||||
@Schema(description = "流域沿程")
|
||||
private Integer rvcdStepSort;
|
||||
|
||||
@Schema(description = "电站沿程")
|
||||
private Integer rstcdStepSort;
|
||||
|
||||
@Schema(description = "站点沿程")
|
||||
private Integer siteStepSort;
|
||||
|
||||
@Schema(description = "电站图片")
|
||||
private String logo;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.yfd.platform.qgc_base.domain.vo;
|
||||
|
||||
import com.yfd.platform.qgc_eng.eq.entity.vo.LastTmEngEqDataVo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@ -99,4 +100,7 @@ public class EngPointVo {
|
||||
|
||||
@Schema(description = "基地排序")
|
||||
private Integer baseStepSort;
|
||||
|
||||
@Schema(description="电站最新数据:入库流量和出库流量")
|
||||
private LastTmEngEqDataVo lastTmEngEqDataVo;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.qgc_base.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class EngQgcRvcdVo {
|
||||
|
||||
private String rvcd;
|
||||
|
||||
private String rvnm;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.yfd.platform.qgc_base.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class EngRsvrcscdRvcdVo {
|
||||
|
||||
private String wbsCode;
|
||||
|
||||
private String wbsName;
|
||||
|
||||
/**
|
||||
* 旧口径对应上级/关联对象编码,新库这里映射为基地编码。
|
||||
*/
|
||||
private String objId;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.yfd.platform.qgc_base.service;
|
||||
|
||||
import com.yfd.platform.qgc_base.domain.vo.CurrentUserDataScopeVo;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 当前登录用户数据权限公共服务
|
||||
*/
|
||||
public interface ICurrentUserDataScopeService {
|
||||
|
||||
/**
|
||||
* 获取当前用户完整的数据权限范围
|
||||
*/
|
||||
CurrentUserDataScopeVo getCurrentUserDataScope();
|
||||
|
||||
/**
|
||||
* 获取当前用户有权限的电站编码
|
||||
*/
|
||||
Set<String> getCurrentUserAuthorizedStationCodes();
|
||||
|
||||
/**
|
||||
* 获取当前用户有权限的流域编码
|
||||
*/
|
||||
Set<String> getCurrentUserAuthorizedRvcdCodes();
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.yfd.platform.qgc_base.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 当前用户数据权限过滤公共服务
|
||||
*/
|
||||
public interface IDataScopeFilterService {
|
||||
|
||||
/**
|
||||
* 追加当前用户电站权限 SQL 条件
|
||||
*/
|
||||
DataScopeApplyResult appendCurrentUserStationScope(StringBuilder sql, Map<String, Object> paramMap, String columnName);
|
||||
|
||||
/**
|
||||
* 追加当前用户流域权限 SQL 条件
|
||||
*/
|
||||
DataScopeApplyResult appendCurrentUserRvcdScope(StringBuilder sql, Map<String, Object> paramMap, String columnName);
|
||||
|
||||
/**
|
||||
* 追加当前用户电站权限 Wrapper 条件
|
||||
*/
|
||||
<T> DataScopeApplyResult applyCurrentUserStationScope(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> column);
|
||||
|
||||
/**
|
||||
* 追加当前用户流域权限 Wrapper 条件
|
||||
*/
|
||||
<T> DataScopeApplyResult applyCurrentUserRvcdScope(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> column);
|
||||
}
|
||||
@ -7,9 +7,12 @@ import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.qgc_base.domain.SdEngInfoBH;
|
||||
import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngAlarmPointVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngOperatVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngQgcRvcdVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdBVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdRvcdVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngPointVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo;
|
||||
@ -91,5 +94,11 @@ public interface ISdEngInfoBHService extends IService<SdEngInfoBH> {
|
||||
|
||||
DataSourceResult<EngPointVo> getEngPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<EngAlarmPointVo> getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<EngRsvrcscdBVo> getRsvrcscdBKendoList(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<EngRsvrcscdRvcdVo> getRsvrcscdBRvcdList(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<EngQgcRvcdVo> getQgcRvcdList(DataSourceRequest dataSourceRequest);
|
||||
}
|
||||
|
||||
@ -0,0 +1,161 @@
|
||||
package com.yfd.platform.qgc_base.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.yfd.platform.qgc_base.domain.SdEngInfoBH;
|
||||
import com.yfd.platform.qgc_base.domain.vo.CurrentUserDataScopeVo;
|
||||
import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper;
|
||||
import com.yfd.platform.qgc_base.service.ICurrentUserDataScopeService;
|
||||
import com.yfd.platform.qgc_data.domain.SysUserDataScope;
|
||||
import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper;
|
||||
import com.yfd.platform.system.service.IAdminAuthService;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 当前登录用户数据权限公共服务实现
|
||||
*/
|
||||
@Service
|
||||
public class CurrentUserDataScopeServiceImpl implements ICurrentUserDataScopeService {
|
||||
|
||||
private static final int QUERY_BATCH_SIZE = 500;
|
||||
|
||||
@Resource
|
||||
private SysUserDataScopeMapper sysUserDataScopeMapper;
|
||||
|
||||
@Resource
|
||||
private SdEngInfoBHMapper sdEngInfoBHMapper;
|
||||
|
||||
@Resource
|
||||
private IAdminAuthService adminAuthService;
|
||||
|
||||
@Override
|
||||
public CurrentUserDataScopeVo getCurrentUserDataScope() {
|
||||
CurrentUserDataScopeVo scopeVo = new CurrentUserDataScopeVo();
|
||||
if (adminAuthService.isCurrentManagedAdmin()) {
|
||||
scopeVo.setManagedAdmin(true);
|
||||
return scopeVo;
|
||||
}
|
||||
|
||||
String userId = SecurityUtils.getUserId();
|
||||
if (!StringUtils.hasText(userId)) {
|
||||
return scopeVo;
|
||||
}
|
||||
|
||||
List<SysUserDataScope> validPermissions = sysUserDataScopeMapper.selectValidPermissions(userId);
|
||||
if (validPermissions == null || validPermissions.isEmpty()) {
|
||||
return scopeVo;
|
||||
}
|
||||
|
||||
Set<String> directStationCodes = collectOrgIdsByType(validPermissions, "STATION");
|
||||
Set<String> directRvcdCodes = collectOrgIdsByType(validPermissions, "RVCD");
|
||||
Set<String> stationCodes = new LinkedHashSet<>();
|
||||
Set<String> rvcdCodes = new LinkedHashSet<>();
|
||||
|
||||
if (!directStationCodes.isEmpty()) {
|
||||
List<SdEngInfoBH> stationList = listStationsByStcds(directStationCodes);
|
||||
stationCodes.addAll(extractStationCodes(stationList));
|
||||
rvcdCodes.addAll(extractLegacyBasinCodes(stationList));
|
||||
}
|
||||
|
||||
if (!directRvcdCodes.isEmpty()) {
|
||||
List<SdEngInfoBH> stationList = listStationsByReachcds(directRvcdCodes);
|
||||
stationCodes.addAll(extractStationCodes(stationList));
|
||||
rvcdCodes.addAll(extractLegacyBasinCodes(stationList));
|
||||
}
|
||||
|
||||
scopeVo.setStationCodes(stationCodes);
|
||||
scopeVo.setRvcdCodes(rvcdCodes);
|
||||
return scopeVo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCurrentUserAuthorizedStationCodes() {
|
||||
return getCurrentUserDataScope().getStationCodes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getCurrentUserAuthorizedRvcdCodes() {
|
||||
return getCurrentUserDataScope().getRvcdCodes();
|
||||
}
|
||||
|
||||
private Set<String> collectOrgIdsByType(List<SysUserDataScope> scopes, String orgType) {
|
||||
Set<String> orgIds = new LinkedHashSet<>();
|
||||
for (SysUserDataScope scope : scopes) {
|
||||
if (scope == null || !orgType.equalsIgnoreCase(scope.getOrgType())) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.hasText(scope.getOrgId())) {
|
||||
orgIds.add(scope.getOrgId());
|
||||
}
|
||||
}
|
||||
return orgIds;
|
||||
}
|
||||
|
||||
private List<SdEngInfoBH> listStationsByStcds(Set<String> stationCodes) {
|
||||
return listStationsByColumn(stationCodes, QueryDimension.STATION);
|
||||
}
|
||||
|
||||
private List<SdEngInfoBH> listStationsByReachcds(Set<String> rvcdCodes) {
|
||||
return listStationsByColumn(rvcdCodes, QueryDimension.REACH);
|
||||
}
|
||||
|
||||
private List<SdEngInfoBH> listStationsByColumn(Set<String> codes, QueryDimension queryDimension) {
|
||||
List<SdEngInfoBH> result = new ArrayList<>();
|
||||
if (codes == null || codes.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<String> codeList = new ArrayList<>(codes);
|
||||
for (int i = 0; i < codeList.size(); i += QUERY_BATCH_SIZE) {
|
||||
int end = Math.min(i + QUERY_BATCH_SIZE, codeList.size());
|
||||
List<String> batchCodes = codeList.subList(i, end);
|
||||
LambdaQueryWrapper<SdEngInfoBH> wrapper = new LambdaQueryWrapper<SdEngInfoBH>()
|
||||
.select(SdEngInfoBH::getStcd, SdEngInfoBH::getReachcd, SdEngInfoBH::getEnnm);
|
||||
if (queryDimension == QueryDimension.STATION) {
|
||||
wrapper.in(SdEngInfoBH::getStcd, batchCodes);
|
||||
} else {
|
||||
wrapper.in(SdEngInfoBH::getReachcd, batchCodes);
|
||||
}
|
||||
result.addAll(sdEngInfoBHMapper.selectList(wrapper));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<String> extractStationCodes(List<SdEngInfoBH> stationList) {
|
||||
Set<String> stationCodes = new LinkedHashSet<>();
|
||||
if (stationList == null || stationList.isEmpty()) {
|
||||
return stationCodes;
|
||||
}
|
||||
for (SdEngInfoBH station : stationList) {
|
||||
if (station != null && StringUtils.hasText(station.getStcd())) {
|
||||
stationCodes.add(station.getStcd());
|
||||
}
|
||||
}
|
||||
return stationCodes;
|
||||
}
|
||||
|
||||
private Set<String> extractLegacyBasinCodes(List<SdEngInfoBH> stationList) {
|
||||
Set<String> rvcdCodes = new LinkedHashSet<>();
|
||||
if (stationList == null || stationList.isEmpty()) {
|
||||
return rvcdCodes;
|
||||
}
|
||||
for (SdEngInfoBH station : stationList) {
|
||||
if (station != null && StringUtils.hasText(station.getEnnm()) && StringUtils.hasText(station.getReachcd())) {
|
||||
rvcdCodes.add(station.getReachcd());
|
||||
}
|
||||
}
|
||||
return rvcdCodes;
|
||||
}
|
||||
|
||||
private enum QueryDimension {
|
||||
STATION,
|
||||
REACH
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,154 @@
|
||||
package com.yfd.platform.qgc_base.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.yfd.platform.qgc_base.domain.vo.CurrentUserDataScopeVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult;
|
||||
import com.yfd.platform.qgc_base.service.ICurrentUserDataScopeService;
|
||||
import com.yfd.platform.qgc_base.service.IDataScopeFilterService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 当前用户数据权限过滤公共服务实现
|
||||
*/
|
||||
@Service
|
||||
public class DataScopeFilterServiceImpl implements IDataScopeFilterService {
|
||||
|
||||
private static final int IN_BATCH_SIZE = 900;
|
||||
|
||||
@Resource
|
||||
private ICurrentUserDataScopeService currentUserDataScopeService;
|
||||
|
||||
@Override
|
||||
public DataScopeApplyResult appendCurrentUserStationScope(StringBuilder sql, Map<String, Object> paramMap, String columnName) {
|
||||
CurrentUserDataScopeVo scopeVo = currentUserDataScopeService.getCurrentUserDataScope();
|
||||
return appendScopeCondition(sql, paramMap, columnName, scopeVo, scopeVo.getStationCodes(), "stationScope");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataScopeApplyResult appendCurrentUserRvcdScope(StringBuilder sql, Map<String, Object> paramMap, String columnName) {
|
||||
CurrentUserDataScopeVo scopeVo = currentUserDataScopeService.getCurrentUserDataScope();
|
||||
return appendScopeCondition(sql, paramMap, columnName, scopeVo, scopeVo.getRvcdCodes(), "rvcdScope");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DataScopeApplyResult applyCurrentUserStationScope(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> column) {
|
||||
CurrentUserDataScopeVo scopeVo = currentUserDataScopeService.getCurrentUserDataScope();
|
||||
return applyScopeCondition(wrapper, column, scopeVo, scopeVo.getStationCodes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DataScopeApplyResult applyCurrentUserRvcdScope(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> column) {
|
||||
CurrentUserDataScopeVo scopeVo = currentUserDataScopeService.getCurrentUserDataScope();
|
||||
return applyScopeCondition(wrapper, column, scopeVo, scopeVo.getRvcdCodes());
|
||||
}
|
||||
|
||||
private DataScopeApplyResult appendScopeCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
String columnName,
|
||||
CurrentUserDataScopeVo scopeVo,
|
||||
Set<String> scopeValues,
|
||||
String paramPrefix) {
|
||||
DataScopeApplyResult result = initResult(scopeVo, scopeValues);
|
||||
if (result.isManagedAdmin() || result.isEmptyResult()) {
|
||||
return result;
|
||||
}
|
||||
if (!StringUtils.hasText(columnName)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<List<String>> batches = splitValues(scopeValues);
|
||||
if (batches.isEmpty()) {
|
||||
result.setEmptyResult(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
sql.append(" AND (");
|
||||
for (int i = 0; i < batches.size(); i++) {
|
||||
if (i > 0) {
|
||||
sql.append(" OR ");
|
||||
}
|
||||
List<String> batch = batches.get(i);
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
for (int j = 0; j < batch.size(); j++) {
|
||||
String key = buildParamKey(paramMap, paramPrefix, i, j);
|
||||
paramMap.put(key, batch.get(j));
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
sql.append(columnName).append(" IN (").append(String.join(", ", placeholders)).append(")");
|
||||
}
|
||||
sql.append(") ");
|
||||
result.setConditionApplied(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
private <T> DataScopeApplyResult applyScopeCondition(LambdaQueryWrapper<T> wrapper,
|
||||
SFunction<T, ?> column,
|
||||
CurrentUserDataScopeVo scopeVo,
|
||||
Set<String> scopeValues) {
|
||||
DataScopeApplyResult result = initResult(scopeVo, scopeValues);
|
||||
if (result.isManagedAdmin() || result.isEmptyResult()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<List<String>> batches = splitValues(scopeValues);
|
||||
if (batches.isEmpty()) {
|
||||
result.setEmptyResult(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
wrapper.and(innerWrapper -> {
|
||||
for (int i = 0; i < batches.size(); i++) {
|
||||
if (i > 0) {
|
||||
innerWrapper.or();
|
||||
}
|
||||
innerWrapper.in(column, batches.get(i));
|
||||
}
|
||||
});
|
||||
result.setConditionApplied(true);
|
||||
return result;
|
||||
}
|
||||
|
||||
private DataScopeApplyResult initResult(CurrentUserDataScopeVo scopeVo, Collection<String> scopeValues) {
|
||||
DataScopeApplyResult result = new DataScopeApplyResult();
|
||||
if (scopeVo != null && scopeVo.isManagedAdmin()) {
|
||||
result.setManagedAdmin(true);
|
||||
return result;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(scopeValues)) {
|
||||
result.setEmptyResult(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<List<String>> splitValues(Collection<String> values) {
|
||||
List<List<String>> batches = new ArrayList<>();
|
||||
if (CollectionUtils.isEmpty(values)) {
|
||||
return batches;
|
||||
}
|
||||
|
||||
List<String> valueList = new ArrayList<>(values);
|
||||
for (int i = 0; i < valueList.size(); i += IN_BATCH_SIZE) {
|
||||
int end = Math.min(i + IN_BATCH_SIZE, valueList.size());
|
||||
batches.add(valueList.subList(i, end));
|
||||
}
|
||||
return batches;
|
||||
}
|
||||
|
||||
private String buildParamKey(Map<String, Object> paramMap, String paramPrefix, int batchIndex, int itemIndex) {
|
||||
String key = paramPrefix + "_" + batchIndex + "_" + itemIndex;
|
||||
while (paramMap.containsKey(key)) {
|
||||
key = key + "_n";
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,8 @@ package com.yfd.platform.qgc_base.service.impl;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@ -23,21 +25,28 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.qgc_data.domain.SysUserDataScope;
|
||||
import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper;
|
||||
import com.yfd.platform.qgc_base.domain.SdEngInfoBH;
|
||||
import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult;
|
||||
import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngAlarmPointVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngOperatVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngQgcRvcdVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdBVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngRsvrcscdRvcdVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngPointVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngStbprpDataVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngStBaseInfoVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo;
|
||||
import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo;
|
||||
import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper;
|
||||
import com.yfd.platform.qgc_base.service.IDataScopeFilterService;
|
||||
import com.yfd.platform.qgc_base.service.IMsOperationLogService;
|
||||
import com.yfd.platform.qgc_base.service.ISdEngInfoBHService;
|
||||
import com.yfd.platform.qgc_eng.eq.entity.vo.LastTmEngEqDataVo;
|
||||
import com.yfd.platform.system.service.IAdminAuthService;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import com.yfd.platform.utils.RedisCacheUtil;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
@ -59,6 +68,10 @@ import java.util.stream.Collectors;
|
||||
public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEngInfoBH> implements ISdEngInfoBHService {
|
||||
|
||||
private static final Map<String, String> ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>();
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
@Resource
|
||||
private IDataScopeFilterService dataScopeFilterService;
|
||||
|
||||
static {
|
||||
ENG_CODE_NAME_FIELD_MAP.put("baseId", "baseName");
|
||||
@ -126,8 +139,26 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "engInfoCache#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public List<SdEngInfoBH> selectForDropdown(SdEngInfoBHRequest sdEngInfoBHRequest) {
|
||||
List<SdEngInfoBH> allData = this.selectForDropdownCached(sdEngInfoBHRequest);
|
||||
|
||||
if (adminAuthService.isCurrentManagedAdmin()) {
|
||||
return allData;
|
||||
}
|
||||
Set<String> authorizedStations = getUserAuthorizedStationCodes();
|
||||
if (authorizedStations != null && !authorizedStations.isEmpty()) {
|
||||
return allData.stream()
|
||||
.filter(item -> authorizedStations.contains(item.getStcd()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 纯数据库查询(可缓存),不包含权限过滤逻辑
|
||||
*/
|
||||
@Cacheable(cacheNames = "engInfoCache#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public List<SdEngInfoBH> selectForDropdownCached(SdEngInfoBHRequest sdEngInfoBHRequest) {
|
||||
String baseId = sdEngInfoBHRequest.getBaseId();
|
||||
String hbrvcd = sdEngInfoBHRequest.getHbrvcd();
|
||||
String ennm = sdEngInfoBHRequest.getEnnm();
|
||||
@ -138,27 +169,14 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
LambdaQueryWrapper<SdEngInfoBH> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(StringUtils.hasText(baseId), SdEngInfoBH::getBaseId, baseId)
|
||||
.eq(StringUtils.hasText(hbrvcd), SdEngInfoBH::getHbrvcd, hbrvcd)
|
||||
.eq(StrUtil.isNotBlank(reachcd), SdEngInfoBH::getRvcd, reachcd)
|
||||
.eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getReachcd, rvcd)
|
||||
.eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getReachcd, rvcd)
|
||||
.eq(StrUtil.isNotBlank(reachcd), SdEngInfoBH::getReachcd, reachcd)
|
||||
.eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getRvcd, rvcd)
|
||||
.in(rvcds != null && !rvcds.isEmpty(), SdEngInfoBH::getReachcd, rvcds)
|
||||
.in(hbrvcds != null && !hbrvcds.isEmpty(), SdEngInfoBH::getHbrvcd, hbrvcds)
|
||||
.like(StringUtils.hasText(ennm), SdEngInfoBH::getEnnm, ennm)
|
||||
.select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm, SdEngInfoBH::getReachcdName, SdEngInfoBH::getYrgeb, SdEngInfoBH::getBaseId)
|
||||
.orderByAsc(SdEngInfoBH::getBaseId,SdEngInfoBH::getOrderIndex);
|
||||
|
||||
if(adminAuthService.isCurrentManagedAdmin()){
|
||||
return this.list(wrapper);
|
||||
}
|
||||
Set<String> authorizedStations = getUserAuthorizedStationCodes();
|
||||
if (authorizedStations != null && !authorizedStations.isEmpty()) {
|
||||
List<SdEngInfoBH> list = this.list(wrapper);
|
||||
return list.stream()
|
||||
.filter(item -> authorizedStations.contains(item.getStcd()))
|
||||
.collect(Collectors.toList());
|
||||
}else{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
.orderByAsc(SdEngInfoBH::getBaseId, SdEngInfoBH::getOrderIndex);
|
||||
return this.list(wrapper);
|
||||
}
|
||||
@Override
|
||||
public Set<String> getUserAuthorizedStationCodes() {
|
||||
@ -995,6 +1013,18 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
|
||||
@Override
|
||||
public EngStInfoResultVo getStcdInfo(String stcd) {
|
||||
if (StrUtil.isBlank(stcd)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, Object> stInfoMap = microservicDynamicSQLMapper.getOneBySql(buildStcdInfoViewSql(), Collections.singletonMap("stcd", stcd));
|
||||
if (stInfoMap != null && !stInfoMap.isEmpty()) {
|
||||
EngStInfoResultVo result = new EngStInfoResultVo();
|
||||
result.setMsStbprpT(buildCamelCaseMsStbprpTMap(stInfoMap));
|
||||
result.setStBaseInfo(buildStBaseInfo(stInfoMap));
|
||||
return result;
|
||||
}
|
||||
|
||||
EngBaseInfoVo baseInfo = getStInfoByStcd(stcd);
|
||||
if (baseInfo == null) {
|
||||
return null;
|
||||
@ -1021,6 +1051,138 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
return result;
|
||||
}
|
||||
|
||||
private String buildStcdInfoViewSql() {
|
||||
return "SELECT " +
|
||||
"t.STCD AS stcd, " +
|
||||
"t.ENNM AS ennm, " +
|
||||
"t.STNM AS stnm, " +
|
||||
"t.STTP AS sttp, " +
|
||||
"t.STTP_CODE AS sttpCode, " +
|
||||
"t.STTP_NAME AS sttpName, " +
|
||||
"t.STTP_FULL_PATH AS sttpFullPath, " +
|
||||
"t.STTP_TREE_LEVEL AS sttpTreeLevel, " +
|
||||
"t.RSTCD AS rstcd, " +
|
||||
"t.BASE_ID AS baseId, " +
|
||||
"t.BASE_NAME AS baseName, " +
|
||||
"t.HBRVCD AS hbrvcd, " +
|
||||
"t.HBRVCD_NAME AS hbrvcdName, " +
|
||||
"t.RVCD AS rvcd, " +
|
||||
"t.RVCD_NAME AS rvcdName, " +
|
||||
"t.ADDVCD AS addvcd, " +
|
||||
"t.ADDVNM AS addvcdName, " +
|
||||
"t.HYCD AS hycd, " +
|
||||
"t.HYNM AS hynm, " +
|
||||
"t.TOP_HYCD AS topHycd, " +
|
||||
"t.TOP_HYNM AS topHynm, " +
|
||||
"t.LGTD AS lgtd, " +
|
||||
"t.LTTD AS lttd, " +
|
||||
"t.STLC AS stlc, " +
|
||||
"t.USFL AS usfl, " +
|
||||
"t.DTIN AS dtin, " +
|
||||
"t.DTIN_TM AS dtinTm, " +
|
||||
"t.BLDSTT_CODE AS bldsttCode, " +
|
||||
"CASE WHEN t.BLDSTT_CODE =2 THEN '已建' WHEN t.BLDSTT_CODE =1 THEN '在建' ELSE '未建/规划' END AS bldsttCcodeName, " +
|
||||
"t.INTRODUCE AS introduce, " +
|
||||
"t.LOGO AS logo, " +
|
||||
"t.INFFILE AS inffile, " +
|
||||
"t.INV AS inv, " +
|
||||
"t.INVINMN AS invinmn, " +
|
||||
"t.STDSDT AS stdsdt, " +
|
||||
"t.PSTSTDT AS pststdt, " +
|
||||
"t.PESSTDT AS pesstdt, " +
|
||||
"t.SWDT AS swdt, " +
|
||||
"t.JCDT AS jcdt, " +
|
||||
"t.WDDT AS wddt, " +
|
||||
"t.ORDER_INDEX AS orderIndex, " +
|
||||
"t.REMARK AS remark, " +
|
||||
"t.VLSR AS vlsr, " +
|
||||
"t.VLSR_TM AS vlsrTm, " +
|
||||
"t.RECORD_USER AS recordUser, " +
|
||||
"t.RECORD_TIME AS recordTime, " +
|
||||
"t.MODIFY_USER AS modifyUser, " +
|
||||
"t.MODIFY_TIME AS modifyTime, " +
|
||||
"t.IS_DELETED AS isDeleted, " +
|
||||
"t.DELETE_USER AS deleteUser, " +
|
||||
"t.DELETE_TIME AS deleteTime, " +
|
||||
"t.DATA_SOURCE AS dataSource " +
|
||||
"FROM V_MS_STBPRP_T t " +
|
||||
"WHERE t.STCD = #{map.stcd}";
|
||||
}
|
||||
|
||||
private EngStBaseInfoVo buildStBaseInfo(Map<String, Object> stInfoMap) {
|
||||
EngStBaseInfoVo stBaseInfo = new EngStBaseInfoVo();
|
||||
stBaseInfo.setStcd(getMapString(stInfoMap, "stcd"));
|
||||
stBaseInfo.setStnm(getMapString(stInfoMap, "stnm"));
|
||||
stBaseInfo.setSttpCode(getMapString(stInfoMap, "sttpCode"));
|
||||
stBaseInfo.setSttpName(getMapString(stInfoMap, "sttpName"));
|
||||
stBaseInfo.setSttpFullPath(getMapString(stInfoMap, "sttpFullPath"));
|
||||
stBaseInfo.setSttpTreeLevel(getMapInteger(stInfoMap, "sttpTreeLevel"));
|
||||
stBaseInfo.setStCode(null);
|
||||
stBaseInfo.setStName(null);
|
||||
stBaseInfo.setBaseId(getMapString(stInfoMap, "baseId"));
|
||||
stBaseInfo.setBaseName(getMapString(stInfoMap, "baseName"));
|
||||
stBaseInfo.setHbrvcd(getMapString(stInfoMap, "hbrvcd"));
|
||||
stBaseInfo.setHbrvcdName(getMapString(stInfoMap, "hbrvcdName"));
|
||||
stBaseInfo.setRvcd(getMapString(stInfoMap, "rvcd"));
|
||||
stBaseInfo.setRvcdName(getMapString(stInfoMap, "rvcdName"));
|
||||
return stBaseInfo;
|
||||
}
|
||||
|
||||
private Map<String, Object> buildCamelCaseMsStbprpTMap(Map<String, Object> stInfoMap) {
|
||||
LinkedHashMap<String, Object> result = new LinkedHashMap<>();
|
||||
List<String> canonicalKeys = Arrays.asList(
|
||||
"stcd", "stnm","ennm", "sttp", "sttpCode", "sttpName", "sttpFullPath", "sttpTreeLevel",
|
||||
"rstcd", "baseId", "baseName", "hbrvcd", "hbrvcdName", "rvcd", "rvcdName", "addvcd","addvcdName","hycd","hynm","topHycd","topHynm",
|
||||
"lgtd", "lttd", "stlc", "usfl", "dtin", "dtinTm", "bldsttCode", "introduce", "logo",
|
||||
"inffile","bldsttCcodeName", "inv", "invinmn", "stdsdt", "pststdt", "pesstdt", "swdt", "jcdt", "wddt",
|
||||
"orderIndex", "remark", "vlsr", "vlsrTm", "recordUser", "recordTime", "modifyUser",
|
||||
"modifyTime", "isDeleted", "deleteUser", "deleteTime", "dataSource"
|
||||
);
|
||||
for (String canonicalKey : canonicalKeys) {
|
||||
result.put(canonicalKey, getMapValue(stInfoMap, canonicalKey));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getMapString(Map<String, Object> source, String key) {
|
||||
Object value = getMapValue(source, key);
|
||||
return value == null ? null : String.valueOf(value);
|
||||
}
|
||||
|
||||
private Integer getMapInteger(Map<String, Object> source, String key) {
|
||||
Object value = getMapValue(source, key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Number number) {
|
||||
return number.intValue();
|
||||
}
|
||||
return Integer.parseInt(String.valueOf(value));
|
||||
}
|
||||
|
||||
private Object getMapValue(Map<String, Object> source, String key) {
|
||||
if (source == null || source.isEmpty() || StrUtil.isBlank(key)) {
|
||||
return null;
|
||||
}
|
||||
if (source.containsKey(key)) {
|
||||
return source.get(key);
|
||||
}
|
||||
String upperKey = key.toUpperCase(Locale.ROOT);
|
||||
if (source.containsKey(upperKey)) {
|
||||
return source.get(upperKey);
|
||||
}
|
||||
String lowerKey = key.toLowerCase(Locale.ROOT);
|
||||
if (source.containsKey(lowerKey)) {
|
||||
return source.get(lowerKey);
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : source.entrySet()) {
|
||||
if (entry.getKey() != null && entry.getKey().equalsIgnoreCase(key)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String buildVmsstbprptViewSql() {
|
||||
return "SELECT " +
|
||||
"eng.STCD AS id, " +
|
||||
@ -2699,9 +2861,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
.append("t.LGTD AS lgtd, ")
|
||||
.append("t.LTTD AS lttd, ")
|
||||
.append("t.AVQ AS avq, ")
|
||||
.append("t.YRGEB AS ttpwr, ")
|
||||
.append("p.TTPWR AS ttpwr, ")
|
||||
.append("t.FSLTDZ AS normz, ")
|
||||
.append("t.YRGEB AS yrge, ")
|
||||
.append("p.YRGE AS yrge, ")
|
||||
.append("t.BASE_ID AS baseId, ")
|
||||
.append("t.JCDT AS jcdt, ")
|
||||
.append("t.ADDVCD_NAME AS addvcdName, ")
|
||||
@ -2730,6 +2892,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
.append(" WHEN t.PRSC IN ('3') THEN 2 ")
|
||||
.append(" END AS endInstalledType ")
|
||||
.append("FROM SD_ENGINFO_B_H t ")
|
||||
.append("LEFT JOIN SD_PWR_B_H p ON t.STCD = p.STCD AND NVL(p.IS_DELETED, 0) = 0 ")
|
||||
.append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = t.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ")
|
||||
.append("LEFT JOIN MS_ALONG_B along ON along.RVCD = t.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 ")
|
||||
.append("LEFT JOIN ( ")
|
||||
@ -2754,8 +2917,13 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
.append("AND NVL(t.USFL, 1) = 1 ")
|
||||
.append("AND t.LGTD IS NOT NULL ")
|
||||
.append("AND t.LTTD IS NOT NULL ");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
DataScopeApplyResult scopeApplyResult = dataScopeFilterService.appendCurrentUserStationScope(sql, paramMap, "t.STCD");
|
||||
if (scopeApplyResult.isEmptyResult()) {
|
||||
result.setData(new ArrayList<>());
|
||||
result.setTotal(0L);
|
||||
return result;
|
||||
}
|
||||
String filterSql = buildEngPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql);
|
||||
@ -2766,12 +2934,376 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
|
||||
Page<?> page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
|
||||
List<EngPointVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EngPointVo.class);
|
||||
|
||||
if(CollUtil.isNotEmpty(list)){
|
||||
for( EngPointVo engPointVo: list ){
|
||||
String stcd = engPointVo.getStcd();
|
||||
//查询最新一条数据的缓存
|
||||
LastTmEngEqDataVo lastTmEngEqDataVo = redisCacheUtil.fromJson(redisCacheUtil.getString("eqAnchorPointLastDate:"+stcd),LastTmEngEqDataVo.class);
|
||||
if (ObjectUtil.isEmpty(lastTmEngEqDataVo)){
|
||||
lastTmEngEqDataVo = new LastTmEngEqDataVo();
|
||||
lastTmEngEqDataVo.setStcd(engPointVo.getStcd());
|
||||
}else{
|
||||
lastTmEngEqDataVo.setStcd(engPointVo.getStcd());
|
||||
}
|
||||
// 设置电站名称、装机容量、正常蓄水位
|
||||
lastTmEngEqDataVo.setStnm(engPointVo.getEnnm());
|
||||
lastTmEngEqDataVo.setTtpwr(engPointVo.getTtpwr());
|
||||
lastTmEngEqDataVo.setNormz(engPointVo.getNormz());
|
||||
engPointVo.setLastTmEngEqDataVo(lastTmEngEqDataVo);
|
||||
}
|
||||
}
|
||||
result.setData(list);
|
||||
result.setTotal(page == null ? list.size() : page.getTotal());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<EngAlarmPointVo> getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
String startTimeText = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime");
|
||||
String endTimeText = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime");
|
||||
|
||||
Date startTime;
|
||||
Date endTime;
|
||||
String yyyy = null;
|
||||
if (StrUtil.isNotBlank(startTimeText) && StrUtil.isNotBlank(endTimeText)) {
|
||||
startTime = parseAlarmPointTime(startTimeText);
|
||||
endTime = parseAlarmPointTime(endTimeText);
|
||||
} else {
|
||||
yyyy = String.valueOf(DateUtil.year(new Date()));
|
||||
Map<String, Date> yearRange = buildAlarmPointYearRange(yyyy);
|
||||
startTime = yearRange.get("startTime");
|
||||
endTime = yearRange.get("endTime");
|
||||
}
|
||||
|
||||
Map<String, Object> pointParamMap = new HashMap<>();
|
||||
StringBuilder pointSql = new StringBuilder(buildAlarmPointBaseSql());
|
||||
// DataScopeApplyResult scopeApplyResult = dataScopeFilterService.appendCurrentUserStationScope(pointSql, pointParamMap, "eng.STCD");
|
||||
List<EngAlarmPointVo> points= microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
pointSql.toString(),
|
||||
pointParamMap,
|
||||
EngAlarmPointVo.class
|
||||
);
|
||||
// if (scopeApplyResult.isEmptyResult()) {
|
||||
// points = new ArrayList<>();
|
||||
// } else {
|
||||
// points = microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
// pointSql.toString(),
|
||||
// pointParamMap,
|
||||
// EngAlarmPointVo.class
|
||||
// );
|
||||
// }
|
||||
|
||||
Map<String, Object> countParamMap = new HashMap<>();
|
||||
countParamMap.put("alarmPointStartTime", startTime);
|
||||
countParamMap.put("alarmPointEndTime", endTime);
|
||||
List<Map<String, Object>> countRows = microservicDynamicSQLMapper.getAllList(buildAlarmPointCountSql(), countParamMap);
|
||||
Map<String, Integer> qecCountMap = buildAlarmPointQecCountMap(countRows);
|
||||
Map<String, Integer> wqCountMap = buildAlarmPointWqCountMap(countRows);
|
||||
|
||||
List<Map<String, Object>> expressionRows = microservicDynamicSQLMapper.getAllList(buildAlarmPointLegendSql(), new HashMap<>());
|
||||
List<EngAlarmPointVo> resultList = mergeAlarmPointData(points, qecCountMap, wqCountMap, expressionRows, yyyy);
|
||||
|
||||
DataSourceResult<EngAlarmPointVo> result = new DataSourceResult<>();
|
||||
result.setData(resultList);
|
||||
result.setTotal(resultList.size());
|
||||
result.setAggregates(new HashMap<>());
|
||||
return result;
|
||||
}
|
||||
|
||||
private String buildAlarmPointBaseSql() {
|
||||
return "SELECT " +
|
||||
"eng.STCD AS stcd, " +
|
||||
"'ENG' AS sttp, " +
|
||||
"eng.ENNM AS ennm, " +
|
||||
"eng.ENNM AS titleName, " +
|
||||
"eng.LOGO AS logo, " +
|
||||
"eng.RVCD AS rvcd, " +
|
||||
"eng.RVCD_NAME AS rvnm, " +
|
||||
"eng.ADDVCD AS addvcd, " +
|
||||
"eng.BASE_ID AS baseId, " +
|
||||
"NVL(eng.BASE_NAME, hb.BASENAME) AS baseName, " +
|
||||
"eng.LGTD AS lgtd, " +
|
||||
"eng.LTTD AS lttd, " +
|
||||
"eng.ELEV AS dtmel, " +
|
||||
"eng.YRGEB AS ttpwr, " +
|
||||
"'ENG' AS sttpMap, " +
|
||||
"CASE WHEN eng.PRSC IN (1, 2) THEN 1 WHEN eng.PRSC = 3 THEN 2 END AS endInstalledType, " +
|
||||
"CASE " +
|
||||
" WHEN eng.PRSC IN (1, 2) AND NVL(eng.BLDSTT_CODE, 0) = 2 THEN 'large_eng_built' " +
|
||||
" WHEN eng.PRSC IN (1, 2) AND NVL(eng.BLDSTT_CODE, 0) = 1 THEN 'large_eng_ubuilt' " +
|
||||
" WHEN eng.PRSC IN (1, 2) THEN 'large_eng_nbuilt' " +
|
||||
" WHEN eng.PRSC = 3 AND NVL(eng.BLDSTT_CODE, 0) = 2 THEN 'mid_eng_built' " +
|
||||
" WHEN eng.PRSC = 3 AND NVL(eng.BLDSTT_CODE, 0) = 1 THEN 'mid_eng_ubuilt' " +
|
||||
" WHEN eng.PRSC = 3 THEN 'mid_eng_nbuilt' " +
|
||||
" ELSE NULL END AS anchoPointState, " +
|
||||
"eng.STCD AS rstcd, " +
|
||||
"eng.STCD AS rstcds, " +
|
||||
"'ENG' AS sttpCode, " +
|
||||
"NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " +
|
||||
"NVL(rstSort.SORT, 999999) AS rstcdStepSort, " +
|
||||
"NVL(siteSort.SORT, 999999) AS siteStepSort " +
|
||||
"FROM SD_ENGINFO_B_H eng " +
|
||||
"LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN ( " +
|
||||
" SELECT det.SORT, cfg.RVCD, det.STCD " +
|
||||
" FROM MS_ALONGDET_B det " +
|
||||
" INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " +
|
||||
" WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " +
|
||||
") rstSort ON rstSort.RVCD = eng.HBRVCD AND rstSort.STCD = eng.STCD " +
|
||||
"LEFT JOIN ( " +
|
||||
" SELECT det.SORT, cfg.RVCD, det.STCD " +
|
||||
" FROM MS_ALONGDET_B det " +
|
||||
" INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " +
|
||||
" WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " +
|
||||
") siteSort ON siteSort.RVCD = eng.HBRVCD AND siteSort.STCD = eng.STCD " +
|
||||
"WHERE NVL(eng.IS_DELETED, 0) = 0 " +
|
||||
"AND NVL(eng.USFL, 0) = 1 " +
|
||||
"AND eng.LGTD IS NOT NULL " +
|
||||
"AND eng.LTTD IS NOT NULL ";
|
||||
}
|
||||
|
||||
private String buildAlarmPointCountSql() {
|
||||
return "SELECT wr.STCD AS stcd, wr.STCD AS rstcd, COUNT(wr.STCD) AS count, 'QEC' AS ys " +
|
||||
"FROM MS_WARN_RECORD_W wr " +
|
||||
"WHERE NVL(wr.IS_DELETED, 0) = 0 " +
|
||||
"AND wr.TB_ID IN (SELECT tb.ID FROM ST_TB_B tb WHERE tb.TB_CODE = 'QEC_R' AND NVL(tb.IS_DELETED, 0) = 0) " +
|
||||
"AND wr.YS = 'QEC' " +
|
||||
"AND wr.SFGB = 'N' " +
|
||||
"AND wr.BTM BETWEEN #{map.alarmPointStartTime} AND #{map.alarmPointEndTime} " +
|
||||
"GROUP BY wr.STCD " +
|
||||
"UNION ALL " +
|
||||
"SELECT wr.STCD AS stcd, wq.RSTCD AS rstcd, COUNT(wr.STCD) AS count, 'WQ' AS ys " +
|
||||
"FROM MS_WARN_RECORD_W wr " +
|
||||
"LEFT JOIN SD_WQ_B_H wq ON wr.STCD = wq.STCD AND NVL(wq.IS_DELETED, 0) = 0 " +
|
||||
"WHERE NVL(wr.IS_DELETED, 0) = 0 " +
|
||||
"AND wr.TB_ID IN (SELECT tb.ID FROM ST_TB_B tb WHERE tb.TB_CODE = 'WQ_R' AND NVL(tb.IS_DELETED, 0) = 0) " +
|
||||
"AND wr.SFGB = 'N' " +
|
||||
"AND wr.BTM BETWEEN #{map.alarmPointStartTime} AND #{map.alarmPointEndTime} " +
|
||||
"AND wq.RSTCD IS NOT NULL " +
|
||||
"GROUP BY wr.STCD, wq.RSTCD";
|
||||
}
|
||||
|
||||
private String buildAlarmPointLegendSql() {
|
||||
return "SELECT EXPRESSION AS expression, NAME_EN AS nameEn " +
|
||||
"FROM MS_MAPLEGEND_B " +
|
||||
"WHERE LAYER_CODE = 'eng_alarm_point' " +
|
||||
"AND IF_SHOW = 1 " +
|
||||
"AND NVL(IS_DELETED, 0) = 0 " +
|
||||
"AND EXPRESSION IS NOT NULL " +
|
||||
"ORDER BY NVL(ORDER_INDEX, 999999), ID";
|
||||
}
|
||||
|
||||
private Map<String, Date> buildAlarmPointYearRange(String yearText) {
|
||||
Date endTime = new Date();
|
||||
String currentYear = String.valueOf(DateUtil.year(endTime));
|
||||
Date startTime = DateUtil.parse(currentYear + "-01-01");
|
||||
if (StrUtil.isNotBlank(yearText) && !currentYear.equals(yearText)) {
|
||||
startTime = DateUtil.parse(yearText + "-01-01");
|
||||
endTime = DateUtil.parse(yearText + "-12-31");
|
||||
}
|
||||
Map<String, Date> result = new HashMap<>();
|
||||
result.put("startTime", startTime);
|
||||
result.put("endTime", endTime);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Integer> buildAlarmPointQecCountMap(List<Map<String, Object>> countRows) {
|
||||
Map<String, Integer> result = new HashMap<>();
|
||||
if (CollUtil.isEmpty(countRows)) {
|
||||
return result;
|
||||
}
|
||||
for (Map<String, Object> row : countRows) {
|
||||
if (!"QEC".equalsIgnoreCase(safeAlarmValue(firstPresentAlarmValue(row, "YS", "ys")))) {
|
||||
continue;
|
||||
}
|
||||
String stcd = safeAlarmValue(firstPresentAlarmValue(row, "RSTCD", "rstcd", "STCD", "stcd"));
|
||||
if (StrUtil.isBlank(stcd)) {
|
||||
continue;
|
||||
}
|
||||
result.put(stcd, toAlarmIntegerValue(firstPresentAlarmValue(row, "COUNT", "count")));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Integer> buildAlarmPointWqCountMap(List<Map<String, Object>> countRows) {
|
||||
Map<String, Integer> result = new HashMap<>();
|
||||
if (CollUtil.isEmpty(countRows)) {
|
||||
return result;
|
||||
}
|
||||
for (Map<String, Object> row : countRows) {
|
||||
if (!"WQ".equalsIgnoreCase(safeAlarmValue(firstPresentAlarmValue(row, "YS", "ys")))) {
|
||||
continue;
|
||||
}
|
||||
Integer count = toAlarmIntegerValue(firstPresentAlarmValue(row, "COUNT", "count"));
|
||||
if (count == null) {
|
||||
count = 0;
|
||||
}
|
||||
String rstcdText = safeAlarmValue(firstPresentAlarmValue(row, "RSTCD", "rstcd"));
|
||||
if (StrUtil.isBlank(rstcdText)) {
|
||||
continue;
|
||||
}
|
||||
for (String rstcd : rstcdText.split(",")) {
|
||||
String trimmed = StrUtil.trim(rstcd);
|
||||
if (StrUtil.isBlank(trimmed)) {
|
||||
continue;
|
||||
}
|
||||
result.put(trimmed, result.getOrDefault(trimmed, 0) + count);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<EngAlarmPointVo> mergeAlarmPointData(List<EngAlarmPointVo> points,
|
||||
Map<String, Integer> qecCountMap,
|
||||
Map<String, Integer> wqCountMap,
|
||||
List<Map<String, Object>> expressionRows,
|
||||
String yyyy) {
|
||||
List<EngAlarmPointVo> result = new ArrayList<>();
|
||||
if (CollUtil.isEmpty(points)) {
|
||||
return result;
|
||||
}
|
||||
for (EngAlarmPointVo point : points) {
|
||||
if (point == null || !isAlarmPointVisible(point.getAnchoPointState())) {
|
||||
continue;
|
||||
}
|
||||
point.setAnchoPointState(normalizeAlarmPointState(point.getAnchoPointState()) + "_ALARM");
|
||||
point.setStqCount(qecCountMap.getOrDefault(point.getStcd(), 0));
|
||||
point.setWqCount(wqCountMap.getOrDefault(point.getStcd(), 0));
|
||||
point.setZCount(0);
|
||||
point.setWtCount(0);
|
||||
point.setYyyy(yyyy);
|
||||
point.setSttpCode("ENG");
|
||||
int total = point.getStqCount() + point.getWqCount();
|
||||
applyAlarmPointRange(point, total, expressionRows);
|
||||
result.add(point);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isAlarmPointVisible(String state) {
|
||||
return "large_eng_built".equals(state)
|
||||
|| "mid_eng_built".equals(state)
|
||||
|| "large_eng_ubuilt".equals(state)
|
||||
|| "mid_eng_ubuilt".equals(state);
|
||||
}
|
||||
|
||||
private String normalizeAlarmPointState(String state) {
|
||||
if ("large_eng_ubuilt".equals(state)) {
|
||||
return "large_eng_built";
|
||||
}
|
||||
if ("mid_eng_ubuilt".equals(state)) {
|
||||
return "mid_eng_built";
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private void applyAlarmPointRange(EngAlarmPointVo point, int total, List<Map<String, Object>> expressionRows) {
|
||||
if (point == null || CollUtil.isEmpty(expressionRows)) {
|
||||
return;
|
||||
}
|
||||
for (Map<String, Object> row : expressionRows) {
|
||||
String expression = safeAlarmValue(firstPresentAlarmValue(row, "EXPRESSION", "expression"));
|
||||
if (!matchesAlarmExpression(expression, total)) {
|
||||
continue;
|
||||
}
|
||||
String nameEn = safeAlarmValue(firstPresentAlarmValue(row, "NAMEEN", "nameEn", "NAME_EN"));
|
||||
if (StrUtil.isNotBlank(nameEn)) {
|
||||
point.setAnchoPointState(point.getAnchoPointState() + "_" + nameEn);
|
||||
point.setRange(nameEn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesAlarmExpression(String range, int value) {
|
||||
if (StrUtil.isBlank(range)) {
|
||||
return false;
|
||||
}
|
||||
if (range.matches("x=\\d+")) {
|
||||
return value == Integer.parseInt(range.substring(2));
|
||||
}
|
||||
if (range.matches("x>\\d+")) {
|
||||
return value > Integer.parseInt(range.substring(2));
|
||||
}
|
||||
if (range.matches("x>=\\d+")) {
|
||||
return value >= Integer.parseInt(range.substring(3));
|
||||
}
|
||||
if (range.matches("x<\\d+")) {
|
||||
return value < Integer.parseInt(range.substring(2));
|
||||
}
|
||||
if (range.matches("x<=\\d+")) {
|
||||
return value <= Integer.parseInt(range.substring(3));
|
||||
}
|
||||
if (range.matches("\\d+<x<\\d+")) {
|
||||
String[] split = range.split("<x<");
|
||||
return value > Integer.parseInt(split[0]) && value < Integer.parseInt(split[1]);
|
||||
}
|
||||
if (range.matches("\\d+<=x<=\\d+")) {
|
||||
String[] split = range.split("<=x<=");
|
||||
return value >= Integer.parseInt(split[0]) && value <= Integer.parseInt(split[1]);
|
||||
}
|
||||
if (range.matches("\\d+<x<=\\d+")) {
|
||||
String[] split = range.split("<x<=");
|
||||
return value > Integer.parseInt(split[0]) && value <= Integer.parseInt(split[1]);
|
||||
}
|
||||
if (range.matches("\\d+<=x<\\d+")) {
|
||||
String[] split = range.split("<=x<");
|
||||
return value >= Integer.parseInt(split[0]) && value < Integer.parseInt(split[1]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Date parseAlarmPointTime(String timeText) {
|
||||
if (StrUtil.isBlank(timeText)) {
|
||||
return null;
|
||||
}
|
||||
String value = timeText.trim();
|
||||
if (value.length() <= 10) {
|
||||
return DateUtil.parse(value, "yyyy-MM-dd");
|
||||
}
|
||||
return DateUtil.parse(value, "yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
private Object firstPresentAlarmValue(Map<String, Object> row, String... keys) {
|
||||
if (row == null || keys == null) {
|
||||
return null;
|
||||
}
|
||||
for (String key : keys) {
|
||||
if (row.containsKey(key)) {
|
||||
return row.get(key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Integer toAlarmIntegerValue(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Number number) {
|
||||
return number.intValue();
|
||||
}
|
||||
String text = String.valueOf(value).trim();
|
||||
if (StrUtil.isBlank(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(text);
|
||||
} catch (NumberFormatException ex) {
|
||||
try {
|
||||
return Double.valueOf(text).intValue();
|
||||
} catch (NumberFormatException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String safeAlarmValue(Object value) {
|
||||
return value == null ? "" : String.valueOf(value).trim();
|
||||
}
|
||||
|
||||
private String buildEngPointFilterCondition(DataSourceRequest.FilterDescriptor filter,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
@ -2983,6 +3515,60 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<EngRsvrcscdRvcdVo> getRsvrcscdBRvcdList(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceResult<EngRsvrcscdRvcdVo> result = new DataSourceResult<>();
|
||||
result.setAggregates(new HashMap<>());
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT DISTINCT ")
|
||||
.append("dic.HBRVCD AS wbsCode, ")
|
||||
.append("dic.HBRVNM AS wbsName, ")
|
||||
.append("dic.BASEID AS objId, ")
|
||||
.append("NVL(dic.BASEID, 'ZZZZZZZZ') AS baseOrder, ")
|
||||
.append("NVL(dic.ORDER_INDEX, 999999) AS orderIndex ")
|
||||
.append("FROM SD_HBRV_DIC dic ")
|
||||
.append("INNER JOIN SD_RSVRCSCD_B r ON r.RVCD = dic.HBRVCD AND NVL(r.IS_DELETED, 0) = 0 ")
|
||||
.append("WHERE NVL(dic.IS_DELETED, 0) = 0 ")
|
||||
.append("AND NVL(dic.ENABLED, 1) = 1 ");
|
||||
|
||||
// 动态过滤条件(原有代码)
|
||||
appendRsvrcscdRvcdPresetFilters(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), sql, paramMap, new int[]{0});
|
||||
|
||||
// 使用别名排序
|
||||
sql.append(" ORDER BY baseOrder ASC, orderIndex ASC, wbsCode ASC");
|
||||
|
||||
List<EngRsvrcscdRvcdVo> list = microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
sql.toString(), paramMap, EngRsvrcscdRvcdVo.class);
|
||||
result.setData(list);
|
||||
result.setTotal(list.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<EngQgcRvcdVo> getQgcRvcdList(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceResult<EngQgcRvcdVo> result = new DataSourceResult<>();
|
||||
result.setAggregates(new HashMap<>());
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT DISTINCT ")
|
||||
.append("rv.RVCD AS rvcd, ")
|
||||
.append("rv.RVNM AS rvnm, ")
|
||||
.append("NVL(rv.ORDER_INDEX, 999999) AS order_index ")
|
||||
.append("FROM SD_RVCD_DIC rv ")
|
||||
.append("INNER JOIN MS_LYSXJGX_B rel ON rel.QGC_RVCD = rv.RVCD AND NVL(rel.IS_DELETED, 0) = 0 ")
|
||||
.append("WHERE NVL(rv.IS_DELETED, 0) = 0 ")
|
||||
.append("AND NVL(rv.ENABLED, 1) = 1 ")
|
||||
.append("ORDER BY order_index ASC, rv.RVCD ASC");
|
||||
|
||||
List<EngQgcRvcdVo> list = microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
sql.toString(), new HashMap<>(), EngQgcRvcdVo.class);
|
||||
result.setData(list);
|
||||
result.setTotal(list.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
private String buildRsvrcscdBFilterCondition(DataSourceRequest.FilterDescriptor filter,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
@ -3123,4 +3709,125 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl<SdEngInfoBHMapper, SdEng
|
||||
}
|
||||
return " ORDER BY " + String.join(", ", orderItems);
|
||||
}
|
||||
|
||||
private void appendRsvrcscdRvcdPresetFilters(DataSourceRequest.FilterDescriptor filter,
|
||||
StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
if (filter == null) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.hasText(filter.getField())) {
|
||||
String field = filter.getField();
|
||||
String operator = filter.getOperator() == null ? "eq" : filter.getOperator().toLowerCase();
|
||||
Object value = filter.getValue();
|
||||
if (!StringUtils.hasText(operator)) {
|
||||
operator = "eq";
|
||||
}
|
||||
if ("baseId".equals(field)) {
|
||||
appendRsvrcscdRvcdLeafCondition(sql, "dic.BASEID", operator, value, paramMap, indexHolder);
|
||||
return;
|
||||
}
|
||||
if ("treeLevel".equals(field)) {
|
||||
appendRsvrcscdRvcdLeafCondition(sql, "dic.GRD", operator, value, paramMap, indexHolder);
|
||||
return;
|
||||
}
|
||||
if ("wbsType".equals(field)) {
|
||||
// 旧口径走 SD_WBS_B.WBS_TYPE,这里已固定替换成 SD_HBRV_DIC,保留参数但不参与过滤。
|
||||
return;
|
||||
}
|
||||
if ("wbsCode".equals(field)) {
|
||||
appendRsvrcscdRvcdLeafCondition(sql, "dic.HBRVCD", operator, value, paramMap, indexHolder);
|
||||
return;
|
||||
}
|
||||
if ("wbsName".equals(field)) {
|
||||
appendRsvrcscdRvcdLeafCondition(sql, "dic.HBRVNM", operator, value, paramMap, indexHolder);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (filter.getFilters() == null || filter.getFilters().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
|
||||
appendRsvrcscdRvcdPresetFilters(child, sql, paramMap, indexHolder);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendRsvrcscdRvcdLeafCondition(StringBuilder sql,
|
||||
String column,
|
||||
String operator,
|
||||
Object value,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
if (!StringUtils.hasText(column)) {
|
||||
return;
|
||||
}
|
||||
if ("isnull".equals(operator)) {
|
||||
sql.append(" AND ").append(column).append(" IS NULL ");
|
||||
return;
|
||||
}
|
||||
if ("isnotnull".equals(operator)) {
|
||||
sql.append(" AND ").append(column).append(" IS NOT NULL ");
|
||||
return;
|
||||
}
|
||||
if ("in".equals(operator)) {
|
||||
List<Object> values = normalizeFilterValues(value);
|
||||
if (values.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
for (Object item : values) {
|
||||
String key = "rsvrcdRvcdParam" + indexHolder[0]++;
|
||||
paramMap.put(key, item);
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
sql.append(" AND ").append(column).append(" IN (").append(String.join(", ", placeholders)).append(") ");
|
||||
return;
|
||||
}
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
String key = "rsvrcdRvcdParam" + indexHolder[0]++;
|
||||
switch (operator) {
|
||||
case "eq" -> {
|
||||
paramMap.put(key, value);
|
||||
sql.append(" AND ").append(column).append(" = #{map.").append(key).append("} ");
|
||||
}
|
||||
case "neq" -> {
|
||||
paramMap.put(key, value);
|
||||
sql.append(" AND ").append(column).append(" <> #{map.").append(key).append("} ");
|
||||
}
|
||||
case "contains" -> {
|
||||
paramMap.put(key, "%" + value + "%");
|
||||
sql.append(" AND ").append(column).append(" LIKE #{map.").append(key).append("} ");
|
||||
}
|
||||
case "startswith" -> {
|
||||
paramMap.put(key, value + "%");
|
||||
sql.append(" AND ").append(column).append(" LIKE #{map.").append(key).append("} ");
|
||||
}
|
||||
case "endswith" -> {
|
||||
paramMap.put(key, "%" + value);
|
||||
sql.append(" AND ").append(column).append(" LIKE #{map.").append(key).append("} ");
|
||||
}
|
||||
case "gt" -> {
|
||||
paramMap.put(key, value);
|
||||
sql.append(" AND ").append(column).append(" > #{map.").append(key).append("} ");
|
||||
}
|
||||
case "gte" -> {
|
||||
paramMap.put(key, value);
|
||||
sql.append(" AND ").append(column).append(" >= #{map.").append(key).append("} ");
|
||||
}
|
||||
case "lt" -> {
|
||||
paramMap.put(key, value);
|
||||
sql.append(" AND ").append(column).append(" < #{map.").append(key).append("} ");
|
||||
}
|
||||
case "lte" -> {
|
||||
paramMap.put(key, value);
|
||||
sql.append(" AND ").append(column).append(" <= #{map.").append(key).append("} ");
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo;
|
||||
import com.yfd.platform.qgc_eng.eq.entity.vo.StBaseInfo;
|
||||
import com.yfd.platform.qgc_eng.eq.entity.vo.StcdInfoVo;
|
||||
import com.yfd.platform.qgc_eng.eq.service.EngEqDataService;
|
||||
import com.yfd.platform.qgc_env.wq.entity.vo.MsWarnRuleDetailBVo;
|
||||
import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
@ -5939,7 +5940,7 @@ public class EngEqDataServiceImpl implements EngEqDataService {
|
||||
.append(" WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' ")
|
||||
.append(") siteSort ON siteSort.RVCD = eng.HBRVCD AND siteSort.STCD = a.STCD ")
|
||||
.append("WHERE NVL(a.IS_DELETED, 0) = 0 ")
|
||||
.append("AND NVL(a.USFL, 1) = 1 ")
|
||||
// .append("AND NVL(a.USFL, 1) = 1 ")
|
||||
.append("AND a.LGTD IS NOT NULL ")
|
||||
.append("AND a.LTTD IS NOT NULL ")
|
||||
.append("AND a.STTP IN (SELECT STTP_CODE FROM SD_STTP_B WHERE DESCRIPTION = 'EQ') ")
|
||||
@ -6000,6 +6001,20 @@ public class EngEqDataServiceImpl implements EngEqDataService {
|
||||
resultList.add(eqdsVo);
|
||||
}
|
||||
|
||||
Map<String, Date> qecLimitQueryMap = new LinkedHashMap<>();
|
||||
Date currentDate = new Date();
|
||||
for (EngEqdsVo eqdsVo : resultList) {
|
||||
if (eqdsVo == null || StrUtil.isBlank(eqdsVo.getRstcd()) || qecLimitQueryMap.containsKey(eqdsVo.getRstcd())) {
|
||||
continue;
|
||||
}
|
||||
qecLimitQueryMap.put(eqdsVo.getRstcd(), currentDate);
|
||||
}
|
||||
Map<String, MsWarnRuleDetailBVo> qecLimitMap = getQecLimitMap(qecLimitQueryMap);
|
||||
for (EngEqdsVo eqdsVo : resultList) {
|
||||
MsWarnRuleDetailBVo ruleDetail = qecLimitMap.get(eqdsVo.getRstcd());
|
||||
eqdsVo.setQecLimit(ruleDetail == null ? null : ruleDetail.getMinVal());
|
||||
}
|
||||
|
||||
SiteAvoidanceUtils.calcSiteMapLev(resultList,
|
||||
EngEqdsVo::getStcd,
|
||||
EngEqdsVo::getLgtd,
|
||||
@ -6011,4 +6026,152 @@ public class EngEqDataServiceImpl implements EngEqDataService {
|
||||
dataSourceResult.setTotal(page == null ? resultList.size() : page.getTotal());
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
private Map<String, MsWarnRuleDetailBVo> getQecLimitMap(Map<String, Date> stcdTmMap) {
|
||||
Map<String, MsWarnRuleDetailBVo> resultMap = new HashMap<>();
|
||||
if (stcdTmMap == null || stcdTmMap.isEmpty()) {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
.append("rel.STCD AS stcd, ")
|
||||
.append("det.ID AS id, ")
|
||||
.append("det.RULE_ID AS ruleId, ")
|
||||
.append("det.TB_ID AS tbId, ")
|
||||
.append("det.YS AS ys, ")
|
||||
.append("det.TM AS tm, ")
|
||||
.append("det.BEGIN_TIME AS beginTime, ")
|
||||
.append("det.END_TIME AS endTime, ")
|
||||
.append("det.MIN_VAL AS minVal, ")
|
||||
.append("det.MAX_VAL AS maxVal, ")
|
||||
.append("det.VLSR AS vlsr, ")
|
||||
.append("det.VLSR_TM AS vlsrTm ")
|
||||
.append("FROM MS_WARN_RULE_STBPRP_B rel ")
|
||||
.append("INNER JOIN MS_WARN_RULE_B rule ON rule.ID = rel.RULE_ID ")
|
||||
.append(" AND rule.RULE_TYPE = 'EQMN' ")
|
||||
.append(" AND NVL(rule.IS_DELETED, 0) = 0 ")
|
||||
.append("INNER JOIN MS_WARN_RULE_DETAIL_B det ON det.RULE_ID = rule.ID ")
|
||||
.append(" AND det.YS = 'QEC' ")
|
||||
.append(" AND NVL(det.IS_DELETED, 0) = 0 ")
|
||||
.append("INNER JOIN ST_TB_B tb ON tb.ID = det.TB_ID ")
|
||||
.append(" AND tb.TB_CODE = 'QEC_R' ")
|
||||
.append(" AND NVL(tb.IS_DELETED, 0) = 0 ")
|
||||
.append("WHERE NVL(rel.IS_DELETED, 0) = 0 ");
|
||||
appendInCondition(sql, paramMap, "rel.STCD", stcdTmMap.keySet(), "qecLimitStcd");
|
||||
sql.append("ORDER BY rel.STCD, det.TM DESC, LPAD(det.BEGIN_TIME, 4, '0') DESC NULLS LAST, ")
|
||||
.append("LPAD(det.END_TIME, 4, '0') DESC NULLS LAST");
|
||||
|
||||
List<Map<String, Object>> ruleRows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap);
|
||||
if (CollUtil.isEmpty(ruleRows)) {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
Map<String, List<MsWarnRuleDetailBVo>> groupedRuleMap = new HashMap<>();
|
||||
for (Map<String, Object> row : ruleRows) {
|
||||
String stcd = asString(row.get("STCD"));
|
||||
if (StrUtil.isBlank(stcd)) {
|
||||
continue;
|
||||
}
|
||||
groupedRuleMap.computeIfAbsent(stcd, key -> new ArrayList<>()).add(toMsWarnRuleDetailBVo(row));
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Date> entry : stcdTmMap.entrySet()) {
|
||||
MsWarnRuleDetailBVo detail = resolveQecLimitDetail(entry.getValue(), groupedRuleMap.get(entry.getKey()));
|
||||
if (detail != null) {
|
||||
resultMap.put(entry.getKey(), detail);
|
||||
}
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
private MsWarnRuleDetailBVo resolveQecLimitDetail(Date queryDate, List<MsWarnRuleDetailBVo> ruleRows) {
|
||||
if (queryDate == null || CollUtil.isEmpty(ruleRows)) {
|
||||
return null;
|
||||
}
|
||||
Date currentTm = null;
|
||||
List<MsWarnRuleDetailBVo> currentRows = new ArrayList<>();
|
||||
String monthDay = DateTimeFormatter.ofPattern("MMdd").format(
|
||||
queryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
);
|
||||
for (MsWarnRuleDetailBVo row : ruleRows) {
|
||||
Date tm = row.getTm();
|
||||
if (tm == null || queryDate.compareTo(tm) < 0) {
|
||||
continue;
|
||||
}
|
||||
if (currentTm != null && !currentTm.equals(tm)) {
|
||||
return matchQecLimitDetail(monthDay, currentRows);
|
||||
}
|
||||
currentTm = tm;
|
||||
currentRows.add(row);
|
||||
}
|
||||
if (currentTm == null) {
|
||||
return null;
|
||||
}
|
||||
return matchQecLimitDetail(monthDay, currentRows);
|
||||
}
|
||||
|
||||
private MsWarnRuleDetailBVo matchQecLimitDetail(String monthDay, List<MsWarnRuleDetailBVo> ruleRows) {
|
||||
MsWarnRuleDetailBVo defaultValue = null;
|
||||
for (MsWarnRuleDetailBVo row : ruleRows) {
|
||||
if (row == null || row.getMinVal() == null) {
|
||||
continue;
|
||||
}
|
||||
String beginTime = normalizeMonthDay(row.getBeginTime());
|
||||
String endTime = normalizeMonthDay(row.getEndTime());
|
||||
if (StrUtil.isNotBlank(beginTime) && StrUtil.isNotBlank(endTime)) {
|
||||
if (isMonthDayInRange(monthDay, beginTime, endTime)) {
|
||||
return row;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (StrUtil.isBlank(beginTime) && StrUtil.isBlank(endTime)) {
|
||||
defaultValue = row;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private MsWarnRuleDetailBVo toMsWarnRuleDetailBVo(Map<String, Object> row) {
|
||||
MsWarnRuleDetailBVo vo = new MsWarnRuleDetailBVo();
|
||||
vo.setId(asString(row.get("ID")));
|
||||
vo.setRuleId(asString(row.get("RULEID")));
|
||||
vo.setTbId(asString(row.get("TBID")));
|
||||
vo.setYs(asString(row.get("YS")));
|
||||
vo.setTm(toDate(row.get("TM")));
|
||||
vo.setBeginTime(asString(row.get("BEGINTIME")));
|
||||
vo.setEndTime(asString(row.get("ENDTIME")));
|
||||
vo.setMinVal(toBigDecimal(row.get("MINVAL")));
|
||||
vo.setMaxVal(toBigDecimal(row.get("MAXVAL")));
|
||||
vo.setVlsr(asString(row.get("VLSR")));
|
||||
vo.setVlsrTm(toDate(row.get("VLSRTM")));
|
||||
return vo;
|
||||
}
|
||||
|
||||
private void appendInCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
String column,
|
||||
Iterable<String> values,
|
||||
String prefix) {
|
||||
if (values == null) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
int index = 0;
|
||||
for (String value : values) {
|
||||
if (StrUtil.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
String key = prefix + index++;
|
||||
paramMap.put(key, value.trim());
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
if (CollUtil.isEmpty(placeholders)) {
|
||||
return;
|
||||
}
|
||||
sql.append(" AND ").append(column).append(" IN (")
|
||||
.append(String.join(", ", placeholders))
|
||||
.append(") ");
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,4 +152,10 @@ public class FbStationController {
|
||||
public ResponseResult getFbPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(fbStationService.getFbPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/point/built/GetKendoListCust")
|
||||
@Operation(summary = "增殖站地图描点接口(仅查询在建状态的)")
|
||||
public ResponseResult getFbBuiltPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(fbStationService.getFbBuiltPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,4 +65,6 @@ public interface FbStationService {
|
||||
DataSourceResult<TableVo> getFishbreedrFishKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<FbTracingPointVo> getFbPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<FbTracingPointVo> getFbBuiltPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
}
|
||||
|
||||
@ -4577,6 +4577,15 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
|
||||
@Override
|
||||
public DataSourceResult<FbTracingPointVo> getFbPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
return queryFbPointKendoListCust(dataSourceRequest, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<FbTracingPointVo> getFbBuiltPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
return queryFbPointKendoListCust(dataSourceRequest, true);
|
||||
}
|
||||
|
||||
private DataSourceResult<FbTracingPointVo> queryFbPointKendoListCust(DataSourceRequest dataSourceRequest, boolean builtMode) {
|
||||
DataSourceResult<FbTracingPointVo> dataSourceResult = new DataSourceResult<>();
|
||||
dataSourceResult.setAggregates(new HashMap<>());
|
||||
|
||||
@ -4589,6 +4598,9 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
DataSourceLoadOptionsBase devRequest = dataSourceRequest.toDevRequest();
|
||||
String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(devRequest, "rstcd");
|
||||
String sttp = QgcQueryWrapperUtil.getFilterFieldValue(devRequest, "sttp");
|
||||
if(StrUtil.isBlank(sttp)){
|
||||
sttp= QgcQueryWrapperUtil.getFilterFieldValue(devRequest, "sttpCode");
|
||||
}
|
||||
String bldsttCcode = QgcQueryWrapperUtil.getFilterFieldValue(devRequest, "bldsttCcode");
|
||||
|
||||
if (StrUtil.isEmpty(sttp)) {
|
||||
@ -4614,7 +4626,7 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
.append("a.RSTCD AS rstcds, ")
|
||||
.append("a.BASE_ID AS baseId, ")
|
||||
.append("a.DTIN AS dtin, ")
|
||||
.append("eng.ENNM AS ennm, ")
|
||||
.append("COALESCE(eng.ENNM, '') AS ennm, ")
|
||||
.append("eng.RVCD AS rvcd, ")
|
||||
.append("eng.ADDVCD AS addvcd, ")
|
||||
.append("NVL(siteSort.SORT, 999999) AS siteStepSort, ")
|
||||
@ -4648,7 +4660,7 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
.append(" AND t.TM BETWEEN ADD_MONTHS(SYSDATE, -12) AND SYSDATE ")
|
||||
.append(" GROUP BY t.RSTCD ")
|
||||
.append(") b ON a.STCD = b.stcd ")
|
||||
.append("WHERE NVL(a.USFL, 1) = 1 ")
|
||||
.append("WHERE 1 = 1 ")
|
||||
.append("AND a.LGTD IS NOT NULL ")
|
||||
.append("AND a.LTTD IS NOT NULL ");
|
||||
|
||||
@ -4670,7 +4682,7 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
|
||||
|
||||
String filterSql = QgcQueryWrapperUtil.buildFilterCondition(
|
||||
dataSourceRequest == null ? null : dataSourceRequest.getFilter(),
|
||||
dataSourceRequest.getFilter(),
|
||||
paramMap,
|
||||
new int[]{0},
|
||||
this::mapWeFvColumn
|
||||
@ -4683,7 +4695,12 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
Page<?> page = devRequest == null ? null : QgcQueryWrapperUtil.buildPage(devRequest, devRequest.getSkip(), devRequest.getTake());
|
||||
List<FbTracingPointVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, FbTracingPointVo.class);
|
||||
|
||||
list = getPointLegend(list);
|
||||
if (builtMode) {
|
||||
enrichFbBuiltPointYearStatistics(list, sttp);
|
||||
list = getBuiltPointLegend(list);
|
||||
} else {
|
||||
list = getPointLegend(list);
|
||||
}
|
||||
|
||||
SiteAvoidanceUtils.calcSiteMapLev(list,
|
||||
FbTracingPointVo::getStcd,
|
||||
@ -4697,6 +4714,53 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
private void enrichFbBuiltPointYearStatistics(List<FbTracingPointVo> list, String sttp) {
|
||||
if (CollUtil.isEmpty(list) || !"FB".equalsIgnoreCase(sttp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String currentYear = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
|
||||
Map<String, Object> planParamMap = new HashMap<>();
|
||||
planParamMap.put("yr", currentYear);
|
||||
String planSql = "SELECT plan.RSTCD AS stcd, SUM(det.FCNT) AS fcnt "
|
||||
+ "FROM SD_ENGFRPLAN_B plan "
|
||||
+ "INNER JOIN SD_ENGFRPLANDET_B det ON plan.ID = det.RPJH_ID "
|
||||
+ "WHERE NVL(plan.IS_DELETED, 0) = 0 "
|
||||
+ "AND NVL(det.IS_DELETED, 0) = 0 "
|
||||
+ "AND TO_CHAR(plan.PLANSD, 'YYYY') = #{map.yr} "
|
||||
+ "GROUP BY plan.RSTCD";
|
||||
List<FbPointCountVo> planList = microservicDynamicSQLMapper.getAllListWithResultType(planSql, planParamMap, FbPointCountVo.class);
|
||||
|
||||
Map<String, Object> actualParamMap = new HashMap<>();
|
||||
actualParamMap.put("yr", currentYear);
|
||||
String actualSql = "SELECT run.RSTCD AS stcd, SUM(det.FCNT) AS fcnt "
|
||||
+ "FROM SD_ENGFR_R run "
|
||||
+ "INNER JOIN SD_RPIMNFISH_R det ON run.ID = det.RPIMN_ID "
|
||||
+ "WHERE NVL(run.IS_DELETED, 0) = 0 "
|
||||
+ "AND NVL(det.IS_DELETED, 0) = 0 "
|
||||
+ "AND TO_CHAR(run.TM, 'YYYY') = #{map.yr} "
|
||||
+ "GROUP BY run.RSTCD";
|
||||
List<FbPointCountVo> actualList = microservicDynamicSQLMapper.getAllListWithResultType(actualSql, actualParamMap, FbPointCountVo.class);
|
||||
|
||||
Map<String, Long> planMap = planList.stream()
|
||||
.filter(item -> StrUtil.isNotBlank(item.getStcd()))
|
||||
.collect(Collectors.toMap(FbPointCountVo::getStcd, FbPointCountVo::getFcnt, (left, right) -> left));
|
||||
Map<String, Long> actualMap = actualList.stream()
|
||||
.filter(item -> StrUtil.isNotBlank(item.getStcd()))
|
||||
.collect(Collectors.toMap(FbPointCountVo::getStcd, FbPointCountVo::getFcnt, (left, right) -> left));
|
||||
|
||||
list.forEach(item -> {
|
||||
Long planCount = planMap.get(item.getStcd());
|
||||
Long actualCount = actualMap.get(item.getStcd());
|
||||
item.setYr(currentYear);
|
||||
item.setJhCnt(planCount);
|
||||
item.setFished(actualCount);
|
||||
if (planCount != null) {
|
||||
item.setUnfished(actualCount == null ? planCount : Math.max(planCount - actualCount, 0L));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String mapWeFvColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
@ -4705,6 +4769,7 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
case "rstcd" -> "a.RSTCD";
|
||||
case "stcd" -> "a.STCD";
|
||||
case "sttp" -> "a.STTP";
|
||||
case "sttpcode" -> "a.STTP";
|
||||
case "bldsttccode" -> "a.BLDSTT_CODE";
|
||||
case "lgtd" -> "a.LGTD";
|
||||
default -> null;
|
||||
@ -4727,4 +4792,41 @@ public class FbStationServiceImpl implements FbStationService {
|
||||
}
|
||||
return voList;
|
||||
}
|
||||
|
||||
private List<FbTracingPointVo> getBuiltPointLegend(List<FbTracingPointVo> voList) {
|
||||
for (FbTracingPointVo pointVo : voList) {
|
||||
Integer bldstt = pointVo.getBldstt();
|
||||
String sttp = pointVo.getSttp();
|
||||
if (bldstt != null && bldstt == 1) {
|
||||
if ("FB".equals(sttp)) {
|
||||
pointVo.setAnchoPointState("fb_built");
|
||||
}
|
||||
if ("SG".equals(sttp)) {
|
||||
pointVo.setAnchoPointState("sg_built");
|
||||
}
|
||||
}
|
||||
}
|
||||
return voList;
|
||||
}
|
||||
|
||||
private static class FbPointCountVo {
|
||||
private String stcd;
|
||||
private Long fcnt;
|
||||
|
||||
public String getStcd() {
|
||||
return stcd;
|
||||
}
|
||||
|
||||
public void setStcd(String stcd) {
|
||||
this.stcd = stcd;
|
||||
}
|
||||
|
||||
public Long getFcnt() {
|
||||
return fcnt;
|
||||
}
|
||||
|
||||
public void setFcnt(Long fcnt) {
|
||||
this.fcnt = fcnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1955,13 +1955,13 @@ public class FhHabitatServiceImpl implements FhHabitatService {
|
||||
.append("t.DTIN AS dtin ")
|
||||
.append("FROM ( ")
|
||||
.append(" SELECT STCD, STNM, 'FH' AS STTP_CODE, RSTCD, BASE_ID, HBRVCD, LGTD, LTTD, BLPRD AS BLDSTT_CCODE, ELEV, DTIN ")
|
||||
.append(" FROM SD_FHBT_B_H WHERE NVL(IS_DELETED, 0) = 0 AND USFL = 1 ")
|
||||
.append(" FROM SD_FHBT_B_H WHERE NVL(IS_DELETED, 0) = 0 ")
|
||||
.append(" UNION ALL ")
|
||||
.append(" SELECT STCD, STNM, STTP AS STTP_CODE, RSTCD, BASE_ID, HBRVCD, LGTD, LTTD, BLDSTT_CODE AS BLDSTT_CCODE, ELEV, DTIN ")
|
||||
.append(" FROM SD_VA_B_H WHERE NVL(IS_DELETED, 0) = 0 AND USFL = 1 ")
|
||||
.append(" FROM SD_VA_B_H WHERE NVL(IS_DELETED, 0) = 0 ")
|
||||
.append(" UNION ALL ")
|
||||
.append(" SELECT STCD, STNM, STTP AS STTP_CODE, RSTCD, BASE_ID, HBRVCD, LGTD, LTTD, BLDSTT_CODE AS BLDSTT_CCODE, ELEV, DTIN ")
|
||||
.append(" FROM SD_VP_B_H WHERE NVL(IS_DELETED, 0) = 0 AND USFL = 1 ")
|
||||
.append(" FROM SD_VP_B_H WHERE NVL(IS_DELETED, 0) = 0 ")
|
||||
.append(") t ")
|
||||
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = t.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ")
|
||||
.append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(t.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 ")
|
||||
|
||||
@ -106,6 +106,12 @@ public class FishPassageController {
|
||||
return ResponseResult.successData(fpBuildService.getStInfoByStcd(stcd));
|
||||
}
|
||||
|
||||
@PostMapping("/point/qgc/GetKendoListCust")
|
||||
@Operation(summary = "环保部-过鱼设施描点接口")
|
||||
public ResponseResult getQgcFpPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(fpBuildService.getQgcFpPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/point/built/GetKendoListCust")
|
||||
@Operation(summary = "过鱼设施地图描点接口(仅查询在建状态的)")
|
||||
public ResponseResult getFpBuiltPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
|
||||
@ -15,6 +15,9 @@ public class FpAnchoPointVo {
|
||||
@Schema(description = "站名")
|
||||
private String stnm;
|
||||
|
||||
@Schema(description = "站点图片")
|
||||
private String logo;
|
||||
|
||||
@Schema(description = "弹框站点名称")
|
||||
private String titleName;
|
||||
|
||||
@ -45,6 +48,9 @@ public class FpAnchoPointVo {
|
||||
@Schema(description = "运行状态")
|
||||
private String run;
|
||||
|
||||
@Schema(description = "运行状态名称")
|
||||
private String runName;
|
||||
|
||||
@Schema(description = "设施类型")
|
||||
private String dwtp;
|
||||
|
||||
@ -78,12 +84,24 @@ public class FpAnchoPointVo {
|
||||
@Schema(description = "达标状态子类型")
|
||||
private Integer stdSstate;
|
||||
|
||||
@Schema(description = "达标状态子类型名称")
|
||||
private String stdSstateName;
|
||||
|
||||
@Schema(description = "地图避让")
|
||||
private Integer distance;
|
||||
|
||||
@Schema(description = "澜沧江运行状态")
|
||||
private Integer lcjStatus;
|
||||
|
||||
@Schema(description = "澜沧江运行状态名称")
|
||||
private String lcjStatusName;
|
||||
|
||||
@Schema(description = "年份")
|
||||
private String yr;
|
||||
|
||||
@Schema(description = "过鱼种类")
|
||||
private Integer ftpTypeCount;
|
||||
|
||||
@Schema(description = "过鱼数量")
|
||||
private Integer ftpCount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
package com.yfd.platform.qgc_env.fp.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "过鱼设施鱼类统计")
|
||||
public class FpFishStatisticsVo {
|
||||
|
||||
@Schema(description = "站点编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "鱼类名称")
|
||||
private String ftp;
|
||||
|
||||
@Schema(description = "鱼编码")
|
||||
private String fishId;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer count;
|
||||
}
|
||||
@ -21,5 +21,7 @@ public interface FpBuildService {
|
||||
|
||||
FpVmsstbprptVo getStInfoByStcd(String stcd);
|
||||
|
||||
DataSourceResult<FpAnchoPointVo> getQgcFpPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<FpAnchoPointVo> getFpBuiltPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.qgc_env.fp.entity.vo.FpAnchoPointVo;
|
||||
import com.yfd.platform.qgc_env.fp.entity.vo.FpConstructionSituationVo;
|
||||
import com.yfd.platform.qgc_env.fp.entity.vo.FpFishDicVo;
|
||||
import com.yfd.platform.qgc_env.fp.entity.vo.FpFishStatisticsVo;
|
||||
import com.yfd.platform.qgc_env.fp.entity.vo.FpVmsstbprptVo;
|
||||
import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils;
|
||||
import com.yfd.platform.qgc_env.fp.service.FpBuildService;
|
||||
@ -28,6 +29,8 @@ import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class FpBuildServiceImpl implements FpBuildService {
|
||||
@ -214,6 +217,99 @@ public class FpBuildServiceImpl implements FpBuildService {
|
||||
return list.getFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<FpAnchoPointVo> getQgcFpPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceResult<FpAnchoPointVo> dataSourceResult = new DataSourceResult<>();
|
||||
dataSourceResult.setAggregates(new HashMap<>());
|
||||
if (dataSourceRequest == null) {
|
||||
dataSourceResult.setData(new ArrayList<>());
|
||||
dataSourceResult.setTotal(0L);
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
StringBuilder sql = new StringBuilder("SELECT " +
|
||||
"fp.STCD AS stcd, " +
|
||||
"fp.STNM AS stnm, " +
|
||||
"fp.LOGO AS logo, " +
|
||||
"fp.STNM AS titleName, " +
|
||||
"fp.BLDSTT_CODE AS bldsttCcode, " +
|
||||
"fp.BLDSTT_CODE AS bldstt, " +
|
||||
"fp.LTTD AS lttd, " +
|
||||
"fp.LGTD AS lgtd, " +
|
||||
"fp.ELEV AS dtmel, " +
|
||||
"fp.RSTCD AS rstcds, " +
|
||||
"eng.ENNM AS ennm, " +
|
||||
"'FP' AS sttpCode, " +
|
||||
"state.RUN_STATE AS run, " +
|
||||
"CASE WHEN state.RUN_STATE = 1 THEN '运行中' WHEN state.RUN_STATE IN (0, 2) THEN '未运行' ELSE NULL END AS runName, " +
|
||||
"fp.STTP AS dwtp, " +
|
||||
"CASE " +
|
||||
"WHEN fp.STTP = 'FP_1' THEN '鱼道' " +
|
||||
"WHEN fp.STTP = 'FP_2' THEN '仿自然通道' " +
|
||||
"WHEN fp.STTP = 'FP_3' THEN '集运鱼系统' " +
|
||||
"WHEN fp.STTP = 'FP_4' THEN '升鱼机' " +
|
||||
"ELSE '其它' END AS dwtpName, " +
|
||||
"fp.STTP AS sttpMap, " +
|
||||
"eng.RVCD AS rvcd, " +
|
||||
"eng.ADDVCD AS addvcd, " +
|
||||
"eng.BASE_ID AS baseId, " +
|
||||
"fp.STTP AS sttp, " +
|
||||
"CASE " +
|
||||
"WHEN fp.STTP = 'FP_1' THEN 'GY_1' " +
|
||||
"WHEN fp.STTP = 'FP_2' THEN 'GY_2' " +
|
||||
"WHEN fp.STTP = 'FP_3' THEN 'GY_3' " +
|
||||
"WHEN fp.STTP = 'FP_4' THEN 'GY_4' " +
|
||||
"ELSE 'GY_5' END AS anchoPointState, " +
|
||||
"fp.MWAY AS mway, " +
|
||||
"fp.DTIN AS dtin, " +
|
||||
"state.STD_SSTATE AS stdSstate, " +
|
||||
"CASE WHEN state.STD_SSTATE = 1 THEN '正常运行' " +
|
||||
"WHEN state.STD_SSTATE IN (0, 2) THEN '暂无数据' " +
|
||||
"WHEN state.STD_SSTATE = 3 THEN '未正常运行' ELSE NULL END AS stdSstateName, " +
|
||||
"CASE WHEN recent.STCD IS NULL THEN 2 ELSE 1 END AS lcjStatus, " +
|
||||
"CASE WHEN recent.STCD IS NULL THEN '暂无数据' ELSE '正常运行' END AS lcjStatusName, " +
|
||||
"fp.ORDER_INDEX AS orderIndex " +
|
||||
"FROM SD_FPSS_B_H fp " +
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN (SELECT s.STCD, s.RUN_STATE, s.STD_SSTATE " +
|
||||
" FROM MS_STSTATE_T s " +
|
||||
" INNER JOIN (SELECT STCD, MAX(YR) AS YR FROM MS_STSTATE_T WHERE NVL(IS_DELETED, 0) = 0 GROUP BY STCD) latest " +
|
||||
" ON latest.STCD = s.STCD AND latest.YR = s.YR " +
|
||||
" WHERE NVL(s.IS_DELETED, 0) = 0) state ON state.STCD = fp.STCD " +
|
||||
"LEFT JOIN (SELECT STCD FROM SD_FPSSRL_R WHERE NVL(IS_DELETED, 0) = 0 AND TM BETWEEN ADD_MONTHS(SYSDATE, -12) AND SYSDATE GROUP BY STCD " +
|
||||
" UNION " +
|
||||
" SELECT STCD FROM SD_FPSS_R WHERE NVL(IS_DELETED, 0) = 0 AND STRDT >= ADD_MONTHS(SYSDATE, -12) AND NVL(ENDDT, STRDT) <= SYSDATE GROUP BY STCD) recent " +
|
||||
"ON recent.STCD = fp.STCD " +
|
||||
"WHERE NVL(fp.IS_DELETED, 0) = 0 AND fp.STTP !='FPQ'");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
|
||||
String filterSql = buildFpPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql).append(" ");
|
||||
}
|
||||
sql.append(buildFpPointOrderBySql(dataSourceRequest.getSort()));
|
||||
|
||||
Page<?> page = QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
|
||||
List<FpAnchoPointVo> resultList = microservicDynamicSQLMapper.pageAllListWithResultType(
|
||||
page, sql.toString(), paramMap, FpAnchoPointVo.class);
|
||||
|
||||
if (CollUtil.isNotEmpty(resultList)) {
|
||||
fillQgcFpPointStatistics(resultList);
|
||||
applyFpPointLegend(resultList);
|
||||
SiteAvoidanceUtils.calcSiteMapLev(resultList,
|
||||
FpAnchoPointVo::getStcd,
|
||||
FpAnchoPointVo::getLgtd,
|
||||
FpAnchoPointVo::getLttd,
|
||||
FpAnchoPointVo::getAnchoPointState,
|
||||
FpAnchoPointVo::setDistance);
|
||||
}
|
||||
|
||||
dataSourceResult.setData(resultList);
|
||||
dataSourceResult.setTotal(page == null ? resultList.size() : page.getTotal());
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
private String buildFishDicBaseSql() {
|
||||
return "SELECT " +
|
||||
"src.ID AS id, " +
|
||||
@ -1185,12 +1281,17 @@ public class FpBuildServiceImpl implements FpBuildService {
|
||||
" fp.DTIN AS dtin\n" +
|
||||
"FROM SD_FPSS_B_H fp\n" +
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0\n" +
|
||||
"WHERE NVL(fp.IS_DELETED, 0) = 0 AND fp.BLDSTT_CODE = 1 AND fp.LGTD IS NOT NULL AND fp.LTTD IS NOT NULL ");
|
||||
"WHERE NVL(fp.IS_DELETED, 0) = 0 ");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
|
||||
String filterSql = buildFpPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
String filterSql = QgcQueryWrapperUtil.buildFilterCondition(
|
||||
dataSourceRequest.getFilter(),
|
||||
paramMap,
|
||||
new int[]{0},
|
||||
this::mapFpColumn
|
||||
);
|
||||
// String filterSql = buildFpPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql).append(" ");
|
||||
}
|
||||
@ -1227,6 +1328,205 @@ public class FpBuildServiceImpl implements FpBuildService {
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
private void fillQgcFpPointStatistics(List<FpAnchoPointVo> pointList) {
|
||||
List<String> stcdList = pointList.stream()
|
||||
.map(FpAnchoPointVo::getStcd)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(stcdList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String year = queryLatestFpYear(stcdList);
|
||||
List<FpFishStatisticsVo> manualList = queryQgcFpManualFishStatistics(stcdList, year);
|
||||
Set<String> manualStcdSet = manualList.stream()
|
||||
.map(FpFishStatisticsVo::getStcd)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
List<String> autoQueryStcdList = stcdList.stream()
|
||||
.filter(stcd -> !manualStcdSet.contains(stcd))
|
||||
.collect(Collectors.toList());
|
||||
List<FpFishStatisticsVo> autoList = queryQgcFpAutoFishStatistics(autoQueryStcdList, year);
|
||||
if (CollUtil.isNotEmpty(autoList)) {
|
||||
manualList.addAll(autoList);
|
||||
}
|
||||
Map<String, List<FpFishStatisticsVo>> stcdDataMap = manualList.stream()
|
||||
.collect(Collectors.groupingBy(FpFishStatisticsVo::getStcd));
|
||||
for (FpAnchoPointVo vo : pointList) {
|
||||
vo.setYr(year);
|
||||
List<FpFishStatisticsVo> fishStatistics = stcdDataMap.get(vo.getStcd());
|
||||
if (CollUtil.isEmpty(fishStatistics)) {
|
||||
continue;
|
||||
}
|
||||
vo.setFtpTypeCount(fishStatistics.size());
|
||||
vo.setFtpCount(fishStatistics.stream()
|
||||
.filter(item -> item.getCount() != null)
|
||||
.mapToInt(FpFishStatisticsVo::getCount)
|
||||
.sum());
|
||||
}
|
||||
}
|
||||
|
||||
private String queryLatestFpYear(List<String> stcdList) {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder("SELECT MAX(t.YR) AS yr FROM (" +
|
||||
"SELECT TO_CHAR(STRDT, 'yyyy') AS YR, STCD FROM SD_FPSS_R WHERE NVL(IS_DELETED, 0) = 0 " +
|
||||
"UNION ALL " +
|
||||
"SELECT TO_CHAR(TM, 'yyyy') AS YR, STCD FROM SD_FPSSRL_R WHERE NVL(IS_DELETED, 0) = 0) t WHERE 1 = 1 ");
|
||||
appendInCondition(sql, paramMap, "t.STCD", stcdList, "fpYear");
|
||||
List<FpAnchoPointVo> list = microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, FpAnchoPointVo.class);
|
||||
if (CollUtil.isEmpty(list) || StrUtil.isBlank(list.getFirst().getYr())) {
|
||||
return String.valueOf(java.time.LocalDate.now().getYear());
|
||||
}
|
||||
return list.getFirst().getYr();
|
||||
}
|
||||
|
||||
private List<FpFishStatisticsVo> queryQgcFpManualFishStatistics(List<String> stcdList, String year) {
|
||||
if (CollUtil.isEmpty(stcdList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder("SELECT data.STCD AS stcd, data.FTP AS fishId, dict.NAME AS ftp, SUM(data.FCNT) AS count " +
|
||||
"FROM (SELECT t.STCD, t.FTP, t.FCNT, eng.HBRVCD " +
|
||||
" FROM SD_FPSS_R t " +
|
||||
" INNER JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD AND NVL(fp.IS_DELETED, 0) = 0 " +
|
||||
" LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " +
|
||||
" WHERE NVL(t.IS_DELETED, 0) = 0 ");
|
||||
paramMap.put("manualYear", year);
|
||||
sql.append(" AND TO_CHAR(t.STRDT, 'yyyy') = #{map.manualYear}) data ")
|
||||
.append("INNER JOIN (SELECT DISTINCT rel.FISH_ID, rel.RVCD, dic.NAME " +
|
||||
" FROM SD_FISHDICTORY_RLTN_B rel " +
|
||||
" LEFT JOIN SD_FISHDICTORY_B dic ON dic.ID = rel.ZY_FISH_ID " +
|
||||
" WHERE NVL(rel.IS_DELETED, 0) = 0 AND NVL(dic.IS_DELETED, 0) = 0 " +
|
||||
" AND (rel.FISH_ID <> rel.ZY_FISH_ID OR rel.RVCD = 'ZY')) dict " +
|
||||
"ON dict.FISH_ID = data.FTP AND (dict.RVCD = data.HBRVCD OR dict.RVCD = 'ZY') WHERE 1 = 1 ");
|
||||
appendInCondition(sql, paramMap, "data.STCD", stcdList, "fpManual");
|
||||
sql.append(" GROUP BY data.STCD, data.FTP, dict.NAME");
|
||||
return microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, FpFishStatisticsVo.class);
|
||||
}
|
||||
|
||||
private List<FpFishStatisticsVo> queryQgcFpAutoFishStatistics(List<String> stcdList, String year) {
|
||||
if (CollUtil.isEmpty(stcdList)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder("SELECT data.STCD AS stcd, data.FTP AS fishId, dict.NAME AS ftp, SUM(data.FCNT) AS count " +
|
||||
"FROM (SELECT t.STCD, t.FTP, t.FCNT, eng.HBRVCD " +
|
||||
" FROM SD_FPSSRL_R t " +
|
||||
" INNER JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD AND NVL(fp.IS_DELETED, 0) = 0 " +
|
||||
" LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " +
|
||||
" WHERE NVL(t.IS_DELETED, 0) = 0 ");
|
||||
paramMap.put("autoYear", year);
|
||||
sql.append(" AND TO_CHAR(t.TM, 'yyyy') = #{map.autoYear}) data ")
|
||||
.append("INNER JOIN (SELECT DISTINCT rel.FISH_ID, rel.RVCD, dic.NAME " +
|
||||
" FROM SD_FISHDICTORY_RLTN_B rel " +
|
||||
" LEFT JOIN SD_FISHDICTORY_B dic ON dic.ID = rel.ZY_FISH_ID " +
|
||||
" WHERE NVL(rel.IS_DELETED, 0) = 0 AND NVL(dic.IS_DELETED, 0) = 0 " +
|
||||
" AND (rel.FISH_ID <> rel.ZY_FISH_ID OR rel.RVCD = 'ZY')) dict " +
|
||||
"ON dict.FISH_ID = data.FTP AND (dict.RVCD = data.HBRVCD OR dict.RVCD = 'ZY') WHERE 1 = 1 ");
|
||||
appendInCondition(sql, paramMap, "data.STCD", stcdList, "fpAuto");
|
||||
sql.append(" GROUP BY data.STCD, data.FTP, dict.NAME");
|
||||
return microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, FpFishStatisticsVo.class);
|
||||
}
|
||||
|
||||
private void applyFpPointLegend(List<FpAnchoPointVo> voList) {
|
||||
for (FpAnchoPointVo pointVo : voList) {
|
||||
if (!"2".equals(pointVo.getBldstt())) {
|
||||
if ("FP_1".equals(pointVo.getSttp())) {
|
||||
pointVo.setAnchoPointState("GY_1_INCOMPLETE");
|
||||
} else if ("FP_2".equals(pointVo.getSttp())) {
|
||||
pointVo.setAnchoPointState("GY_2_INCOMPLETE");
|
||||
} else if ("FP_3".equals(pointVo.getSttp())) {
|
||||
pointVo.setAnchoPointState("GY_3_INCOMPLETE");
|
||||
} else if ("FP_4".equals(pointVo.getSttp())) {
|
||||
pointVo.setAnchoPointState("GY_4_INCOMPLETE");
|
||||
} else {
|
||||
pointVo.setAnchoPointState("GY_5_INCOMPLETE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendInCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
String column,
|
||||
List<String> values,
|
||||
String prefix) {
|
||||
if (CollUtil.isEmpty(values)) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
int index = 0;
|
||||
for (String value : values) {
|
||||
if (StrUtil.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
String key = prefix + index++;
|
||||
paramMap.put(key, value);
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
if (CollUtil.isEmpty(placeholders)) {
|
||||
return;
|
||||
}
|
||||
sql.append(" AND ").append(column).append(" IN (")
|
||||
.append(String.join(", ", placeholders))
|
||||
.append(") ");
|
||||
}
|
||||
|
||||
private String buildFpPointOrderBySql(List<DataSourceRequest.SortDescriptor> sorts) {
|
||||
if (CollUtil.isEmpty(sorts)) {
|
||||
return " ORDER BY fp.ORDER_INDEX ASC NULLS LAST, fp.STCD ASC";
|
||||
}
|
||||
List<String> orderItems = new ArrayList<>();
|
||||
for (DataSourceRequest.SortDescriptor sort : sorts) {
|
||||
if (sort == null || StrUtil.isBlank(sort.getField())) {
|
||||
continue;
|
||||
}
|
||||
String column = mapFpPointOrderColumn(sort.getField());
|
||||
if (StrUtil.isBlank(column)) {
|
||||
continue;
|
||||
}
|
||||
String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC";
|
||||
orderItems.add(column + " " + direction + " NULLS LAST");
|
||||
}
|
||||
if (orderItems.isEmpty()) {
|
||||
return " ORDER BY fp.ORDER_INDEX ASC NULLS LAST, fp.STCD ASC";
|
||||
}
|
||||
return " ORDER BY " + String.join(", ", orderItems);
|
||||
}
|
||||
|
||||
private String mapFpPointOrderColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
return switch (field) {
|
||||
case "stcd" -> "fp.STCD";
|
||||
case "stnm", "titleName" -> "fp.STNM";
|
||||
case "bldsttCcode", "bldstt" -> "fp.BLDSTT_CODE";
|
||||
case "lgtd" -> "fp.LGTD";
|
||||
case "lttd" -> "fp.LTTD";
|
||||
case "ennm" -> "eng.ENNM";
|
||||
case "baseId" -> "eng.BASE_ID";
|
||||
case "rvcd" -> "eng.RVCD";
|
||||
case "addvcd" -> "eng.ADDVCD";
|
||||
case "run" -> "state.RUN_STATE";
|
||||
case "stdSstate" -> "state.STD_SSTATE";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private String mapFpColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
return switch (field.toLowerCase()) {
|
||||
case "bldsttccode" -> "fp.BLDSTT_CODE";
|
||||
case "lgtd" -> "fp.LGTD";
|
||||
case "lttd" -> "fp.LTTD";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private String buildFpPointFilterCondition(DataSourceRequest.FilterDescriptor filter,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
@ -1267,6 +1567,12 @@ public class FpBuildServiceImpl implements FpBuildService {
|
||||
case "rvcd" -> "eng.RVCD";
|
||||
case "addvcd" -> "eng.ADDVCD";
|
||||
case "sttp" -> "fp.STTP";
|
||||
case "bldsttCcode", "bldstt" -> "fp.BLDSTT_CODE";
|
||||
case "lgtd" -> "fp.LGTD";
|
||||
case "lttd" -> "fp.LTTD";
|
||||
case "run" -> "state.RUN_STATE";
|
||||
case "stdSstate" -> "state.STD_SSTATE";
|
||||
case "lcjStatus" -> "CASE WHEN recent.STCD IS NULL THEN 2 ELSE 1 END";
|
||||
default -> null;
|
||||
};
|
||||
if (column == null) {
|
||||
|
||||
@ -89,8 +89,15 @@ public class FprMonitorController {
|
||||
|
||||
@PostMapping("/sdFprdR/point/getFprdPointList")
|
||||
@Operation(summary = "鱼类调查装置锚点信息")
|
||||
public ResponseResult getFprdPointList(@RequestBody FprdRunDataAo ao) {
|
||||
List<FprdPointInfoVo> result = fprMonitorService.getFprdInfoList(ao);
|
||||
public ResponseResult getFprdPointList(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
List<FprdPointInfoVo> result = fprMonitorService.getFprdPointList(dataSourceRequest);
|
||||
return ResponseResult.successData(result);
|
||||
}
|
||||
|
||||
@PostMapping("/point/getFprdPointList")
|
||||
@Operation(summary = "鱼类调查装置锚点信息(AO入参)")
|
||||
public ResponseResult getFprdPointListByAo(@RequestBody FprdRunDataAo ao) {
|
||||
List<FprdPointInfoVo> result = fprMonitorService.getFprdPointList(ao);
|
||||
return ResponseResult.successData(result);
|
||||
}
|
||||
|
||||
|
||||
@ -31,5 +31,7 @@ public interface FprMonitorService {
|
||||
|
||||
List<String> getFishInfo();
|
||||
|
||||
List<FprdPointInfoVo> getFprdInfoList(FprdRunDataAo ao);
|
||||
List<FprdPointInfoVo> getFprdPointList(FprdRunDataAo ao);
|
||||
|
||||
List<FprdPointInfoVo> getFprdPointList(DataSourceRequest dataSourceRequest);
|
||||
}
|
||||
|
||||
@ -129,11 +129,24 @@ public class FprMonitorServiceImpl implements FprMonitorService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FprdPointInfoVo> getFprdInfoList(FprdRunDataAo ao) {
|
||||
validateFprdRunDataAo(ao);
|
||||
public List<FprdPointInfoVo> getFprdPointList(FprdRunDataAo ao) {
|
||||
validateFprdPointAo(ao);
|
||||
return listFprdPointInfo(ao.getBaseId(), ao.getHbrvcd(), ao.getStcd());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FprdPointInfoVo> getFprdPointList(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId");
|
||||
String hbrvcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "hbrvcd");
|
||||
String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd");
|
||||
validateFprdPointRequest(baseId);
|
||||
return listFprdPointInfo(baseId, hbrvcd, stcd);
|
||||
}
|
||||
|
||||
private List<FprdPointInfoVo> listFprdPointInfo(String baseId, String hbrvcd, String stcd) {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("baseId", ao.getBaseId());
|
||||
|
||||
|
||||
StringBuilder sql = new StringBuilder("SELECT ")
|
||||
.append("aim.STCD AS stcd, ")
|
||||
@ -143,17 +156,17 @@ public class FprMonitorServiceImpl implements FprMonitorService {
|
||||
.append("TO_CHAR(aim.BLDSTT_CODE) AS bldstt, ")
|
||||
.append("aim.LTTD AS lttd, ")
|
||||
.append("aim.LGTD AS lgtd, ")
|
||||
.append("aim.DTMEL AS dtmel, ")
|
||||
// .append("aim.DTMEL AS dtmel, ")
|
||||
.append("aim.RSTCD AS rstcds, ")
|
||||
.append("eng.ENNM AS ennm, ")
|
||||
.append("aim.STTP AS sttpCode, ")
|
||||
.append("aim.DWTP AS dwtp, ")
|
||||
.append("aim.DWTP AS dwtpName, ")
|
||||
// .append("aim.DWTP AS dwtp, ")
|
||||
// .append("aim.DWTP AS dwtpName, ")
|
||||
.append("aim.STTP AS sttpMap, ")
|
||||
.append("aim.RVCD AS rvcd, ")
|
||||
.append("rv.RVNM AS rvcdName, ")
|
||||
.append("aim.ADDVCD AS addvcd, ")
|
||||
.append("addv.ADDVCD_NAME AS addvcdName, ")
|
||||
// .append("aim.ADDVCD AS addvcd, ")
|
||||
// .append("addv.ADDVCD_NAME AS addvcdName, ")
|
||||
.append("aim.HBRVCD AS hbrvcd, ")
|
||||
.append("hbrv.HBRVNM AS hbrvcdName, ")
|
||||
.append("aim.BASE_ID AS baseId, ")
|
||||
@ -163,7 +176,7 @@ public class FprMonitorServiceImpl implements FprMonitorService {
|
||||
.append("'' AS anchoPointState, ")
|
||||
.append("aim.MWAY AS mway, ")
|
||||
.append("aim.DTIN AS dtin, ")
|
||||
.append("aim.STDSSTATE AS stdSstate, ")
|
||||
// .append("aim.STDSSTATE AS stdSstate, ")
|
||||
.append("aim.STLC AS stlc ")
|
||||
.append("FROM SD_AIMONITOR_B_H aim ")
|
||||
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = aim.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ")
|
||||
@ -173,23 +186,26 @@ public class FprMonitorServiceImpl implements FprMonitorService {
|
||||
.append(" AND NVL(hbrv.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND NVL(hbrv.ENABLED, 1) = 1 ")
|
||||
.append("LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = aim.RVCD ")
|
||||
.append("LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = aim.ADDVCD ")
|
||||
// .append("LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = aim.ADDVCD ")
|
||||
.append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = aim.STTP ")
|
||||
.append(" AND NVL(sttp.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND NVL(sttp.ENABLE, 1) = 1 ")
|
||||
.append("WHERE NVL(aim.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND aim.STTP = 'FPRD' ")
|
||||
.append(" AND aim.LGTD IS NOT NULL ")
|
||||
.append(" AND aim.BASE_ID = #{map.baseId}");
|
||||
.append(" AND aim.LGTD IS NOT NULL ");
|
||||
|
||||
if (StrUtil.isNotBlank(ao.getHbrvcd())) {
|
||||
if (StrUtil.isNotBlank(baseId)) {
|
||||
sql.append(" AND aim.BASE_ID = #{map.baseId}");
|
||||
}
|
||||
paramMap.put("baseId", baseId);
|
||||
if (StrUtil.isNotBlank(hbrvcd)) {
|
||||
sql.append(" AND aim.HBRVCD = #{map.hbrvcd}");
|
||||
paramMap.put("hbrvcd", ao.getHbrvcd());
|
||||
paramMap.put("hbrvcd", hbrvcd);
|
||||
}
|
||||
|
||||
if (StrUtil.isNotBlank(ao.getStcd())) {
|
||||
if (StrUtil.isNotBlank(stcd)) {
|
||||
sql.append(" AND aim.STCD = #{map.stcd}");
|
||||
paramMap.put("stcd", ao.getStcd());
|
||||
paramMap.put("stcd", stcd);
|
||||
}
|
||||
|
||||
List<FprdPointInfoVo> resultList = microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
@ -691,6 +707,19 @@ public class FprMonitorServiceImpl implements FprMonitorService {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateFprdPointRequest(String baseId) {
|
||||
// if (StrUtil.isBlank(baseId)) {
|
||||
// throw new BizException("基地编码(baseId)不能为空.");
|
||||
// }
|
||||
}
|
||||
|
||||
private void validateFprdPointAo(FprdRunDataAo ao) {
|
||||
if (ao == null) {
|
||||
throw new BizException("请求参数不能为空.");
|
||||
}
|
||||
validateFprdPointRequest(ao.getBaseId());
|
||||
}
|
||||
|
||||
private String buildFishDicBaseSql() {
|
||||
return "SELECT " +
|
||||
"src.ID AS id, " +
|
||||
|
||||
@ -1948,7 +1948,7 @@ public class VpConstructionServiceImpl implements VpConstructionService {
|
||||
" t.STTP AS sttp,\n" +
|
||||
" t.DTIN AS dtin\n" +
|
||||
"FROM (\n" +
|
||||
" SELECT STCD, STNM, STTP, LGTD, LTTD, ELEV, RSTCD, BASE_ID, RVCD, ADDVCD, BLDSTT_CODE, DTIN\n" +
|
||||
" SELECT STCD, STNM, STTP, LGTD, LTTD, ELEV, RSTCD, BASE_ID,NULL RVCD,NULL ADDVCD, BLDSTT_CODE, DTIN\n" +
|
||||
" FROM SD_VP_B_H\n" +
|
||||
" WHERE NVL(IS_DELETED, 0) = 0 AND BLDSTT_CODE = 1 AND LGTD IS NOT NULL AND LTTD IS NOT NULL\n" +
|
||||
" UNION ALL\n" +
|
||||
@ -1960,10 +1960,16 @@ public class VpConstructionServiceImpl implements VpConstructionService {
|
||||
" FROM SD_FHBT_B_H\n" +
|
||||
" WHERE NVL(IS_DELETED, 0) = 0 AND LGTD IS NOT NULL AND LTTD IS NOT NULL\n" +
|
||||
") t\n" +
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = t.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ");
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = t.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 WHERE 1=1");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
String filterSql = buildFhvapPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
String filterSql = QgcQueryWrapperUtil.buildFilterCondition(
|
||||
dataSourceRequest.getFilter(),
|
||||
paramMap,
|
||||
new int[]{0},
|
||||
this::mapVpColumn
|
||||
);
|
||||
// String filterSql = buildFhvapPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql);
|
||||
}
|
||||
@ -1991,6 +1997,26 @@ public class VpConstructionServiceImpl implements VpConstructionService {
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
private String mapVpColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, String> columnMap = new HashMap<>();
|
||||
columnMap.put("stcd", "t.STCD");
|
||||
columnMap.put("stnm", "t.STNM");
|
||||
columnMap.put("sttpcode", "t.STTP");
|
||||
columnMap.put("bldsttccode", "t.BLDSTT_CODE");
|
||||
columnMap.put("lgtd", "t.LGTD");
|
||||
columnMap.put("lttd", "t.LTTD");
|
||||
columnMap.put("baseId", "t.BASE_ID");
|
||||
columnMap.put("rvcd", "t.RVCD");
|
||||
columnMap.put("addvcd", "t.ADDVCD");
|
||||
columnMap.put("rstcds", "t.RSTCD");
|
||||
columnMap.put("ennm", "eng.ENNM");
|
||||
return columnMap.get(field.toLowerCase());
|
||||
}
|
||||
|
||||
|
||||
private String buildFhvapPointFilterCondition(DataSourceRequest.FilterDescriptor filter,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
@ -2149,19 +2175,25 @@ public class VpConstructionServiceImpl implements VpConstructionService {
|
||||
" we.ELEV AS dtmel,\n" +
|
||||
" we.RSTCD AS rstcds,\n" +
|
||||
" eng.ENNM AS ennm,\n" +
|
||||
" 'WVA' AS sttpMap,\n" +
|
||||
" we.STTP AS sttpMap,\n" +
|
||||
" we.RVCD AS rvcd,\n" +
|
||||
" we.ADDVCD AS addvcd,\n" +
|
||||
// " we.ADDVCD AS addvcd,\n" +
|
||||
" we.BASE_ID AS baseId,\n" +
|
||||
" 'WVA' AS sttp,\n" +
|
||||
" we.STTP AS sttp,\n" +
|
||||
" 'wild_animal_legend' AS anchoPointState,\n" +
|
||||
" 'WVA' AS sttpCode\n" +
|
||||
"FROM SD_WE_B_H we\n" +
|
||||
" we.STTP AS sttpCode\n" +
|
||||
"FROM SD_AIMONITOR_B_H we\n" +
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = we.RSTCD AND NVL(eng.IS_DELETED, 0) = 0\n" +
|
||||
"WHERE we.LGTD IS NOT NULL AND we.LTTD IS NOT NULL ");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
String filterSql = buildWvaPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
String filterSql = QgcQueryWrapperUtil.buildFilterCondition(
|
||||
dataSourceRequest.getFilter(),
|
||||
paramMap,
|
||||
new int[]{0},
|
||||
this::mapVapWvaColumn
|
||||
);
|
||||
// String filterSql = buildWvaPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql);
|
||||
}
|
||||
@ -2176,6 +2208,26 @@ public class VpConstructionServiceImpl implements VpConstructionService {
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
private String mapVapWvaColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, String> columnMap = new HashMap<>();
|
||||
columnMap.put("stcd", "we.STCD");
|
||||
columnMap.put("stnm", "we.STNM");
|
||||
columnMap.put("sttpcode", "we.STTP");
|
||||
columnMap.put("bldsttccode", "we.BLDSTT_CODE");
|
||||
columnMap.put("lgtd", "we.LGTD");
|
||||
columnMap.put("lttd", "we.LTTD");
|
||||
columnMap.put("baseId", "we.BASE_ID");
|
||||
columnMap.put("rvcd", "we.RVCD");
|
||||
columnMap.put("addvcd", "we.ADDVCD");
|
||||
columnMap.put("rstcds", "weRSTCD");
|
||||
columnMap.put("ennm", "eng.ENNM");
|
||||
return columnMap.get(field.toLowerCase());
|
||||
}
|
||||
|
||||
|
||||
private String buildWvaPointFilterCondition(DataSourceRequest.FilterDescriptor filter,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
|
||||
@ -65,6 +65,12 @@ public class VdMonitorController {
|
||||
return ResponseResult.successData(vdMonitorService.getVdPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/aiPoint/GetKendoListCust")
|
||||
@Operation(summary = "视频站AI设施锚点")
|
||||
public ResponseResult getVdAiPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(vdMonitorService.getVdAiPointKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/runData/GetKendoListCust")
|
||||
@Operation(summary = "查询视频监控运行数据")
|
||||
public ResponseResult getRunDataKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
|
||||
@ -0,0 +1,107 @@
|
||||
package com.yfd.platform.qgc_env.vd.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Schema(description = "视频站AI设施锚点信息")
|
||||
public class VdAiPointVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "锚点状态")
|
||||
private String anchoPointState;
|
||||
|
||||
@Schema(description = "地图站类标识")
|
||||
private String sttpMap;
|
||||
|
||||
@Schema(description = "锚点站类")
|
||||
private String sttp;
|
||||
|
||||
@Schema(description = "视频站编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "视频站名称")
|
||||
private String stnm;
|
||||
|
||||
@Schema(description = "经度")
|
||||
private BigDecimal lgtd;
|
||||
|
||||
@Schema(description = "纬度")
|
||||
private BigDecimal lttd;
|
||||
|
||||
@Schema(description = "流域编码")
|
||||
private String rvcd;
|
||||
|
||||
@Schema(description = "行政区编码")
|
||||
private String addvcd;
|
||||
|
||||
@Schema(description = "流域名称")
|
||||
private String rvnm;
|
||||
|
||||
@Schema(description = "基地编码")
|
||||
private String baseId;
|
||||
|
||||
@Schema(description = "所属电站编码")
|
||||
private String rstcds;
|
||||
|
||||
@Schema(description = "所属电站编码")
|
||||
private String rstcd;
|
||||
|
||||
@Schema(description = "高程")
|
||||
private BigDecimal dtmel;
|
||||
|
||||
@Schema(description = "标题")
|
||||
private String titleName;
|
||||
|
||||
@Schema(description = "电站名称")
|
||||
private String ennm;
|
||||
|
||||
@Schema(description = "站类名称")
|
||||
private String sttpName;
|
||||
|
||||
@Schema(description = "站点排序")
|
||||
private Integer siteStepSort;
|
||||
|
||||
@Schema(description = "站类编码")
|
||||
private String sttpCode;
|
||||
|
||||
@Schema(description = "栖息地编码")
|
||||
private String fhstcd;
|
||||
|
||||
@Schema(description = "栖息地名称")
|
||||
private String fhstnm;
|
||||
|
||||
@Schema(description = "基地流域编码")
|
||||
private String hbrvcd;
|
||||
|
||||
@Schema(description = "基地流域名称")
|
||||
private String hbrvcdName;
|
||||
|
||||
@Schema(description = "播放地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "站址")
|
||||
private String stlc;
|
||||
|
||||
@Schema(description = "AI是否启用")
|
||||
private Integer aiEnabled;
|
||||
|
||||
@Schema(description = "AI外部站码")
|
||||
private String aiExtCode;
|
||||
|
||||
@Schema(description = "AI外部站名")
|
||||
private String aiExtName;
|
||||
|
||||
@Schema(description = "AI频率")
|
||||
private String aiFrequency;
|
||||
|
||||
@Schema(description = "AI站类编码")
|
||||
private String aiSttpCode;
|
||||
|
||||
@Schema(description = "AI站类名称")
|
||||
private String aiSttpName;
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.vd.service;
|
||||
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdAiPointVo;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo;
|
||||
@ -20,5 +21,7 @@ public interface VdMonitorService {
|
||||
|
||||
DataSourceResult<?> getVdPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<VdAiPointVo> getVdAiPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<VdRunDataVo> getRunDataKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.common.GroupHelper;
|
||||
import com.yfd.platform.common.GroupingInfo;
|
||||
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdAiPointVo;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdPointVo;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo;
|
||||
import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo;
|
||||
@ -229,6 +230,72 @@ public class VdMonitorServiceImpl implements VdMonitorService {
|
||||
return queryVdPointDetailList(dataSourceRequest, loadOptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<VdAiPointVo> getVdAiPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
Page<?> page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
|
||||
String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId");
|
||||
String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd");
|
||||
String hbrvcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "hbrvcd");
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
.append("t.stcd AS stcd, ")
|
||||
.append("t.stnm AS stnm, ")
|
||||
.append("t.anchoPointState AS anchoPointState, ")
|
||||
.append("t.sttpMap AS sttpMap, ")
|
||||
.append("t.sttp AS sttp, ")
|
||||
.append("t.lgtd AS lgtd, ")
|
||||
.append("t.lttd AS lttd, ")
|
||||
.append("t.rvcd AS rvcd, ")
|
||||
.append("t.addvcd AS addvcd, ")
|
||||
.append("t.rvnm AS rvnm, ")
|
||||
.append("t.baseId AS baseId, ")
|
||||
.append("t.rstcds AS rstcds, ")
|
||||
.append("t.rstcd AS rstcd, ")
|
||||
.append("t.dtmel AS dtmel, ")
|
||||
.append("t.titleName AS titleName, ")
|
||||
.append("t.ennm AS ennm, ")
|
||||
.append("t.sttpName AS sttpName, ")
|
||||
.append("t.siteStepSort AS siteStepSort, ")
|
||||
.append("t.sttpCode AS sttpCode, ")
|
||||
.append("t.fhstcd AS fhstcd, ")
|
||||
.append("t.fhstnm AS fhstnm, ")
|
||||
.append("t.hbrvcd AS hbrvcd, ")
|
||||
.append("t.hbrvcdName AS hbrvcdName, ")
|
||||
.append("t.url AS url, ")
|
||||
.append("t.stlc AS stlc, ")
|
||||
.append("t.aiEnabled AS aiEnabled, ")
|
||||
.append("t.aiExtCode AS aiExtCode, ")
|
||||
.append("t.aiExtName AS aiExtName, ")
|
||||
.append("t.aiFrequency AS aiFrequency, ")
|
||||
.append("t.aiSttpCode AS aiSttpCode, ")
|
||||
.append("t.aiSttpName AS aiSttpName ")
|
||||
.append("FROM (")
|
||||
.append(buildVdAiPointCoreSql())
|
||||
.append(") t WHERE 1 = 1 ");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
if (StrUtil.isNotBlank(baseId)) {
|
||||
paramMap.put("vdAiBaseId", baseId);
|
||||
sql.append(" AND t.baseId = #{map.vdAiBaseId} ");
|
||||
}
|
||||
if (StrUtil.isNotBlank(hbrvcd)) {
|
||||
paramMap.put("vdAiHbrvcd", hbrvcd);
|
||||
sql.append(" AND t.hbrvcd = #{map.vdAiHbrvcd} ");
|
||||
}
|
||||
appendVdAiRstcdCondition(sql, paramMap, parseArrayLikeValues(rstcd));
|
||||
sql.append(" ORDER BY t.siteStepSort ASC NULLS LAST, t.stcd ASC");
|
||||
|
||||
List<VdAiPointVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
|
||||
page, sql.toString(), paramMap, VdAiPointVo.class);
|
||||
DataSourceResult<VdAiPointVo> result = new DataSourceResult<>();
|
||||
result.setData(list);
|
||||
result.setTotal(page != null ? page.getTotal() : list.size());
|
||||
result.setAggregates(new HashMap<>());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<VdRunDataVo> getRunDataKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
@ -703,6 +770,68 @@ public class VdMonitorServiceImpl implements VdMonitorService {
|
||||
" AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 ";
|
||||
}
|
||||
|
||||
private String buildVdAiPointCoreSql() {
|
||||
return "SELECT " +
|
||||
"src.STCD AS stcd, " +
|
||||
"src.STNM AS stnm, " +
|
||||
"'aispjk' AS anchoPointState, " +
|
||||
"'AIVD' AS sttpMap, " +
|
||||
"src.STTP AS sttp, " +
|
||||
"src.LGTD AS lgtd, " +
|
||||
"src.LTTD AS lttd, " +
|
||||
"NVL(eng.RVCD, src.RVCD) AS rvcd, " +
|
||||
"NVL(eng.ADDVCD, src.ADDVCD) AS addvcd, " +
|
||||
"rv.RVNM AS rvnm, " +
|
||||
"NVL(eng.BASE_ID, src.BASE_ID) AS baseId, " +
|
||||
"src.RSTCD AS rstcds, " +
|
||||
"src.RSTCD AS rstcd, " +
|
||||
"src.ELEV AS dtmel, " +
|
||||
"src.STNM AS titleName, " +
|
||||
"eng.ENNM AS ennm, " +
|
||||
"vdSttp.STTP_NAME AS sttpName, " +
|
||||
"NVL(siteSort.SORT, 999999) AS siteStepSort, " +
|
||||
"'AIVD' AS sttpCode, " +
|
||||
"src.FHSTCD AS fhstcd, " +
|
||||
"fh.STNM AS fhstnm, " +
|
||||
"NVL(eng.HBRVCD, src.HBRVCD) AS hbrvcd, " +
|
||||
"hbrv.HBRVNM AS hbrvcdName, " +
|
||||
"src.URL AS url, " +
|
||||
"src.STLC AS stlc, " +
|
||||
"src.AI_ENABLED AS aiEnabled, " +
|
||||
"src.AI_EXT_CODE AS aiExtCode, " +
|
||||
"src.AI_EXT_NAME AS aiExtName, " +
|
||||
"src.AI_FREQUENCY AS aiFrequency, " +
|
||||
"(SELECT LISTAGG(ai.STTP, ',') WITHIN GROUP (ORDER BY ai.STTP) " +
|
||||
" FROM SD_AIMONITOR_B_H ai " +
|
||||
" WHERE NVL(ai.IS_DELETED, 0) = 0 " +
|
||||
" AND ai.STTP LIKE 'AI_%' " +
|
||||
" AND INSTR(',' || src.AI_EXT_CODE || ',', ',' || ai.STCD || ',') > 0) AS aiSttpCode, " +
|
||||
"(SELECT LISTAGG(sttp.STTP_NAME, ',') WITHIN GROUP (ORDER BY ai.STTP) " +
|
||||
" FROM SD_AIMONITOR_B_H ai " +
|
||||
" LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = ai.STTP " +
|
||||
" AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " +
|
||||
" WHERE NVL(ai.IS_DELETED, 0) = 0 " +
|
||||
" AND ai.STTP LIKE 'AI_%' " +
|
||||
" AND INSTR(',' || src.AI_EXT_CODE || ',', ',' || ai.STCD || ',') > 0) AS aiSttpName " +
|
||||
"FROM SD_VDINFO_B src " +
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = src.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN SD_FHBT_B_H fh ON fh.STCD = src.FHSTCD AND NVL(fh.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = NVL(eng.RVCD, src.RVCD) " +
|
||||
"LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(eng.HBRVCD, src.HBRVCD) " +
|
||||
" AND hbrv.BASEID = NVL(eng.BASE_ID, src.BASE_ID) " +
|
||||
" AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " +
|
||||
"LEFT JOIN SD_STTP_B vdSttp ON vdSttp.STTP_CODE = src.STTP " +
|
||||
" AND NVL(vdSttp.IS_DELETED, 0) = 0 AND NVL(vdSttp.ENABLE, 1) = 1 " +
|
||||
"LEFT JOIN (SELECT det.SORT, cfg.RVCD, det.STCD FROM MS_ALONGDET_B det " +
|
||||
"INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " +
|
||||
"WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common') siteSort " +
|
||||
"ON siteSort.RVCD = NVL(eng.HBRVCD, src.HBRVCD) AND siteSort.STCD = src.STCD " +
|
||||
"WHERE src.STTP LIKE 'VD%' " +
|
||||
"AND src.AI_EXT_CODE IS NOT NULL " +
|
||||
"AND src.LGTD IS NOT NULL " +
|
||||
"AND src.LTTD IS NOT NULL ";
|
||||
}
|
||||
|
||||
private String buildRunDataCoreSql() {
|
||||
return "SELECT " +
|
||||
"run.ID AS id, " +
|
||||
@ -1183,6 +1312,44 @@ public class VdMonitorServiceImpl implements VdMonitorService {
|
||||
return values;
|
||||
}
|
||||
|
||||
private List<String> parseArrayLikeValues(String value) {
|
||||
List<String> values = new ArrayList<>();
|
||||
if (StrUtil.isBlank(value)) {
|
||||
return values;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
||||
trimmed = trimmed.substring(1, trimmed.length() - 1);
|
||||
}
|
||||
if (StrUtil.isBlank(trimmed)) {
|
||||
return values;
|
||||
}
|
||||
for (String item : trimmed.split(",")) {
|
||||
String normalized = StrUtil.trim(item.replace("\"", "").replace("'", ""));
|
||||
if (StrUtil.isNotBlank(normalized)) {
|
||||
values.add(normalized);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private void appendVdAiRstcdCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
List<String> rstcdList) {
|
||||
if (CollUtil.isEmpty(rstcdList)) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
for (int i = 0; i < rstcdList.size(); i++) {
|
||||
String key = "vdAiRstcd" + i;
|
||||
paramMap.put(key, rstcdList.get(i));
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
sql.append(" AND t.rstcds IN (")
|
||||
.append(String.join(", ", placeholders))
|
||||
.append(") ");
|
||||
}
|
||||
|
||||
private void appendNormalizedValues(List<Object> values, Object value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
|
||||
@ -22,6 +22,7 @@ import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo;
|
||||
import com.yfd.platform.qgc_env.warn.service.WarnDataService;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -260,6 +261,7 @@ public class WarnDataServiceImpl implements WarnDataService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "warn#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public DataSourceResult<AlarmPointVo> getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
String startTimeText = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime");
|
||||
|
||||
@ -0,0 +1,310 @@
|
||||
package com.yfd.platform.qgc_env.wq.entity;
|
||||
|
||||
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 io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("SD_WQ_R")
|
||||
@Schema(description = "水质监测数据表实体")
|
||||
public class SdWqR {
|
||||
|
||||
@TableId(value = "ID", type = IdType.ASSIGN_UUID)
|
||||
@Schema(description = "主键")
|
||||
private String id;
|
||||
|
||||
@TableField("STCD")
|
||||
@Schema(description = "站码")
|
||||
private String stcd;
|
||||
|
||||
@TableField("TM")
|
||||
@Schema(description = "采样时间")
|
||||
private Date tm;
|
||||
|
||||
@TableField("WQGRD")
|
||||
@Schema(description = "水质类别")
|
||||
private String wqgrd;
|
||||
|
||||
|
||||
@Schema(description = "水质类别")
|
||||
@TableField(exist = false)
|
||||
private String wqgrdName;
|
||||
|
||||
@TableField("PERIOD")
|
||||
@Schema(description = "丰平枯时期")
|
||||
private String period;
|
||||
|
||||
@TableField("SPSTLC")
|
||||
@Schema(description = "水平位置")
|
||||
private Long spstlc;
|
||||
|
||||
@TableField("WTMP")
|
||||
@Schema(description = "水温")
|
||||
private BigDecimal wtmp;
|
||||
|
||||
@TableField("PH")
|
||||
@Schema(description = "PH")
|
||||
private BigDecimal ph;
|
||||
|
||||
@TableField("DOX")
|
||||
@Schema(description = "溶解氧")
|
||||
private BigDecimal dox;
|
||||
|
||||
@TableField("CODMN")
|
||||
@Schema(description = "高锰酸盐指数")
|
||||
private BigDecimal codmn;
|
||||
|
||||
@TableField("CODCR")
|
||||
@Schema(description = "化学需氧量")
|
||||
private BigDecimal codcr;
|
||||
|
||||
@TableField("BOD5")
|
||||
@Schema(description = "五日生化需氧量")
|
||||
private BigDecimal bod5;
|
||||
|
||||
@TableField("NH3N")
|
||||
@Schema(description = "氨氮")
|
||||
private BigDecimal nh3n;
|
||||
|
||||
@TableField("TP")
|
||||
@Schema(description = "总磷")
|
||||
private BigDecimal tp;
|
||||
|
||||
@TableField("TN")
|
||||
@Schema(description = "总氮")
|
||||
private BigDecimal tn;
|
||||
|
||||
@TableField("CU")
|
||||
@Schema(description = "铜")
|
||||
private BigDecimal cu;
|
||||
|
||||
@TableField("ZN")
|
||||
@Schema(description = "锌")
|
||||
private BigDecimal zn;
|
||||
|
||||
@TableField("F")
|
||||
@Schema(description = "氟化物")
|
||||
private BigDecimal f;
|
||||
|
||||
@TableField("SE")
|
||||
@Schema(description = "硒")
|
||||
private BigDecimal se;
|
||||
|
||||
@TableField("ARS")
|
||||
@Schema(description = "砷")
|
||||
private BigDecimal ars;
|
||||
|
||||
@TableField("HG")
|
||||
@Schema(description = "汞")
|
||||
private BigDecimal hg;
|
||||
|
||||
@TableField("CD")
|
||||
@Schema(description = "镉")
|
||||
private BigDecimal cd;
|
||||
|
||||
@TableField("CR6")
|
||||
@Schema(description = "铬(六价)")
|
||||
private BigDecimal cr6;
|
||||
|
||||
@TableField("PB")
|
||||
@Schema(description = "铅")
|
||||
private BigDecimal pb;
|
||||
|
||||
@TableField("CN")
|
||||
@Schema(description = "氰化物")
|
||||
private BigDecimal cn;
|
||||
|
||||
@TableField("VLPH")
|
||||
@Schema(description = "挥发酚")
|
||||
private BigDecimal vlph;
|
||||
|
||||
@TableField("OIL")
|
||||
@Schema(description = "石油类")
|
||||
private BigDecimal oil;
|
||||
|
||||
@TableField("LAS")
|
||||
@Schema(description = "阴离子表面活性剂")
|
||||
private BigDecimal las;
|
||||
|
||||
@TableField("S2")
|
||||
@Schema(description = "硫化物")
|
||||
private BigDecimal s2;
|
||||
|
||||
@TableField("FCG")
|
||||
@Schema(description = "粪大肠菌群")
|
||||
private BigDecimal fcg;
|
||||
|
||||
@TableField("CL")
|
||||
@Schema(description = "氯化物")
|
||||
private BigDecimal cl;
|
||||
|
||||
@TableField("SO4")
|
||||
@Schema(description = "硫酸盐")
|
||||
private BigDecimal so4;
|
||||
|
||||
@TableField("NO3")
|
||||
@Schema(description = "硝氮/硝酸盐氮")
|
||||
private BigDecimal no3;
|
||||
|
||||
@TableField("THRD")
|
||||
@Schema(description = "总硬度")
|
||||
private BigDecimal thrd;
|
||||
|
||||
@TableField("COND")
|
||||
@Schema(description = "电导率")
|
||||
private BigDecimal cond;
|
||||
|
||||
@TableField("FE")
|
||||
@Schema(description = "铁")
|
||||
private BigDecimal fe;
|
||||
|
||||
@TableField("MN")
|
||||
@Schema(description = "锰")
|
||||
private BigDecimal mn;
|
||||
|
||||
@TableField("AL")
|
||||
@Schema(description = "铝")
|
||||
private BigDecimal al;
|
||||
|
||||
@TableField("CHLA")
|
||||
@Schema(description = "叶绿素a")
|
||||
private BigDecimal chla;
|
||||
|
||||
@TableField("CLARITY")
|
||||
@Schema(description = "透明度")
|
||||
private BigDecimal clarity;
|
||||
|
||||
@TableField("TU")
|
||||
@Schema(description = "浊度")
|
||||
private BigDecimal tu;
|
||||
|
||||
@TableField("CYANO")
|
||||
@Schema(description = "蓝绿藻")
|
||||
private BigDecimal cyano;
|
||||
|
||||
@TableField("NI")
|
||||
@Schema(description = "镍")
|
||||
private BigDecimal ni;
|
||||
|
||||
@TableField("TOD")
|
||||
@Schema(description = "总氧/总需氧量")
|
||||
private BigDecimal tod;
|
||||
|
||||
@TableField("SFDB")
|
||||
@Schema(description = "是否达标")
|
||||
private Integer sfdb;
|
||||
|
||||
@TableField("FID")
|
||||
@Schema(description = "文件ID")
|
||||
private String fid;
|
||||
|
||||
@TableField("VLSR")
|
||||
@Schema(description = "数据来源")
|
||||
private String vlsr;
|
||||
|
||||
@TableField("WQ_SFDBHN_YS")
|
||||
@Schema(description = "水质不达标的要素")
|
||||
private String wqSfdbhnYs;
|
||||
|
||||
@TableField("REMARK")
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@TableField("TLI_SUM")
|
||||
@Schema(description = "综合营养状态指数")
|
||||
private BigDecimal tliSum;
|
||||
|
||||
@TableField("TLI_SUM_LEVEL")
|
||||
@Schema(description = "综合营养状态指数分级")
|
||||
private String tliSumLevel;
|
||||
|
||||
@TableField("CA")
|
||||
@Schema(description = "钙")
|
||||
private BigDecimal ca;
|
||||
|
||||
@TableField("PO4")
|
||||
@Schema(description = "磷酸盐")
|
||||
private BigDecimal po4;
|
||||
|
||||
@TableField("N_NO2")
|
||||
@Schema(description = "亚硝酸盐氮(弃用)")
|
||||
private BigDecimal nNo2;
|
||||
|
||||
@TableField("NA")
|
||||
@Schema(description = "钠")
|
||||
private BigDecimal na;
|
||||
|
||||
@TableField("K")
|
||||
@Schema(description = "钾")
|
||||
private BigDecimal k;
|
||||
|
||||
@TableField("TOC")
|
||||
@Schema(description = "总有机碳")
|
||||
private BigDecimal toc;
|
||||
|
||||
@TableField("OPOR")
|
||||
@Schema(description = "有机磷农药")
|
||||
private BigDecimal opor;
|
||||
|
||||
@TableField("SS")
|
||||
@Schema(description = "悬浮物")
|
||||
private BigDecimal ss;
|
||||
|
||||
@TableField("NO2")
|
||||
@Schema(description = "亚硝酸盐氮")
|
||||
private BigDecimal no2;
|
||||
|
||||
@TableField("ORP")
|
||||
@Schema(description = "氧化还原电位")
|
||||
private BigDecimal orp;
|
||||
|
||||
@TableField("FWGHTEMP")
|
||||
@Schema(description = "FWGHTEMP")
|
||||
private BigDecimal fwghtemp;
|
||||
|
||||
@TableField("RECORD_USER")
|
||||
@Schema(description = "创建人")
|
||||
private String recordUser;
|
||||
|
||||
@TableField("RECORD_TIME")
|
||||
@Schema(description = "创建时间")
|
||||
private Date recordTime;
|
||||
|
||||
@TableField("MODIFY_USER")
|
||||
@Schema(description = "更新人")
|
||||
private String modifyUser;
|
||||
|
||||
@TableField("MODIFY_TIME")
|
||||
@Schema(description = "更新时间")
|
||||
private Date modifyTime;
|
||||
|
||||
@TableField("IS_DELETED")
|
||||
@Schema(description = "是否已删除")
|
||||
private Integer isDeleted;
|
||||
|
||||
@TableField("DELETE_USER")
|
||||
@Schema(description = "删除人")
|
||||
private String deleteUser;
|
||||
|
||||
@TableField("DELETE_TIME")
|
||||
@Schema(description = "删除时间")
|
||||
private Date deleteTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private Integer sfdbNew;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String tmNew;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String baseId;
|
||||
|
||||
@TableField(exist = false)
|
||||
private Integer dtinType;
|
||||
}
|
||||
@ -0,0 +1,139 @@
|
||||
package com.yfd.platform.qgc_env.wq.entity.ao;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@Schema(description = "定时任务基础参数")
|
||||
public class JobBaseAo {
|
||||
|
||||
public static final String JOB_TYPE_DAY = "day";
|
||||
public static final String JOB_TYPE_HOUR = "hour";
|
||||
|
||||
@Schema(description = "job类型 day=天 hour=小时", example = "hour", allowableValues = "day,hour")
|
||||
private String jobType;
|
||||
|
||||
@Schema(description = "只能是数字或特定字符串,为空=1。job类型为天即单位为天,类型为小时即单位小时 today=当天 am15=跨月15天取开始月份1号", example = "2")
|
||||
private String jobStep;
|
||||
|
||||
@Schema(description = "开始时间", example = "2022-08-01 00:00:00")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date startTime;
|
||||
|
||||
@Schema(description = "结束时间", example = "2022-08-31 23:59:59")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date endTime;
|
||||
|
||||
@Schema(description = "设施类型")
|
||||
private String sttpCode;
|
||||
|
||||
@Schema(description = "测站编码集合")
|
||||
private Set<String> stcds;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remarks;
|
||||
|
||||
public void initTime() {
|
||||
Date startTime = this.getStartTime();
|
||||
Date endTime = this.getEndTime();
|
||||
if (startTime == null || endTime == null) {
|
||||
Date now = new Date();
|
||||
String num = this.getJobStep() != null && !"".equals(this.getJobStep().trim()) ? this.getJobStep() : "1";
|
||||
if ("hour".equals(this.getJobType())) {
|
||||
if ("today".equalsIgnoreCase(num)) {
|
||||
startTime = getDayStartTime(now);
|
||||
endTime = parseWholeMinuteEnd(now);
|
||||
} else {
|
||||
startTime = parseWholeMinuteStart(DateUtils.addHours(now, -Integer.parseInt(num)));
|
||||
endTime = parseWholeMinuteEnd(now);
|
||||
}
|
||||
} else if ("day".equals(this.getJobType())) {
|
||||
if ("today".equalsIgnoreCase(num)) {
|
||||
startTime = getDayStartTime(now);
|
||||
endTime = parseWholeMinuteEnd(now);
|
||||
} else if (num.toLowerCase().startsWith("am")) {
|
||||
num = num.replace("am", "");
|
||||
startTime = getMonthFirstDayStartTime(DateUtils.addDays(now, -Integer.parseInt(num)));
|
||||
endTime = parseWholeMinuteEnd(now);
|
||||
} else {
|
||||
startTime = getDayStartTime(DateUtils.addDays(now, -Integer.parseInt(num)));
|
||||
endTime = parseWholeMinuteEnd(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startTime != null && endTime != null) {
|
||||
if (startTime.getTime() > endTime.getTime()) {
|
||||
throw new RuntimeException("开始时间不能大于结束时间");
|
||||
} else {
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("开始时间和结束时间不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
private Date getMonthFirstDayStartTime(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private static Date getDayStartTime(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private static Date parseWholeMinuteEnd(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.MINUTE, 59);
|
||||
calendar.set(Calendar.SECOND, 59);
|
||||
calendar.set(Calendar.MILLISECOND, 999);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private static Date parseWholeMinuteStart(Date date) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private static class DateUtils {
|
||||
public static Date addHours(Date date, int hours) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.HOUR_OF_DAY, hours);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
public static Date addDays(Date date, int days) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.add(Calendar.DAY_OF_MONTH, days);
|
||||
return calendar.getTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.yfd.platform.qgc_env.wq.entity.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@ -11,6 +12,8 @@ import java.util.Map;
|
||||
@Data
|
||||
@Schema(description = "水质实时数据")
|
||||
public class EnvWqDataVo {
|
||||
@Schema(description = "id")
|
||||
private String id;
|
||||
@Schema(description = "测站编码")
|
||||
private String stcd;
|
||||
@Schema(description = "电站编码")
|
||||
@ -137,6 +140,34 @@ public class EnvWqDataVo {
|
||||
private Integer rstcdStepSort;
|
||||
@Schema(description = "测站排序")
|
||||
private Integer siteStepSort;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String recordUser;
|
||||
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private Date recordTime;
|
||||
|
||||
|
||||
@Schema(description = "更新人")
|
||||
private String modifyUser;
|
||||
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private Date modifyTime;
|
||||
|
||||
|
||||
@Schema(description = "是否已删除")
|
||||
private Integer isDeleted;
|
||||
|
||||
|
||||
@Schema(description = "删除人")
|
||||
private String deleteUser;
|
||||
|
||||
|
||||
@Schema(description = "删除时间")
|
||||
private Date deleteTime;
|
||||
|
||||
@Schema(description = "水质要素最小限值集合")
|
||||
private List<Map<String, Object>> min;
|
||||
@Schema(description = "水质要素最大限值集合")
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.yfd.platform.qgc_env.wq.mapper;
|
||||
|
||||
import com.yfd.platform.qgc_env.wq.entity.SdWqR;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface WqJobMapper {
|
||||
|
||||
List<SdWqR> getWqLastData(@Param("ao") JobBaseAo ao);
|
||||
|
||||
List<SdWqR> getWqYsLastData(@Param("startTimeStr") String startTimeStr, @Param("endTimeStr") String endTimeStr);
|
||||
|
||||
void mergeWqR(@Param("wqRs") List<SdWqR> wqRs);
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.yfd.platform.qgc_env.wq.service;
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import com.yfd.platform.qgc_env.wq.entity.vo.WqBaseInfoVo;
|
||||
import com.yfd.platform.qgc_env.wq.entity.vo.EnvWqAnchorPointVo;
|
||||
|
||||
@ -45,4 +46,6 @@ public interface EnvWqDataService {
|
||||
boolean removeKendoByIds(BatchDeleteAo batchDeleteAo);
|
||||
|
||||
DataSourceResult<EnvWqAnchorPointVo> getAnchorPointKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
void wqLastData(JobBaseAo ao);
|
||||
}
|
||||
|
||||
@ -4,24 +4,28 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.yfd.platform.common.*;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.qgc_base.domain.MsOperationLog;
|
||||
import com.yfd.platform.qgc_base.domain.MsOperationLogDetail;
|
||||
import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult;
|
||||
import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo;
|
||||
import com.yfd.platform.qgc_base.entity.vo.DataParam;
|
||||
import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper;
|
||||
import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper;
|
||||
import com.yfd.platform.qgc_base.service.IDataScopeFilterService;
|
||||
import com.yfd.platform.qgc_env.wq.entity.SdWqR;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import com.yfd.platform.qgc_env.wq.entity.vo.*;
|
||||
import com.yfd.platform.qgc_env.wq.mapper.WqJobMapper;
|
||||
import com.yfd.platform.qgc_env.wq.service.EnvWqDataService;
|
||||
import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo;
|
||||
import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils;
|
||||
import com.yfd.platform.utils.KendoUtil;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import com.yfd.platform.utils.RequestHolder;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import com.yfd.platform.utils.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -45,6 +49,12 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||
@Service
|
||||
public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
|
||||
@Resource
|
||||
private IDataScopeFilterService dataScopeFilterService;
|
||||
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
|
||||
private static final String WQ_HOUR_TABLE_NAME = "SD_WQ_R";
|
||||
private static final String WQ_DAY_TABLE_NAME = "SD_WQDAY_S";
|
||||
private static final String WQ_MONTH_TABLE_NAME = "SD_WQDRTP_S";
|
||||
@ -153,6 +163,9 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
@Resource
|
||||
private MsOperationLogDetailMapper msOperationLogDetailMapper;
|
||||
|
||||
@Resource
|
||||
private WqJobMapper wqJobMapper;
|
||||
|
||||
@Override
|
||||
public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) {
|
||||
boolean calculated = CommonConstant.CALCULATE_SUCCESS.equals(
|
||||
@ -4544,6 +4557,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
}
|
||||
|
||||
@Override
|
||||
// @Cacheable(cacheNames = "weCache#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public DataSourceResult<EnvWqAnchorPointVo> getAnchorPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceResult<EnvWqAnchorPointVo> dataSourceResult = new DataSourceResult<>();
|
||||
dataSourceResult.setAggregates(new HashMap<>());
|
||||
@ -4570,6 +4584,15 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
.append("t.ELEV AS dtmel, ")
|
||||
.append("t.STLC AS stlc, ")
|
||||
.append("t.WWQTG AS wwqtg, ")
|
||||
.append("CASE t.WWQTG " +
|
||||
" WHEN '1' THEN 'Ⅰ' " +
|
||||
" WHEN '2' THEN 'Ⅱ' " +
|
||||
" WHEN '3' THEN 'Ⅲ' " +
|
||||
" WHEN '4' THEN 'Ⅳ' " +
|
||||
" WHEN '5' THEN 'Ⅴ' " +
|
||||
" WHEN '6' THEN 'V' " +
|
||||
" ELSE '未知' " +
|
||||
"END AS wwqtgName,")
|
||||
.append("t.DTIN_TYPE AS dtinType, ")
|
||||
.append("t.RSTCD AS rstcd, ")
|
||||
.append("t.FHSTCD AS fhstcd, ")
|
||||
@ -4610,6 +4633,13 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
.append("AND NVL(t.USFL, 1) = 1 ");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
|
||||
DataScopeApplyResult scopeApplyResult = dataScopeFilterService.appendCurrentUserStationScope(sql, paramMap, "t.RSTCD");
|
||||
if (scopeApplyResult.isEmptyResult()) {
|
||||
dataSourceResult.setData(new ArrayList<>());
|
||||
dataSourceResult.setTotal(0L);
|
||||
return dataSourceResult;
|
||||
}
|
||||
String filterSql = buildWqPointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql);
|
||||
@ -4628,15 +4658,16 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<EnvWqDataVo> wqDataList = queryWqDataByStcdBatch(stcdList);
|
||||
Map<String, EnvWqDataVo> wqDataMap = wqDataList.stream()
|
||||
.collect(Collectors.toMap(EnvWqDataVo::getStcd, Function.identity(), (oldValue, newValue) -> newValue));
|
||||
// List<EnvWqDataVo> wqDataList = queryWqDataByStcdBatch(stcdList);
|
||||
// Map<String, EnvWqDataVo> wqDataMap = wqDataList.stream()
|
||||
// .collect(Collectors.toMap(EnvWqDataVo::getStcd, Function.identity(), (oldValue, newValue) -> newValue));
|
||||
|
||||
for (EnvWqAnchorPointVo anchorPointVo : wqVoList) {
|
||||
EnvWqDataVo wqData = wqDataMap.get(anchorPointVo.getStcd());
|
||||
EnvWqDataVo wqData = redisCacheUtil.fromJson(redisCacheUtil.getString("wqLastDate:" + anchorPointVo.getStcd()), EnvWqDataVo.class);
|
||||
if (wqData != null) {
|
||||
anchorPointVo.setTm(wqData.getTm());
|
||||
anchorPointVo.setWqGrd(wqData.getWqgrd());
|
||||
anchorPointVo.setWqGrdName(wqData.getWqgrdName());
|
||||
anchorPointVo.setSfdb(wqData.getSfdb());
|
||||
anchorPointVo.setWtmp(wqData.getWtmp());
|
||||
anchorPointVo.setPh(wqData.getPh());
|
||||
@ -4718,7 +4749,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
.map(s -> "'" + s + "'")
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
String wqDataSql = "SELECT STCD, TM, WQGRD, SFDB, WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, TOD " +
|
||||
String wqDataSql = "SELECT STCD, TM, WQGRD,CASE WQGRD WHEN '1' THEN 'Ⅰ' WHEN '2' THEN 'Ⅱ' WHEN '3' THEN 'Ⅲ' WHEN '4' THEN 'Ⅳ' WHEN '5' THEN 'Ⅴ' WHEN '6' THEN 'V' ELSE '未知' END AS wqgrdName, SFDB, WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, TOD " +
|
||||
"FROM ( " +
|
||||
" SELECT t.*, ROW_NUMBER() OVER (PARTITION BY t.STCD ORDER BY t.TM DESC) AS rn " +
|
||||
" FROM SD_WQ_R t " +
|
||||
@ -4940,4 +4971,29 @@ public class EnvWqDataServiceImpl implements EnvWqDataService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wqLastData(JobBaseAo ao) {
|
||||
List<SdWqR> wqDataVos = wqJobMapper.getWqLastData(ao);
|
||||
String startTimeStr = DateUtil.format(ao.getStartTime(), "yyyy-MM-dd HH:mm:ss");
|
||||
String endTimeStr = DateUtil.format(ao.getEndTime(), "yyyy-MM-dd HH:mm:ss");
|
||||
List<SdWqR> wqYsDataVos = wqJobMapper.getWqYsLastData(startTimeStr, endTimeStr);
|
||||
if (CollectionUtils.isNotEmpty(wqYsDataVos)) {
|
||||
for (SdWqR wqDataVo : wqYsDataVos) {
|
||||
redisCacheUtil.setString("wqYsLastDate:" + wqDataVo.getStcd(), JSONUtil.toJsonStr(wqDataVo));
|
||||
}
|
||||
}
|
||||
if (CollUtil.isEmpty(wqDataVos)) {
|
||||
return;
|
||||
}
|
||||
if (!wqDataVos.isEmpty()) {
|
||||
List<List<SdWqR>> newWqrListPartition = CollUtil.split(wqDataVos, 300);
|
||||
for (List<SdWqR> t : newWqrListPartition) {
|
||||
wqJobMapper.mergeWqR(t);
|
||||
}
|
||||
}
|
||||
for (SdWqR wqDataVo : wqDataVos) {
|
||||
redisCacheUtil.setString("wqLastDate:" + wqDataVo.getStcd(), JSONUtil.toJsonStr(wqDataVo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.yfd.platform.common.*;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.qgc_base.domain.vo.DataScopeApplyResult;
|
||||
import com.yfd.platform.qgc_base.service.IDataScopeFilterService;
|
||||
import com.yfd.platform.qgc_env.wt.entity.vo.DfltkwFacilityCountVo;
|
||||
import com.yfd.platform.qgc_env.wt.entity.vo.FishSpawnVo;
|
||||
import com.yfd.platform.qgc_env.wt.entity.vo.RstcdTreeInfoVo;
|
||||
@ -25,7 +27,10 @@ import com.yfd.platform.qgc_env.wt.entity.vo.WaterTempMapVO;
|
||||
import com.yfd.platform.qgc_env.wt.mapper.SdWtMonitorMapper;
|
||||
import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils;
|
||||
import com.yfd.platform.qgc_env.wt.service.SdWtMonitorService;
|
||||
import com.yfd.platform.qgc_job.vo.WtLastDataVo;
|
||||
import com.yfd.platform.qgc_job.vo.WtvtPointVo;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import com.yfd.platform.utils.RedisCacheUtil;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Data;
|
||||
@ -58,6 +63,12 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
|
||||
@Resource
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Resource
|
||||
private IDataScopeFilterService dataScopeFilterService;
|
||||
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
|
||||
@Override
|
||||
public DataSourceResult getEvnmAutoMonitorList(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
@ -2886,6 +2897,14 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
|
||||
}
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
DataScopeApplyResult scopeApplyResult = dataScopeFilterService.appendCurrentUserStationScope(sql, paramMap, "t.RSTCD");
|
||||
if (scopeApplyResult.isEmptyResult()) {
|
||||
dataSourceResult.setData(new ArrayList<>());
|
||||
dataSourceResult.setTotal(0L);
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
// Map<String, Object> paramMap = new HashMap<>();
|
||||
if (StrUtil.isNotEmpty(bldsttCcode)) {
|
||||
paramMap.put("bldsttCcode", bldsttCcode);
|
||||
}
|
||||
@ -3031,6 +3050,19 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
|
||||
vo.setAnchoPointState("WT_2");
|
||||
}
|
||||
}
|
||||
|
||||
if(vo.getEnfc()==1){
|
||||
//垂向水温
|
||||
WtvtPointVo wtvtPointVo =redisCacheUtil.fromJson(redisCacheUtil.getString("wtvtPointData:" + vo.getStcd()), WtvtPointVo.class);
|
||||
vo.setWtvtInfo(wtvtPointVo);
|
||||
}else{
|
||||
//河道水温
|
||||
WtLastDataVo sdWtrvR = redisCacheUtil.fromJson(redisCacheUtil.getString("wtLastData:" + vo.getStcd()), WtLastDataVo.class);
|
||||
if(sdWtrvR !=null){
|
||||
vo.setTm(sdWtrvR.getTm());
|
||||
vo.setTemperature(sdWtrvR.getWt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SiteAvoidanceUtils.calcSiteMapLev(resultList,
|
||||
|
||||
@ -150,6 +150,12 @@ public class WeFishController {
|
||||
return ResponseResult.successData(weFishService.getQgcWeFishPoint(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/we/point/qgc/GetKendoListCust")
|
||||
@Operation(summary = "环保部-水生生态调查-地图锚点")
|
||||
public ResponseResult getQgcWePoint(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(weFishService.getQgcWePoint(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/te/tet/spec/GetKendoListCust")
|
||||
@Operation(summary = "重点陆生动物二级页面")
|
||||
public ResponseResult getTeSpecialAnimalList(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.yfd.platform.qgc_env.wte.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "水生生态调查锚点鱼类统计")
|
||||
public class WePointFishStatVo {
|
||||
|
||||
@Schema(description = "断面编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "鱼类名称")
|
||||
private String fishName;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer count;
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package com.yfd.platform.qgc_env.wte.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "环保部-水生生态调查-锚点")
|
||||
public class WePointQgcVo {
|
||||
|
||||
@Schema(description = "站点编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "断面名称")
|
||||
private String stnm;
|
||||
|
||||
@Schema(description = "经度")
|
||||
private BigDecimal lgtd;
|
||||
|
||||
@Schema(description = "纬度")
|
||||
private BigDecimal lttd;
|
||||
|
||||
@Schema(description = "高程")
|
||||
private BigDecimal dtmel;
|
||||
|
||||
@Schema(description = "关联电站编码冗余")
|
||||
private String rstcds;
|
||||
|
||||
@Schema(description = "电站名称")
|
||||
private String ennm;
|
||||
|
||||
@Schema(description = "最新调查时间")
|
||||
private String tm;
|
||||
|
||||
@Schema(description = "描点状态")
|
||||
private String anchoPointState;
|
||||
|
||||
@Schema(description = "锚点类型")
|
||||
private String sttpMap;
|
||||
|
||||
@Schema(description = "站点类型")
|
||||
private String sttp;
|
||||
|
||||
@Schema(description = "设施类型")
|
||||
private String sttpCode;
|
||||
|
||||
@Schema(description = "弹框标题")
|
||||
private String titleName;
|
||||
|
||||
@Schema(description = "流域编码")
|
||||
private String rvcd;
|
||||
|
||||
@Schema(description = "行政编码")
|
||||
private String addvcd;
|
||||
|
||||
@Schema(description = "基地编码")
|
||||
private String baseId;
|
||||
|
||||
@Schema(description = "关联电站编码")
|
||||
private String rstcd;
|
||||
|
||||
@Schema(description = "沿程排序")
|
||||
private Integer siteStepSort;
|
||||
|
||||
@Schema(description = "地图避让")
|
||||
private Integer distance;
|
||||
|
||||
@Schema(description = "调查鱼类列表")
|
||||
private List<WePointFishStatVo> fishList;
|
||||
}
|
||||
@ -53,6 +53,8 @@ public interface WeFishService {
|
||||
|
||||
DataSourceResult<WeFishPointQgcVo> getQgcWeFishPoint(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<WePointQgcVo> getQgcWePoint(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<WeTeSpecialAnimalVo> getTeSpecialAnimalList(DataSourceRequest dataSourceRequest);
|
||||
|
||||
List<WeDefaultDataVo> getWeDefaultData(String stcd);
|
||||
|
||||
@ -10,11 +10,13 @@ import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.common.GroupHelper;
|
||||
import com.yfd.platform.common.GroupingInfo;
|
||||
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils;
|
||||
import com.yfd.platform.qgc_env.wte.entity.vo.*;
|
||||
import com.yfd.platform.qgc_env.wte.service.WeFishService;
|
||||
import com.yfd.platform.utils.KendoUtil;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -1034,6 +1036,7 @@ public class WeFishServiceImpl implements WeFishService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "weCache#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public DataSourceResult<WeFishPointQgcVo> getQgcWeFishPoint(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
String stcd = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "stcd");
|
||||
@ -1065,6 +1068,171 @@ public class WeFishServiceImpl implements WeFishService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "weCache#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public DataSourceResult<WePointQgcVo> getQgcWePoint(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceResult<WePointQgcVo> result = new DataSourceResult<>();
|
||||
result.setAggregates(new HashMap<>());
|
||||
if (dataSourceRequest == null) {
|
||||
result.setData(new ArrayList<>());
|
||||
result.setTotal(0L);
|
||||
return result;
|
||||
}
|
||||
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
|
||||
String stcd = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "stcd");
|
||||
String startTime = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "startTime");
|
||||
String endTime = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "endTime");
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
.append("section.STCD AS stcd, ")
|
||||
.append("section.STNM AS stnm, ")
|
||||
.append("section.LGTD AS lgtd, ")
|
||||
.append("section.LTTD AS lttd, ")
|
||||
.append("section.ELEV AS dtmel, ")
|
||||
.append("section.RSTCD AS rstcds, ")
|
||||
.append("eng.ENNM AS ennm, ")
|
||||
.append("TO_CHAR(latest.TM, 'yyyy-mm-dd hh24:mi:ss') AS tm, ")
|
||||
.append("'WE' AS anchoPointState, ")
|
||||
.append("'WE' AS sttpMap, ")
|
||||
.append("'WE' AS sttp, ")
|
||||
.append("'WE' AS sttpCode, ")
|
||||
.append("section.STNM AS titleName, ")
|
||||
.append("section.RVCD AS rvcd, ")
|
||||
.append("section.ADDVCD AS addvcd, ")
|
||||
.append("section.BASE_ID AS baseId, ")
|
||||
.append("section.RSTCD AS rstcd, ")
|
||||
.append("siteSort.SORT AS siteStepSort ")
|
||||
.append("FROM SD_WE_B_H section ")
|
||||
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ")
|
||||
.append("LEFT JOIN ( ")
|
||||
.append(" SELECT STCD, MAX(TM) AS TM ")
|
||||
.append(" FROM SD_WE_R ")
|
||||
.append(" WHERE NVL(IS_DELETED, 0) = 0 AND STATUS = 1 ")
|
||||
.append(" GROUP BY STCD ")
|
||||
.append(") latest ON latest.STCD = section.STCD ")
|
||||
.append("LEFT JOIN MS_ALONG_B along ON along.RVCD = section.HBRVCD ")
|
||||
.append(" AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 ")
|
||||
.append("LEFT JOIN ( ")
|
||||
.append(" SELECT det.SORT, cfg.RVCD, det.STCD ")
|
||||
.append(" FROM MS_ALONGDET_B det ")
|
||||
.append(" INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID ")
|
||||
.append(" WHERE NVL(det.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND NVL(cfg.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND cfg.CODE = 'common' ")
|
||||
.append(") siteSort ON siteSort.RVCD = section.HBRVCD AND siteSort.STCD = section.STCD ")
|
||||
.append("WHERE NVL(section.USFL, 1) = 1 ");
|
||||
|
||||
String filterSql = buildWePointFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append("AND ").append(filterSql).append(" ");
|
||||
}
|
||||
sql.append(buildWePointOrderBySql(dataSourceRequest.getSort()));
|
||||
|
||||
Page<?> page = loadOptions == null ? null
|
||||
: QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
|
||||
List<WePointQgcVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
|
||||
page,
|
||||
sql.toString(),
|
||||
paramMap,
|
||||
WePointQgcVo.class
|
||||
);
|
||||
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
result.setData(list);
|
||||
result.setTotal(page != null ? page.getTotal() : 0L);
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, List<WePointFishStatVo>> fishMap = queryWePointFishMap(
|
||||
list.stream().map(WePointQgcVo::getStcd).filter(StrUtil::isNotBlank).distinct().toList(),
|
||||
stcd,
|
||||
startTime,
|
||||
endTime
|
||||
);
|
||||
for (WePointQgcVo vo : list) {
|
||||
vo.setFishList(fishMap.get(vo.getStcd()));
|
||||
}
|
||||
|
||||
SiteAvoidanceUtils.calcSiteMapLev(list,
|
||||
WePointQgcVo::getStcd,
|
||||
WePointQgcVo::getLgtd,
|
||||
WePointQgcVo::getLttd,
|
||||
WePointQgcVo::getAnchoPointState,
|
||||
WePointQgcVo::setDistance);
|
||||
|
||||
result.setData(list);
|
||||
result.setTotal(page != null ? page.getTotal() : list.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, List<WePointFishStatVo>> queryWePointFishMap(List<String> stcdList,
|
||||
String stcd,
|
||||
String startTime,
|
||||
String endTime) {
|
||||
Map<String, List<WePointFishStatVo>> result = new LinkedHashMap<>();
|
||||
if (CollUtil.isEmpty(stcdList)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
.append("we.STCD AS stcd, ")
|
||||
.append("dict.NAME AS fishName, ")
|
||||
.append("SUM(fish.FCNT) AS count ")
|
||||
.append("FROM SD_WE_R we ")
|
||||
.append("INNER JOIN SD_WEFISH_R fish ON fish.WER_ID = we.ID ")
|
||||
.append(" AND NVL(fish.IS_DELETED, 0) = 0 ")
|
||||
.append("INNER JOIN SD_WE_B_H section ON section.STCD = we.STCD ")
|
||||
.append(" AND NVL(section.USFL, 1) = 1 ")
|
||||
.append("INNER JOIN ( ")
|
||||
.append(" SELECT STCD, MAX(TM) AS TM ")
|
||||
.append(" FROM SD_WE_R ")
|
||||
.append(" WHERE NVL(IS_DELETED, 0) = 0 AND STATUS = 1 ")
|
||||
.append(" GROUP BY STCD ")
|
||||
.append(") latest ON latest.STCD = we.STCD AND latest.TM = we.TM ")
|
||||
.append("LEFT JOIN ( ")
|
||||
.append(" SELECT DISTINCT rel.FISH_ID, rel.RVCD, dic.NAME ")
|
||||
.append(" FROM SD_FISHDICTORY_RLTN_B rel ")
|
||||
.append(" LEFT JOIN SD_FISHDICTORY_B dic ON rel.ZY_FISH_ID = dic.ID ")
|
||||
.append(" WHERE NVL(rel.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND NVL(dic.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND (rel.FISH_ID <> rel.ZY_FISH_ID OR rel.RVCD = 'ZY') ")
|
||||
.append(") dict ON fish.FTP = dict.FISH_ID AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ")
|
||||
.append("WHERE fish.FCNT IS NOT NULL ")
|
||||
.append("AND NVL(we.IS_DELETED, 0) = 0 ")
|
||||
.append("AND NVL(we.STATUS, 1) = 1 ");
|
||||
|
||||
appendWePointInCondition(sql, paramMap, "we.STCD", stcdList, "stcdList");
|
||||
if (StrUtil.isNotBlank(stcd)) {
|
||||
paramMap.put("filterStcd", stcd);
|
||||
sql.append("AND we.STCD = #{map.filterStcd} ");
|
||||
}
|
||||
if (StrUtil.isNotBlank(startTime) && StrUtil.isNotBlank(endTime)) {
|
||||
paramMap.put("startTime", startTime);
|
||||
paramMap.put("endTime", endTime);
|
||||
sql.append("AND we.TM BETWEEN TO_DATE(#{map.startTime}, 'yyyy-mm-dd hh24:mi:ss') ")
|
||||
.append("AND TO_DATE(#{map.endTime}, 'yyyy-mm-dd hh24:mi:ss') ");
|
||||
}
|
||||
sql.append("GROUP BY we.STCD, dict.NAME ORDER BY SUM(fish.FCNT)");
|
||||
|
||||
List<WePointFishStatVo> rows = microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
sql.toString(),
|
||||
paramMap,
|
||||
WePointFishStatVo.class
|
||||
);
|
||||
for (WePointFishStatVo row : rows) {
|
||||
if (row == null || StrUtil.isBlank(row.getStcd())) {
|
||||
continue;
|
||||
}
|
||||
result.computeIfAbsent(row.getStcd(), key -> new ArrayList<>()).add(row);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSourceResult<WeTeSpecialAnimalVo> getTeSpecialAnimalList(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
@ -2489,6 +2657,96 @@ public class WeFishServiceImpl implements WeFishService {
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
private String buildWePointFilterCondition(DataSourceRequest.FilterDescriptor filter,
|
||||
Map<String, Object> paramMap,
|
||||
int[] indexHolder) {
|
||||
return QgcQueryWrapperUtil.buildFilterCondition(filter, paramMap, indexHolder, this::mapWePointColumn);
|
||||
}
|
||||
|
||||
private String mapWePointColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return switch (field) {
|
||||
case "stcd" -> "section.STCD";
|
||||
case "lgtd" -> "section.LGTD";
|
||||
case "stnm", "titleName" -> "section.STNM";
|
||||
case "ennm" -> "eng.ENNM";
|
||||
case "rvcd" -> "section.RVCD";
|
||||
case "addvcd" -> "section.ADDVCD";
|
||||
case "baseId" -> "section.BASE_ID";
|
||||
case "rstcd", "rstcds" -> "section.RSTCD";
|
||||
case "tm" -> "latest.TM";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private String buildWePointOrderBySql(List<DataSourceRequest.SortDescriptor> sorts) {
|
||||
if (CollUtil.isEmpty(sorts)) {
|
||||
return " ORDER BY siteSort.SORT NULLS LAST";
|
||||
}
|
||||
List<String> orderByParts = new ArrayList<>();
|
||||
for (DataSourceRequest.SortDescriptor sort : sorts) {
|
||||
if (sort == null || StrUtil.isBlank(sort.getField())) {
|
||||
continue;
|
||||
}
|
||||
String column = mapWePointSortColumn(sort.getField());
|
||||
if (StrUtil.isBlank(column)) {
|
||||
continue;
|
||||
}
|
||||
String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC";
|
||||
orderByParts.add(column + " " + direction + " NULLS LAST");
|
||||
}
|
||||
if (orderByParts.isEmpty()) {
|
||||
return " ORDER BY siteSort.SORT NULLS LAST";
|
||||
}
|
||||
return " ORDER BY " + String.join(", ", orderByParts);
|
||||
}
|
||||
|
||||
private String mapWePointSortColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
return switch (field) {
|
||||
case "stcd" -> "section.STCD";
|
||||
case "stnm", "titleName" -> "section.STNM";
|
||||
case "ennm" -> "eng.ENNM";
|
||||
case "tm" -> "latest.TM";
|
||||
case "rvcd" -> "section.RVCD";
|
||||
case "addvcd" -> "section.ADDVCD";
|
||||
case "baseId" -> "section.BASE_ID";
|
||||
case "siteStepSort" -> "siteSort.SORT";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private void appendWePointInCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
String column,
|
||||
List<String> values,
|
||||
String paramPrefix) {
|
||||
if (CollUtil.isEmpty(values) || StrUtil.isBlank(column)) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
int index = 0;
|
||||
for (String value : values) {
|
||||
if (StrUtil.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
String key = paramPrefix + "_" + index++;
|
||||
paramMap.put(key, value);
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
if (CollUtil.isEmpty(placeholders)) {
|
||||
return;
|
||||
}
|
||||
sql.append("AND ").append(column).append(" IN (")
|
||||
.append(String.join(", ", placeholders))
|
||||
.append(") ");
|
||||
}
|
||||
|
||||
private String buildTeSpecialAnimalDetailSql() {
|
||||
return "SELECT DISTINCT " +
|
||||
"b.ID AS id, " +
|
||||
|
||||
@ -24,7 +24,9 @@ import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDrtpDataVo;
|
||||
import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDataVo;
|
||||
import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils;
|
||||
import com.yfd.platform.qgc_env.zq.service.ZqMonitorService;
|
||||
import com.yfd.platform.qgc_job.vo.ZqLastDataVo;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import com.yfd.platform.utils.RedisCacheUtil;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
@ -50,7 +52,6 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
|
||||
private static final String ZQ_MONTH_TABLE_NAME = "SD_RIVERDRTP_S";
|
||||
private static final Map<String, String> ZQ_UPDATE_COLUMN_MAP = new LinkedHashMap<>();
|
||||
private static final Map<String, String> ZQ_FIELD_MEANING_MAP = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
ZQ_UPDATE_COLUMN_MAP.put("z", "Z");
|
||||
ZQ_UPDATE_COLUMN_MAP.put("q", "Q");
|
||||
@ -90,6 +91,8 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
|
||||
|
||||
@Resource
|
||||
private MsOperationLogDetailMapper msOperationLogDetailMapper;
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "zqCache#7200", keyGenerator = "cacheKeyGenerator")
|
||||
@ -2374,6 +2377,7 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = "zqCache#3600", keyGenerator = "cacheKeyGenerator")
|
||||
public DataSourceResult<ZqPoint> getZqPointKendoListCust(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceResult<ZqPoint> dataSourceResult = new DataSourceResult<>();
|
||||
dataSourceResult.setAggregates(new HashMap<>());
|
||||
@ -2425,7 +2429,13 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest();
|
||||
String filterSql = buildMsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
String filterSql = QgcQueryWrapperUtil.buildFilterCondition(
|
||||
dataSourceRequest.getFilter(),
|
||||
paramMap,
|
||||
new int[]{0},
|
||||
this::mapZqColumn
|
||||
);
|
||||
// String filterSql = buildMsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0});
|
||||
if (StrUtil.isNotBlank(filterSql)) {
|
||||
sql.append(" AND ").append(filterSql).append(" ");
|
||||
}
|
||||
@ -2434,7 +2444,16 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
|
||||
|
||||
Page<?> page = QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
|
||||
List<ZqPoint> resultList = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, ZqPoint.class);
|
||||
|
||||
resultList.forEach(item->{
|
||||
//获取流量站最新数据
|
||||
ZqLastDataVo zqLastData = redisCacheUtil.fromJson(redisCacheUtil.getString("zqLastData:"+item.getStcd()), ZqLastDataVo.class);
|
||||
if(zqLastData !=null){
|
||||
item.setTm(zqLastData.getTm());
|
||||
item.setQ(zqLastData.getQ());
|
||||
item.setZ(zqLastData.getZ());
|
||||
item.setV(zqLastData.getV());
|
||||
}
|
||||
});
|
||||
SiteAvoidanceUtils.calcSiteMapLev(resultList,
|
||||
ZqPoint::getStcd,
|
||||
ZqPoint::getLgtd,
|
||||
@ -2446,4 +2465,16 @@ public class ZqMonitorServiceImpl implements ZqMonitorService {
|
||||
dataSourceResult.setTotal(page == null ? resultList.size() : page.getTotal());
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
|
||||
private String mapZqColumn(String field) {
|
||||
if (StrUtil.isBlank(field)) {
|
||||
return null;
|
||||
}
|
||||
return switch (field.toLowerCase()) {
|
||||
case "dtintype" -> "rb.DTIN_TYPE";
|
||||
case "lgtd" -> "rb.LGTD";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package com.yfd.platform.qgc_job.service;
|
||||
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
|
||||
public interface IDwJobService {
|
||||
|
||||
void wtLastData(JobBaseAo ao);
|
||||
|
||||
void wtvtPointData(JobBaseAo ao);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.yfd.platform.qgc_job.service;
|
||||
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
|
||||
public interface IEqJobService {
|
||||
|
||||
void eqAnchorPointLastDate(JobBaseAo ao);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.yfd.platform.qgc_job.service;
|
||||
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
|
||||
public interface IFhJobService {
|
||||
|
||||
void zqLastData(JobBaseAo ao);
|
||||
}
|
||||
@ -0,0 +1,291 @@
|
||||
package com.yfd.platform.qgc_job.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import com.yfd.platform.qgc_job.service.IDwJobService;
|
||||
import com.yfd.platform.qgc_job.vo.WtLastDataVo;
|
||||
import com.yfd.platform.qgc_job.vo.WtvtPointDataVo;
|
||||
import com.yfd.platform.qgc_job.vo.WtvtPointVo;
|
||||
import com.yfd.platform.utils.RedisCacheUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DwJobServiceImpl implements IDwJobService {
|
||||
|
||||
private static final String WT_LAST_DATA_KEY_PREFIX = "wtLastData:";
|
||||
private static final String WTVT_POINT_DATA_KEY_PREFIX = "wtvtPointData:";
|
||||
|
||||
@Resource
|
||||
private MicroservicDynamicSQLMapper<?> microservicDynamicSQLMapper;
|
||||
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
|
||||
@Override
|
||||
public void wtLastData(JobBaseAo ao) {
|
||||
if (ao == null) {
|
||||
throw new RuntimeException("任务参数不能为空");
|
||||
}
|
||||
ao.initTime();
|
||||
Date startTime = ao.getStartTime();
|
||||
Date endTime = ao.getEndTime();
|
||||
Set<String> stcds = ao.getStcds();
|
||||
|
||||
List<Map<String, Date>> dateList = getInterValDate(startTime, endTime);
|
||||
Map<String, WtLastDataVo> lastDataMap = new LinkedHashMap<>();
|
||||
for (int index = dateList.size() - 1; index >= 0; index--) {
|
||||
Map<String, Date> dateMap = dateList.get(index);
|
||||
Date segmentStartTime = dateMap.get("startTime");
|
||||
Date segmentEndTime = dateMap.get("endTime");
|
||||
List<WtLastDataVo> wtLastDataList = getWtLastData(stcds, segmentStartTime, segmentEndTime);
|
||||
for (WtLastDataVo wtLastDataVo : wtLastDataList) {
|
||||
if (wtLastDataVo == null || wtLastDataVo.getStcd() == null || lastDataMap.containsKey(wtLastDataVo.getStcd())) {
|
||||
continue;
|
||||
}
|
||||
lastDataMap.put(wtLastDataVo.getStcd(), wtLastDataVo);
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (Map.Entry<String, WtLastDataVo> entry : lastDataMap.entrySet()) {
|
||||
String stcd = entry.getKey();
|
||||
WtLastDataVo wtLastDataVo = entry.getValue();
|
||||
WtLastDataVo redisData = redisCacheUtil.fromJson(redisCacheUtil.getString(WT_LAST_DATA_KEY_PREFIX + stcd), WtLastDataVo.class);
|
||||
if (shouldRefresh(redisData, wtLastDataVo)) {
|
||||
redisCacheUtil.setString(WT_LAST_DATA_KEY_PREFIX + stcd, JSONUtil.toJsonStr(wtLastDataVo));
|
||||
count++;
|
||||
} else {
|
||||
redisCacheUtil.delete(WT_LAST_DATA_KEY_PREFIX + stcd);
|
||||
}
|
||||
}
|
||||
log.info("本次更新水温缓存{}条", count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wtvtPointData(JobBaseAo ao) {
|
||||
if (ao == null) {
|
||||
throw new RuntimeException("任务参数不能为空");
|
||||
}
|
||||
ao.initTime();
|
||||
Date startTime = ao.getStartTime();
|
||||
Date endTime = ao.getEndTime();
|
||||
Set<String> stcds = ao.getStcds();
|
||||
|
||||
List<Map<String, Date>> dateList = getInterValDate(startTime, endTime);
|
||||
Map<String, List<WtvtPointDataVo>> lastDataMap = new LinkedHashMap<>();
|
||||
for (int index = dateList.size() - 1; index >= 0; index--) {
|
||||
Map<String, Date> dateMap = dateList.get(index);
|
||||
Date segmentStartTime = dateMap.get("startTime");
|
||||
Date segmentEndTime = dateMap.get("endTime");
|
||||
List<WtvtPointDataVo> wtvtLastDataList = getWtvtPointLastData(stcds, segmentStartTime, segmentEndTime);
|
||||
if (CollUtil.isEmpty(wtvtLastDataList)) {
|
||||
continue;
|
||||
}
|
||||
Map<String, List<WtvtPointDataVo>> groupedMap = new LinkedHashMap<>();
|
||||
for (WtvtPointDataVo wtvtPointDataVo : wtvtLastDataList) {
|
||||
if (wtvtPointDataVo == null || wtvtPointDataVo.getStcd() == null) {
|
||||
continue;
|
||||
}
|
||||
groupedMap.computeIfAbsent(wtvtPointDataVo.getStcd(), key -> new ArrayList<>()).add(wtvtPointDataVo);
|
||||
}
|
||||
for (Map.Entry<String, List<WtvtPointDataVo>> entry : groupedMap.entrySet()) {
|
||||
if (!lastDataMap.containsKey(entry.getKey())) {
|
||||
lastDataMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (Map.Entry<String, List<WtvtPointDataVo>> entry : lastDataMap.entrySet()) {
|
||||
String stcd = entry.getKey();
|
||||
WtvtPointVo wtvtPointVo = buildWtvtPointVo(stcd, entry.getValue());
|
||||
WtvtPointVo redisData = redisCacheUtil.fromJson(redisCacheUtil.getString(WTVT_POINT_DATA_KEY_PREFIX + stcd), WtvtPointVo.class);
|
||||
if (shouldRefresh(redisData, wtvtPointVo)) {
|
||||
redisCacheUtil.setString(WTVT_POINT_DATA_KEY_PREFIX + wtvtPointVo.getStcd(), JSONUtil.toJsonStr(wtvtPointVo));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
log.info("本次更新垂向水温缓存{}条", count);
|
||||
}
|
||||
|
||||
private boolean shouldRefresh(WtLastDataVo redisData, WtLastDataVo currentData) {
|
||||
if (currentData == null || currentData.getTm() == null) {
|
||||
return false;
|
||||
}
|
||||
return redisData == null || redisData.getTm() == null || DateUtil.compare(redisData.getTm(), currentData.getTm()) < 0;
|
||||
}
|
||||
|
||||
private boolean shouldRefresh(WtvtPointVo redisData, WtvtPointVo currentData) {
|
||||
if (currentData == null || currentData.getTm() == null) {
|
||||
return false;
|
||||
}
|
||||
return redisData == null || redisData.getTm() == null || DateUtil.compare(redisData.getTm(), currentData.getTm()) < 0;
|
||||
}
|
||||
|
||||
private List<WtLastDataVo> getWtLastData(Set<String> stcds, Date startTime, Date endTime) {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("startTime", startTime);
|
||||
paramMap.put("endTime", endTime);
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
.append(" data.ID AS id, ")
|
||||
.append(" data.STCD AS stcd, ")
|
||||
.append(" data.TM AS tm, ")
|
||||
.append(" data.WT AS wt, ")
|
||||
.append(" data.REMARK AS remark, ")
|
||||
.append(" data.FID AS fid, ")
|
||||
.append(" data.RECORD_USER AS recordUser, ")
|
||||
.append(" data.RECORD_TIME AS recordTime, ")
|
||||
.append(" data.MODIFY_USER AS modifyUser, ")
|
||||
.append(" data.MODIFY_TIME AS modifyTime, ")
|
||||
.append(" data.IS_DELETED AS isDeleted, ")
|
||||
.append(" data.DELETE_USER AS deleteUser, ")
|
||||
.append(" data.DELETE_TIME AS deleteTime ")
|
||||
.append("FROM ( ")
|
||||
.append(" SELECT t.*, ROW_NUMBER() OVER (PARTITION BY t.STCD ORDER BY t.TM DESC, t.RECORD_TIME DESC, t.ID DESC) AS rn ")
|
||||
.append(" FROM SD_WTRV_R t ")
|
||||
.append(" WHERE NVL(t.IS_DELETED, 0) = 0 ")
|
||||
.append(" AND t.TM >= #{map.startTime} ")
|
||||
.append(" AND t.TM <= #{map.endTime} ");
|
||||
appendInCondition(sql, paramMap, "t.STCD", stcds, "wtLastDataStcd");
|
||||
sql.append(") data WHERE data.rn = 1");
|
||||
return microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, WtLastDataVo.class);
|
||||
}
|
||||
|
||||
private List<WtvtPointDataVo> getWtvtPointLastData(Set<String> stcds, Date startTime, Date endTime) {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
paramMap.put("startTime", startTime);
|
||||
paramMap.put("endTime", endTime);
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("WITH temp AS ( ")
|
||||
.append(" SELECT STCD, VWT, TM, WTHG ")
|
||||
.append(" FROM ( ")
|
||||
.append(" SELECT STCD, VWT, TM, WTHG, DENSE_RANK() OVER (PARTITION BY STCD ORDER BY TM DESC) AS rn ")
|
||||
.append(" FROM SD_WTVT_R ")
|
||||
.append(" WHERE NVL(IS_DELETED, 0) = 0 ")
|
||||
.append(" AND TM >= #{map.startTime} ")
|
||||
.append(" AND TM <= #{map.endTime} ");
|
||||
appendInCondition(sql, paramMap, "STCD", stcds, "wtvtPointDataStcd");
|
||||
sql.append(" ) ")
|
||||
.append(" WHERE rn = 1 ")
|
||||
.append(") ")
|
||||
.append("SELECT ")
|
||||
.append(" t1.STCD AS stcd, ")
|
||||
.append(" t2.TM AS tm, ")
|
||||
.append(" t1.AVGWT AS avgwt, ")
|
||||
.append(" t2.VWT AS vwt, ")
|
||||
.append(" t2.WTHG AS wthg, ")
|
||||
.append(" t2.MINRN AS minrn, ")
|
||||
.append(" t2.MAXRN AS maxrn ")
|
||||
.append("FROM ( ")
|
||||
.append(" SELECT STCD, ROUND(AVG(VWT), 2) AS AVGWT ")
|
||||
.append(" FROM temp GROUP BY STCD ")
|
||||
.append(") t1 ")
|
||||
.append("INNER JOIN ( ")
|
||||
.append(" SELECT * FROM ( ")
|
||||
.append(" SELECT ")
|
||||
.append(" STCD, VWT, TM, WTHG, ")
|
||||
.append(" ROW_NUMBER() OVER (PARTITION BY STCD ORDER BY WTHG ASC) AS minrn, ")
|
||||
.append(" ROW_NUMBER() OVER (PARTITION BY STCD ORDER BY WTHG DESC) AS maxrn ")
|
||||
.append(" FROM temp ")
|
||||
.append(" ) WHERE MINRN = 1 OR MAXRN = 1 ")
|
||||
.append(") t2 ON t1.STCD = t2.STCD");
|
||||
return microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, WtvtPointDataVo.class);
|
||||
}
|
||||
|
||||
private WtvtPointVo buildWtvtPointVo(String stcd, List<WtvtPointDataVo> wtvtPointDataVoList) {
|
||||
WtvtPointVo wtvtPointVo = new WtvtPointVo();
|
||||
wtvtPointVo.setStcd(stcd);
|
||||
if (CollUtil.isEmpty(wtvtPointDataVoList)) {
|
||||
return wtvtPointVo;
|
||||
}
|
||||
for (WtvtPointDataVo wtvtPointDataVo : wtvtPointDataVoList) {
|
||||
if (wtvtPointDataVo == null) {
|
||||
continue;
|
||||
}
|
||||
wtvtPointVo.setTm(wtvtPointDataVo.getTm());
|
||||
wtvtPointVo.setAvgWt(wtvtPointDataVo.getAvgwt());
|
||||
if (Integer.valueOf(1).equals(wtvtPointDataVo.getMinrn())) {
|
||||
wtvtPointVo.setMinWthg(wtvtPointDataVo.getWthg());
|
||||
wtvtPointVo.setMinWthgWt(wtvtPointDataVo.getVwt());
|
||||
}
|
||||
if (Integer.valueOf(1).equals(wtvtPointDataVo.getMaxrn())) {
|
||||
wtvtPointVo.setMaxWthg(wtvtPointDataVo.getWthg());
|
||||
wtvtPointVo.setMaxWthgWt(wtvtPointDataVo.getVwt());
|
||||
}
|
||||
}
|
||||
return wtvtPointVo;
|
||||
}
|
||||
|
||||
// 以指定时间间隔分隔开始时间和结束时间,保持旧平台 7 天分段口径
|
||||
private List<Map<String, Date>> getInterValDate(Date startTime, Date endTime) {
|
||||
int num = 7;
|
||||
List<Map<String, Date>> dateList = new ArrayList<>();
|
||||
long interval = DateUtil.betweenDay(startTime, endTime, false);
|
||||
if (interval <= num) {
|
||||
Map<String, Date> dateMap = new HashMap<>();
|
||||
dateMap.put("startTime", startTime);
|
||||
dateMap.put("endTime", endTime);
|
||||
dateList.add(dateMap);
|
||||
return dateList;
|
||||
}
|
||||
while (startTime.getTime() < endTime.getTime()) {
|
||||
Map<String, Date> dateMap = new HashMap<>();
|
||||
DateTime dateTime = DateUtil.offsetDay(startTime, num);
|
||||
dateMap.put("startTime", startTime);
|
||||
if (dateTime.getTime() < endTime.getTime()) {
|
||||
dateMap.put("endTime", DateUtil.offsetSecond(dateTime, -1));
|
||||
} else {
|
||||
dateMap.put("endTime", endTime);
|
||||
}
|
||||
dateList.add(dateMap);
|
||||
startTime = dateTime;
|
||||
}
|
||||
dateList.sort(Comparator.comparing(item -> item.get("startTime")));
|
||||
return dateList;
|
||||
}
|
||||
|
||||
private void appendInCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
String column,
|
||||
Set<String> values,
|
||||
String prefix) {
|
||||
if (CollUtil.isEmpty(values)) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
int index = 0;
|
||||
for (String value : values) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = prefix + index++;
|
||||
paramMap.put(key, value.trim());
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
if (CollUtil.isEmpty(placeholders)) {
|
||||
return;
|
||||
}
|
||||
sql.append(" AND ").append(column).append(" IN (")
|
||||
.append(String.join(", ", placeholders))
|
||||
.append(") ");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package com.yfd.platform.qgc_job.service.impl;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import com.yfd.platform.qgc_job.service.IEqJobService;
|
||||
import com.yfd.platform.qgc_job.vo.EqAnchorPointLastDateVo;
|
||||
import com.yfd.platform.utils.RedisCacheUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class EqJobServiceImpl implements IEqJobService {
|
||||
|
||||
@Resource
|
||||
private MicroservicDynamicSQLMapper<?> microservicDynamicSQLMapper;
|
||||
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
|
||||
@Override
|
||||
public void eqAnchorPointLastDate(JobBaseAo ao) {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
// 旧逻辑只按当前时间截取最新一条工程运行数据,ao 在此方法中不参与过滤
|
||||
paramMap.put("currentTime", new Date());
|
||||
|
||||
List<EqAnchorPointLastDateVo> eqDataVos = microservicDynamicSQLMapper.getAllListWithResultType(
|
||||
buildEqAnchorPointLastDateSql(),
|
||||
paramMap,
|
||||
EqAnchorPointLastDateVo.class
|
||||
);
|
||||
for (EqAnchorPointLastDateVo eqDataVo : eqDataVos) {
|
||||
redisCacheUtil.setString("eqAnchorPointLastDate:" + eqDataVo.getStcd(), JSONUtil.toJsonStr(eqDataVo));
|
||||
}
|
||||
}
|
||||
|
||||
private String buildEqAnchorPointLastDateSql() {
|
||||
return "SELECT " +
|
||||
"run.STCD AS stcd, " +
|
||||
"run.TM AS tm, " +
|
||||
"run.QI AS qi, " +
|
||||
"run.QO AS qo, " +
|
||||
"run.RZ AS rz, " +
|
||||
"run.DZ AS dz, " +
|
||||
"qec.QEC_LIMIT AS qecLimit, " +
|
||||
"qec.QEC_C AS qecC, " +
|
||||
"qec.MWR_LIMIT AS mwrLimit, " +
|
||||
"qec.MWR_C AS mwrC, " +
|
||||
"NVL(qec.AVQ_LIMIT, eng.AVQ) AS avqLimit, " +
|
||||
"qec.AVQ_C AS avqC, " +
|
||||
"qecDetail.VLSR AS vlsr, " +
|
||||
"qecDetail.VLSR_TM AS vlsrTm, " +
|
||||
"mwrDetail.VLSR AS mwrVlsr, " +
|
||||
"mwrDetail.VLSR_TM AS mwrVlsrTm " +
|
||||
"FROM ( " +
|
||||
" SELECT STCD, MAX(TM) AS TM " +
|
||||
" FROM SD_HYDROPW_R " +
|
||||
" WHERE NVL(IS_DELETED, 0) = 0 " +
|
||||
" AND TM <= #{map.currentTime} " +
|
||||
" GROUP BY STCD " +
|
||||
") lastRun " +
|
||||
"INNER JOIN SD_HYDROPW_R run " +
|
||||
" ON lastRun.STCD = run.STCD " +
|
||||
" AND lastRun.TM = run.TM " +
|
||||
" AND NVL(run.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN SD_QEC_R qec " +
|
||||
" ON qec.STCD = run.STCD " +
|
||||
" AND qec.TM = run.TM " +
|
||||
" AND NVL(qec.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN SD_ENGINFO_B_H eng " +
|
||||
" ON eng.STCD = run.STCD " +
|
||||
" AND NVL(eng.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN MS_WARN_RULE_DETAIL_B qecDetail " +
|
||||
" ON qecDetail.ID = qec.QEC_RULE_DID " +
|
||||
" AND NVL(qecDetail.IS_DELETED, 0) = 0 " +
|
||||
"LEFT JOIN MS_WARN_RULE_DETAIL_B mwrDetail " +
|
||||
" ON mwrDetail.ID = qec.QEC_MWRRULE_DID " +
|
||||
" AND NVL(mwrDetail.IS_DELETED, 0) = 0";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
package com.yfd.platform.qgc_job.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.qgc_env.wq.entity.ao.JobBaseAo;
|
||||
import com.yfd.platform.qgc_job.service.IFhJobService;
|
||||
import com.yfd.platform.qgc_job.vo.ZqLastDataVo;
|
||||
import com.yfd.platform.utils.RedisCacheUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class FhJobServiceImpl implements IFhJobService {
|
||||
|
||||
private static final String ZQ_LAST_DATA_KEY_PREFIX = "zqLastData:";
|
||||
|
||||
@Resource
|
||||
private MicroservicDynamicSQLMapper<?> microservicDynamicSQLMapper;
|
||||
|
||||
@Resource
|
||||
private RedisCacheUtil redisCacheUtil;
|
||||
|
||||
@Override
|
||||
public void zqLastData(JobBaseAo ao) {
|
||||
Set<String> stcds = ao == null ? null : ao.getStcds();
|
||||
List<ZqLastDataVo> zqDataVos = getZqLastData(stcds);
|
||||
if (CollUtil.isEmpty(zqDataVos)) {
|
||||
return;
|
||||
}
|
||||
for (ZqLastDataVo zqDataVo : zqDataVos) {
|
||||
if (zqDataVo == null || zqDataVo.getStcd() == null) {
|
||||
continue;
|
||||
}
|
||||
redisCacheUtil.setString(ZQ_LAST_DATA_KEY_PREFIX + zqDataVo.getStcd(), JSONUtil.toJsonStr(zqDataVo));
|
||||
}
|
||||
log.info("本次更新河道水情缓存{}条", zqDataVos.size());
|
||||
}
|
||||
|
||||
private List<ZqLastDataVo> getZqLastData(Set<String> stcds) {
|
||||
Map<String, Object> paramMap = new HashMap<>();
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT ")
|
||||
.append("t.STCD AS stcd, ")
|
||||
.append("t.Z AS z, ")
|
||||
.append("t.Q AS q, ")
|
||||
.append("t.V AS v, ")
|
||||
.append("t.TM AS tm ")
|
||||
.append("FROM SD_RIVER_R t ")
|
||||
.append("INNER JOIN ( ")
|
||||
.append(" SELECT STCD, MAX(TM) AS tm ")
|
||||
.append(" FROM SD_RIVER_R ")
|
||||
.append(" WHERE NVL(IS_DELETED, 0) = 0 ");
|
||||
appendInCondition(sql, paramMap, "STCD", stcds, "zqLastDataInnerStcd");
|
||||
sql.append(" GROUP BY STCD ")
|
||||
.append(") t1 ON t.STCD = t1.STCD AND t.TM = t1.tm ")
|
||||
.append("WHERE NVL(t.IS_DELETED, 0) = 0 ");
|
||||
appendInCondition(sql, paramMap, "t.STCD", stcds, "zqLastDataOuterStcd");
|
||||
return microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, ZqLastDataVo.class);
|
||||
}
|
||||
|
||||
private void appendInCondition(StringBuilder sql,
|
||||
Map<String, Object> paramMap,
|
||||
String column,
|
||||
Set<String> values,
|
||||
String prefix) {
|
||||
if (CollUtil.isEmpty(values)) {
|
||||
return;
|
||||
}
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
int index = 0;
|
||||
for (String value : values) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = prefix + index++;
|
||||
paramMap.put(key, value.trim());
|
||||
placeholders.add("#{map." + key + "}");
|
||||
}
|
||||
if (CollUtil.isEmpty(placeholders)) {
|
||||
return;
|
||||
}
|
||||
sql.append(" AND ").append(column).append(" IN (")
|
||||
.append(String.join(", ", placeholders))
|
||||
.append(") ");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package com.yfd.platform.qgc_job.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Schema(description = "电站锚点最新缓存数据")
|
||||
public class EqAnchorPointLastDateVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "电站编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "电站名称")
|
||||
private String stnm;
|
||||
|
||||
@Schema(description = "数据时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date tm;
|
||||
|
||||
@Schema(description = "装机容量")
|
||||
private BigDecimal ttpwr;
|
||||
|
||||
@Schema(description = "生态流量限值(环保部)")
|
||||
private BigDecimal qecLimit;
|
||||
|
||||
@Schema(description = "生态流量限值(水利部)")
|
||||
private BigDecimal mwrLimit;
|
||||
|
||||
@Schema(description = "生态流量限值(多年平均)")
|
||||
private BigDecimal avqLimit;
|
||||
|
||||
@Schema(description = "生态流量系数(环保部)")
|
||||
private BigDecimal qecC;
|
||||
|
||||
@Schema(description = "生态流量系数(水利部)")
|
||||
private BigDecimal mwrC;
|
||||
|
||||
@Schema(description = "生态流量系数(多年平均)")
|
||||
private BigDecimal avqC;
|
||||
|
||||
@Schema(description = "正常蓄水位")
|
||||
private BigDecimal normz;
|
||||
|
||||
@Schema(description = "死水位")
|
||||
private BigDecimal ddz;
|
||||
|
||||
@Schema(description = "入库流量")
|
||||
private BigDecimal qi;
|
||||
|
||||
@Schema(description = "出库流量")
|
||||
private BigDecimal qo;
|
||||
|
||||
@Schema(description = "坝上水位")
|
||||
private BigDecimal rz;
|
||||
|
||||
@Schema(description = "坝下水位")
|
||||
private BigDecimal dz;
|
||||
|
||||
@Schema(description = "规则来源")
|
||||
private String vlsr;
|
||||
|
||||
@Schema(description = "规则来源时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date vlsrTm;
|
||||
|
||||
@Schema(description = "规则来源(水利部)")
|
||||
private String mwrVlsr;
|
||||
|
||||
@Schema(description = "规则来源时间(水利部)")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date mwrVlsrTm;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.yfd.platform.qgc_job.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Schema(description = "水温最新缓存数据")
|
||||
public class WtLastDataVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "主键ID")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "站点编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "数据时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date tm;
|
||||
|
||||
@Schema(description = "水温")
|
||||
private BigDecimal wt;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "附件ID")
|
||||
private String fid;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String recordUser;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date recordTime;
|
||||
|
||||
@Schema(description = "更新人")
|
||||
private String modifyUser;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date modifyTime;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
private Integer isDeleted;
|
||||
|
||||
@Schema(description = "删除人")
|
||||
private String deleteUser;
|
||||
|
||||
@Schema(description = "删除时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.yfd.platform.qgc_job.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;
|
||||
|
||||
@Data
|
||||
@Schema(description = "垂向水温锚点中间数据")
|
||||
public class WtvtPointDataVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "站点编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "数据时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date tm;
|
||||
|
||||
@Schema(description = "平均水温")
|
||||
private Double avgwt;
|
||||
|
||||
@Schema(description = "水温")
|
||||
private Double vwt;
|
||||
|
||||
@Schema(description = "测量深度")
|
||||
private Double wthg;
|
||||
|
||||
@Schema(description = "最小深度行号")
|
||||
private Integer minrn;
|
||||
|
||||
@Schema(description = "最大深度行号")
|
||||
private Integer maxrn;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.yfd.platform.qgc_job.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;
|
||||
|
||||
@Data
|
||||
@Schema(description = "垂向水温锚点缓存数据")
|
||||
public class WtvtPointVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "站点编码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "数据时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date tm;
|
||||
|
||||
@Schema(description = "平均温度")
|
||||
private Double avgWt;
|
||||
|
||||
@Schema(description = "最大测量深度")
|
||||
private Double maxWthg;
|
||||
|
||||
@Schema(description = "最大测量深度水温")
|
||||
private Double maxWthgWt;
|
||||
|
||||
@Schema(description = "最小测量深度")
|
||||
private Double minWthg;
|
||||
|
||||
@Schema(description = "最小测量深度水温")
|
||||
private Double minWthgWt;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.yfd.platform.qgc_job.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Schema(description = "河道水情最新缓存")
|
||||
public class ZqLastDataVo {
|
||||
|
||||
@Schema(description = "站码")
|
||||
private String stcd;
|
||||
|
||||
@Schema(description = "水位")
|
||||
private BigDecimal z;
|
||||
|
||||
@Schema(description = "流量")
|
||||
private BigDecimal q;
|
||||
|
||||
@Schema(description = "流速")
|
||||
private BigDecimal v;
|
||||
|
||||
@Schema(description = "时间")
|
||||
private Date tm;
|
||||
}
|
||||
@ -41,6 +41,34 @@ public interface MsMapmoduleBMapper extends BaseMapper<MsMapmoduleB> {
|
||||
List<MapLayerVo> getMapLayerTree(@Param("moduleId") String moduleId, @Param("sid") String sid,
|
||||
@Param("templateId") String templateId);
|
||||
|
||||
/**
|
||||
* 按模块ID集合查询地图图层树(用于非管理员按用户菜单权限取图层)
|
||||
*/
|
||||
@Select("<script>"
|
||||
+ "SELECT DISTINCT BML.ID,BML.ANCHOR_PARAM_JSON, BML.PARENT_ID AS parentId, BML.TITLE, BML.CODE, BML.LABEL_LEVEL AS labelLevel, "
|
||||
+ "BML.CHECKABLE, BML.TYPE, BML.Z_INDEX AS zIndex, BML.STTP_TYPE AS sttpType, BML.LAYERS, "
|
||||
+ "BML.PARAMJSON AS paramJson, BML.URL, BML.URL_THD AS urlThd, BML.OPACITY, BML.SYSTEM_ID AS systemId, "
|
||||
+ "BML.OPTIONS, BMM.MULTI_SELECT AS multiSelect, BMM.CAN_BE_CHECKED AS canBeChecked, "
|
||||
+ "CASE WHEN BMM.CHECKED IS NULL THEN 0 ELSE BMM.CHECKED END AS checked, BML.ORDER_INDEX "
|
||||
+ "FROM MS_MAPLAYER_B BML INNER JOIN MS_MAPMODULE_B BMM ON BML.ID = BMM.RES_ID "
|
||||
+ "WHERE BMM.IS_DELETED = 0 AND BMM.RES_TYPE = 'layer' "
|
||||
+ "<if test=\"moduleIds != null and moduleIds.size() > 0\">"
|
||||
+ " AND BMM.MODULE_ID IN "
|
||||
+ "<foreach collection=\"moduleIds\" item=\"moduleId\" open=\"(\" separator=\",\" close=\")\">"
|
||||
+ "#{moduleId}"
|
||||
+ "</foreach>"
|
||||
+ "</if>"
|
||||
+ "<if test=\"sid != null and sid != ''\"> AND BMM.SYSTEM_ID = #{sid}</if>"
|
||||
+ "<choose>"
|
||||
+ "<when test=\"templateId != null and templateId != ''\"> AND BMM.TEMPLATE_ID = #{templateId}</when>"
|
||||
+ "<otherwise> AND (BMM.TEMPLATE_ID IS NULL OR BMM.TEMPLATE_ID = '00000000-0000-0000-0000-000000000000')</otherwise>"
|
||||
+ "</choose>"
|
||||
+ " AND BML.ENABLE = 1 AND BML.IS_DELETED = 0 AND (BML.TYPE NOT IN ('YXDT','DXDT','SLDT') OR BML.TYPE IS NULL) "
|
||||
+ "ORDER BY BML.ORDER_INDEX"
|
||||
+ "</script>")
|
||||
List<MapLayerVo> getMapLayerTreeByModuleIds(@Param("moduleIds") List<String> moduleIds, @Param("sid") String sid,
|
||||
@Param("templateId") String templateId);
|
||||
|
||||
/**
|
||||
* 查询地图工具箱(关联MS_MAPMODULE_B与MS_MAPTOOLBOX_B)
|
||||
*/
|
||||
@ -132,4 +160,4 @@ public interface MsMapmoduleBMapper extends BaseMapper<MsMapmoduleB> {
|
||||
")\n" +
|
||||
"AND IS_DELETED = 0")
|
||||
MsMapmoduleB selectLayerById(@Param("id") String id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,18 +2,23 @@ package com.yfd.platform.qgc_sys.mapLayer.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.domain.MsMapmoduleB;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.domain.MsMaplayerB;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.entity.vo.MapLayerAo;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.entity.vo.MapLayerVo;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.mapper.MsMaplayerBMapper;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.mapper.MsMapmoduleBMapper;
|
||||
import com.yfd.platform.qgc_sys.mapLayer.service.IMapLayerBizService;
|
||||
import com.yfd.platform.system.domain.SysMenu;
|
||||
import com.yfd.platform.system.domain.SysDictionary;
|
||||
import com.yfd.platform.system.domain.SysDictionaryItems;
|
||||
import com.yfd.platform.system.domain.SysUser;
|
||||
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
|
||||
import com.yfd.platform.system.mapper.SysDictionaryMapper;
|
||||
import com.yfd.platform.system.mapper.SysMenuMapper;
|
||||
import com.yfd.platform.system.mapper.SysUserMapper;
|
||||
import com.yfd.platform.system.service.IAdminAuthService;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -43,6 +48,12 @@ public class MapLayerBizServiceImpl implements IMapLayerBizService {
|
||||
@Resource
|
||||
private MsMapmoduleBMapper msMapmoduleBMapper;
|
||||
|
||||
@Resource
|
||||
private SysMenuMapper sysMenuMapper;
|
||||
|
||||
@Resource
|
||||
private IAdminAuthService adminAuthService;
|
||||
|
||||
@Override
|
||||
public List<MsMaplayerB> getMapLayerTree(MapLayerAo flag) {
|
||||
// 1. 查询字典 "DTZJLX" 获取需要排除的图层类型
|
||||
@ -173,12 +184,27 @@ public class MapLayerBizServiceImpl implements IMapLayerBizService {
|
||||
|
||||
@Override
|
||||
public List<MapLayerVo> getMapLayerTree(String moduleId, String systemId, String templateId) {
|
||||
// 通过 JOIN 查询 MS_MAPLAYER_B 和 MS_MAPMODULE_B
|
||||
List<MapLayerVo> allLayers = msMapmoduleBMapper.getMapLayerTree(moduleId, systemId, templateId);
|
||||
|
||||
if (allLayers == null || allLayers.isEmpty()) {
|
||||
List<MapLayerVo> allLayers;
|
||||
boolean currentManagedAdmin = adminAuthService.isCurrentManagedAdmin();
|
||||
if (currentManagedAdmin) {
|
||||
allLayers = msMapmoduleBMapper.getMapLayerTree(moduleId, systemId, templateId);
|
||||
} else {
|
||||
List<String> currentUserModuleIds = getCurrentUserModuleIds();
|
||||
if (currentUserModuleIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
allLayers = msMapmoduleBMapper.getMapLayerTreeByModuleIds(currentUserModuleIds, systemId, templateId);
|
||||
allLayers = supplementMissingParentLayers(allLayers);
|
||||
allLayers = deduplicateMapLayers(allLayers);
|
||||
}
|
||||
if (allLayers.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if (!currentManagedAdmin) {
|
||||
Set<String> checkedLayerIds = getCurrentModuleCheckedLayerIds(moduleId, systemId, templateId);
|
||||
resetCheckedStatus(allLayers, checkedLayerIds);
|
||||
}
|
||||
allLayers = sortMapLayerVos(allLayers);
|
||||
|
||||
// 取第一级
|
||||
List<MapLayerVo> parents = allLayers.stream()
|
||||
@ -211,4 +237,177 @@ public class MapLayerBizServiceImpl implements IMapLayerBizService {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getCurrentUserModuleIds() {
|
||||
String userId = SecurityUtils.getUserId();
|
||||
if (StrUtil.isBlank(userId)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<SysMenu> userMenus = sysMenuMapper.selectMenuByUserId(userId, null);
|
||||
if (userMenus == null || userMenus.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return userMenus.stream()
|
||||
.map(SysMenu::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<MapLayerVo> supplementMissingParentLayers(List<MapLayerVo> layers) {
|
||||
if (layers == null || layers.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<MapLayerVo> result = new ArrayList<>(layers);
|
||||
Set<String> existingIds = result.stream()
|
||||
.map(MapLayerVo::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
Set<String> pendingParentIds = result.stream()
|
||||
.map(MapLayerVo::getParentId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.filter(parentId -> !existingIds.contains(parentId))
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
while (!pendingParentIds.isEmpty()) {
|
||||
LambdaQueryWrapper<MsMaplayerB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(MsMaplayerB::getId, pendingParentIds)
|
||||
.eq(MsMaplayerB::getIsDeleted, 0)
|
||||
.eq(MsMaplayerB::getEnable, 1)
|
||||
.and(w -> w.notIn(MsMaplayerB::getType, "YXDT", "DXDT", "SLDT").or().isNull(MsMaplayerB::getType))
|
||||
.orderByAsc(MsMaplayerB::getOrderIndex);
|
||||
List<MsMaplayerB> parentLayers = msMaplayerBMapper.selectList(wrapper);
|
||||
if (parentLayers == null || parentLayers.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Set<String> nextParentIds = new LinkedHashSet<>();
|
||||
for (MsMaplayerB parentLayer : parentLayers) {
|
||||
if (parentLayer == null || StrUtil.isBlank(parentLayer.getId()) || existingIds.contains(parentLayer.getId())) {
|
||||
continue;
|
||||
}
|
||||
result.add(toMapLayerVo(parentLayer));
|
||||
existingIds.add(parentLayer.getId());
|
||||
if (StrUtil.isNotBlank(parentLayer.getParentId()) && !existingIds.contains(parentLayer.getParentId())) {
|
||||
nextParentIds.add(parentLayer.getParentId());
|
||||
}
|
||||
}
|
||||
pendingParentIds = nextParentIds;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<MapLayerVo> sortMapLayerVos(List<MapLayerVo> layers) {
|
||||
return layers.stream()
|
||||
.sorted(Comparator
|
||||
.comparingInt((MapLayerVo item) -> parseOrderIndex(item.getOrderIndex()))
|
||||
.thenComparing(item -> StrUtil.nullToDefault(item.getId(), "")))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private int parseOrderIndex(String orderIndex) {
|
||||
if (StrUtil.isBlank(orderIndex)) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(orderIndex);
|
||||
} catch (NumberFormatException ex) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
private MapLayerVo toMapLayerVo(MsMaplayerB layer) {
|
||||
MapLayerVo vo = new MapLayerVo();
|
||||
vo.setId(layer.getId());
|
||||
vo.setParentId(layer.getParentId());
|
||||
vo.setTitle(layer.getTitle());
|
||||
vo.setCode(layer.getCode());
|
||||
vo.setLabelLevel(layer.getLabelLevel());
|
||||
vo.setCheckable(layer.getCheckable());
|
||||
vo.setType(layer.getType());
|
||||
vo.setZIndex(layer.getZIndex());
|
||||
vo.setSttpType(layer.getSttpType());
|
||||
vo.setLayers(layer.getLayers());
|
||||
vo.setUrl(layer.getUrl());
|
||||
vo.setUrlThd(layer.getUrlThd());
|
||||
vo.setOpacity(layer.getOpacity());
|
||||
vo.setParamJson(layer.getParamJson());
|
||||
vo.setAnchorParamJson(layer.getAnchorParamJson());
|
||||
vo.setOptions(layer.getOptions());
|
||||
vo.setOrderIndex(layer.getOrderIndex() == null ? null : String.valueOf(layer.getOrderIndex()));
|
||||
vo.setChecked(0);
|
||||
vo.setCanBeChecked(0);
|
||||
vo.setMultiSelect(1);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private List<MapLayerVo> deduplicateMapLayers(List<MapLayerVo> layers) {
|
||||
Map<String, MapLayerVo> uniqueMap = new LinkedHashMap<>();
|
||||
for (MapLayerVo layer : layers) {
|
||||
if (layer == null || StrUtil.isBlank(layer.getId())) {
|
||||
continue;
|
||||
}
|
||||
uniqueMap.putIfAbsent(layer.getId(), layer);
|
||||
}
|
||||
return new ArrayList<>(uniqueMap.values());
|
||||
}
|
||||
|
||||
private Set<String> getCurrentModuleCheckedLayerIds(String moduleId, String systemId, String templateId) {
|
||||
if (StrUtil.isBlank(moduleId)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
LambdaQueryWrapper<MsMapmoduleB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(MsMapmoduleB::getModuleId, moduleId)
|
||||
.eq(MsMapmoduleB::getResType, "layer")
|
||||
.eq(MsMapmoduleB::getIsDeleted, 0)
|
||||
.select(MsMapmoduleB::getResId);
|
||||
if (StrUtil.isNotBlank(systemId)) {
|
||||
wrapper.eq(MsMapmoduleB::getSystemId, systemId);
|
||||
}
|
||||
if (StrUtil.isNotBlank(templateId)) {
|
||||
wrapper.eq(MsMapmoduleB::getTemplateId, templateId);
|
||||
} else {
|
||||
wrapper.and(w -> w.isNull(MsMapmoduleB::getTemplateId)
|
||||
.or()
|
||||
.eq(MsMapmoduleB::getTemplateId, "00000000-0000-0000-0000-000000000000"));
|
||||
}
|
||||
List<MsMapmoduleB> moduleLayers = msMapmoduleBMapper.selectList(wrapper);
|
||||
if (moduleLayers == null || moduleLayers.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> checkedIds = moduleLayers.stream()
|
||||
.map(MsMapmoduleB::getResId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
if (checkedIds.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<String> pendingParentIds = new LinkedHashSet<>(checkedIds);
|
||||
while (!pendingParentIds.isEmpty()) {
|
||||
LambdaQueryWrapper<MsMaplayerB> wrapperParent = new LambdaQueryWrapper<>();
|
||||
wrapperParent.in(MsMaplayerB::getId, pendingParentIds)
|
||||
.eq(MsMaplayerB::getIsDeleted, 0)
|
||||
.select(MsMaplayerB::getId, MsMaplayerB::getParentId);
|
||||
List<MsMaplayerB> currentLayers = msMaplayerBMapper.selectList(wrapperParent);
|
||||
if (currentLayers == null || currentLayers.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Set<String> nextParentIds = new LinkedHashSet<>();
|
||||
for (MsMaplayerB currentLayer : currentLayers) {
|
||||
if (StrUtil.isNotBlank(currentLayer.getParentId()) && checkedIds.add(currentLayer.getParentId())) {
|
||||
nextParentIds.add(currentLayer.getParentId());
|
||||
}
|
||||
}
|
||||
pendingParentIds = nextParentIds;
|
||||
}
|
||||
return checkedIds;
|
||||
}
|
||||
|
||||
private void resetCheckedStatus(List<MapLayerVo> layers, Set<String> checkedLayerIds) {
|
||||
if (layers == null || layers.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Set<String> normalizedCheckedIds = checkedLayerIds == null ? Collections.emptySet() : checkedLayerIds;
|
||||
for (MapLayerVo layer : layers) {
|
||||
layer.setChecked(normalizedCheckedIds.contains(layer.getId()) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,9 +19,12 @@ import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -134,7 +137,8 @@ public class MapmoduleBServiceImpl extends ServiceImpl<MsMapmoduleBMapper, MsMap
|
||||
|
||||
// 1. GIS图层区
|
||||
List<MapLayerVo> layer = mapLayerBizService.getMapLayerTree(
|
||||
mapmoduleB.getModuleId(), mapmoduleB.getSystemId(), templateId);
|
||||
mapmoduleB.getModuleId(), mapmoduleB.getSystemId(), templateId);;
|
||||
|
||||
mapmoduleVo.setMapLayerVos(layer);
|
||||
|
||||
// 2. 地图图例
|
||||
@ -182,4 +186,23 @@ public class MapmoduleBServiceImpl extends ServiceImpl<MsMapmoduleBMapper, MsMap
|
||||
}
|
||||
return msMaptoolboxBList;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasCurrentUserModulePermission(String moduleId) {
|
||||
if (StrUtil.isBlank(moduleId) || StrUtil.equalsIgnoreCase(moduleId, "common")) {
|
||||
return true;
|
||||
}
|
||||
String userId = SecurityUtils.getUserId();
|
||||
if (StrUtil.isBlank(userId)) {
|
||||
return false;
|
||||
}
|
||||
List<SysMenu> userMenus = sysMenuMapper.selectMenuByUserId(userId, null);
|
||||
if (userMenus == null || userMenus.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Set<String> menuIds = userMenus.stream()
|
||||
.map(SysMenu::getId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
return menuIds.contains(moduleId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,124 @@
|
||||
package com.yfd.platform.system.controller;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.yfd.platform.annotation.Log;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetRequest;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
import com.yfd.platform.system.service.IPushConfigService;
|
||||
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.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 java.util.Date;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/system/pushConfig")
|
||||
@Tag(name = "推送配置")
|
||||
public class PushConfigController {
|
||||
|
||||
@Resource
|
||||
private IPushConfigService pushConfigService;
|
||||
|
||||
@Operation(summary = "查询推送配置列表")
|
||||
@GetMapping("/getPushConfigList")
|
||||
public ResponseResult getPushConfigList(Page<PushConfig> page,
|
||||
String categoryName,
|
||||
String messageType,
|
||||
Integer targetType,
|
||||
Integer status) {
|
||||
return ResponseResult.successData(pushConfigService.getPushConfigPage(page, categoryName, messageType, targetType, status));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据ID查询推送配置")
|
||||
@GetMapping("/getPushConfigById")
|
||||
public ResponseResult getPushConfigById(@RequestParam String id) {
|
||||
return ResponseResult.successData(pushConfigService.getById(id));
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "新增推送配置")
|
||||
@Operation(summary = "新增推送配置")
|
||||
@PostMapping("/addPushConfig")
|
||||
public ResponseResult addPushConfig(@RequestBody PushConfig pushConfig) {
|
||||
return pushConfigService.addPushConfig(pushConfig) ? ResponseResult.success() : ResponseResult.error("新增失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "修改推送配置")
|
||||
@Operation(summary = "修改推送配置")
|
||||
@PostMapping("/updatePushConfig")
|
||||
public ResponseResult updatePushConfig(@RequestBody PushConfig pushConfig) {
|
||||
return pushConfigService.updatePushConfig(pushConfig) ? ResponseResult.success() : ResponseResult.error("修改失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "删除推送配置")
|
||||
@Operation(summary = "删除推送配置")
|
||||
@PostMapping("/deletePushConfig")
|
||||
public ResponseResult deletePushConfig(@RequestParam String ids) {
|
||||
return pushConfigService.deletePushConfig(ids) ? ResponseResult.success() : ResponseResult.error("删除失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "设置推送配置状态")
|
||||
@Operation(summary = "设置推送配置状态")
|
||||
@PostMapping("/setPushConfigStatus")
|
||||
public ResponseResult setPushConfigStatus(@RequestParam String id, @RequestParam Integer status) {
|
||||
return pushConfigService.setPushConfigStatus(id, status) ? ResponseResult.success() : ResponseResult.error("设置失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "设置短信推送开关")
|
||||
@Operation(summary = "设置短信推送开关")
|
||||
@PostMapping("/setPushConfigSmsSwitch")
|
||||
public ResponseResult setPushConfigSmsSwitch(@RequestParam String id, @RequestParam Integer isSms) {
|
||||
return pushConfigService.setPushConfigSmsSwitch(id, isSms) ? ResponseResult.success() : ResponseResult.error("设置失败");
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "保存推送目标")
|
||||
@Operation(summary = "保存推送目标")
|
||||
@PostMapping("/savePushTargets")
|
||||
public ResponseResult savePushTargets(@RequestBody PushConfigTargetRequest request) {
|
||||
return pushConfigService.savePushTargets(request) ? ResponseResult.success() : ResponseResult.error("保存失败");
|
||||
}
|
||||
|
||||
@Operation(summary = "查询推送目标")
|
||||
@GetMapping("/getPushTargets")
|
||||
public ResponseResult getPushTargets(@RequestParam String configId) {
|
||||
return ResponseResult.successData(pushConfigService.getPushTargets(configId));
|
||||
}
|
||||
|
||||
@Log(module = "推送配置", value = "立即执行推送配置")
|
||||
@Operation(summary = "立即执行推送配置")
|
||||
@PostMapping("/execution")
|
||||
public ResponseResult execution(@RequestParam String configId) {
|
||||
return pushConfigService.executeNow(configId) ? ResponseResult.success() : ResponseResult.error("执行失败");
|
||||
}
|
||||
|
||||
@Operation(summary = "查询推送历史主表")
|
||||
@GetMapping("/getPushHistoryList")
|
||||
public ResponseResult getPushHistoryList(Page<PushHistory> page,
|
||||
String configId,
|
||||
Integer status,
|
||||
String messageTypeCode,
|
||||
String startTime,
|
||||
String endTime) {
|
||||
Date start = StrUtil.isBlank(startTime) ? null : DateUtil.parse(startTime);
|
||||
Date end = StrUtil.isBlank(endTime) ? null : DateUtil.parse(endTime);
|
||||
return ResponseResult.successData(pushConfigService.getPushHistoryPage(page, configId, status, messageTypeCode, start, end));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询推送历史明细")
|
||||
@GetMapping("/getPushHistoryDetailList")
|
||||
public ResponseResult getPushHistoryDetailList(Page<PushHistoryDetail> page,
|
||||
String historyId,
|
||||
Integer status) {
|
||||
return ResponseResult.successData(pushConfigService.getPushHistoryDetailPage(page, historyId, status));
|
||||
}
|
||||
}
|
||||
@ -78,7 +78,7 @@ public class SmsVerifyCodeController {
|
||||
*/
|
||||
@PostMapping("/sendCode")
|
||||
@Operation(summary = "发送验证码")
|
||||
public ResponseResult sendVerifyCode(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult sendVerifyCode(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
String phone = smsVerifyCodeRequest.getPhone();
|
||||
Integer type = smsVerifyCodeRequest.getType();
|
||||
|
||||
@ -91,21 +91,21 @@ public class SmsVerifyCodeController {
|
||||
|
||||
// 1. 注册验证码校验
|
||||
if (type.equals(SmsVerifyCode.TYPE_REGISTER)) {
|
||||
SysUser existUser = userService.getUserByPhone(phone);
|
||||
SysUser existUser = userService.getUserByPhone(phone,tenantId);
|
||||
if (existUser != null) {
|
||||
return ResponseResult.error("该手机号已注册");
|
||||
}
|
||||
}
|
||||
// 2. 找回密码验证码校验
|
||||
else if (type.equals(SmsVerifyCode.TYPE_FIND_PASSWORD)) {
|
||||
SysUser existUser = userService.getUserByPhone(phone);
|
||||
SysUser existUser = userService.getUserByPhone(phone,tenantId);
|
||||
if (existUser == null) {
|
||||
return ResponseResult.error("该手机号未注册");
|
||||
}
|
||||
}
|
||||
// 3. 登录验证码校验(新增)
|
||||
else if (type.equals(SmsVerifyCode.TYPE_LOGIN)) {
|
||||
SysUser existUser = userService.getUserByPhone(phone);
|
||||
SysUser existUser = userService.getUserByPhone(phone,tenantId);
|
||||
if (existUser == null) {
|
||||
return ResponseResult.error("该手机号未注册,请先注册");
|
||||
}
|
||||
@ -118,7 +118,7 @@ public class SmsVerifyCodeController {
|
||||
return ResponseResult.error("类型错误:1-注册 2-找回密码 3-登录");
|
||||
}
|
||||
|
||||
String code = smsVerifyCodeService.sendVerifyCode(phone, type);
|
||||
String code = smsVerifyCodeService.sendVerifyCode(phone, type,tenantId);
|
||||
if (code == null) {
|
||||
return ResponseResult.error("验证码发送失败,请稍后重试");
|
||||
}
|
||||
@ -132,7 +132,7 @@ public class SmsVerifyCodeController {
|
||||
*/
|
||||
@PostMapping("/batchSendContent")
|
||||
@Operation(summary = "批量发送短信")
|
||||
public ResponseResult batchSendContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult batchSendContent(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
|
||||
List<String> phoneList = smsVerifyCodeRequest.getPhoneList();
|
||||
if(phoneList==null){
|
||||
@ -148,7 +148,7 @@ public class SmsVerifyCodeController {
|
||||
*/
|
||||
@PostMapping("/batchUrgeContent")
|
||||
@Operation(summary = "催促")
|
||||
public ResponseResult batchUrgeContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult batchUrgeContent(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
List<String> userIds = smsVerifyCodeRequest.getUserIds();
|
||||
String content = smsVerifyCodeRequest.getContent();
|
||||
|
||||
@ -161,7 +161,7 @@ public class SmsVerifyCodeController {
|
||||
}
|
||||
|
||||
try {
|
||||
int successCount = smsVerifyCodeService.urgeByUserIds(userIds, content);
|
||||
int successCount = smsVerifyCodeService.urgeByUserIds(tenantId,userIds, content);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
// result.put("successCount", successCount);
|
||||
result.put("totalCount", userIds.size());
|
||||
@ -180,7 +180,7 @@ public class SmsVerifyCodeController {
|
||||
@PostMapping("/register")
|
||||
@Operation(summary = "注册用户")
|
||||
@Transactional
|
||||
public ResponseResult register(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult register(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
String code = smsVerifyCodeRequest.getCode();
|
||||
if (smsVerifyCodeRequest.getPhone() == null || smsVerifyCodeRequest.getPhone().isEmpty()) {
|
||||
return ResponseResult.error("手机号不能为空");
|
||||
@ -195,12 +195,12 @@ public class SmsVerifyCodeController {
|
||||
return ResponseResult.error("验证码不能为空");
|
||||
}
|
||||
|
||||
boolean verified = smsVerifyCodeService.verifyCode(smsVerifyCodeRequest.getPhone(), code, SmsVerifyCode.TYPE_REGISTER);
|
||||
boolean verified = smsVerifyCodeService.verifyCode(smsVerifyCodeRequest.getPhone(), code, SmsVerifyCode.TYPE_REGISTER,tenantId);
|
||||
if (!verified) {
|
||||
return ResponseResult.error("验证码错误或已过期");
|
||||
}
|
||||
|
||||
SysUser existUser = userService.getUserByPhone(smsVerifyCodeRequest.getPhone());
|
||||
SysUser existUser = userService.getUserByPhone(smsVerifyCodeRequest.getPhone(),tenantId);
|
||||
if (existUser != null) {
|
||||
return ResponseResult.error("该手机号已注册");
|
||||
}
|
||||
@ -225,7 +225,7 @@ public class SmsVerifyCodeController {
|
||||
user.setCompanyCode(smsVerifyCodeRequest.getCompanyCode());
|
||||
boolean success = userService.save(user);
|
||||
// 给注册用户加上默认权限
|
||||
SysUser savedUser = userService.getUserByPhone(smsVerifyCodeRequest.getPhone());
|
||||
SysUser savedUser = userService.getUserByPhone(smsVerifyCodeRequest.getPhone(),tenantId);
|
||||
if (savedUser != null) {
|
||||
this.addDefaultRole(savedUser.getId(), smsVerifyCodeRequest);
|
||||
}
|
||||
@ -338,7 +338,7 @@ public class SmsVerifyCodeController {
|
||||
*/
|
||||
@PostMapping("/resetPassword")
|
||||
@Operation(summary = "找回密码")
|
||||
public ResponseResult resetPassword(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult resetPassword(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
String password = smsVerifyCodeRequest.getPassword();
|
||||
String phone = smsVerifyCodeRequest.getPhone();
|
||||
String code = smsVerifyCodeRequest.getCode();
|
||||
@ -352,12 +352,12 @@ public class SmsVerifyCodeController {
|
||||
return ResponseResult.error("新密码不能为空");
|
||||
}
|
||||
|
||||
boolean verified = smsVerifyCodeService.verifyCode(phone, code, SmsVerifyCode.TYPE_FIND_PASSWORD);
|
||||
boolean verified = smsVerifyCodeService.verifyCode(phone, code, SmsVerifyCode.TYPE_FIND_PASSWORD,tenantId);
|
||||
if (!verified) {
|
||||
return ResponseResult.error("验证码错误或已过期");
|
||||
}
|
||||
|
||||
SysUser existUser = userService.getUserByPhone(phone);
|
||||
SysUser existUser = userService.getUserByPhone(phone,tenantId);
|
||||
if (existUser == null) {
|
||||
return ResponseResult.error("该手机号未注册");
|
||||
}
|
||||
@ -382,11 +382,11 @@ public class SmsVerifyCodeController {
|
||||
*/
|
||||
@PostMapping("/verifyCode")
|
||||
@Operation(summary = "验证验证码")
|
||||
public ResponseResult verifyCode(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult verifyCode(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
String phone = smsVerifyCodeRequest.getPhone();
|
||||
String code = smsVerifyCodeRequest.getCode();
|
||||
Integer type = smsVerifyCodeRequest.getType();
|
||||
boolean valid = smsVerifyCodeService.verifyCode(phone, code, type);
|
||||
boolean valid = smsVerifyCodeService.verifyCode(phone, code, type,tenantId);
|
||||
if (valid) {
|
||||
return ResponseResult.success();
|
||||
} else {
|
||||
@ -399,7 +399,7 @@ public class SmsVerifyCodeController {
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
@Operation(summary = "短信验证码登录")
|
||||
public ResponseResult smsLogin(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
public ResponseResult smsLogin(@RequestHeader(value = "Tenant_id", required = false) String tenantId,@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
|
||||
String phone = smsVerifyCodeRequest.getPhone();
|
||||
String code = smsVerifyCodeRequest.getCode();
|
||||
if (phone == null || phone.isEmpty()) {
|
||||
@ -409,12 +409,12 @@ public class SmsVerifyCodeController {
|
||||
return ResponseResult.error("验证码不能为空");
|
||||
}
|
||||
|
||||
boolean verified = smsVerifyCodeService.verifyCode(phone, code, SmsVerifyCode.TYPE_LOGIN);
|
||||
boolean verified = smsVerifyCodeService.verifyCode(phone, code, SmsVerifyCode.TYPE_LOGIN,tenantId);
|
||||
if (!verified) {
|
||||
return ResponseResult.error("验证码错误或已过期");
|
||||
}
|
||||
|
||||
SysUser user = userService.getUserByPhone(phone);
|
||||
SysUser user = userService.getUserByPhone(phone,tenantId);
|
||||
if (user == null) {
|
||||
return ResponseResult.error("该手机号未注册");
|
||||
}
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_CONFIG")
|
||||
public class PushConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String categoryCode;
|
||||
|
||||
private String categoryName;
|
||||
|
||||
private String baseIdList;
|
||||
|
||||
private String baseNameList;
|
||||
|
||||
private String messageType;
|
||||
|
||||
private String cronExpression;
|
||||
|
||||
private Integer targetType;
|
||||
|
||||
private Integer isSms;
|
||||
|
||||
private Long pushCount;
|
||||
|
||||
private Long dailyPushCount;
|
||||
|
||||
private Date finishTime;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private Date updatedAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PushConfigTargetRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String configId;
|
||||
|
||||
/**
|
||||
* 0-用户,1-角色
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
private List<String> userRoleIds;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class PushConfigTargetVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private String configId;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private String userRoleId;
|
||||
|
||||
private String targetName;
|
||||
|
||||
private String targetPhone;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_CONFIG_USER")
|
||||
public class PushConfigUser implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String configId;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private String userRoleId;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_HISTORY")
|
||||
public class PushHistory implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String configId;
|
||||
|
||||
private Date planTime;
|
||||
|
||||
private String messageTypeCode;
|
||||
|
||||
private String messageTypeName;
|
||||
|
||||
private String title;
|
||||
|
||||
private String content;
|
||||
|
||||
private Long pushedCount;
|
||||
|
||||
private Long successCount;
|
||||
|
||||
private Long failCount;
|
||||
|
||||
private Long pendingCount;
|
||||
|
||||
private String sendChannel;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String source;
|
||||
|
||||
private String relation;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private Date updatedAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("PUSH_HISTORY_DETAIL")
|
||||
public class PushHistoryDetail implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
private String historyId;
|
||||
|
||||
private String targetName;
|
||||
|
||||
private String targetPhone;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String sendChannel;
|
||||
|
||||
private Date sendTime;
|
||||
|
||||
private String errorMsg;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private String recordUser;
|
||||
|
||||
private String modifyUser;
|
||||
|
||||
private Date modifyTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
private String deleteUser;
|
||||
|
||||
private Date deleteTime;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.yfd.platform.system.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class PushTargetUserVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String userId;
|
||||
|
||||
private String targetName;
|
||||
|
||||
private String targetPhone;
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.yfd.platform.system.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;
|
||||
|
||||
@ -115,4 +116,18 @@ public class QuartzJob implements Serializable {
|
||||
@Schema(description = "备用3")
|
||||
private String custom3;
|
||||
|
||||
/**
|
||||
* 业务模块编码(如:PUSH-推送配置,SYNC-数据同步,REPORT-报表生成)
|
||||
*/
|
||||
@Schema(description = "业务模块编码")
|
||||
@TableField("BIZ_MODULE")
|
||||
private String bizModule;
|
||||
|
||||
/**
|
||||
* 关联业务表的主键ID(如 PUSH_CONFIG.ID)
|
||||
*/
|
||||
@Schema(description = "关联业务主键ID")
|
||||
@TableField("BIZ_ID")
|
||||
private String bizId;
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.yfd.platform.system.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 lombok.Data;
|
||||
@ -63,4 +64,10 @@ public class SmsVerifyCode implements Serializable {
|
||||
* 0-未使用 1-已使用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@TableField("TENANT_ID")
|
||||
private String tenantId;
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
|
||||
public interface PushConfigMapper extends BaseMapper<PushConfig> {
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetVo;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
import com.yfd.platform.system.domain.PushTargetUserVo;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PushConfigUserMapper extends BaseMapper<PushConfigUser> {
|
||||
|
||||
List<PushTargetUserVo> selectAllActiveUsers();
|
||||
|
||||
List<PushTargetUserVo> selectTargetUsersByConfigId(@Param("configId") String configId);
|
||||
|
||||
List<PushConfigTargetVo> selectConfigTargets(@Param("configId") String configId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
|
||||
public interface PushHistoryDetailMapper extends BaseMapper<PushHistoryDetail> {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
|
||||
public interface PushHistoryMapper extends BaseMapper<PushHistory> {
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetRequest;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetVo;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface IPushConfigService extends IService<PushConfig> {
|
||||
|
||||
Page<PushConfig> getPushConfigPage(Page<PushConfig> page,
|
||||
String categoryName,
|
||||
String messageType,
|
||||
Integer targetType,
|
||||
Integer status);
|
||||
|
||||
boolean addPushConfig(PushConfig pushConfig);
|
||||
|
||||
boolean updatePushConfig(PushConfig pushConfig);
|
||||
|
||||
boolean deletePushConfig(String ids);
|
||||
|
||||
boolean setPushConfigStatus(String id, Integer status);
|
||||
|
||||
boolean setPushConfigSmsSwitch(String id, Integer isSms);
|
||||
|
||||
boolean savePushTargets(PushConfigTargetRequest request);
|
||||
|
||||
List<PushConfigTargetVo> getPushTargets(String configId);
|
||||
|
||||
Page<PushHistory> getPushHistoryPage(Page<PushHistory> page,
|
||||
String configId,
|
||||
Integer status,
|
||||
String messageTypeCode,
|
||||
Date startTime,
|
||||
Date endTime);
|
||||
|
||||
Page<PushHistoryDetail> getPushHistoryDetailPage(Page<PushHistoryDetail> page,
|
||||
String historyId,
|
||||
Integer status);
|
||||
|
||||
boolean executeNow(String configId);
|
||||
|
||||
void executePushConfig(String configId);
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
|
||||
public interface IPushConfigUserService extends IService<PushConfigUser> {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
|
||||
public interface IPushHistoryDetailService extends IService<PushHistoryDetail> {
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.yfd.platform.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
|
||||
public interface IPushHistoryService extends IService<PushHistory> {
|
||||
}
|
||||
@ -18,7 +18,7 @@ public interface ISmsVerifyCodeService extends IService<SmsVerifyCode> {
|
||||
* @param type 1-注册 2-找回密码
|
||||
* @return 验证码
|
||||
*/
|
||||
String sendVerifyCode(String phone, Integer type);
|
||||
String sendVerifyCode(String phone, Integer type,String tenantId);
|
||||
|
||||
/**
|
||||
* 验证验证码
|
||||
@ -27,7 +27,7 @@ public interface ISmsVerifyCodeService extends IService<SmsVerifyCode> {
|
||||
* @param type 类型 1-注册 2-找回密码
|
||||
* @return 是否验证通过
|
||||
*/
|
||||
boolean verifyCode(String phone, String code, Integer type);
|
||||
boolean verifyCode(String phone, String code, Integer type,String tenantId);
|
||||
|
||||
/**
|
||||
* 标记验证码已使用
|
||||
@ -50,5 +50,5 @@ public interface ISmsVerifyCodeService extends IService<SmsVerifyCode> {
|
||||
boolean sendAuditNotify(String phone, String auditStatus, String reason);
|
||||
|
||||
void batchSendContent(List<String> phoneList, String content);
|
||||
int urgeByUserIds(List<String> userIds, String content);
|
||||
int urgeByUserIds(String tenantId,List<String> userIds, String content);
|
||||
}
|
||||
@ -155,7 +155,7 @@ public interface IUserService extends IService<SysUser> {
|
||||
*phone 手机号
|
||||
* 返回值说明: 用户对象
|
||||
************************************/
|
||||
SysUser getUserByPhone(String phone);
|
||||
SysUser getUserByPhone(String phone,String tenantId);
|
||||
|
||||
/***********************************
|
||||
* 用途说明:根据手机号修改密码
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.yfd.platform.system.service.IPushConfigService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service("pushConfigQuartzExecutor")
|
||||
public class PushConfigQuartzExecutor {
|
||||
|
||||
@Resource
|
||||
private IPushConfigService pushConfigService;
|
||||
|
||||
public void execute(String configId) {
|
||||
pushConfigService.executePushConfig(configId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,511 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.system.domain.PushConfig;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetRequest;
|
||||
import com.yfd.platform.system.domain.PushConfigTargetVo;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
import com.yfd.platform.system.domain.PushTargetUserVo;
|
||||
import com.yfd.platform.system.domain.QuartzJob;
|
||||
import com.yfd.platform.system.mapper.PushConfigMapper;
|
||||
import com.yfd.platform.system.mapper.PushConfigUserMapper;
|
||||
import com.yfd.platform.system.service.IPushConfigService;
|
||||
import com.yfd.platform.system.service.IPushConfigUserService;
|
||||
import com.yfd.platform.system.service.IPushHistoryDetailService;
|
||||
import com.yfd.platform.system.service.IPushHistoryService;
|
||||
import com.yfd.platform.system.service.IQuartzJobService;
|
||||
import com.yfd.platform.utils.QuartzManage;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.quartz.CronExpression;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class PushConfigServiceImpl extends ServiceImpl<PushConfigMapper, PushConfig> implements IPushConfigService {
|
||||
|
||||
private static final String QUARTZ_BIZ_TYPE = "PUSH_CONFIG";
|
||||
private static final String DEFAULT_SEND_CHANNEL = "SMS";
|
||||
private static final String DEFAULT_SOURCE = "PUSH_CONFIG";
|
||||
|
||||
@Resource
|
||||
private PushConfigUserMapper pushConfigUserMapper;
|
||||
|
||||
@Resource
|
||||
private IPushConfigUserService pushConfigUserService;
|
||||
|
||||
@Resource
|
||||
private IPushHistoryService pushHistoryService;
|
||||
|
||||
@Resource
|
||||
private IPushHistoryDetailService pushHistoryDetailService;
|
||||
|
||||
@Resource
|
||||
private IQuartzJobService quartzJobService;
|
||||
|
||||
@Resource
|
||||
private QuartzManage quartzManage;
|
||||
|
||||
@Override
|
||||
public Page<PushConfig> getPushConfigPage(Page<PushConfig> page,
|
||||
String categoryName,
|
||||
String messageType,
|
||||
Integer targetType,
|
||||
Integer status) {
|
||||
LambdaQueryWrapper<PushConfig> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(PushConfig::getIsDeleted, 0)
|
||||
.like(StrUtil.isNotBlank(categoryName), PushConfig::getCategoryName, categoryName)
|
||||
.like(StrUtil.isNotBlank(messageType), PushConfig::getMessageType, messageType)
|
||||
.eq(targetType != null, PushConfig::getTargetType, targetType)
|
||||
.eq(status != null, PushConfig::getStatus, status)
|
||||
.orderByDesc(PushConfig::getUpdatedAt, PushConfig::getCreatedAt);
|
||||
return this.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean addPushConfig(PushConfig pushConfig) {
|
||||
validatePushConfig(pushConfig, false);
|
||||
Date now = new Date();
|
||||
pushConfig.setCreatedAt(now);
|
||||
pushConfig.setUpdatedAt(now);
|
||||
pushConfig.setModifyTime(now);
|
||||
pushConfig.setRecordUser(currentUserIdOrSystem());
|
||||
pushConfig.setModifyUser(currentUserIdOrSystem());
|
||||
pushConfig.setIsDeleted(0);
|
||||
pushConfig.setStatus(pushConfig.getStatus() == null ? 1 : pushConfig.getStatus());
|
||||
pushConfig.setIsSms(pushConfig.getIsSms() == null ? 0 : pushConfig.getIsSms());
|
||||
pushConfig.setPushCount(pushConfig.getPushCount() == null ? 0L : pushConfig.getPushCount());
|
||||
pushConfig.setDailyPushCount(pushConfig.getDailyPushCount() == null ? 0L : pushConfig.getDailyPushCount());
|
||||
return this.save(pushConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updatePushConfig(PushConfig pushConfig) {
|
||||
validatePushConfig(pushConfig, true);
|
||||
PushConfig dbConfig = getAvailableConfig(pushConfig.getId());
|
||||
dbConfig.setCategoryCode(pushConfig.getCategoryCode());
|
||||
dbConfig.setCategoryName(pushConfig.getCategoryName());
|
||||
dbConfig.setBaseIdList(pushConfig.getBaseIdList());
|
||||
dbConfig.setBaseNameList(pushConfig.getBaseNameList());
|
||||
dbConfig.setMessageType(pushConfig.getMessageType());
|
||||
dbConfig.setCronExpression(pushConfig.getCronExpression());
|
||||
dbConfig.setTargetType(pushConfig.getTargetType());
|
||||
// dbConfig.setIsSms(pushConfig.getIsSms() == null ? 0 : pushConfig.getIsSms());
|
||||
// dbConfig.setStatus(pushConfig.getStatus() == null ? dbConfig.getStatus() : pushConfig.getStatus());
|
||||
dbConfig.setUpdatedAt(new Date());
|
||||
dbConfig.setModifyTime(new Date());
|
||||
dbConfig.setModifyUser(currentUserIdOrSystem());
|
||||
boolean updated = this.updateById(dbConfig);
|
||||
if (updated) {
|
||||
if (Objects.equals(dbConfig.getTargetType(), 1)) {
|
||||
softDeleteTargets(dbConfig.getId(), currentUserIdOrSystem(), new Date());
|
||||
}
|
||||
refreshQuartzJobIfExists(dbConfig);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deletePushConfig(String ids) {
|
||||
if (StrUtil.isBlank(ids)) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
Date now = new Date();
|
||||
String userId = currentUserIdOrSystem();
|
||||
for (String id : ids.split(",")) {
|
||||
String configId = StrUtil.trim(id);
|
||||
if (StrUtil.isBlank(configId)) {
|
||||
continue;
|
||||
}
|
||||
PushConfig config = getAvailableConfig(configId);
|
||||
config.setIsDeleted(1);
|
||||
config.setDeleteUser(userId);
|
||||
config.setDeleteTime(now);
|
||||
config.setModifyUser(userId);
|
||||
config.setModifyTime(now);
|
||||
config.setUpdatedAt(now);
|
||||
this.updateById(config);
|
||||
softDeleteTargets(configId, userId, now);
|
||||
deleteQuartzJob(configId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean setPushConfigStatus(String id, Integer status) {
|
||||
if (StrUtil.isBlank(id) || status == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
PushConfig config = getAvailableConfig(id);
|
||||
config.setStatus(status);
|
||||
if (Objects.equals(status, 0)) {
|
||||
config.setIsSms(0);
|
||||
}
|
||||
config.setUpdatedAt(new Date());
|
||||
config.setModifyTime(new Date());
|
||||
config.setModifyUser(currentUserIdOrSystem());
|
||||
boolean updated = this.updateById(config);
|
||||
// if (updated) {
|
||||
// syncQuartzJobBySwitch(config);
|
||||
// }
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean setPushConfigSmsSwitch(String id, Integer isSms) {
|
||||
if (StrUtil.isBlank(id) || isSms == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
if (!Objects.equals(isSms, 0) && !Objects.equals(isSms, 1)) {
|
||||
throw new BizException("短信推送开关值不正确.");
|
||||
}
|
||||
PushConfig config = getAvailableConfig(id);
|
||||
config.setIsSms(isSms);
|
||||
config.setUpdatedAt(new Date());
|
||||
config.setModifyTime(new Date());
|
||||
config.setModifyUser(currentUserIdOrSystem());
|
||||
boolean updated = this.updateById(config);
|
||||
if (updated) {
|
||||
syncQuartzJobBySwitch(config);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean savePushTargets(PushConfigTargetRequest request) {
|
||||
validatePushTargetRequest(request);
|
||||
PushConfig config = getAvailableConfig(request.getConfigId());
|
||||
validateTargetTypeMatch(config.getTargetType(), request.getType());
|
||||
Date now = new Date();
|
||||
String userId = currentUserIdOrSystem();
|
||||
softDeleteTargets(config.getId(), userId, now);
|
||||
if (request.getUserRoleIds() == null || request.getUserRoleIds().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
List<PushConfigUser> list = new ArrayList<>();
|
||||
for (String userRoleId : request.getUserRoleIds()) {
|
||||
String targetId = StrUtil.trim(userRoleId);
|
||||
if (StrUtil.isBlank(targetId)) {
|
||||
continue;
|
||||
}
|
||||
PushConfigUser relation = new PushConfigUser();
|
||||
relation.setConfigId(config.getId());
|
||||
relation.setType(request.getType());
|
||||
relation.setUserRoleId(targetId);
|
||||
relation.setCreatedAt(now);
|
||||
relation.setRecordUser(userId);
|
||||
relation.setModifyUser(userId);
|
||||
relation.setModifyTime(now);
|
||||
relation.setIsDeleted(0);
|
||||
list.add(relation);
|
||||
}
|
||||
return list.isEmpty() || pushConfigUserService.saveBatch(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PushConfigTargetVo> getPushTargets(String configId) {
|
||||
if (StrUtil.isBlank(configId)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return pushConfigUserMapper.selectConfigTargets(configId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PushHistory> getPushHistoryPage(Page<PushHistory> page,
|
||||
String configId,
|
||||
Integer status,
|
||||
String messageTypeCode,
|
||||
Date startTime,
|
||||
Date endTime) {
|
||||
LambdaQueryWrapper<PushHistory> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(PushHistory::getIsDeleted, 0)
|
||||
.eq(StrUtil.isNotBlank(configId), PushHistory::getConfigId, configId)
|
||||
.eq(status != null, PushHistory::getStatus, status)
|
||||
.eq(StrUtil.isNotBlank(messageTypeCode), PushHistory::getMessageTypeCode, messageTypeCode)
|
||||
.ge(startTime != null, PushHistory::getPlanTime, startTime)
|
||||
.le(endTime != null, PushHistory::getPlanTime, endTime)
|
||||
.orderByDesc(PushHistory::getPlanTime, PushHistory::getCreatedAt);
|
||||
return pushHistoryService.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<PushHistoryDetail> getPushHistoryDetailPage(Page<PushHistoryDetail> page,
|
||||
String historyId,
|
||||
Integer status) {
|
||||
LambdaQueryWrapper<PushHistoryDetail> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(PushHistoryDetail::getIsDeleted, 0)
|
||||
.eq(StrUtil.isNotBlank(historyId), PushHistoryDetail::getHistoryId, historyId)
|
||||
.eq(status != null, PushHistoryDetail::getStatus, status)
|
||||
.orderByDesc(PushHistoryDetail::getCreatedAt, PushHistoryDetail::getSendTime);
|
||||
return pushHistoryDetailService.page(page, wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeNow(String configId) {
|
||||
executePushConfig(configId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void executePushConfig(String configId) {
|
||||
PushConfig config = getAvailableConfig(configId);
|
||||
List<PushTargetUserVo> targets = resolveTargets(config);
|
||||
Date now = new Date();
|
||||
String operator = currentUserIdOrSystem();
|
||||
|
||||
PushHistory history = new PushHistory();
|
||||
history.setConfigId(config.getId());
|
||||
history.setPlanTime(now);
|
||||
history.setMessageTypeCode(config.getCategoryCode());
|
||||
history.setMessageTypeName(config.getCategoryName());
|
||||
history.setTitle(buildDefaultTitle(config));
|
||||
history.setContent(buildDefaultContent(config));
|
||||
history.setPushedCount(0L);
|
||||
history.setSuccessCount(0L);
|
||||
history.setFailCount(0L);
|
||||
history.setPendingCount((long) targets.size());
|
||||
history.setSendChannel(DEFAULT_SEND_CHANNEL);
|
||||
history.setStatus(0);
|
||||
history.setSource(DEFAULT_SOURCE);
|
||||
history.setRelation(StrUtil.blankToDefault(config.getBaseNameList(), config.getCategoryName()));
|
||||
history.setCreatedAt(now);
|
||||
history.setUpdatedAt(now);
|
||||
history.setRecordUser(operator);
|
||||
history.setModifyUser(operator);
|
||||
history.setModifyTime(now);
|
||||
history.setIsDeleted(0);
|
||||
pushHistoryService.save(history);
|
||||
|
||||
if (!targets.isEmpty()) {
|
||||
List<PushHistoryDetail> detailList = new ArrayList<>();
|
||||
for (PushTargetUserVo target : targets) {
|
||||
PushHistoryDetail detail = new PushHistoryDetail();
|
||||
detail.setHistoryId(history.getId());
|
||||
detail.setTargetName(target.getTargetName());
|
||||
detail.setTargetPhone(target.getTargetPhone());
|
||||
detail.setStatus(0);
|
||||
detail.setSendChannel(DEFAULT_SEND_CHANNEL);
|
||||
detail.setCreatedAt(now);
|
||||
detail.setRecordUser(operator);
|
||||
detail.setModifyUser(operator);
|
||||
detail.setModifyTime(now);
|
||||
detail.setIsDeleted(0);
|
||||
detailList.add(detail);
|
||||
}
|
||||
pushHistoryDetailService.saveBatch(detailList);
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePushConfig(PushConfig pushConfig, boolean requireId) {
|
||||
if (pushConfig == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
if (requireId && StrUtil.isBlank(pushConfig.getId())) {
|
||||
throw new BizException("配置ID不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getCategoryCode())) {
|
||||
throw new BizException("消息类别编码不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getCategoryName())) {
|
||||
throw new BizException("消息类别名称不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getMessageType())) {
|
||||
throw new BizException("消息类型不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(pushConfig.getCronExpression()) || !CronExpression.isValidExpression(pushConfig.getCronExpression())) {
|
||||
throw new BizException("cron表达式格式错误.");
|
||||
}
|
||||
if (pushConfig.getTargetType() == null || (pushConfig.getTargetType() != 1 && pushConfig.getTargetType() != 2 && pushConfig.getTargetType() != 3)) {
|
||||
throw new BizException("推送目标类型不正确.");
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePushTargetRequest(PushConfigTargetRequest request) {
|
||||
if (request == null) {
|
||||
throw new BizException("参数不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(request.getConfigId())) {
|
||||
throw new BizException("推送配置ID不能为空.");
|
||||
}
|
||||
if (request.getType() == null || (request.getType() != 0 && request.getType() != 1)) {
|
||||
throw new BizException("绑定类型不正确.");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTargetTypeMatch(Integer targetType, Integer relationType) {
|
||||
if (targetType == null) {
|
||||
return;
|
||||
}
|
||||
if (targetType == 1) {
|
||||
throw new BizException("当前配置为所有人推送,无需绑定目标.");
|
||||
}
|
||||
if (targetType == 2 && !Objects.equals(relationType, 0)) {
|
||||
throw new BizException("按人推送只能绑定用户.");
|
||||
}
|
||||
if (targetType == 3 && !Objects.equals(relationType, 1)) {
|
||||
throw new BizException("按角色推送只能绑定角色.");
|
||||
}
|
||||
}
|
||||
|
||||
private PushConfig getAvailableConfig(String id) {
|
||||
List<PushConfig> list = this.list(new LambdaQueryWrapper<PushConfig>()
|
||||
.eq(PushConfig::getId, id)
|
||||
.eq(PushConfig::getIsDeleted, 0));
|
||||
PushConfig config = list.isEmpty() ? null : list.get(0);
|
||||
if (config == null) {
|
||||
throw new BizException("推送配置不存在.");
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private void softDeleteTargets(String configId, String userId, Date now) {
|
||||
LambdaUpdateWrapper<PushConfigUser> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(PushConfigUser::getConfigId, configId)
|
||||
.eq(PushConfigUser::getIsDeleted, 0)
|
||||
.set(PushConfigUser::getIsDeleted, 1)
|
||||
.set(PushConfigUser::getDeleteUser, userId)
|
||||
.set(PushConfigUser::getDeleteTime, now)
|
||||
.set(PushConfigUser::getModifyUser, userId)
|
||||
.set(PushConfigUser::getModifyTime, now);
|
||||
pushConfigUserService.update(updateWrapper);
|
||||
}
|
||||
|
||||
private void syncQuartzJob(PushConfig config) {
|
||||
QuartzJob quartzJob = getPushQuartzJob(config.getId());
|
||||
Date now = new Date();
|
||||
if (quartzJob == null) {
|
||||
quartzJob = new QuartzJob();
|
||||
quartzJob.setBizModule(QUARTZ_BIZ_TYPE);
|
||||
quartzJob.setBizId(config.getId());
|
||||
}
|
||||
quartzJob.setJobName("推送配置-" + config.getCategoryName());
|
||||
quartzJob.setJobClass("pushConfigQuartzExecutor");
|
||||
quartzJob.setJobMethod("execute");
|
||||
quartzJob.setJobCron(config.getCronExpression());
|
||||
quartzJob.setJobParams(config.getId());
|
||||
quartzJob.setDescription("推送配置定时任务-" + config.getMessageType());
|
||||
quartzJob.setStatus(Objects.equals(config.getStatus(), 1) ? "1" : "0");
|
||||
quartzJob.setLastmodifier(currentUsernameOrSystem());
|
||||
quartzJob.setLastmodifydate(new Timestamp(now.getTime()));
|
||||
quartzJob.setOrderno(0);
|
||||
if (StrUtil.isBlank(quartzJob.getId())) {
|
||||
quartzJobService.save(quartzJob);
|
||||
quartzManage.addJob(quartzJob);
|
||||
} else {
|
||||
quartzJobService.updateById(quartzJob);
|
||||
quartzManage.updateJobCron(quartzJob);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshQuartzJobIfExists(PushConfig config) {
|
||||
QuartzJob quartzJob = getPushQuartzJob(config.getId());
|
||||
if (quartzJob == null) {
|
||||
return;
|
||||
}
|
||||
if (canCreateQuartzJob(config)) {
|
||||
syncQuartzJob(config);
|
||||
} else {
|
||||
deleteQuartzJob(config.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void syncQuartzJobBySwitch(PushConfig config) {
|
||||
if (canCreateQuartzJob(config)) {
|
||||
syncQuartzJob(config);
|
||||
} else {
|
||||
deleteQuartzJob(config.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canCreateQuartzJob(PushConfig config) {
|
||||
return config != null
|
||||
&& Objects.equals(config.getStatus(), 1)
|
||||
&& Objects.equals(config.getIsSms(), 1);
|
||||
}
|
||||
|
||||
private void deleteQuartzJob(String configId) {
|
||||
QuartzJob quartzJob = getPushQuartzJob(configId);
|
||||
if (quartzJob != null) {
|
||||
quartzManage.deleteJob(quartzJob);
|
||||
quartzJobService.removeById(quartzJob.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private QuartzJob getPushQuartzJob(String configId) {
|
||||
List<QuartzJob> list = quartzJobService.list(new LambdaQueryWrapper<QuartzJob>()
|
||||
.eq(QuartzJob::getBizModule, QUARTZ_BIZ_TYPE)
|
||||
.eq(QuartzJob::getBizId, configId));
|
||||
return list.isEmpty() ? null : list.getFirst();
|
||||
}
|
||||
|
||||
private List<PushTargetUserVo> resolveTargets(PushConfig config) {
|
||||
List<PushTargetUserVo> rawTargets;
|
||||
if (Objects.equals(config.getTargetType(), 1)) {
|
||||
rawTargets = pushConfigUserMapper.selectAllActiveUsers();
|
||||
} else {
|
||||
rawTargets = pushConfigUserMapper.selectTargetUsersByConfigId(config.getId());
|
||||
}
|
||||
if (rawTargets == null || rawTargets.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<String, PushTargetUserVo> targetMap = new LinkedHashMap<>();
|
||||
for (PushTargetUserVo target : rawTargets) {
|
||||
if (target == null || StrUtil.isBlank(target.getUserId()) || StrUtil.isBlank(target.getTargetPhone())) {
|
||||
continue;
|
||||
}
|
||||
targetMap.putIfAbsent(target.getUserId(), target);
|
||||
}
|
||||
return new ArrayList<>(targetMap.values());
|
||||
}
|
||||
|
||||
private String buildDefaultTitle(PushConfig config) {
|
||||
return StrUtil.format("【{}】默认推送标题", StrUtil.blankToDefault(config.getCategoryName(), "消息通知"));
|
||||
}
|
||||
|
||||
private String buildDefaultContent(PushConfig config) {
|
||||
return StrUtil.format("【{}】默认推送内容,消息类型:{},执行时间:{}",
|
||||
StrUtil.blankToDefault(config.getCategoryName(), "消息通知"),
|
||||
StrUtil.blankToDefault(config.getMessageType(), "未配置"),
|
||||
DateUtil.formatDateTime(new Date()));
|
||||
}
|
||||
|
||||
private String currentUserIdOrSystem() {
|
||||
try {
|
||||
return SecurityUtils.getUserId();
|
||||
} catch (Exception ex) {
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
|
||||
private String currentUsernameOrSystem() {
|
||||
try {
|
||||
return SecurityUtils.getCurrentUsername();
|
||||
} catch (Exception ex) {
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.system.domain.PushConfigUser;
|
||||
import com.yfd.platform.system.mapper.PushConfigUserMapper;
|
||||
import com.yfd.platform.system.service.IPushConfigUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PushConfigUserServiceImpl extends ServiceImpl<PushConfigUserMapper, PushConfigUser> implements IPushConfigUserService {
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.system.domain.PushHistoryDetail;
|
||||
import com.yfd.platform.system.mapper.PushHistoryDetailMapper;
|
||||
import com.yfd.platform.system.service.IPushHistoryDetailService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PushHistoryDetailServiceImpl extends ServiceImpl<PushHistoryDetailMapper, PushHistoryDetail> implements IPushHistoryDetailService {
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.yfd.platform.system.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.system.domain.PushHistory;
|
||||
import com.yfd.platform.system.mapper.PushHistoryMapper;
|
||||
import com.yfd.platform.system.service.IPushHistoryService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PushHistoryServiceImpl extends ServiceImpl<PushHistoryMapper, PushHistory> implements IPushHistoryService {
|
||||
}
|
||||
@ -42,13 +42,15 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String sendVerifyCode(String phone, Integer type) {
|
||||
public String sendVerifyCode(String phone, Integer type,String tenantId) {
|
||||
String code = generateCode();
|
||||
|
||||
LambdaQueryWrapper<SmsVerifyCode> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SmsVerifyCode::getPhone, phone)
|
||||
.eq(SmsVerifyCode::getType, type)
|
||||
.gt(SmsVerifyCode::getTenantId, tenantId)
|
||||
.eq(SmsVerifyCode::getStatus, SmsVerifyCode.STATUS_UNUSED);
|
||||
|
||||
this.remove(queryWrapper);
|
||||
|
||||
SmsVerifyCode verifyCode = new SmsVerifyCode();
|
||||
@ -58,6 +60,7 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
|
||||
verifyCode.setType(type);
|
||||
verifyCode.setStatus(SmsVerifyCode.STATUS_UNUSED);
|
||||
verifyCode.setCreateTime(new Date());
|
||||
verifyCode.setTenantId(tenantId);
|
||||
|
||||
Date expireTime = new Date(System.currentTimeMillis() + CODE_VALID_MINUTES * 60 * 1000L);
|
||||
verifyCode.setExpireTime(expireTime);
|
||||
@ -75,11 +78,12 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verifyCode(String phone, String code, Integer type) {
|
||||
public boolean verifyCode(String phone, String code, Integer type,String tenantId) {
|
||||
LambdaQueryWrapper<SmsVerifyCode> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SmsVerifyCode::getPhone, phone)
|
||||
.eq(SmsVerifyCode::getCode, code)
|
||||
.eq(SmsVerifyCode::getType, type)
|
||||
.eq(SmsVerifyCode::getTenantId, tenantId)
|
||||
.eq(SmsVerifyCode::getStatus, SmsVerifyCode.STATUS_UNUSED)
|
||||
.gt(SmsVerifyCode::getExpireTime, new Date());
|
||||
|
||||
@ -150,14 +154,14 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
|
||||
|
||||
|
||||
@Override
|
||||
public int urgeByUserIds(List<String> userIds, String content) {
|
||||
public int urgeByUserIds(String tenantId,List<String> userIds, String content) {
|
||||
if (userIds == null || userIds.isEmpty()) {
|
||||
log.warn("催促短信发送失败:用户ID列表为空");
|
||||
return 0;
|
||||
}
|
||||
List<String> ids = userIds.stream().distinct().toList();
|
||||
List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, ids)
|
||||
.eq(SysUser::getRegStatus, "APPROVED").eq(SysUser::getStatus,1).select(SysUser::getPhone));
|
||||
.eq(SysUser::getRegStatus, "APPROVED").eq(SysUser::getTenantId, tenantId).eq(SysUser::getStatus,1).select(SysUser::getPhone));
|
||||
|
||||
if (sysUsers.isEmpty()) {
|
||||
log.warn("催促短信发送失败:未找到有效的手机号,userIds: {}", ids);
|
||||
|
||||
@ -648,9 +648,10 @@ public class UserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysUser getUserByPhone(String phone) {
|
||||
public SysUser getUserByPhone(String phone,String tenantId) {
|
||||
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysUser::getPhone, phone);
|
||||
queryWrapper.eq(SysUser::getTenantId, tenantId);
|
||||
return this.getOne(queryWrapper);
|
||||
}
|
||||
|
||||
|
||||
@ -19,12 +19,12 @@ import com.yfd.platform.config.MessageConfig;
|
||||
import com.yfd.platform.config.thread.ThreadPoolExecutorUtil;
|
||||
import com.yfd.platform.system.domain.Message;
|
||||
import com.yfd.platform.system.domain.QuartzJob;
|
||||
import com.yfd.platform.system.service.IMessageService;
|
||||
import com.yfd.platform.system.service.IQuartzJobService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.sql.Timestamp;
|
||||
@ -32,72 +32,82 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 参考人人开源,https://gitee.com/renrenio/renren-security
|
||||
* 定时任务执行器(禁止同一Job并发执行)
|
||||
*
|
||||
* @author /
|
||||
* @date 2019-01-07
|
||||
*/
|
||||
@Async
|
||||
@DisallowConcurrentExecution
|
||||
@PersistJobDataAfterExecution
|
||||
@SuppressWarnings({"unchecked", "all"})
|
||||
@Slf4j
|
||||
public class ExecutionJob extends QuartzJobBean {
|
||||
|
||||
/**
|
||||
* 该处仅供参考
|
||||
*/
|
||||
private final static ThreadPoolExecutor EXECUTOR =
|
||||
ThreadPoolExecutorUtil.getPoll();
|
||||
private static final ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
|
||||
|
||||
@Resource
|
||||
private IMessageService messageService;
|
||||
|
||||
@Resource
|
||||
private MessageConfig messageConfig;
|
||||
|
||||
@Override
|
||||
public void executeInternal(JobExecutionContext context) {
|
||||
protected void executeInternal(JobExecutionContext context) {
|
||||
QuartzJob quartzJob =
|
||||
(QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
|
||||
// 获取spring bean
|
||||
|
||||
IQuartzJobService quartzJobService =
|
||||
SpringContextHolder.getBean(IQuartzJobService.class);
|
||||
String uuid = quartzJob.getId();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
String jobName = quartzJob.getJobName();
|
||||
String bizModule = quartzJob.getBizModule();
|
||||
String bizId = quartzJob.getBizId();
|
||||
|
||||
try {
|
||||
// 执行任务
|
||||
System.out.println(
|
||||
"--------------------------------------------------------------");
|
||||
System.out.println("任务开始执行,任务名称:" + jobName);
|
||||
QuartzRunnable task = new QuartzRunnable(quartzJob.getJobClass(),
|
||||
logExecutionStart(jobName, bizModule, bizId);
|
||||
|
||||
QuartzRunnable task = new QuartzRunnable(
|
||||
quartzJob.getJobClass(),
|
||||
quartzJob.getJobMethod(),
|
||||
quartzJob.getJobParams());
|
||||
Future<?> future = EXECUTOR.submit(task);
|
||||
future.get();
|
||||
|
||||
long times = System.currentTimeMillis() - startTime;
|
||||
Message message = new Message();
|
||||
message.setCreatetime(new Timestamp(System.currentTimeMillis()));
|
||||
message.setType("1");
|
||||
message.setTitle(quartzJob.getJobName());
|
||||
message.setContent(quartzJob.getDescription());
|
||||
message.setSenderName("定时器");
|
||||
message.setReceiverCodes(quartzJob.getOrderno().toString());
|
||||
message.setReceiverNames("");
|
||||
message.setStatus("1");
|
||||
message.setValidperiod(24);
|
||||
messageConfig.addMessage(message);
|
||||
// 任务状态
|
||||
System.out.println("任务执行完毕,任务名称:" + jobName + ", " +
|
||||
"执行时间:" + times + "毫秒");
|
||||
System.out.println(
|
||||
"--------------------------------------------------------------");
|
||||
logExecutionEnd(jobName, bizModule, bizId, times);
|
||||
|
||||
// sendCompletionMessage(quartzJob);
|
||||
} catch (Exception e) {
|
||||
System.out.println("任务执行失败,任务名称:" + jobName);
|
||||
System.out.println(
|
||||
"--------------------------------------------------------------");
|
||||
log.error("任务执行失败: jobName={}, module={}, bizId={}", jobName, bizModule, bizId, e);
|
||||
quartzJob.setStatus("0");
|
||||
//更新状态
|
||||
quartzJobService.updateById(quartzJob);
|
||||
}
|
||||
}
|
||||
|
||||
private void logExecutionStart(String jobName, String bizModule, String bizId) {
|
||||
log.info("--------------------------------------------------------------");
|
||||
log.info("任务开始执行,任务名称:" + jobName +
|
||||
(bizModule != null ? ",模块:" + bizModule : "") +
|
||||
(bizId != null ? ",业务ID:" + bizId : ""));
|
||||
}
|
||||
|
||||
private void logExecutionEnd(String jobName, String bizModule, String bizId, long times) {
|
||||
log.info("任务执行完毕,任务名称:" + jobName +
|
||||
(bizModule != null ? ",模块:" + bizModule : "") +
|
||||
",执行时间:" + times + "毫秒");
|
||||
log.info("--------------------------------------------------------------");
|
||||
}
|
||||
|
||||
private void sendCompletionMessage(QuartzJob quartzJob) {
|
||||
Message message = new Message();
|
||||
message.setCreatetime(new Timestamp(System.currentTimeMillis()));
|
||||
message.setType("1");
|
||||
message.setTitle(quartzJob.getJobName());
|
||||
message.setContent(quartzJob.getDescription());
|
||||
message.setSenderName("定时器");
|
||||
message.setReceiverCodes(quartzJob.getOrderno().toString());
|
||||
message.setReceiverNames("");
|
||||
message.setStatus("1");
|
||||
message.setValidperiod(24);
|
||||
messageConfig.addMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,15 +18,21 @@ package com.yfd.platform.utils;
|
||||
import com.yfd.platform.system.domain.QuartzJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.*;
|
||||
import org.quartz.impl.matchers.GroupMatcher;
|
||||
import org.quartz.impl.triggers.CronTriggerImpl;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static org.quartz.TriggerBuilder.newTrigger;
|
||||
|
||||
/**
|
||||
* 定时任务管理器(线程安全,支持多模块)
|
||||
*
|
||||
* @author
|
||||
* @date 2019-01-07
|
||||
*/
|
||||
@ -34,154 +40,267 @@ import static org.quartz.TriggerBuilder.newTrigger;
|
||||
@Component
|
||||
public class QuartzManage {
|
||||
|
||||
private static final String JOB_NAME = "TASK_";
|
||||
private static final String JOB_NAME_PREFIX = "TASK_";
|
||||
private static final String GROUP_SEPARATOR = "_";
|
||||
|
||||
@Resource(name = "scheduler")
|
||||
private Scheduler scheduler;
|
||||
|
||||
public void addJob(QuartzJob quartzJob) {
|
||||
try {
|
||||
// 构建job信息
|
||||
JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class).
|
||||
withIdentity(JOB_NAME + quartzJob.getId()).build();
|
||||
/** 按任务ID粒度的锁,避免全局锁竞争 */
|
||||
private static final ReentrantLock GLOBAL_LOCK = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* 构建 JobKey(包含 bizModule 用于分组隔离)
|
||||
*/
|
||||
private JobKey buildJobKey(QuartzJob quartzJob) {
|
||||
String group = resolveGroup(quartzJob);
|
||||
return JobKey.jobKey(JOB_NAME_PREFIX + quartzJob.getId(), group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 TriggerKey
|
||||
*/
|
||||
private TriggerKey buildTriggerKey(QuartzJob quartzJob) {
|
||||
String group = resolveGroup(quartzJob);
|
||||
return TriggerKey.triggerKey(JOB_NAME_PREFIX + quartzJob.getId(), group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 Quartz 分组名:有 bizModule 则按模块分组,否则默认分组
|
||||
*/
|
||||
private String resolveGroup(QuartzJob quartzJob) {
|
||||
if (quartzJob.getBizModule() != null && !quartzJob.getBizModule().isBlank()) {
|
||||
return quartzJob.getBizModule();
|
||||
}
|
||||
return "DEFAULT";
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加定时任务(线程安全)
|
||||
*/
|
||||
public void addJob(QuartzJob quartzJob) {
|
||||
GLOBAL_LOCK.lock();
|
||||
try {
|
||||
JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class)
|
||||
.withIdentity(buildJobKey(quartzJob))
|
||||
.storeDurably()
|
||||
.build();
|
||||
|
||||
//通过触发器名和cron 表达式创建 Trigger
|
||||
Trigger cronTrigger = newTrigger()
|
||||
.withIdentity(JOB_NAME + quartzJob.getId())
|
||||
.withIdentity(buildTriggerKey(quartzJob))
|
||||
.startNow()
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getJobCron()))
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getJobCron())
|
||||
.withMisfireHandlingInstructionDoNothing())
|
||||
.build();
|
||||
|
||||
cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob);
|
||||
|
||||
//重置启动时间
|
||||
((CronTriggerImpl) cronTrigger).setStartTime(new Date());
|
||||
|
||||
//执行定时任务
|
||||
scheduler.scheduleJob(jobDetail, cronTrigger);
|
||||
|
||||
// 暂停任务
|
||||
if ("0".equals(quartzJob.getStatus())) {
|
||||
pauseJob(quartzJob);
|
||||
scheduler.pauseJob(buildJobKey(quartzJob));
|
||||
}
|
||||
log.info("创建定时任务成功: module={}, bizId={}, jobName={}",
|
||||
quartzJob.getBizModule(), quartzJob.getBizId(), quartzJob.getJobName());
|
||||
} catch (Exception e) {
|
||||
log.error("创建定时任务失败", e);
|
||||
throw new RuntimeException("创建定时任务失败");
|
||||
log.error("创建定时任务失败: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId(), e);
|
||||
throw new RuntimeException("创建定时任务失败", e);
|
||||
} finally {
|
||||
GLOBAL_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新job cron表达式
|
||||
*
|
||||
* @param quartzJob /
|
||||
* 更新任务 Cron 表达式(线程安全,check-then-act 原子化)
|
||||
*/
|
||||
public void updateJobCron(QuartzJob quartzJob) {
|
||||
GLOBAL_LOCK.lock();
|
||||
try {
|
||||
TriggerKey triggerKey =
|
||||
TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
|
||||
CronTrigger trigger =
|
||||
(CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
// 如果不存在则创建一个定时任务
|
||||
TriggerKey triggerKey = buildTriggerKey(quartzJob);
|
||||
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
|
||||
if (trigger == null) {
|
||||
addJob(quartzJob);
|
||||
trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
return;
|
||||
}
|
||||
|
||||
CronScheduleBuilder scheduleBuilder =
|
||||
CronScheduleBuilder.cronSchedule(quartzJob.getJobCron());
|
||||
trigger =
|
||||
trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
|
||||
//重置启动时间
|
||||
CronScheduleBuilder.cronSchedule(quartzJob.getJobCron())
|
||||
.withMisfireHandlingInstructionDoNothing();
|
||||
trigger = trigger.getTriggerBuilder()
|
||||
.withIdentity(triggerKey)
|
||||
.withSchedule(scheduleBuilder)
|
||||
.build();
|
||||
((CronTriggerImpl) trigger).setStartTime(new Date());
|
||||
trigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob);
|
||||
|
||||
scheduler.rescheduleJob(triggerKey, trigger);
|
||||
// 暂停任务
|
||||
if ("0".equals(quartzJob.getStatus())) {
|
||||
pauseJob(quartzJob);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("更新定时任务失败", e);
|
||||
throw new RuntimeException("更新定时任务失败");
|
||||
}
|
||||
|
||||
if ("0".equals(quartzJob.getStatus())) {
|
||||
scheduler.pauseJob(buildJobKey(quartzJob));
|
||||
} else {
|
||||
scheduler.resumeJob(buildJobKey(quartzJob));
|
||||
}
|
||||
log.info("更新定时任务成功: module={}, bizId={}, jobName={}",
|
||||
quartzJob.getBizModule(), quartzJob.getBizId(), quartzJob.getJobName());
|
||||
} catch (Exception e) {
|
||||
log.error("更新定时任务失败: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId(), e);
|
||||
throw new RuntimeException("更新定时任务失败", e);
|
||||
} finally {
|
||||
GLOBAL_LOCK.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个job
|
||||
*
|
||||
* @param quartzJob /
|
||||
* 删除任务
|
||||
*/
|
||||
public void deleteJob(QuartzJob quartzJob) {
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
|
||||
JobKey jobKey = buildJobKey(quartzJob);
|
||||
scheduler.pauseJob(jobKey);
|
||||
scheduler.deleteJob(jobKey);
|
||||
log.info("删除定时任务成功: module={}, bizId={}, jobName={}",
|
||||
quartzJob.getBizModule(), quartzJob.getBizId(), quartzJob.getJobName());
|
||||
} catch (Exception e) {
|
||||
log.error("删除定时任务失败", e);
|
||||
throw new RuntimeException("删除定时任务失败");
|
||||
log.error("删除定时任务失败: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId(), e);
|
||||
throw new RuntimeException("删除定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复一个job
|
||||
*
|
||||
* @param quartzJob /
|
||||
* 恢复任务
|
||||
*/
|
||||
public void resumeJob(QuartzJob quartzJob) {
|
||||
try {
|
||||
TriggerKey triggerKey =
|
||||
TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
|
||||
CronTrigger trigger =
|
||||
(CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
// 如果不存在则创建一个定时任务
|
||||
TriggerKey triggerKey = buildTriggerKey(quartzJob);
|
||||
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
if (trigger == null) {
|
||||
addJob(quartzJob);
|
||||
return;
|
||||
}
|
||||
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
|
||||
scheduler.resumeJob(jobKey);
|
||||
scheduler.resumeJob(buildJobKey(quartzJob));
|
||||
log.info("恢复定时任务成功: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId());
|
||||
} catch (Exception e) {
|
||||
log.error("恢复定时任务失败", e);
|
||||
throw new RuntimeException("恢复定时任务失败");
|
||||
log.error("恢复定时任务失败: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId(), e);
|
||||
throw new RuntimeException("恢复定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即执行job
|
||||
*
|
||||
* @param quartzJob /
|
||||
* 立即执行任务(保留已有 JobDataMap,追加最新 quartzJob 数据)
|
||||
*/
|
||||
public void runJobNow(QuartzJob quartzJob) {
|
||||
try {
|
||||
TriggerKey triggerKey =
|
||||
TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
|
||||
CronTrigger trigger =
|
||||
(CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
// 如果不存在则创建一个定时任务
|
||||
TriggerKey triggerKey = buildTriggerKey(quartzJob);
|
||||
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
|
||||
if (trigger == null) {
|
||||
log.warn("任务不存在,先创建再执行: jobName={}", quartzJob.getJobName());
|
||||
addJob(quartzJob);
|
||||
trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
|
||||
}
|
||||
JobDataMap dataMap = new JobDataMap();
|
||||
|
||||
JobDataMap dataMap = trigger.getJobDataMap();
|
||||
dataMap.put(QuartzJob.JOB_KEY, quartzJob);
|
||||
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
|
||||
|
||||
JobKey jobKey = buildJobKey(quartzJob);
|
||||
scheduler.triggerJob(jobKey, dataMap);
|
||||
log.info("手动触发任务执行: module={}, bizId={}, jobName={}",
|
||||
quartzJob.getBizModule(), quartzJob.getBizId(), quartzJob.getJobName());
|
||||
} catch (Exception e) {
|
||||
log.error("定时任务执行失败", e);
|
||||
throw new RuntimeException("定时任务执行失败");
|
||||
log.error("手动触发任务失败: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId(), e);
|
||||
throw new RuntimeException("定时任务执行失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停一个job
|
||||
*
|
||||
* @param quartzJob /
|
||||
* 暂停任务
|
||||
*/
|
||||
public void pauseJob(QuartzJob quartzJob) {
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
|
||||
scheduler.pauseJob(jobKey);
|
||||
scheduler.pauseJob(buildJobKey(quartzJob));
|
||||
log.info("暂停定时任务成功: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId());
|
||||
} catch (Exception e) {
|
||||
log.error("定时任务暂停失败", e);
|
||||
throw new RuntimeException("定时任务暂停失败");
|
||||
log.error("定时任务暂停失败: module={}, bizId={}", quartzJob.getBizModule(), quartzJob.getBizId(), e);
|
||||
throw new RuntimeException("定时任务暂停失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 多模块支持方法 ====================
|
||||
|
||||
/**
|
||||
* 根据业务模块和业务ID查找已存在的任务
|
||||
*
|
||||
* @param bizModule 业务模块编码
|
||||
* @param bizId 业务主键ID
|
||||
* @return 是否存在
|
||||
*/
|
||||
public boolean existsByBiz(String bizModule, String bizId) {
|
||||
if (bizModule == null || bizModule.isBlank() || bizId == null || bizId.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.groupEquals(bizModule));
|
||||
for (JobKey jobKey : jobKeys) {
|
||||
JobDetail detail = scheduler.getJobDetail(jobKey);
|
||||
if (detail != null) {
|
||||
QuartzJob job = (QuartzJob) detail.getJobDataMap().get(QuartzJob.JOB_KEY);
|
||||
if (job != null && bizId.equals(job.getBizId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
log.error("查询任务失败: module={}, bizId={}", bizModule, bizId, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模块暂停该模块下所有任务
|
||||
*/
|
||||
public void pauseAllByModule(String bizModule) {
|
||||
if (bizModule == null || bizModule.isBlank()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.groupEquals(bizModule));
|
||||
scheduler.pauseJobs(org.quartz.impl.matchers.GroupMatcher.groupEquals(bizModule));
|
||||
log.info("暂停模块[{}]下所有任务,共{}个", bizModule, jobKeys.size());
|
||||
} catch (SchedulerException e) {
|
||||
log.error("暂停模块任务失败: module={}", bizModule, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模块恢复该模块下所有任务
|
||||
*/
|
||||
public void resumeAllByModule(String bizModule) {
|
||||
if (bizModule == null || bizModule.isBlank()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
scheduler.resumeJobs(org.quartz.impl.matchers.GroupMatcher.groupEquals(bizModule));
|
||||
log.info("恢复模块[{}]下所有任务", bizModule);
|
||||
} catch (SchedulerException e) {
|
||||
log.error("恢复模块任务失败: module={}", bizModule, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模块删除该模块下所有任务
|
||||
*/
|
||||
public void deleteAllByModule(String bizModule) {
|
||||
if (bizModule == null || bizModule.isBlank()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.groupEquals(bizModule));
|
||||
scheduler.deleteJobs(new java.util.ArrayList<>(jobKeys));
|
||||
log.info("删除模块[{}]下所有任务,共{}个", bizModule, jobKeys.size());
|
||||
} catch (SchedulerException e) {
|
||||
log.error("删除模块任务失败: module={}", bizModule, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
package com.yfd.platform.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -12,8 +15,9 @@ import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RedisCacheUtil {
|
||||
|
||||
static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@ -41,6 +45,21 @@ public class RedisCacheUtil {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
public <T> T fromJson(String json, Class<T> clazz) {
|
||||
if (!StringUtils.isBlank(json) && clazz != null) {
|
||||
try {
|
||||
return (T)objectMapper.readValue(json, clazz);
|
||||
} catch (Exception var4) {
|
||||
if (log.isErrorEnabled()) {
|
||||
log.error(var4.getMessage(), var4);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(String key) {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
@ -111,9 +111,11 @@ spring:
|
||||
matching-strategy: ant_path_matcher
|
||||
data:
|
||||
redis:
|
||||
host: "${REDIS_HOST:172.16.21.142}"
|
||||
# host: "${REDIS_HOST:172.16.21.142}"
|
||||
host: "${REDIS_HOST:localhost}"
|
||||
port: "${REDIS_PORT:6379}"
|
||||
password: "${REDIS_PASSWORD:zny5678}"
|
||||
password: "${REDIS_PASSWORD:}"
|
||||
# password: "${REDIS_PASSWORD:zny5678}"
|
||||
database: "${REDIS_DATABASE:15}"
|
||||
timeout: 10000ms
|
||||
lettuce:
|
||||
|
||||
56
backend/src/main/resources/mapper/qgc_env/wq/WqJobMapper.xml
Normal file
56
backend/src/main/resources/mapper/qgc_env/wq/WqJobMapper.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?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.yfd.platform.qgc_env.wq.mapper.WqJobMapper">
|
||||
|
||||
<select id="getWqLastData" resultType="com.yfd.platform.qgc_env.wq.entity.SdWqR">
|
||||
SELECT SHR.*,CASE SHR.WQGRD
|
||||
WHEN '1' THEN 'Ⅰ'
|
||||
WHEN '2' THEN 'Ⅱ'
|
||||
WHEN '3' THEN 'Ⅲ'
|
||||
WHEN '4' THEN 'Ⅳ'
|
||||
WHEN '5' THEN 'Ⅴ'
|
||||
WHEN '6' THEN 'V'
|
||||
ELSE '未知'
|
||||
END AS wqgrdName FROM (
|
||||
SELECT STCD, MAX(TM) TM FROM SD_WQ_R WHERE NVL(IS_DELETED, 0) = 0 GROUP BY STCD
|
||||
) T LEFT JOIN SD_WQ_R SHR ON T.STCD = SHR.STCD AND SHR.TM = T.TM
|
||||
</select>
|
||||
|
||||
<select id="getWqYsLastData" resultType="com.yfd.platform.qgc_env.wq.entity.SdWqR">
|
||||
SELECT * FROM (
|
||||
SELECT SD_WQ_R.*,CASE SD_WQ_R.WQGRD
|
||||
WHEN '1' THEN 'Ⅰ'
|
||||
WHEN '2' THEN 'Ⅱ'
|
||||
WHEN '3' THEN 'Ⅲ'
|
||||
WHEN '4' THEN 'Ⅳ'
|
||||
WHEN '5' THEN 'Ⅴ'
|
||||
WHEN '6' THEN 'V'
|
||||
ELSE '未知'
|
||||
END AS wqgrdName,
|
||||
RANK() OVER (PARTITION BY STCD ORDER BY TM DESC) AS RANK
|
||||
FROM SD_WQ_R
|
||||
WHERE NVL(IS_DELETED, 0) = 0
|
||||
AND <![CDATA[ TM >= TO_DATE(#{startTimeStr}, 'yyyy-MM-dd HH24:mi:ss') ]]>
|
||||
AND <![CDATA[ TM <= TO_DATE(#{endTimeStr}, 'yyyy-MM-dd HH24:mi:ss') ]]>
|
||||
AND (NH3N IS NOT NULL OR TP IS NOT NULL OR TN IS NOT NULL)
|
||||
) WHERE RANK = 1
|
||||
</select>
|
||||
|
||||
<update id="mergeWqR">
|
||||
MERGE INTO SD_WQ_R T
|
||||
USING (
|
||||
<foreach collection="wqRs" index="index" item="wqR" open="" close="" separator="union all">
|
||||
SELECT #{wqR.id,jdbcType=VARCHAR} AS ID
|
||||
, #{wqR.wqgrd,jdbcType=VARCHAR} AS WQGRD
|
||||
, #{wqR.sfdb,jdbcType=NUMERIC} AS SFDB
|
||||
, #{wqR.wqSfdbhnYs,jdbcType=VARCHAR} AS WQ_SFDBHN_YS
|
||||
, SYSDATE AS MODIFY_TIME
|
||||
FROM DUAL
|
||||
</foreach>
|
||||
) S
|
||||
ON (T.ID = S.ID)
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET T.WQGRD = S.WQGRD, T.SFDB = S.SFDB, T.WQ_SFDBHN_YS = S.WQ_SFDBHN_YS, T.MODIFY_TIME = S.MODIFY_TIME
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,76 @@
|
||||
<?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.yfd.platform.system.mapper.PushConfigUserMapper">
|
||||
|
||||
<select id="selectAllActiveUsers" resultType="com.yfd.platform.system.domain.PushTargetUserVo">
|
||||
SELECT
|
||||
u.ID AS userId,
|
||||
NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME)) AS targetName,
|
||||
u.PHONE AS targetPhone
|
||||
FROM SYS_USER u
|
||||
WHERE u.STATUS = 1
|
||||
AND u.PHONE IS NOT NULL
|
||||
AND TRIM(u.PHONE) IS NOT NULL
|
||||
</select>
|
||||
|
||||
<select id="selectTargetUsersByConfigId" resultType="com.yfd.platform.system.domain.PushTargetUserVo">
|
||||
SELECT DISTINCT
|
||||
t.userId,
|
||||
t.targetName,
|
||||
t.targetPhone
|
||||
FROM (
|
||||
SELECT
|
||||
u.ID AS userId,
|
||||
NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME)) AS targetName,
|
||||
u.PHONE AS targetPhone
|
||||
FROM PUSH_CONFIG_USER pcu
|
||||
INNER JOIN SYS_USER u ON u.ID = pcu.USER_ROLE_ID
|
||||
WHERE pcu.CONFIG_ID = #{configId}
|
||||
AND pcu.TYPE = 0
|
||||
AND NVL(pcu.IS_DELETED, 0) = 0
|
||||
AND u.STATUS = 1
|
||||
AND u.PHONE IS NOT NULL
|
||||
AND TRIM(u.PHONE) IS NOT NULL
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
u.ID AS userId,
|
||||
NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME)) AS targetName,
|
||||
u.PHONE AS targetPhone
|
||||
FROM PUSH_CONFIG_USER pcu
|
||||
INNER JOIN SYS_ROLE_USERS sru ON sru.ROLEID = pcu.USER_ROLE_ID
|
||||
INNER JOIN SYS_USER u ON u.ID = sru.USERID
|
||||
WHERE pcu.CONFIG_ID = #{configId}
|
||||
AND pcu.TYPE = 1
|
||||
AND NVL(pcu.IS_DELETED, 0) = 0
|
||||
AND u.STATUS = 1
|
||||
AND u.PHONE IS NOT NULL
|
||||
AND TRIM(u.PHONE) IS NOT NULL
|
||||
) t
|
||||
</select>
|
||||
|
||||
<select id="selectConfigTargets" resultType="com.yfd.platform.system.domain.PushConfigTargetVo">
|
||||
SELECT
|
||||
pcu.ID AS id,
|
||||
pcu.CONFIG_ID AS configId,
|
||||
pcu.TYPE AS type,
|
||||
pcu.USER_ROLE_ID AS userRoleId,
|
||||
CASE
|
||||
WHEN pcu.TYPE = 0 THEN NVL(u.REAL_NAME, NVL(u.NICKNAME, u.USERNAME))
|
||||
ELSE r.ROLENAME
|
||||
END AS targetName,
|
||||
CASE
|
||||
WHEN pcu.TYPE = 0 THEN u.PHONE
|
||||
ELSE NULL
|
||||
END AS targetPhone
|
||||
FROM PUSH_CONFIG_USER pcu
|
||||
LEFT JOIN SYS_USER u ON pcu.TYPE = 0 AND u.ID = pcu.USER_ROLE_ID
|
||||
LEFT JOIN SYS_ROLE r ON pcu.TYPE = 1 AND r.ID = pcu.USER_ROLE_ID
|
||||
WHERE pcu.CONFIG_ID = #{configId}
|
||||
AND NVL(pcu.IS_DELETED, 0) = 0
|
||||
ORDER BY pcu.CREATED_AT DESC, pcu.ID DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@ -12,9 +12,9 @@ VITE_APP_BASE_API = '/dev-api'
|
||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
|
||||
# 汤伟
|
||||
VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||
# VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||
# 李林
|
||||
# VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||
VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||
|
||||
# 测试环境线上10.84.121.122:
|
||||
VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122'
|
||||
|
||||
100
frontend/src/api/system/map/pushManagement/index.ts
Normal file
100
frontend/src/api/system/map/pushManagement/index.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取列表
|
||||
export function getPushConfigList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushConfigList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//新增推送配置
|
||||
export function addPushConfig(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/addPushConfig',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
//修改新增配置
|
||||
export function deletePushConfig(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/deletePushConfig',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//删除新增配置
|
||||
export function updatePushConfig(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/updatePushConfig',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//推送目标配置 --用户
|
||||
export function queryUsersList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/queryUsersList',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//推送目标配置 -- 角色
|
||||
export function queryRolesList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/queryRolesList',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//查询推送目标
|
||||
export function getPushTargets(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushTargets',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//新增推送目标
|
||||
export function savePushTargets(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/savePushTargets',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//短信提醒状态修改
|
||||
export function setPushConfigSmsSwitch(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/setPushConfigSmsSwitch',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//获取推送历史列表
|
||||
export function postPushHistoryList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/postPushHistoryList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
//推送情况
|
||||
export function getPushHistoryDetailList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushHistoryDetailList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//s数量
|
||||
export function getPushHistoryDetailById(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushHistoryDetailById',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
@ -79,21 +79,21 @@ const data = ref([
|
||||
name: '正常',
|
||||
num: '0',
|
||||
warnState: '1',
|
||||
icon: 'iconfont icon-shuidianzhan1 zhuangji',
|
||||
icon: 'iconfont icon-map-rgszzDabiao zhuangji',
|
||||
background: '#78c300',
|
||||
},
|
||||
{
|
||||
name: '告警',
|
||||
num: '0',
|
||||
warnState: '2',
|
||||
icon: 'iconfont icon-shuidianzhanGaojing shebeiZhengchang',
|
||||
icon: 'iconfont icon-map-rgszzDabiao shebeiZhengchang',
|
||||
background: '#e55555',
|
||||
},
|
||||
{
|
||||
name: '无数据',
|
||||
num: '0',
|
||||
warnState: '0',
|
||||
icon: 'iconfont icon-shuidianzhanWushujv shebeiLixian',
|
||||
icon: 'iconfont icon-map-rgszzDabiao shebeiLixian',
|
||||
background: '#8d8d8d',
|
||||
},
|
||||
]);
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<a-button type="link" @click="backToLogin" class="back-button">
|
||||
<span>← 返回</span>
|
||||
</a-button>
|
||||
<h3 class="forgot-password-title">忘记密码</h3>
|
||||
<!-- <h3 class="forgot-password-title">忘记密码</h3> -->
|
||||
</div>
|
||||
|
||||
<a-form
|
||||
@ -32,7 +32,11 @@
|
||||
class="form-container"
|
||||
>
|
||||
<a-form-item label="" name="phone">
|
||||
<a-input placeholder="请输入手机号" size="large">
|
||||
<a-input
|
||||
v-model:value="forgotPasswordForm.phone"
|
||||
placeholder="请输入手机号"
|
||||
size="large"
|
||||
>
|
||||
<template #prefix>
|
||||
<MobileOutlined />
|
||||
</template>
|
||||
@ -42,9 +46,10 @@
|
||||
<a-form-item label="" name="captcha">
|
||||
<div class="captcha-row">
|
||||
<a-input
|
||||
v-model="forgotPasswordForm.captcha"
|
||||
v-model:value="forgotPasswordForm.captcha"
|
||||
placeholder="请输入验证码"
|
||||
size="large"
|
||||
autocomplete="current-captcha"
|
||||
class="captcha-input"
|
||||
>
|
||||
<template #prefix>
|
||||
@ -69,7 +74,8 @@
|
||||
|
||||
<a-form-item label="" name="newPassword">
|
||||
<a-input-password
|
||||
v-model="forgotPasswordForm.newPassword"
|
||||
v-model:value="forgotPasswordForm.newPassword"
|
||||
autocomplete="current-password"
|
||||
placeholder="请输入新密码"
|
||||
size="large"
|
||||
>
|
||||
@ -79,6 +85,19 @@
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="" name="confirmPassword">
|
||||
<a-input-password
|
||||
v-model:value="forgotPasswordForm.confirmPassword"
|
||||
autocomplete="current-confirmPassword"
|
||||
placeholder="请再次输入密码"
|
||||
size="large"
|
||||
>
|
||||
<template #prefix>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
</a-input-password>
|
||||
</a-form-item>
|
||||
|
||||
<a-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@ -162,32 +181,51 @@
|
||||
>
|
||||
<span>登录</span>
|
||||
</a-button>
|
||||
<!-- <a-button
|
||||
type="link"
|
||||
size="mini"
|
||||
block
|
||||
@click="showForgotPasswordPage"
|
||||
:style="{ marginTop: '10px', border: 'none' }"
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
忘记密码
|
||||
</a-button> -->
|
||||
<a-checkbox v-model:checked="remember" style="margin-top: 10px"
|
||||
>记住密码</a-checkbox
|
||||
>
|
||||
<a-button
|
||||
type="link"
|
||||
size="mini"
|
||||
@click="showForgotPasswordPage"
|
||||
:style="{ marginTop: '10px', border: 'none' }"
|
||||
>
|
||||
忘记密码
|
||||
</a-button>
|
||||
<!-- <a-button
|
||||
type="link"
|
||||
size="mini"
|
||||
@click="goRegister"
|
||||
:style="{ marginTop: '10px', border: 'none' }"
|
||||
>
|
||||
用户注册
|
||||
</a-button> -->
|
||||
</div>
|
||||
|
||||
<!-- 忘记密码 -->
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
|
||||
<!-- 短信登录 Tab (占位) -->
|
||||
<!-- <a-tab-pane key="sms" tab="短信登录">
|
||||
<a-tab-pane key="sms" tab="短信登录">
|
||||
<a-form
|
||||
:model="loginData"
|
||||
:rules="loginRules"
|
||||
:rules="state.smsLoginRules"
|
||||
layout="vertical"
|
||||
class="form-container"
|
||||
@finish="onSmsLogin"
|
||||
>
|
||||
<a-form-item label="" name="username">
|
||||
<a-input
|
||||
v-model:value="loginData.username"
|
||||
autocomplete="current-username"
|
||||
placeholder="请输入手机号"
|
||||
size="large"
|
||||
>
|
||||
@ -199,9 +237,8 @@
|
||||
<a-form-item label="" name="captcha">
|
||||
<div class="captcha-row">
|
||||
<a-input
|
||||
v-model="loginData.code"
|
||||
v-model:value="loginData.code"
|
||||
placeholder="请输入验证码"
|
||||
autocomplete="current-captcha"
|
||||
size="large"
|
||||
class="captcha-input"
|
||||
>
|
||||
@ -235,8 +272,36 @@
|
||||
>
|
||||
<span>登录</span>
|
||||
</a-button>
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
"
|
||||
>
|
||||
<a-button
|
||||
type="link"
|
||||
size="mini"
|
||||
block
|
||||
@click="showForgotPasswordPage"
|
||||
:style="{ marginTop: '10px', border: 'none' }"
|
||||
style="width: 20%;"
|
||||
>
|
||||
忘记密码
|
||||
</a-button>
|
||||
<!-- <a-button
|
||||
type="link"
|
||||
size="mini"
|
||||
block
|
||||
@click="goRegister"
|
||||
:style="{ marginTop: '10px', border: 'none' }"
|
||||
>
|
||||
注册
|
||||
</a-button> -->
|
||||
</div>
|
||||
</a-form>
|
||||
</a-tab-pane> -->
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</div>
|
||||
@ -248,19 +313,23 @@
|
||||
import { onMounted, reactive, ref, toRefs, watch } from "vue";
|
||||
import loginImg from "@/assets/images/logo.png";
|
||||
import { UserOutlined, LockOutlined, MobileOutlined } from "@ant-design/icons-vue";
|
||||
import { getCaptcha } from "@/api/auth";
|
||||
import { getCaptcha, sendSmsCode, smsLoginApi, resetPassword } from "@/api/auth";
|
||||
import { message } from "ant-design-vue";
|
||||
import { setToken } from "@/utils/auth";
|
||||
import Cookies from "js-cookie";
|
||||
// 组件依赖
|
||||
|
||||
import router from "@/router";
|
||||
// API依赖
|
||||
import { useRoute } from "vue-router";
|
||||
import { LoginData } from "@/api/auth/types";
|
||||
|
||||
//密码加密
|
||||
import { encrypt } from "@/utils/rsaEncrypt";
|
||||
import { encrypt, decrypt } from "@/utils/rsaEncrypt";
|
||||
|
||||
// 状态管理依赖
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
|
||||
// 国际化
|
||||
import { useI18n } from "vue-i18n";
|
||||
@ -280,6 +349,7 @@ const forgotPasswordForm = ref({
|
||||
phone: "",
|
||||
captcha: "",
|
||||
newPassword: "",
|
||||
confirmPassword: "",
|
||||
});
|
||||
// 忘记密码
|
||||
const showForgotPassword = ref(false);
|
||||
@ -299,6 +369,10 @@ const state = reactive({
|
||||
password: [{ required: true, trigger: "blur", message: t("login.rulesPassword") }],
|
||||
code: [{ required: true, trigger: "blur", message: "请输入验证码" }],
|
||||
},
|
||||
smsLoginRules: {
|
||||
username: [{ required: true, trigger: "blur", message: "请输入手机号" }],
|
||||
code: [{ required: true, trigger: "blur", message: "请输入验证码" }],
|
||||
},
|
||||
loginImg: loginImg[0],
|
||||
loading: false,
|
||||
passwordType: "password",
|
||||
@ -320,15 +394,80 @@ const forgotPasswordRules = ref({
|
||||
captcha: [{ required: true, message: "验证码不能为空", trigger: "blur" }],
|
||||
newPassword: [
|
||||
{ required: true, message: "新密码不能为空", trigger: "blur" },
|
||||
{ min: 6, message: "密码长度不能少于6位", trigger: "blur" },
|
||||
{ min: 10, message: "密码长度不能少于10位", trigger: "blur" },
|
||||
{
|
||||
validator: (rule: any, value: string) => {
|
||||
if (!value) return Promise.resolve();
|
||||
|
||||
// 检查密码复杂度:至少包含四类字符中的三类
|
||||
const hasUpperCase = /[A-Z]/.test(value);
|
||||
const hasLowerCase = /[a-z]/.test(value);
|
||||
const hasNumber = /\d/.test(value);
|
||||
const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value);
|
||||
|
||||
const typeCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecialChar].filter(
|
||||
Boolean
|
||||
).length;
|
||||
|
||||
if (typeCount < 3) {
|
||||
return Promise.reject(
|
||||
new Error("密码必须包含大写字母、小写字母、数字、特殊字符中的至少三种")
|
||||
);
|
||||
}
|
||||
|
||||
// 检查连续重复字符
|
||||
if (/(.)\1{1,}/.test(value)) {
|
||||
return Promise.reject(new Error("密码不能包含连续重复字符"));
|
||||
}
|
||||
|
||||
// 检查连续递增/递减数字
|
||||
for (let i = 0; i < value.length - 1; i++) {
|
||||
if (/\d/.test(value[i]) && /\d/.test(value[i + 1])) {
|
||||
const diff = value.charCodeAt(i + 1) - value.charCodeAt(i);
|
||||
if (Math.abs(diff) === 1) {
|
||||
return Promise.reject(new Error("密码不能包含连续递增或递减的数字"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查连续递增/递减字母
|
||||
for (let i = 0; i < value.length - 1; i++) {
|
||||
if (/[a-zA-Z]/.test(value[i]) && /[a-zA-Z]/.test(value[i + 1])) {
|
||||
const diff = value.charCodeAt(i + 1) - value.charCodeAt(i);
|
||||
if (Math.abs(diff) === 1) {
|
||||
return Promise.reject(new Error("密码不能包含连续递增或递减的字母"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
},
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
confirmPassword: [
|
||||
// { required: true, message: "请再次输入密码", trigger: "blur" },
|
||||
{
|
||||
validator: (rule: any, value: string) => {
|
||||
if (!value) {
|
||||
return Promise.reject(new Error("请再次输入密码"));
|
||||
}
|
||||
if (value !== forgotPasswordForm.value.newPassword) {
|
||||
return Promise.reject(new Error("两次输入的密码不一致"));
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const { loginData, loginRules, loading,
|
||||
// passwordType, capslockTooltipDisabled
|
||||
} = toRefs(
|
||||
state
|
||||
);
|
||||
const {
|
||||
loginData,
|
||||
loginRules,
|
||||
loading,
|
||||
// passwordType, capslockTooltipDisabled
|
||||
} = toRefs(state);
|
||||
|
||||
// function checkCapslock(e: any) {
|
||||
// const { key } = e;
|
||||
@ -364,8 +503,19 @@ function onFinish() {
|
||||
userStore
|
||||
.login(user)
|
||||
.then(() => {
|
||||
if (remember.value == true) {
|
||||
Cookies.set("username", user.username, { expires: 30 });
|
||||
Cookies.set("password", user.password, { expires: 30 });
|
||||
Cookies.set("rememberMe", String(remember.value), { expires: 30 });
|
||||
} else {
|
||||
// 如果用户取消勾选记住密码,应该移除 cookie
|
||||
Cookies.remove("username");
|
||||
Cookies.remove("password");
|
||||
Cookies.remove("rememberMe");
|
||||
}
|
||||
router.push({ path: "/" });
|
||||
state.loading = false;
|
||||
message.success("登录成功");
|
||||
})
|
||||
.catch(() => {
|
||||
getCode();
|
||||
@ -373,6 +523,93 @@ function onFinish() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信验证码登录
|
||||
*/
|
||||
const onSmsLogin = async () => {
|
||||
try {
|
||||
// ========== 第一部分:表单验证 ==========
|
||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||
if (!loginData.value.username || !phoneRegex.test(loginData.value.username)) {
|
||||
message.error("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!loginData.value.code || loginData.value.code.trim() === "") {
|
||||
message.error("请输入验证码");
|
||||
return;
|
||||
}
|
||||
|
||||
// ========== 第二部分:设置加载状态 ==========
|
||||
state.loading = true;
|
||||
|
||||
// ========== 第三部分:调用短信登录 API ==========
|
||||
console.log("开始调用短信登录API, 手机号:", loginData.value.username);
|
||||
const res: any = await smsLoginApi(
|
||||
loginData.value.username, // 手机号
|
||||
loginData.value.code // 短信验证码
|
||||
);
|
||||
console.log("短信登录API响应:", res);
|
||||
|
||||
// ========== 第四部分:检查响应结果 ==========
|
||||
console.log("检查响应结果, res.code:", res.code, "类型:", typeof res.code);
|
||||
|
||||
// 注意:code 可能是字符串 "0" 或数字 0,需要兼容处理
|
||||
if (res.code !== 0 && res.code !== "0") {
|
||||
console.error("短信登录失败, 错误码:", res.code, "错误信息:", res.msg);
|
||||
message.error(res.msg || "登录失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// ========== 第五部分:提取并存储 Token ==========
|
||||
console.log("开始提取Token, res.data:", res.data);
|
||||
const token = res.data?.token || res.data; // 兼容两种结构
|
||||
|
||||
if (!token) {
|
||||
console.error("Token为空, res.data结构:", JSON.stringify(res.data));
|
||||
message.error("登录失败:未获取到Token");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Token获取成功:", token);
|
||||
// 存储到 Cookie
|
||||
setToken(token);
|
||||
|
||||
// 更新 Store 状态(注意是大写 Token)
|
||||
userStore.Token = token;
|
||||
console.log("Token已存储到Store");
|
||||
|
||||
// ========== 第六部分:获取用户信息和角色 ==========
|
||||
console.log("开始获取用户信息...");
|
||||
const userInfo = await userStore.getInfo();
|
||||
console.log("用户信息获取成功:", userInfo);
|
||||
const roles = userInfo.roles;
|
||||
console.log("用户角色:", roles);
|
||||
|
||||
// ========== 第七部分:生成路由(获取菜单)==========
|
||||
console.log("开始生成路由...");
|
||||
const permissionStore = usePermissionStoreHook();
|
||||
const accessRoutes: any = await permissionStore.generateRoutes(roles);
|
||||
console.log("路由生成成功, 路由数量:", accessRoutes.length);
|
||||
|
||||
// ========== 第八部分:动态添加路由 ==========
|
||||
accessRoutes.forEach((route: any) => {
|
||||
router.addRoute(route);
|
||||
});
|
||||
|
||||
// ========== 第九部分:设置路径并跳转 ==========
|
||||
router.push({ path: accessRoutes[0].children[0].opturl });
|
||||
message.success("登录成功");
|
||||
} catch (error: any) {
|
||||
// ========== 第十部分:错误处理 ==========
|
||||
console.error("短信登录失败", error);
|
||||
message.error(error.message || "登录失败,请重试");
|
||||
} finally {
|
||||
// ========== 第十一部分:关闭加载状态 ==========
|
||||
state.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
route,
|
||||
() => {
|
||||
@ -395,6 +632,22 @@ function getOtherQuery(query: any) {
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
function getCookie() {
|
||||
const username = Cookies.get("username");
|
||||
let password = Cookies.get("password");
|
||||
const rememberMe = Cookies.get("rememberMe");
|
||||
rememberMe == "true" ? (remember.value = Boolean(rememberMe)) : false;
|
||||
// 保存cookie里面的加密后的密码
|
||||
state.cookiePass = password === undefined ? "" : password;
|
||||
password = password === undefined ? state.loginData.password : password;
|
||||
state.loginData = {
|
||||
username: username === undefined ? state.loginData.username : username,
|
||||
password: decrypt(password),
|
||||
code: "",
|
||||
uuid: "",
|
||||
};
|
||||
remember.value = rememberMe === undefined ? false : Boolean(rememberMe);
|
||||
}
|
||||
function getCode() {
|
||||
getCaptcha().then((result: any) => {
|
||||
codeUrl.value = result.data.img;
|
||||
@ -420,7 +673,10 @@ const startCountdown = () => {
|
||||
const showForgotPasswordPage = () => {
|
||||
showForgotPassword.value = true;
|
||||
};
|
||||
|
||||
//注册用户页面
|
||||
const goRegister = () => {
|
||||
router.push({ path: "/register" });
|
||||
};
|
||||
// 返回登录页面
|
||||
const backToLogin = () => {
|
||||
showForgotPassword.value = false;
|
||||
@ -429,6 +685,7 @@ const backToLogin = () => {
|
||||
phone: "",
|
||||
captcha: "",
|
||||
newPassword: "",
|
||||
confirmPassword: "",
|
||||
};
|
||||
};
|
||||
|
||||
@ -456,10 +713,13 @@ const sendSms = async () => {
|
||||
smsButtonDisabled.value = true;
|
||||
|
||||
try {
|
||||
// 模拟发送短信验证码接口
|
||||
// await axios.post('/sms/send', { phone: loginForm.value.username })
|
||||
|
||||
// 模拟发送成功
|
||||
// 调用发送短信验证码接口,type默认为1(注册类型)
|
||||
const res: any = await sendSmsCode(loginData.value.username, 3);
|
||||
if (res.code == 1) {
|
||||
message.success(res.msg);
|
||||
return;
|
||||
}
|
||||
// 发送成功
|
||||
message.success("验证码发送成功");
|
||||
|
||||
// 开始倒计时
|
||||
@ -496,17 +756,23 @@ const sendForgotPasswordSms = async () => {
|
||||
smsButtonDisabled.value = true;
|
||||
|
||||
try {
|
||||
// 模拟发送短信验证码接口
|
||||
// await axios.post('/sms/forgot-password', { phone: forgotPasswordForm.value.phone })
|
||||
// 调用发送短信验证码接口,type=3表示找回密码类型
|
||||
const res: any = await sendSmsCode(forgotPasswordForm.value.phone, 2);
|
||||
|
||||
// 模拟发送成功
|
||||
if (res.code == 1) {
|
||||
message.error(res.msg);
|
||||
smsButtonDisabled.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送成功
|
||||
message.success("验证码发送成功");
|
||||
|
||||
// 开始倒计时
|
||||
startCountdown();
|
||||
} catch (error) {
|
||||
console.error("发送验证码失败", error);
|
||||
message.error("验证码发送失败,请重试");
|
||||
} catch (error: any) {
|
||||
// console.error("发送验证码失败", error);
|
||||
// message.error(error.message || "验证码发送失败,请重试");
|
||||
smsButtonDisabled.value = false;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
@ -514,23 +780,117 @@ const sendForgotPasswordSms = async () => {
|
||||
};
|
||||
// 处理密码重置
|
||||
const handleResetPassword = async () => {
|
||||
loading.value = true;
|
||||
// 先进行表单验证
|
||||
try {
|
||||
// 2. 模拟接口请求 (实际替换为真实重置密码接口)
|
||||
// await axios.post('/user/reset-password', {
|
||||
// phone: forgotPasswordForm.value.phone,
|
||||
// captcha: forgotPasswordForm.value.captcha,
|
||||
// newPassword: forgotPasswordForm.value.newPassword
|
||||
// })
|
||||
// 手动验证各个字段
|
||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||
if (
|
||||
!forgotPasswordForm.value.phone ||
|
||||
!phoneRegex.test(forgotPasswordForm.value.phone)
|
||||
) {
|
||||
message.error("请输入正确的手机号");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 模拟重置成功
|
||||
message.success("密码重置成功");
|
||||
if (!forgotPasswordForm.value.captcha) {
|
||||
message.error("请输入验证码");
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 返回登录页面
|
||||
backToLogin();
|
||||
if (!forgotPasswordForm.value.newPassword) {
|
||||
message.error("请输入新密码");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证确认密码
|
||||
if (!forgotPasswordForm.value.confirmPassword) {
|
||||
message.error("请再次输入密码");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证两次密码是否一致
|
||||
if (
|
||||
forgotPasswordForm.value.newPassword !== forgotPasswordForm.value.confirmPassword
|
||||
) {
|
||||
message.error("两次输入的密码不一致");
|
||||
return;
|
||||
}
|
||||
|
||||
// 密码复杂度校验
|
||||
const password = forgotPasswordForm.value.newPassword;
|
||||
if (password.length < 10) {
|
||||
message.error("密码长度不能少于10位");
|
||||
return;
|
||||
}
|
||||
|
||||
const hasUpperCase = /[A-Z]/.test(password);
|
||||
const hasLowerCase = /[a-z]/.test(password);
|
||||
const hasNumber = /\d/.test(password);
|
||||
const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password);
|
||||
|
||||
const typeCount = [hasUpperCase, hasLowerCase, hasNumber, hasSpecialChar].filter(
|
||||
Boolean
|
||||
).length;
|
||||
if (typeCount < 3) {
|
||||
message.error("密码必须包含大写字母、小写字母、数字、特殊字符中的至少三种");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查连续重复字符
|
||||
if (/(.)\1{1,}/.test(password)) {
|
||||
message.error("密码不能包含连续重复字符");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查连续递增/递减数字
|
||||
for (let i = 0; i < password.length - 1; i++) {
|
||||
if (/\d/.test(password[i]) && /\d/.test(password[i + 1])) {
|
||||
const diff = password.charCodeAt(i + 1) - password.charCodeAt(i);
|
||||
if (Math.abs(diff) === 1) {
|
||||
message.error("密码不能包含连续递增或递减的数字");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查连续递增/递减字母
|
||||
for (let i = 0; i < password.length - 1; i++) {
|
||||
if (/[a-zA-Z]/.test(password[i]) && /[a-zA-Z]/.test(password[i + 1])) {
|
||||
const diff = password.charCodeAt(i + 1) - password.charCodeAt(i);
|
||||
if (Math.abs(diff) === 1) {
|
||||
message.error("密码不能包含连续递增或递减的字母");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("密码重置失败", error);
|
||||
message.error("密码重置失败,请重试");
|
||||
console.error("表单验证失败", error);
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
// 对密码进行 RSA 加密
|
||||
const encryptedPassword = encrypt(forgotPasswordForm.value.newPassword);
|
||||
|
||||
// 调用重置密码接口,使用加密后的密码
|
||||
const res: any = await resetPassword(
|
||||
forgotPasswordForm.value.phone,
|
||||
forgotPasswordForm.value.captcha,
|
||||
encryptedPassword
|
||||
);
|
||||
|
||||
if (res.code == 0) {
|
||||
message.success("密码重置成功");
|
||||
// 返回登录页面
|
||||
backToLogin();
|
||||
} else {
|
||||
message.error(res.msg || "密码重置失败");
|
||||
}
|
||||
} catch (error: any) {
|
||||
// console.error("密码重置失败", error);
|
||||
// message.error(error.message || "密码重置失败,请重试");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
@ -538,6 +898,7 @@ const handleResetPassword = async () => {
|
||||
|
||||
onMounted(() => {
|
||||
getCode();
|
||||
getCookie();
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -592,7 +953,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.login-wrapper {
|
||||
position: relative;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 72%;
|
||||
min-height: 600px;
|
||||
@ -603,7 +964,7 @@ onMounted(() => {
|
||||
|
||||
// 左侧背景区域
|
||||
.left-section {
|
||||
.slogan {
|
||||
.slogan {
|
||||
position: absolute;
|
||||
top: 28%;
|
||||
left: 18%;
|
||||
@ -635,10 +996,12 @@ onMounted(() => {
|
||||
/* 验证码布局 */
|
||||
.captcha-row {
|
||||
display: flex;
|
||||
|
||||
.ant-row {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* gap: 12px;
|
||||
align-items: center; */
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:title="isEdit ? '编辑沿程配置' : '新增沿程配置'"
|
||||
:title="isEdit ? '修改编辑推送类型' : '新增编辑推送类型'"
|
||||
v-model:open="modalVisible"
|
||||
:confirm-loading="localLoading"
|
||||
width="1200px"
|
||||
width="35vw"
|
||||
:destroy-on-close="true"
|
||||
ok-text="保存"
|
||||
@cancel="handleCancel"
|
||||
@ -14,279 +14,105 @@
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
name="edit_form"
|
||||
:labelCol="{ span: 5 }"
|
||||
:labelCol="{ span: 4 }"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="沿程配置名称" name="name">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="类型名称" name="messageType">
|
||||
<a-input
|
||||
v-model:value="formData.name"
|
||||
v-model:value="formData.messageType"
|
||||
style="width: 100%"
|
||||
placeholder="请输入沿程配置名称"
|
||||
/> </a-form-item
|
||||
></a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="配置编码" name="code">
|
||||
<a-input
|
||||
v-model:value="formData.code"
|
||||
style="width: 100%"
|
||||
placeholder="请输入配置编码"
|
||||
placeholder="请输入类型名称"
|
||||
/> </a-form-item
|
||||
></a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="所在河段" name="rvnm">
|
||||
<a-input
|
||||
v-model:value="formData.rvnm"
|
||||
<a-col :span="24">
|
||||
<a-form-item label="所属类别" name="categoryCode">
|
||||
<a-select
|
||||
v-model:value="formData.categoryCode"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
placeholder="请输入所在河段"
|
||||
/> </a-form-item
|
||||
></a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="备注" name="description">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
v-model:value="formData.description"
|
||||
style="width: 100%"
|
||||
placeholder="请输入备注"
|
||||
/> </a-form-item
|
||||
:options="categoryCodeOption"
|
||||
@change="handleCategoryChange"
|
||||
></a-select> </a-form-item
|
||||
></a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<div class="config-tree-container">
|
||||
<!-- 新增一级节点区域 -->
|
||||
<div v-if="addingNewNode" class="add-node-row">
|
||||
<a-select
|
||||
v-model:value="newNodeData.stcd"
|
||||
show-search
|
||||
placeholder="请选择站点"
|
||||
style="width: 300px"
|
||||
:filter-option="filterOption"
|
||||
@change="handleNodeSelect"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in stationList"
|
||||
:key="item.stcd"
|
||||
:value="item.stcd"
|
||||
>
|
||||
{{ item.stnm }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click="handleSaveNewNode"
|
||||
style="margin-left: 8px"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
<a-button @click="handleCancelAdd" style="margin-left: 8px">
|
||||
<MinusOutlined />
|
||||
</a-button>
|
||||
</div>
|
||||
<a-button v-else class="mb-4" type="primary" @click="handleAdd">
|
||||
<PlusOutlined /> 新增一级节点
|
||||
</a-button>
|
||||
|
||||
<!-- 树形结构 -->
|
||||
<a-tree
|
||||
v-if="treeData.length > 0"
|
||||
:tree-data="treeData"
|
||||
:default-expand-all="false"
|
||||
:selectable="false"
|
||||
block-node
|
||||
style="width: 300px"
|
||||
>
|
||||
<template #title="{ dataRef }">
|
||||
<!-- 编辑状态:只显示编辑区域 -->
|
||||
<div
|
||||
v-if="editingNode && editingNodeKey === dataRef.key"
|
||||
class="add-child-node-row w-[300px]"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="关联基地">
|
||||
<a-select
|
||||
v-model:value="editNodeData.stcd"
|
||||
show-search
|
||||
placeholder="请选择站点"
|
||||
style="width: 300px"
|
||||
:filter-option="filterOption"
|
||||
@change="handleEditNodeSelect"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in stationList"
|
||||
:key="item.stcd"
|
||||
:value="item.stcd"
|
||||
>
|
||||
{{ item.stnm }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.stop="handleSaveEditNode"
|
||||
style="margin-left: 8px"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
<a-button
|
||||
@click.stop="handleCancelEditNode"
|
||||
style="margin-left: 8px"
|
||||
>
|
||||
<MinusOutlined />
|
||||
</a-button>
|
||||
</div>
|
||||
<!-- 非编辑状态:显示正常节点内容 -->
|
||||
<template v-else>
|
||||
<div class="tree-node-wrapper">
|
||||
<span class="tree-node-title"> {{ getNodeTitle(dataRef) }} </span>
|
||||
<div class="tree-node-actions">
|
||||
<!-- 一级节点:支持新增子节点、编辑、排序、删除 -->
|
||||
<template v-if="!dataRef.parentId">
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleAddChild(dataRef)"
|
||||
title="添加子节点"
|
||||
>
|
||||
<PlusOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleEditNode(dataRef)"
|
||||
title="编辑"
|
||||
>
|
||||
<EditOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleMoveUp(dataRef)"
|
||||
title="上移"
|
||||
:disabled="isFirstNode(dataRef)"
|
||||
>
|
||||
<ArrowUpOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleMoveDown(dataRef)"
|
||||
title="下移"
|
||||
:disabled="isLastNode(dataRef)"
|
||||
>
|
||||
<ArrowDownOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click.stop="handleDeleteNode(dataRef)"
|
||||
title="删除"
|
||||
>
|
||||
<DeleteOutlined />
|
||||
</a-button>
|
||||
</template>
|
||||
<!-- 二级节点:只支持编辑、排序、删除 -->
|
||||
<template v-else>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleEditNode(dataRef)"
|
||||
title="编辑"
|
||||
>
|
||||
<EditOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleMoveUp(dataRef)"
|
||||
title="上移"
|
||||
:disabled="isFirstNode(dataRef)"
|
||||
>
|
||||
<ArrowUpOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@click.stop="handleMoveDown(dataRef)"
|
||||
title="下移"
|
||||
:disabled="isLastNode(dataRef)"
|
||||
>
|
||||
<ArrowDownOutlined />
|
||||
</a-button>
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
@click.stop="handleDeleteNode(dataRef)"
|
||||
title="删除"
|
||||
>
|
||||
<DeleteOutlined />
|
||||
</a-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 子节点添加区域 -->
|
||||
v-model:value="formData.baseIdList"
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
placeholder="请选择"
|
||||
:options="baseIdsOption"
|
||||
@change="handleBaseChange"
|
||||
></a-select> </a-form-item
|
||||
></a-col>
|
||||
</a-row>
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item
|
||||
label="定时任务"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
<div
|
||||
v-if="addingChildNode && currentParentKey === dataRef.key"
|
||||
class="add-child-node-row"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
<a-select
|
||||
v-model:value="childNodeData.stcd"
|
||||
show-search
|
||||
placeholder="请选择站点"
|
||||
style="width: 300px"
|
||||
:filter-option="filterOption"
|
||||
@change="handleChildNodeSelect"
|
||||
<a-input
|
||||
v-model:value="formData.cronExpression"
|
||||
style="width: 70%"
|
||||
placeholder="请输入cron表达式"
|
||||
/>
|
||||
<a-button style="width: 27%" @click="openCronModal"
|
||||
>cron表达式</a-button
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in stationList"
|
||||
:key="item.stcd"
|
||||
:value="item.stcd"
|
||||
>
|
||||
{{ item.stnm }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
<a-button
|
||||
type="primary"
|
||||
@click.stop="handleSaveChildNode"
|
||||
style="margin-left: 8px"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
<a-button
|
||||
@click.stop="handleCancelAddChild"
|
||||
style="margin-left: 8px"
|
||||
>
|
||||
<MinusOutlined />
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-tree>
|
||||
<a-empty v-else description="暂无数据" style="margin-top: 20px" />
|
||||
</div>
|
||||
</a-form-item></a-col
|
||||
>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<a-modal
|
||||
title="Cron表达式选择器"
|
||||
v-model:open="cronModalVisible"
|
||||
width="1200px"
|
||||
:destroy-on-close="true"
|
||||
footer=""
|
||||
@cancel="closeCronModal"
|
||||
>
|
||||
<CronPicker
|
||||
v-model="formData.cronExpression"
|
||||
@confirm="handleCronConfirm"
|
||||
/>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch } from 'vue';
|
||||
import { ref, reactive, computed, watch,onMounted } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
PlusOutlined,
|
||||
MinusOutlined,
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
ArrowUpOutlined,
|
||||
ArrowDownOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
|
||||
import CronPicker from './CronPicker.vue';
|
||||
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
|
||||
import { getDictItemsByCode } from '@/api/dict';
|
||||
import { useDraggable } from '@/utils/drag';
|
||||
interface Props {
|
||||
visible: boolean;
|
||||
initialValues?: any | null;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const categoryCodeOption:any =ref([])
|
||||
const localLoading = ref(false);
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visible: false,
|
||||
@ -309,368 +135,82 @@ const formRef = ref();
|
||||
|
||||
const defaultFormData = reactive({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
code: undefined,
|
||||
rvnm: undefined,
|
||||
description: undefined
|
||||
messageType: undefined,
|
||||
categoryCode: undefined,
|
||||
categoryName: undefined,
|
||||
baseIdList: [],
|
||||
baseNameList: [],
|
||||
cronExpression: undefined
|
||||
});
|
||||
const formData: any = reactive({ ...defaultFormData });
|
||||
const JidiSelectEventStore = useJidiSelectEventStore(); //jidiData
|
||||
const baseIdsOption = computed(() => {
|
||||
const hasAll = (formData.baseIdList || []).includes('all');
|
||||
return JidiSelectEventStore.jidiData.map(item => ({
|
||||
value: item.wbsCode,
|
||||
label: item.wbsName,
|
||||
disabled: hasAll && item.wbsCode !== 'all'
|
||||
}));
|
||||
});
|
||||
|
||||
const handleBaseChange = (value: string[]) => {
|
||||
if ((value || []).includes('all')) {
|
||||
formData.baseIdList = ['all'];
|
||||
formData.baseNameList = ['当前全部'];
|
||||
} else {
|
||||
formData.baseNameList = (value || []).map(code => {
|
||||
const item = JidiSelectEventStore.jidiData.find(d => d.wbsCode === code);
|
||||
return item?.wbsName || '';
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleCategoryChange = (value: string) => {
|
||||
const option = categoryCodeOption.value.find(o => o.value === value);
|
||||
formData.categoryName = option?.label || '';
|
||||
};
|
||||
const rules: Record<string, Rule[]> = {
|
||||
name: [{ required: true, message: '请输入沿程配置名称', trigger: 'blur' }],
|
||||
code: [{ required: true, message: '请输入配置编码', trigger: 'blur' }],
|
||||
rvnm: [{ required: true, message: '请输入所在河段', trigger: 'blur' }]
|
||||
messageType: [{ required: true, message: '请输入类型名称', trigger: 'blur' }],
|
||||
categoryCode: [{ required: true, message: '请选择所属类别', trigger: 'blur' }]
|
||||
};
|
||||
|
||||
const isEdit = computed(() => !!props.initialValues);
|
||||
|
||||
// 树形数据
|
||||
const treeData = ref<any[]>([]);
|
||||
|
||||
// 新增节点相关
|
||||
const addingNewNode = ref(false);
|
||||
const newNodeData = ref({
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: ''
|
||||
});
|
||||
|
||||
// 添加子节点相关
|
||||
const addingChildNode = ref(false);
|
||||
const currentParentKey = ref<string | null>(null);
|
||||
const childNodeData = ref({
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: ''
|
||||
});
|
||||
|
||||
// 编辑节点相关
|
||||
const editingNode = ref(false);
|
||||
const editingNodeKey = ref<string | null>(null);
|
||||
const editNodeData = ref({
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: '',
|
||||
originalData: null as any
|
||||
});
|
||||
|
||||
// 站点列表(模拟数据,实际应从接口获取)
|
||||
const stationList = ref([
|
||||
{ stcd: '1', stnm: '站点A', sttpName: '类型1' },
|
||||
{ stcd: '2', stnm: '站点B', sttpName: '类型2' },
|
||||
{ stcd: '3', stnm: '站点C', sttpName: '类型1' },
|
||||
{ stcd: '4', stnm: '站点D', sttpName: '类型3' }
|
||||
]);
|
||||
|
||||
// 生成唯一ID
|
||||
let nodeIdCounter = 0;
|
||||
const generateNodeId = () => `node_${Date.now()}_${++nodeIdCounter}`;
|
||||
|
||||
// 获取节点标题
|
||||
const getNodeTitle = (dataRef: any) => {
|
||||
if (!dataRef.parentId) {
|
||||
// 一级节点:只显示 stnm
|
||||
return dataRef.stnm || '';
|
||||
} else {
|
||||
// 二级节点:显示 stnm + sttpName
|
||||
return `${dataRef.stnm || ''} ${dataRef.sttpName || ''}`;
|
||||
}
|
||||
const cronModalVisible = ref(false);
|
||||
useDraggable(modalVisible, { boundary: true, resetOnOpen: true });
|
||||
useDraggable(cronModalVisible, { boundary: true, resetOnOpen: true });
|
||||
const openCronModal = () => {
|
||||
cronModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 搜索过滤
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return (
|
||||
option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
);
|
||||
const closeCronModal = () => {
|
||||
cronModalVisible.value = false;
|
||||
};
|
||||
|
||||
// 判断是否为第一个节点
|
||||
const isFirstNode = (dataRef: any) => {
|
||||
const siblings = getSiblings(dataRef);
|
||||
return siblings.length > 0 && siblings[0].key === dataRef.key;
|
||||
const handleCronConfirm = (value: string) => {
|
||||
formData.cronExpression = value;
|
||||
closeCronModal();
|
||||
};
|
||||
|
||||
// 判断是否为最后一个节点
|
||||
const isLastNode = (dataRef: any) => {
|
||||
const siblings = getSiblings(dataRef);
|
||||
return (
|
||||
siblings.length > 0 && siblings[siblings.length - 1].key === dataRef.key
|
||||
);
|
||||
};
|
||||
|
||||
// 获取兄弟节点
|
||||
const getSiblings = (dataRef: any) => {
|
||||
if (!dataRef.parentId) {
|
||||
// 一级节点
|
||||
return treeData.value;
|
||||
} else {
|
||||
// 二级节点,找到父节点的 children
|
||||
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||
return parent?.children || [];
|
||||
}
|
||||
};
|
||||
|
||||
// 根据 key 查找节点
|
||||
const findNodeByKey = (nodes: any[], key: string): any => {
|
||||
for (const node of nodes) {
|
||||
if (node.key === key) {
|
||||
return node;
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
const found = findNodeByKey(node.children, key);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// 新增一级节点
|
||||
const handleAdd = () => {
|
||||
addingNewNode.value = true;
|
||||
newNodeData.value = {
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: ''
|
||||
};
|
||||
};
|
||||
|
||||
// 选择节点
|
||||
const handleNodeSelect = (value: string) => {
|
||||
const station = stationList.value.find(item => item.stcd === value);
|
||||
if (station) {
|
||||
newNodeData.value.stnm = station.stnm;
|
||||
newNodeData.value.sttpName = station.sttpName;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存新增节点
|
||||
const handleSaveNewNode = () => {
|
||||
if (!newNodeData.value.stcd) {
|
||||
message.error('请选择站点');
|
||||
return;
|
||||
}
|
||||
|
||||
const newNode = {
|
||||
key: generateNodeId(),
|
||||
stcd: newNodeData.value.stcd,
|
||||
stnm: newNodeData.value.stnm,
|
||||
sttpName: newNodeData.value.sttpName,
|
||||
parentId: null,
|
||||
children: []
|
||||
};
|
||||
|
||||
treeData.value.push(newNode);
|
||||
addingNewNode.value = false;
|
||||
message.success('添加成功');
|
||||
};
|
||||
|
||||
// 取消新增
|
||||
const handleCancelAdd = () => {
|
||||
addingNewNode.value = false;
|
||||
newNodeData.value = {
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: ''
|
||||
};
|
||||
};
|
||||
|
||||
// 添加子节点(二级节点)
|
||||
const handleAddChild = (parentData: any) => {
|
||||
addingChildNode.value = true;
|
||||
currentParentKey.value = parentData.key;
|
||||
childNodeData.value = {
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: ''
|
||||
};
|
||||
};
|
||||
|
||||
// 选择子节点
|
||||
const handleChildNodeSelect = (value: string) => {
|
||||
const station = stationList.value.find(item => item.stcd === value);
|
||||
if (station) {
|
||||
childNodeData.value.stnm = station.stnm;
|
||||
childNodeData.value.sttpName = station.sttpName;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存新增子节点
|
||||
const handleSaveChildNode = () => {
|
||||
if (!childNodeData.value.stcd) {
|
||||
message.error('请选择站点');
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = findNodeByKey(treeData.value, currentParentKey.value!);
|
||||
if (!parent) {
|
||||
message.error('父节点不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
const newChild = {
|
||||
key: generateNodeId(),
|
||||
stcd: childNodeData.value.stcd,
|
||||
stnm: childNodeData.value.stnm,
|
||||
sttpName: childNodeData.value.sttpName,
|
||||
parentId: parent.key,
|
||||
children: []
|
||||
};
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
// 在子节点列表顶部添加
|
||||
parent.children.unshift(newChild);
|
||||
|
||||
addingChildNode.value = false;
|
||||
currentParentKey.value = null;
|
||||
message.success('添加子节点成功');
|
||||
};
|
||||
|
||||
// 取消添加子节点
|
||||
const handleCancelAddChild = () => {
|
||||
addingChildNode.value = false;
|
||||
currentParentKey.value = null;
|
||||
childNodeData.value = {
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: ''
|
||||
};
|
||||
};
|
||||
|
||||
// 编辑节点
|
||||
const handleEditNode = (dataRef: any) => {
|
||||
editingNode.value = true;
|
||||
editingNodeKey.value = dataRef.key;
|
||||
// 保存原始数据
|
||||
editNodeData.value = {
|
||||
stcd: dataRef.stcd,
|
||||
stnm: dataRef.stnm,
|
||||
sttpName: dataRef.sttpName,
|
||||
originalData: { ...dataRef }
|
||||
};
|
||||
};
|
||||
|
||||
// 选择编辑节点
|
||||
const handleEditNodeSelect = (value: string) => {
|
||||
const station = stationList.value.find(item => item.stcd === value);
|
||||
if (station) {
|
||||
editNodeData.value.stnm = station.stnm;
|
||||
editNodeData.value.sttpName = station.sttpName;
|
||||
editNodeData.value.stcd = station.stcd;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存编辑节点
|
||||
const handleSaveEditNode = () => {
|
||||
if (!editNodeData.value.stcd) {
|
||||
message.error('请选择站点');
|
||||
return;
|
||||
}
|
||||
|
||||
// 找到要编辑的节点
|
||||
const node = findNodeByKey(treeData.value, editingNodeKey.value!);
|
||||
if (!node) {
|
||||
message.error('节点不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新节点数据
|
||||
node.stcd = editNodeData.value.stcd;
|
||||
node.stnm = editNodeData.value.stnm;
|
||||
node.sttpName = editNodeData.value.sttpName;
|
||||
|
||||
editingNode.value = false;
|
||||
editingNodeKey.value = null;
|
||||
message.success('编辑成功');
|
||||
};
|
||||
|
||||
// 取消编辑节点
|
||||
const handleCancelEditNode = () => {
|
||||
editingNode.value = false;
|
||||
editingNodeKey.value = null;
|
||||
editNodeData.value = {
|
||||
stcd: undefined,
|
||||
stnm: '',
|
||||
sttpName: '',
|
||||
originalData: null
|
||||
};
|
||||
};
|
||||
|
||||
// 上移
|
||||
const handleMoveUp = (dataRef: any) => {
|
||||
const siblings = getSiblings(dataRef);
|
||||
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||
|
||||
if (index > 0) {
|
||||
// 交换位置
|
||||
[siblings[index - 1], siblings[index]] = [
|
||||
siblings[index],
|
||||
siblings[index - 1]
|
||||
];
|
||||
message.success('上移成功');
|
||||
}
|
||||
};
|
||||
|
||||
// 下移
|
||||
const handleMoveDown = (dataRef: any) => {
|
||||
const siblings = getSiblings(dataRef);
|
||||
const index = siblings.findIndex(item => item.key === dataRef.key);
|
||||
|
||||
if (index < siblings.length - 1) {
|
||||
// 交换位置
|
||||
[siblings[index], siblings[index + 1]] = [
|
||||
siblings[index + 1],
|
||||
siblings[index]
|
||||
];
|
||||
message.success('下移成功');
|
||||
}
|
||||
};
|
||||
|
||||
// 删除节点
|
||||
const handleDeleteNode = (dataRef: any) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: `确定要删除节点"${dataRef.stnm}"吗?`,
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
if (!dataRef.parentId) {
|
||||
// 删除一级节点
|
||||
const index = treeData.value.findIndex(
|
||||
item => item.key === dataRef.key
|
||||
);
|
||||
if (index > -1) {
|
||||
treeData.value.splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
// 删除二级节点
|
||||
const parent = findNodeByKey(treeData.value, dataRef.parentId);
|
||||
if (parent && parent.children) {
|
||||
const index = parent.children.findIndex(
|
||||
item => item.key === dataRef.key
|
||||
);
|
||||
if (index > -1) {
|
||||
parent.children.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
message.success('删除成功');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await formRef.value.validate();
|
||||
const submitValues = {
|
||||
...formData,
|
||||
captureDate: formData.captureDate
|
||||
? dayjs(formData.captureDate).format('YYYY-MM-DD')
|
||||
: undefined,
|
||||
configNodes: treeData.value // 提交树形数据
|
||||
};
|
||||
emit('ok', submitValues);
|
||||
|
||||
const submitData: any = { ...formData };
|
||||
|
||||
if ((formData.baseIdList || []).includes('all')) {
|
||||
const allCodes = JidiSelectEventStore.jidiData
|
||||
.filter(item => item.wbsCode !== 'all')
|
||||
.map(item => item.wbsCode);
|
||||
const allNames = JidiSelectEventStore.jidiData
|
||||
.filter(item => item.wbsCode !== 'all')
|
||||
.map(item => item.wbsName);
|
||||
submitData.baseIdList = allCodes.join(',');
|
||||
submitData.baseNameList = allNames.join(',');
|
||||
} else {
|
||||
submitData.baseIdList = (formData.baseIdList || []).join(',');
|
||||
submitData.baseNameList = (formData.baseNameList || []).join(',');
|
||||
}
|
||||
emit('ok', submitData);
|
||||
} catch (error) {
|
||||
console.error('Validate Failed:', error);
|
||||
message.error('请检查表单填写是否正确');
|
||||
@ -678,32 +218,46 @@ const handleOk = async () => {
|
||||
};
|
||||
|
||||
const initForm = () => {
|
||||
resetForm();
|
||||
if (props.initialValues) {
|
||||
const values = props.initialValues;
|
||||
Object.keys(formData).forEach(key => {
|
||||
if (values.hasOwnProperty(key)) {
|
||||
if (key === 'captureDate' && values[key]) {
|
||||
formData[key] = dayjs(values[key]);
|
||||
} else if (key === 'baseIdList' || key === 'baseNameList') {
|
||||
formData[key] = values[key] || [];
|
||||
} else {
|
||||
formData[key] = values[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化树形数据
|
||||
if (values.configNodes && Array.isArray(values.configNodes)) {
|
||||
treeData.value = values.configNodes.map((node: any) => ({
|
||||
...node,
|
||||
children:
|
||||
node.children?.map((child: any) => ({
|
||||
...child
|
||||
})) || []
|
||||
}));
|
||||
} else {
|
||||
treeData.value = [];
|
||||
|
||||
if (values.baseIdList) {
|
||||
const baseIds = typeof values.baseIdList === 'string'
|
||||
? values.baseIdList.split(',')
|
||||
: (Array.isArray(values.baseIdList) ? values.baseIdList : []);
|
||||
const allBaseCodes = JidiSelectEventStore.jidiData
|
||||
.filter(item => item.wbsCode !== 'all')
|
||||
.map(item => item.wbsCode);
|
||||
const isAllSelected = allBaseCodes.every(code => baseIds.includes(code));
|
||||
|
||||
if (isAllSelected) {
|
||||
formData.baseIdList = ['all'];
|
||||
formData.baseNameList = ['当前全部'];
|
||||
} else {
|
||||
formData.baseIdList = baseIds;
|
||||
formData.baseNameList = baseIds.map((code: string) => {
|
||||
const item = JidiSelectEventStore.jidiData.find(d => d.wbsCode === code);
|
||||
return item?.wbsName || '';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (values.categoryCode) {
|
||||
const option = categoryCodeOption.value.find(o => o.value === values.categoryCode);
|
||||
formData.categoryName = option?.label || '';
|
||||
}
|
||||
} else {
|
||||
resetForm();
|
||||
}
|
||||
};
|
||||
|
||||
@ -712,8 +266,6 @@ const resetForm = () => {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
Object.assign(formData, defaultFormData);
|
||||
treeData.value = [];
|
||||
addingNewNode.value = false;
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
@ -732,6 +284,17 @@ watch(
|
||||
{ immediate: false }
|
||||
);
|
||||
|
||||
const initOption = async () => {
|
||||
let res = await getDictItemsByCode({dictCode: 'category'});
|
||||
categoryCodeOption.value = res.data.map(item => ({
|
||||
value: item.itemCode,
|
||||
label: item.dictName
|
||||
}));
|
||||
};
|
||||
onMounted(() => {
|
||||
initOption();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
localLoading
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user