接入和风天气,获取项目当地天气情况
This commit is contained in:
@ -263,3 +263,8 @@ justauth:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
redirect-uri: ${justauth.address}/social-callback?source=gitlab
|
||||
weather:
|
||||
key-id: T65EAABUXC
|
||||
project-id: 2JTHPUQ5YY
|
||||
private-key: MC4CAQAwBQYDK2VwBCIEIMAglX7IsxYiTeM+FXXnvCUsIggajeP4s8gAllewm6BN
|
||||
api-host: n35rk53njv.re.qweatherapi.com
|
||||
|
||||
@ -118,6 +118,11 @@ public class EqpMachineryDetailServiceImpl extends ServiceImpl<EqpMachineryDetai
|
||||
if (count > 0) {
|
||||
throw new ServiceException("该编号机械已存在", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
// 操作数据库
|
||||
boolean save = this.save(machineryDetail);
|
||||
if (!save) {
|
||||
throw new ServiceException("新增机械详情失败,数据库异常", HttpStatus.ERROR);
|
||||
}
|
||||
// 修改机械数量
|
||||
LambdaUpdateWrapper<EqpMachinery> lqw = new LambdaUpdateWrapper<>();
|
||||
lqw.eq(EqpMachinery::getId, machineryDetail.getMachineryId());
|
||||
@ -126,11 +131,6 @@ public class EqpMachineryDetailServiceImpl extends ServiceImpl<EqpMachineryDetai
|
||||
if (!update) {
|
||||
throw new ServiceException("修改机械数量失败,数据库异常", HttpStatus.ERROR);
|
||||
}
|
||||
// 操作数据库
|
||||
boolean save = this.save(machineryDetail);
|
||||
if (!save) {
|
||||
throw new ServiceException("新增机械详情失败,数据库异常", HttpStatus.ERROR);
|
||||
}
|
||||
return machineryDetail.getId();
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
package org.dromara.manager.weathermanager;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author lcj
|
||||
* @date 2025/5/12 17:28
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "weather")
|
||||
public class WeatherConfig {
|
||||
|
||||
/**
|
||||
* 凭据 id
|
||||
*/
|
||||
private String keyId;
|
||||
|
||||
/**
|
||||
* 项目 id
|
||||
*/
|
||||
private String projectId;
|
||||
|
||||
/**
|
||||
* 私钥
|
||||
*/
|
||||
private String privateKey;
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
*/
|
||||
private String apiHost;
|
||||
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
package org.dromara.manager.weathermanager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lcj
|
||||
* @date 2025/5/12 17:57
|
||||
*/
|
||||
public interface WeatherConstant {
|
||||
|
||||
/**
|
||||
* 城市三天的天气
|
||||
*/
|
||||
String THREE_DAYS_WEATHER_PATH = "/v7/weather/3d";
|
||||
|
||||
/**
|
||||
* 天气信息
|
||||
*/
|
||||
String DAILY = "daily";
|
||||
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
String FX_DATE = "fxDate";
|
||||
|
||||
/**
|
||||
* 最高温度
|
||||
*/
|
||||
String TEMP_MAX = "tempMax";
|
||||
|
||||
/**
|
||||
* 最低温度
|
||||
*/
|
||||
String TEMP_MIN = "tempMin";
|
||||
|
||||
/**
|
||||
* 日出时间
|
||||
*/
|
||||
String SUN_RISE = "sunrise";
|
||||
|
||||
/**
|
||||
* 日落时间
|
||||
*/
|
||||
String SUN_SET = "sunset";
|
||||
|
||||
/**
|
||||
* 白天天气状态
|
||||
*/
|
||||
String TEXT_DAY = "textDay";
|
||||
|
||||
/**
|
||||
* 晚上天气状态
|
||||
*/
|
||||
String TEXT_NIGHT = "textNight";
|
||||
|
||||
// region 天气情况
|
||||
|
||||
/**
|
||||
* 晴
|
||||
*/
|
||||
List<String> SUNNY = List.of("晴");
|
||||
|
||||
/**
|
||||
* 多云
|
||||
*/
|
||||
List<String> MANY_CLOUD = List.of("多云", "少云", "晴间多云");
|
||||
|
||||
/**
|
||||
* 阴
|
||||
*/
|
||||
List<String> CLOUDY = List.of("阴", "阴天");
|
||||
|
||||
/**
|
||||
* 小雨
|
||||
*/
|
||||
List<String> SMALL_RAIN = List.of("小雨", "毛毛雨", "细雨", "毛毛雨/细雨", "小到中雨");
|
||||
|
||||
/**
|
||||
* 大雨
|
||||
*/
|
||||
List<String> BIG_RAIN = List.of("阵雨", "强阵雨", "中雨", "大雨", "极端降雨", "暴雨", "大暴雨", "特大暴雨", "中到大雨", "大到暴雨", "暴雨到大暴雨", "大暴雨到特大暴雨");
|
||||
|
||||
/**
|
||||
* 小雪
|
||||
*/
|
||||
List<String> SMALL_SNOW = List.of("雪", "小雪", "中雪", "小到中雪");
|
||||
|
||||
/**
|
||||
* 大雪
|
||||
*/
|
||||
List<String> BIG_SNOW = List.of("大雪", "暴雪", "阵雪", "中到大雪", "大到暴雪", "阵雨夹雪");
|
||||
|
||||
/**
|
||||
* 雷雨
|
||||
*/
|
||||
List<String> THUNDERSTORM = List.of("雷阵雨", "强雷阵雨", "雷阵雨伴有冰雹");
|
||||
|
||||
/**
|
||||
* 雨雪
|
||||
*/
|
||||
List<String> RAIN_SNOW = List.of("冻雨", "雨夹雪", "雨雪天气", "阵雨夹雪");
|
||||
|
||||
/**
|
||||
* 霾
|
||||
*/
|
||||
List<String> HAZE = List.of("霾", "雾霾", "中度霾", "重度霾", "严重霾");
|
||||
|
||||
/**
|
||||
* 雾
|
||||
*/
|
||||
List<String> FOG = List.of("薄雾", "雾", "浓雾", "强浓雾", "大雾", "特强浓雾");
|
||||
|
||||
/**
|
||||
* 沙尘
|
||||
*/
|
||||
List<String> SANDSTORM = List.of("扬沙", "浮尘", "沙尘暴", "强沙尘暴");
|
||||
|
||||
/**
|
||||
* 获取天气情况map
|
||||
*
|
||||
* @return 天气情况map
|
||||
*/
|
||||
static Map<String, List<String>> getWeatherStatusMap() {
|
||||
Map<String, List<String>> weatherStatusMap = new HashMap<>();
|
||||
weatherStatusMap.put("sunny", SUNNY);
|
||||
weatherStatusMap.put("manyCloud", MANY_CLOUD);
|
||||
weatherStatusMap.put("cloudy", CLOUDY);
|
||||
weatherStatusMap.put("smallRain", SMALL_RAIN);
|
||||
weatherStatusMap.put("bigRain", BIG_RAIN);
|
||||
weatherStatusMap.put("smallSnow", SMALL_SNOW);
|
||||
weatherStatusMap.put("bigSnow", BIG_SNOW);
|
||||
weatherStatusMap.put("thunderstorm", THUNDERSTORM);
|
||||
weatherStatusMap.put("rainSnow", RAIN_SNOW);
|
||||
weatherStatusMap.put("haze", HAZE);
|
||||
weatherStatusMap.put("fog", FOG);
|
||||
weatherStatusMap.put("sandstorm", SANDSTORM);
|
||||
return weatherStatusMap;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package org.dromara.manager.weathermanager;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.dromara.common.core.constant.HttpStatus;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.*;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* @author lcj
|
||||
* @date 2025/5/12 17:33
|
||||
*/
|
||||
@Component
|
||||
public class WeatherManager {
|
||||
|
||||
@Resource
|
||||
private WeatherConfig weatherConfig;
|
||||
|
||||
/**
|
||||
* 获取天气
|
||||
*
|
||||
* @param lng 经度
|
||||
* @param lat 纬度
|
||||
* @param weatherPath 天气请求路径
|
||||
* @return 天气信息字符串
|
||||
*/
|
||||
public String getWeather(String lng, String lat, String weatherPath) {
|
||||
// 获取小数点后两位的经纬度
|
||||
String lngTwo = roundToTwoDecimalPlacesString(lng);
|
||||
String latTwo = roundToTwoDecimalPlacesString(lat);
|
||||
String location = lngTwo + "," + latTwo;
|
||||
// 获取天气请求路径
|
||||
String dayWeatherUrl = getDayWeatherUrl(weatherPath, location);
|
||||
String body;
|
||||
try (HttpResponse result = HttpRequest.get(dayWeatherUrl)
|
||||
.header("Authorization", "Bearer " + getJwt())
|
||||
.execute()) {
|
||||
int status = result.getStatus();
|
||||
if (status != HttpStatus.SUCCESS) {
|
||||
throw new ServiceException("获取天气失败,状态码:" + status, HttpStatus.ERROR);
|
||||
}
|
||||
body = result.body();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取天气预报 Url
|
||||
*
|
||||
* @param weatherPath 天气请求路径
|
||||
* @param location 位置
|
||||
*/
|
||||
private String getDayWeatherUrl(String weatherPath, String location) {
|
||||
return String.format("https://%s%s?location=%s", weatherConfig.getApiHost(), weatherPath, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取小数点后两位的经纬度
|
||||
*
|
||||
* @param value 经纬度
|
||||
*/
|
||||
private String roundToTwoDecimalPlacesString(String value) {
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(2, RoundingMode.HALF_UP); // 使用 RoundingMode.HALF_UP
|
||||
return bd.toPlainString(); // 防止科学计数法
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 JWT
|
||||
*/
|
||||
private String getJwt() {
|
||||
// Private key
|
||||
String privateKeyString = weatherConfig.getPrivateKey()
|
||||
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||
.replace("-----END PRIVATE KEY-----", "")
|
||||
.trim();
|
||||
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
|
||||
PrivateKey privateKey;
|
||||
try {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("EdDSA");
|
||||
privateKey = keyFactory.generatePrivate(keySpec);
|
||||
} catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
|
||||
throw new ServiceException("获取天气失败,加密错误", HttpStatus.ERROR);
|
||||
}
|
||||
// Header
|
||||
String headerJson = "{\"alg\": \"EdDSA\", \"kid\": \"" + weatherConfig.getKeyId() + "\"}";
|
||||
// Payload
|
||||
long iat = ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond() - 30;
|
||||
long exp = iat + 900;
|
||||
String payloadJson = "{\"sub\": \"" + weatherConfig.getProjectId() + "\", \"iat\": " + iat + ", \"exp\": " + exp + "}";
|
||||
// Base64url header + payload
|
||||
String headerEncoded = Base64.getUrlEncoder().encodeToString(headerJson.getBytes(StandardCharsets.UTF_8));
|
||||
String payloadEncoded = Base64.getUrlEncoder().encodeToString(payloadJson.getBytes(StandardCharsets.UTF_8));
|
||||
String data = headerEncoded + "." + payloadEncoded;
|
||||
// Sign
|
||||
byte[] signature;
|
||||
try {
|
||||
Signature signer = Signature.getInstance("EdDSA");
|
||||
signer.initSign(privateKey);
|
||||
signer.update(data.getBytes(StandardCharsets.UTF_8));
|
||||
signature = signer.sign();
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
|
||||
throw new ServiceException("获取天气失败,加密错误", HttpStatus.ERROR);
|
||||
}
|
||||
String signatureString = Base64.getUrlEncoder().encodeToString(signature);
|
||||
return data + "." + signatureString;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package org.dromara.project.constant;
|
||||
|
||||
/**
|
||||
* @author lcj
|
||||
* @date 2025/5/13 10:33
|
||||
*/
|
||||
public interface BusProjectConstant {
|
||||
|
||||
/**
|
||||
* 项目天气封装信息缓存的 Redis Key 前缀
|
||||
*/
|
||||
String PROJECT_WEATHER_LIST_VO_REDIS_KEY_PREFIX = "project:weather:list";
|
||||
|
||||
}
|
||||
@ -93,7 +93,7 @@ public class BusConstructionUserController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询施工人员大屏数据
|
||||
* 查询大屏施工人员信息
|
||||
*/
|
||||
@SaCheckPermission("project:constructionUser:query")
|
||||
@GetMapping("/gis")
|
||||
|
||||
@ -22,6 +22,7 @@ import org.dromara.project.domain.req.project.BusProjectQueryReq;
|
||||
import org.dromara.project.domain.req.project.BusProjectUpdateReq;
|
||||
import org.dromara.project.domain.vo.project.BusProjectContractorListVo;
|
||||
import org.dromara.project.domain.vo.project.BusProjectVo;
|
||||
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
|
||||
import org.dromara.project.service.IBusProjectService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -121,4 +122,13 @@ public class BusProjectController extends BaseController {
|
||||
return toAjax(projectService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询项目天气
|
||||
*/
|
||||
@GetMapping("/weather/{id}")
|
||||
public R<List<BusProjectWeatherVo>> getWeather(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(projectService.getWeather(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
package org.dromara.project.domain.vo.project;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author lcj
|
||||
* @date 2025/5/13 9:29
|
||||
*/
|
||||
@Data
|
||||
public class BusProjectWeatherVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 4173514725591666698L;
|
||||
|
||||
/**
|
||||
* 日期
|
||||
*/
|
||||
private String date;
|
||||
|
||||
/**
|
||||
* 星期
|
||||
*/
|
||||
private String week;
|
||||
|
||||
/**
|
||||
* 最高温度
|
||||
*/
|
||||
private String tempMax;
|
||||
|
||||
/**
|
||||
* 最低温度
|
||||
*/
|
||||
private String tempMin;
|
||||
|
||||
/**
|
||||
* 日出时间
|
||||
*/
|
||||
private String sunRise;
|
||||
|
||||
/**
|
||||
* 日落时间
|
||||
*/
|
||||
private String sunSet;
|
||||
|
||||
/**
|
||||
* 白天天气状态
|
||||
*/
|
||||
private String dayStatus;
|
||||
|
||||
/**
|
||||
* 白天天气图标
|
||||
*/
|
||||
private String dayIcon;
|
||||
|
||||
/**
|
||||
* 晚上天气状态
|
||||
*/
|
||||
private String nightStatus;
|
||||
|
||||
/**
|
||||
* 晚上天气图标
|
||||
*/
|
||||
private String nightIcon;
|
||||
|
||||
}
|
||||
@ -25,4 +25,9 @@ public class BusProjectNewsGisVo implements Serializable {
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 显示
|
||||
*/
|
||||
private Boolean show;
|
||||
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package org.dromara.project.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.project.domain.BusProject;
|
||||
@ -11,6 +12,7 @@ import org.dromara.project.domain.req.project.BusProjectQueryReq;
|
||||
import org.dromara.project.domain.req.project.BusProjectUpdateReq;
|
||||
import org.dromara.project.domain.vo.project.BusProjectContractorListVo;
|
||||
import org.dromara.project.domain.vo.project.BusProjectVo;
|
||||
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -120,4 +122,12 @@ public interface IBusProjectService extends IService<BusProject> {
|
||||
*/
|
||||
void validAuth(Collection<Long> projectIdList, Long userId);
|
||||
|
||||
/**
|
||||
* 获取天气信息
|
||||
*
|
||||
* @param id 项目id
|
||||
* @return 天气信息列表
|
||||
*/
|
||||
List<BusProjectWeatherVo> getWeather(Long id);
|
||||
|
||||
}
|
||||
|
||||
@ -100,6 +100,7 @@ public class BusProjectNewsServiceImpl extends ServiceImpl<BusProjectNewsMapper,
|
||||
return projectNewsList.stream().map(projectNews -> {
|
||||
BusProjectNewsGisVo projectNewsGisResp = new BusProjectNewsGisVo();
|
||||
BeanUtils.copyProperties(projectNews, projectNewsGisResp);
|
||||
projectNewsGisResp.setShow(false);
|
||||
return projectNewsGisResp;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
package org.dromara.project.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.PhoneUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.dromara.common.core.constant.HttpStatus;
|
||||
import org.dromara.common.core.constant.SystemConstants;
|
||||
@ -17,6 +25,9 @@ import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.manager.weathermanager.WeatherConstant;
|
||||
import org.dromara.manager.weathermanager.WeatherManager;
|
||||
import org.dromara.project.constant.BusProjectConstant;
|
||||
import org.dromara.project.domain.BusContractor;
|
||||
import org.dromara.project.domain.BusProject;
|
||||
import org.dromara.project.domain.BusProjectFile;
|
||||
@ -26,6 +37,7 @@ import org.dromara.project.domain.req.project.BusProjectQueryReq;
|
||||
import org.dromara.project.domain.req.project.BusProjectUpdateReq;
|
||||
import org.dromara.project.domain.vo.project.BusProjectContractorListVo;
|
||||
import org.dromara.project.domain.vo.project.BusProjectVo;
|
||||
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
|
||||
import org.dromara.project.mapper.BusProjectMapper;
|
||||
import org.dromara.project.service.IBusContractorService;
|
||||
import org.dromara.project.service.IBusProjectFileService;
|
||||
@ -33,10 +45,13 @@ import org.dromara.project.service.IBusProjectService;
|
||||
import org.dromara.project.service.IBusUserProjectRelevancyService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -61,6 +76,19 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
|
||||
@Resource
|
||||
private IBusProjectFileService projectFileService;
|
||||
|
||||
@Resource
|
||||
private WeatherManager weatherManager;
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
private final Cache<String, String> WEATHER_CACHE =
|
||||
Caffeine.newBuilder().initialCapacity(1024)
|
||||
.maximumSize(10000L)
|
||||
// 缓存 30 分钟移除
|
||||
.expireAfterWrite(30L, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* 查询项目
|
||||
*
|
||||
@ -432,4 +460,98 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取天气信息
|
||||
*
|
||||
* @param id 项目id
|
||||
* @return 天气信息列表
|
||||
*/
|
||||
@Override
|
||||
public List<BusProjectWeatherVo> getWeather(Long id) {
|
||||
BusProject project = this.getById(id);
|
||||
if (project == null) {
|
||||
throw new ServiceException("项目不存在");
|
||||
}
|
||||
// 构建缓存 key
|
||||
String cacheKey = String.format("%s:%s", BusProjectConstant.PROJECT_WEATHER_LIST_VO_REDIS_KEY_PREFIX, id);
|
||||
// 查询本地缓存(caffeine)
|
||||
String cachedValue = WEATHER_CACHE.getIfPresent(cacheKey);
|
||||
if (cachedValue != null) {
|
||||
// 如果缓存命中,返回结果
|
||||
return JSONUtil.toList(cachedValue, BusProjectWeatherVo.class);
|
||||
}
|
||||
// 查询分布式缓存(Redis)
|
||||
ValueOperations<String, String> valueOps = stringRedisTemplate.opsForValue();
|
||||
cachedValue = valueOps.get(cacheKey);
|
||||
if (cachedValue != null) {
|
||||
// 如果命中Redis,存入本地缓存并返回结果
|
||||
WEATHER_CACHE.put(cacheKey, cachedValue);
|
||||
return JSONUtil.toList(cachedValue, BusProjectWeatherVo.class);
|
||||
}
|
||||
// 获取当天及之后的天气信息
|
||||
String lng = project.getLng();
|
||||
String lat = project.getLat();
|
||||
if (StringUtils.isAnyBlank(lng, lat)) {
|
||||
throw new ServiceException("项目坐标信息为空");
|
||||
}
|
||||
String weatherStr = weatherManager.getWeather(lng, lat, WeatherConstant.THREE_DAYS_WEATHER_PATH);
|
||||
// 解析为 JSONObject
|
||||
JSONObject weatherJson = JSONUtil.parseObj(weatherStr);
|
||||
// 获取 daily 数组
|
||||
JSONArray dailyArray = weatherJson.getJSONArray(WeatherConstant.DAILY);
|
||||
// 循环遍历,封装项目天气信息
|
||||
List<BusProjectWeatherVo> weatherList = new ArrayList<>();
|
||||
for (int i = 0; i < dailyArray.size(); i++) {
|
||||
JSONObject day = dailyArray.getJSONObject(i);
|
||||
BusProjectWeatherVo weatherVo = new BusProjectWeatherVo();
|
||||
// 获取星期
|
||||
String dateStr = day.getStr(WeatherConstant.FX_DATE);
|
||||
DateTime date = DateUtil.parse(dateStr, "yyyy-MM-dd");
|
||||
String week = DateUtil.format(date, "EEE");
|
||||
// 获取天气图标
|
||||
String textDay = day.getStr(WeatherConstant.TEXT_DAY);
|
||||
String textNight = day.getStr(WeatherConstant.TEXT_NIGHT);
|
||||
Map<String, List<String>> weatherStatusMap = WeatherConstant.getWeatherStatusMap();
|
||||
String dayStatus = getWeatherCategory(textDay, weatherStatusMap);
|
||||
String nightStatus = getWeatherCategory(textNight, weatherStatusMap);
|
||||
// 封装数据
|
||||
weatherVo.setDate(dateStr);
|
||||
weatherVo.setWeek(week);
|
||||
weatherVo.setTempMax(day.getStr(WeatherConstant.TEMP_MAX));
|
||||
weatherVo.setTempMin(day.getStr(WeatherConstant.TEMP_MIN));
|
||||
weatherVo.setSunRise(day.getStr(WeatherConstant.SUN_RISE));
|
||||
weatherVo.setSunSet(day.getStr(WeatherConstant.SUN_SET));
|
||||
weatherVo.setDayStatus(textDay);
|
||||
weatherVo.setNightStatus(textNight);
|
||||
weatherVo.setDayIcon(dayStatus);
|
||||
weatherVo.setNightIcon(nightStatus);
|
||||
weatherList.add(weatherVo);
|
||||
}
|
||||
// 更新缓存
|
||||
String cacheValue = JSONUtil.toJsonStr(weatherList);
|
||||
// 更新本地缓存
|
||||
WEATHER_CACHE.put(cacheKey, cacheValue);
|
||||
// 更新 Redis 缓存,设置 5 - 10 分钟随机过期,防止雪崩
|
||||
int cacheExpireTime = 30 * 60 + RandomUtil.randomInt(0, 300);
|
||||
valueOps.set(cacheKey, cacheValue, cacheExpireTime, TimeUnit.SECONDS);
|
||||
// 返回结果
|
||||
return weatherList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据天气图标获取天气类别
|
||||
*
|
||||
* @param icon 天气图标
|
||||
* @param map 天气图标与天气类别的映射关系
|
||||
* @return 天气类别
|
||||
*/
|
||||
public static String getWeatherCategory(String icon, Map<String, List<String>> map) {
|
||||
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
|
||||
if (entry.getValue().contains(icon)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return "cloudy";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ public class QltQualityInspectionGis {
|
||||
/**
|
||||
* 巡检类型
|
||||
*/
|
||||
private String inspectionType;
|
||||
private String inspectionTypeLabel;
|
||||
|
||||
/**
|
||||
* 巡检标题
|
||||
|
||||
@ -38,9 +38,11 @@ import org.dromara.quality.domain.vo.qualityinspection.QltQualityInspectionListG
|
||||
import org.dromara.quality.domain.vo.qualityinspection.QltQualityInspectionVo;
|
||||
import org.dromara.quality.mapper.QltQualityInspectionMapper;
|
||||
import org.dromara.quality.service.IQltQualityInspectionService;
|
||||
import org.dromara.system.domain.vo.SysDictDataVo;
|
||||
import org.dromara.system.domain.vo.SysOssVo;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.service.ISysDictDataService;
|
||||
import org.dromara.system.service.ISysDictTypeService;
|
||||
import org.dromara.system.service.ISysOssService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.utils.DocumentUtils;
|
||||
@ -85,6 +87,9 @@ public class QltQualityInspectionServiceImpl extends ServiceImpl<QltQualityInspe
|
||||
@Resource
|
||||
private ISysDictDataService dictDataService;
|
||||
|
||||
@Resource
|
||||
private ISysDictTypeService dictTypeService;
|
||||
|
||||
/**
|
||||
* 查询质量-检查工单
|
||||
*
|
||||
@ -144,14 +149,22 @@ public class QltQualityInspectionServiceImpl extends ServiceImpl<QltQualityInspe
|
||||
if (CollUtil.isEmpty(qualityInspectionList)) {
|
||||
return gisVo;
|
||||
}
|
||||
// 获取字典值
|
||||
List<SysDictDataVo> dictDataVoList = dictTypeService.selectDictDataByType(QltQualityConstant.QUALITY_INSPECTION_CHECK_TYPE);
|
||||
Map<String, String> dictDataMap = dictDataVoList.stream().collect(Collectors.toMap(SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel));
|
||||
// 获取最新的检查工单
|
||||
List<QltQualityInspection> topList = qualityInspectionList.stream()
|
||||
.sorted(Comparator.comparing(QltQualityInspection::getCreateTime).reversed())
|
||||
.limit(req.getPageSize())
|
||||
.limit(Optional.ofNullable(req.getPageSize()).orElse(20))
|
||||
.toList();
|
||||
// 转换为 GIS 对象,并设置标签
|
||||
List<QltQualityInspectionGis> gisList = topList.stream().map(qualityInspection -> {
|
||||
QltQualityInspectionGis gis = new QltQualityInspectionGis();
|
||||
BeanUtils.copyProperties(qualityInspection, gis);
|
||||
String label = dictDataMap.get(qualityInspection.getInspectionType());
|
||||
if (label != null) {
|
||||
gis.setInspectionTypeLabel(label);
|
||||
}
|
||||
return gis;
|
||||
}).toList();
|
||||
// 获取整改情况
|
||||
|
||||
@ -33,7 +33,12 @@ public class HseSafetyInspectionListGisVo implements Serializable {
|
||||
private Long safetyInspectionCount;
|
||||
|
||||
/**
|
||||
* 整改情况
|
||||
* 整改情况总数
|
||||
*/
|
||||
private Long correctSituationCount;
|
||||
|
||||
/**
|
||||
* 整改情况百分比
|
||||
*/
|
||||
private String correctSituation;
|
||||
|
||||
|
||||
@ -153,7 +153,7 @@ public class HseSafetyInspectionServiceImpl extends ServiceImpl<HseSafetyInspect
|
||||
// 获取最新的班组列表
|
||||
List<HseTeamMeeting> topList = teamMeetings.stream()
|
||||
.sorted(Comparator.comparing(HseTeamMeeting::getCreateTime).reversed())
|
||||
.limit(req.getPageSize())
|
||||
.limit(Optional.ofNullable(req.getPageSize()).orElse(20))
|
||||
.toList();
|
||||
List<Long> teamIds = topList.stream().map(HseTeamMeeting::getTeamId).toList();
|
||||
Map<Long, List<BusProjectTeam>> teamMap = projectTeamService.lambdaQuery()
|
||||
@ -181,6 +181,7 @@ public class HseSafetyInspectionServiceImpl extends ServiceImpl<HseSafetyInspect
|
||||
gisVo.setTeamMeetingList(gisList);
|
||||
gisVo.setTeamMeetingCount((long) teamMeetings.size());
|
||||
gisVo.setSafetyInspectionCount((long) safetyInspectionList.size());
|
||||
gisVo.setCorrectSituationCount(passCount);
|
||||
gisVo.setCorrectSituation(String.format("%.2f", passCount * 100.0 / safetyInspectionList.size()));
|
||||
return gisVo;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user