Compare commits
2 Commits
19ab3f6f06
...
0adbdaa281
Author | SHA1 | Date |
---|---|---|
|
0adbdaa281 | 3 weeks ago |
|
1175aef3dd | 3 weeks ago |
75 changed files with 2876 additions and 151 deletions
@ -0,0 +1,44 @@ |
|||||
|
pipeline { |
||||
|
agent any |
||||
|
stages { |
||||
|
stage('Compile Java') { |
||||
|
steps { |
||||
|
sh 'mvn clean package -Dmaven.test.skip=true' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
stage('Archive') { |
||||
|
steps { |
||||
|
archiveArtifacts artifacts: 'dk-auth/target/dk-auth.jar', fingerprint: true |
||||
|
archiveArtifacts artifacts: 'dk-gateway/target/dk-gateway.jar', fingerprint: true |
||||
|
archiveArtifacts artifacts: 'dk-modules/resource/resource.jar', fingerprint: true |
||||
|
archiveArtifacts artifacts: 'dk-modules/business/target/business.jar', fingerprint: true |
||||
|
archiveArtifacts artifacts: 'dk-modules/sample/sample.jar', fingerprint: true |
||||
|
archiveArtifacts artifacts: 'dk-modules/system/target/system.jar', fingerprint: true |
||||
|
archiveArtifacts artifacts: 'dk-modules/workflow/target/workflow.jar', fingerprint: true |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
stage('Upload') { |
||||
|
steps { |
||||
|
script { |
||||
|
def jars = [ |
||||
|
['src': 'dk-auth/target/dk-auth.jar', 'name': 'dk-auth'], |
||||
|
['src': 'dk-gateway/target/dk-gateway.jar', 'name': 'dk-gateway'], |
||||
|
['src': 'dk-modules/resource/resource.jar', 'name': 'resource'], |
||||
|
['src': 'dk-modules/business/target/business.jar', 'name': 'business'], |
||||
|
['src': 'dk-modules/sample/sample.jar', 'name': 'sample'], |
||||
|
['src': 'dk-modules/system/target/system.jar', 'name': 'system'], |
||||
|
['src': 'dk-modules/workflow/target/workflow.jar', 'name': 'workflow'] |
||||
|
] |
||||
|
for (jar in jars) { |
||||
|
sh """ |
||||
|
cp ${jar.src} ${jar.name}-${BRANCH_NAME}-${BUILD_NUMBER}.jar |
||||
|
|
||||
|
""" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,49 @@ |
|||||
|
package org.dromara.business.utils; |
||||
|
|
||||
|
|
||||
|
import lombok.Data; |
||||
|
|
||||
|
/** |
||||
|
* 坐标点数据模型 |
||||
|
* |
||||
|
* @author Your Name |
||||
|
* @version 1.0 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class CoordinateModel { |
||||
|
private double latitude; |
||||
|
private double longitude; |
||||
|
private String name; |
||||
|
|
||||
|
/** |
||||
|
* 默认构造函数 |
||||
|
*/ |
||||
|
public CoordinateModel() { |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 构造函数 |
||||
|
* |
||||
|
* @param latitude 纬度 |
||||
|
* @param longitude 经度 |
||||
|
*/ |
||||
|
public CoordinateModel(double latitude, double longitude) { |
||||
|
this.latitude = latitude; |
||||
|
this.longitude = longitude; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 构造函数 |
||||
|
* |
||||
|
* @param latitude 纬度 |
||||
|
* @param longitude 经度 |
||||
|
* @param name 名称 |
||||
|
*/ |
||||
|
public CoordinateModel(double latitude, double longitude, String name) { |
||||
|
this.latitude = latitude; |
||||
|
this.longitude = longitude; |
||||
|
this.name = name; |
||||
|
} |
||||
|
} |
@ -0,0 +1,224 @@ |
|||||
|
package org.dromara.business.utils; |
||||
|
|
||||
|
|
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; |
||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; |
||||
|
import org.apache.commons.io.IOUtils; |
||||
|
|
||||
|
import java.io.ByteArrayInputStream; |
||||
|
import java.io.IOException; |
||||
|
import java.io.InputStream; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.rmi.ServerException; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* KMZ文件生成工具类 |
||||
|
* 支持根据经纬度集合生成KMZ文件,可在Google Earth中打开 |
||||
|
* |
||||
|
* @author Your Name |
||||
|
* @version 1.0 |
||||
|
*/ |
||||
|
public class KMZGenerator { |
||||
|
|
||||
|
/** |
||||
|
* 生成包含多个坐标点的KMZ文件并输出到HttpServletResponse |
||||
|
* |
||||
|
* @param coordinates 坐标点集合 |
||||
|
* @param response HttpServletResponse对象 |
||||
|
* @param fileName 文件名(不含扩展名) |
||||
|
* @throws IOException 文件操作异常 |
||||
|
*/ |
||||
|
public static void generateKmzFromCoordinates(List<CoordinateModel> coordinates, HttpServletResponse response, String fileName) |
||||
|
throws IOException { |
||||
|
|
||||
|
//验证坐标点是否有效
|
||||
|
if (!isValidCoordinateList(coordinates)) { |
||||
|
throw new ServerException("坐标点集合无效!"); |
||||
|
} |
||||
|
|
||||
|
// 生成KML内容
|
||||
|
String kmlContent = generateKmlContent(coordinates, fileName); |
||||
|
|
||||
|
// 创建KMZ文件并输出到response
|
||||
|
createKmzFile(kmlContent, response, fileName); |
||||
|
|
||||
|
System.out.println("KMZ文件已生成并输出到response: " + fileName + ".kmz"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成KML内容 |
||||
|
*/ |
||||
|
private static String generateKmlContent(List<CoordinateModel> coordinates, String fileName) { |
||||
|
StringBuilder kml = new StringBuilder(); |
||||
|
kml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); |
||||
|
kml.append("<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"); |
||||
|
kml.append(" <Document>\n"); |
||||
|
// 添加绿色点的Style,引用包内图标
|
||||
|
kml.append(" <Style id=\"green-dot\">\n"); |
||||
|
kml.append(" <IconStyle>\n"); |
||||
|
kml.append(" <scale>1.2</scale>\n"); |
||||
|
kml.append(" <Icon>\n"); |
||||
|
kml.append(" <href>green-dot.png</href>\n"); |
||||
|
kml.append(" </Icon>\n"); |
||||
|
kml.append(" </IconStyle>\n"); |
||||
|
kml.append(" </Style>\n"); |
||||
|
|
||||
|
// 添加坐标点
|
||||
|
coordinates.forEach(coordinate -> { |
||||
|
// 生成包含表格的描述
|
||||
|
String description = generateDescriptionWithTable(coordinate); |
||||
|
|
||||
|
kml.append(" <Placemark>\n"); |
||||
|
kml.append(" <styleUrl>#green-dot</styleUrl>\n"); |
||||
|
kml.append(" <description>").append(escapeXml(description)).append("</description>\n"); |
||||
|
kml.append(" <Point>\n"); |
||||
|
kml.append(" <coordinates>") |
||||
|
.append(coordinate.getLongitude()).append(",") |
||||
|
.append(coordinate.getLatitude()).append(",0") |
||||
|
.append("</coordinates>\n"); |
||||
|
kml.append(" </Point>\n"); |
||||
|
kml.append(" </Placemark>\n"); |
||||
|
|
||||
|
|
||||
|
|
||||
|
}); |
||||
|
|
||||
|
|
||||
|
kml.append(" </Document>\n"); |
||||
|
kml.append("</kml>"); |
||||
|
|
||||
|
return kml.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 创建KMZ文件并输出到HttpServletResponse |
||||
|
*/ |
||||
|
private static void createKmzFile(String kmlContent, HttpServletResponse response, String fileName) throws IOException { |
||||
|
response.setContentType("application/vnd.google-earth.kmz"); |
||||
|
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".kmz\""); |
||||
|
|
||||
|
try (ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(response.getOutputStream())) { |
||||
|
zipOut.setEncoding(StandardCharsets.UTF_8.name()); |
||||
|
|
||||
|
// 添加KML文件到ZIP
|
||||
|
ZipArchiveEntry kmlEntry = new ZipArchiveEntry("doc.kml"); |
||||
|
zipOut.putArchiveEntry(kmlEntry); |
||||
|
|
||||
|
try (InputStream kmlInputStream = new ByteArrayInputStream(kmlContent.getBytes(StandardCharsets.UTF_8))) { |
||||
|
IOUtils.copy(kmlInputStream, zipOut); |
||||
|
} |
||||
|
|
||||
|
zipOut.closeArchiveEntry(); |
||||
|
|
||||
|
// 添加图标图片到ZIP
|
||||
|
ZipArchiveEntry iconEntry = new ZipArchiveEntry("green-dot.png"); |
||||
|
zipOut.putArchiveEntry(iconEntry); |
||||
|
|
||||
|
try (InputStream iconInputStream = KMZGenerator.class.getClassLoader().getResourceAsStream("icon/green.png")) { |
||||
|
IOUtils.copy(iconInputStream, zipOut); |
||||
|
} |
||||
|
|
||||
|
zipOut.closeArchiveEntry(); |
||||
|
|
||||
|
zipOut.finish(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成包含表格的描述 |
||||
|
*/ |
||||
|
private static String generateDescriptionWithTable(CoordinateModel coordinate) { |
||||
|
StringBuilder description = new StringBuilder(); |
||||
|
description.append("<![CDATA["); |
||||
|
description.append("<table border='1' style='border-collapse: collapse; width: 100%;'>"); |
||||
|
description.append("<tr style='background-color: #f2f2f2;'>"); |
||||
|
description.append("<th style='padding: 8px; text-align: left;'>名称</th>"); |
||||
|
description.append("<th style='padding: 8px; text-align: left;'>经度</th>"); |
||||
|
description.append("<th style='padding: 8px; text-align: left;'>纬度</th>"); |
||||
|
description.append("</tr>"); |
||||
|
|
||||
|
description.append("<tr>"); |
||||
|
description.append("<td style='padding: 8px;'>").append(escapeHtml(coordinate.getName())).append("</td>"); |
||||
|
description.append("<td style='padding: 8px;'>").append(String.format("%.13f", coordinate.getLongitude())).append("</td>"); |
||||
|
description.append("<td style='padding: 8px;'>").append(String.format("%.13f", coordinate.getLatitude())).append("</td>"); |
||||
|
description.append("</tr>"); |
||||
|
description.append("</table>"); |
||||
|
description.append("]]>"); |
||||
|
|
||||
|
return description.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 转义HTML特殊字符 |
||||
|
*/ |
||||
|
private static String escapeHtml(String text) { |
||||
|
if (text == null) { |
||||
|
return ""; |
||||
|
} |
||||
|
return text.replace("&", "&") |
||||
|
.replace("<", "<") |
||||
|
.replace(">", ">") |
||||
|
.replace("\"", """) |
||||
|
.replace("'", "'"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 转义XML特殊字符 |
||||
|
*/ |
||||
|
private static String escapeXml(String text) { |
||||
|
if (text == null) { |
||||
|
return ""; |
||||
|
} |
||||
|
return text.replace("&", "&") |
||||
|
.replace("<", "<") |
||||
|
.replace(">", ">") |
||||
|
.replace("\"", """) |
||||
|
.replace("'", "'"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 验证坐标点是否有效 |
||||
|
* |
||||
|
* @param coordinate 坐标点 |
||||
|
* @return 是否有效 |
||||
|
*/ |
||||
|
public static boolean isValidCoordinate(CoordinateModel coordinate) { |
||||
|
if (coordinate == null) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 检查纬度范围 (-90 到 90)
|
||||
|
if (coordinate.getLatitude() < -90 || coordinate.getLatitude() > 90) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 检查经度范围 (-180 到 180)
|
||||
|
if (coordinate.getLongitude() < -180 || coordinate.getLongitude() > 180) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 验证坐标点集合是否有效 |
||||
|
* |
||||
|
* @param coordinates 坐标点集合 |
||||
|
* @return 是否有效 |
||||
|
*/ |
||||
|
public static boolean isValidCoordinateList(List<CoordinateModel> coordinates) { |
||||
|
if (coordinates == null || coordinates.isEmpty()) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
for (CoordinateModel coordinate : coordinates) { |
||||
|
if (!isValidCoordinate(coordinate)) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
} |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 175 B |
@ -0,0 +1,14 @@ |
|||||
|
package org.dromara.sample.feign; |
||||
|
|
||||
|
import org.springframework.cloud.openfeign.FeignClient; |
||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
import org.springframework.web.bind.annotation.PathVariable; |
||||
|
|
||||
|
@FeignClient(name = "gateway",path = "system") |
||||
|
public interface RemoteMsgConfigUserFeign { |
||||
|
|
||||
|
@GetMapping("/msgConfigUser/sendMsg/{deviceSn}/{taskType}") |
||||
|
String sendMsg(@PathVariable String deviceSn, @PathVariable int taskType); |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,229 @@ |
|||||
|
package org.dromara.sample.utils; |
||||
|
|
||||
|
import cn.hutool.json.JSONObject; |
||||
|
import cn.hutool.json.JSONUtil; |
||||
|
import lombok.Data; |
||||
|
import org.dromara.sample.wayline.domain.vo.WaylineJobAtmosphereVo; |
||||
|
|
||||
|
import java.util.*; |
||||
|
|
||||
|
public class AtmosphereCalculateUtil { |
||||
|
|
||||
|
@Data |
||||
|
public static class GridGasStatResult { |
||||
|
private String gasKey; |
||||
|
|
||||
|
private Float concentrationAvag; |
||||
|
private Float concentrationPointMax; |
||||
|
private Float concentrationPointMin; |
||||
|
private Float concentrationMax; // 网格平均最大
|
||||
|
private Float concentrationMin; // 网格平均最小
|
||||
|
|
||||
|
private Double areaTotalSize; // 单位:平方米
|
||||
|
private Double areaLat; // 区域中心纬度
|
||||
|
private Double areaLon; // 区域中心经度
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
public static GridGasStatResult computeStats(List<WaylineJobAtmosphereVo> atmosphereList, |
||||
|
double latGridSize, double lonGridSize, |
||||
|
String gasKey) { |
||||
|
if (atmosphereList == null || atmosphereList.isEmpty()) return null; |
||||
|
|
||||
|
// 计算动态起点
|
||||
|
double baseLat = atmosphereList.stream() |
||||
|
.filter(vo -> vo.getLatitude() != null) |
||||
|
.mapToDouble(vo -> vo.getLatitude()) |
||||
|
.min().orElse(0); |
||||
|
double baseLon = atmosphereList.stream() |
||||
|
.filter(vo -> vo.getLongitude() != null) |
||||
|
.mapToDouble(vo -> vo.getLongitude()) |
||||
|
.min().orElse(0); |
||||
|
|
||||
|
float globalSum = 0; |
||||
|
int globalCount = 0; |
||||
|
float pointMax = Float.MIN_VALUE; |
||||
|
float pointMin = Float.MAX_VALUE; |
||||
|
|
||||
|
double minLat = Double.MAX_VALUE; |
||||
|
double maxLat = -Double.MAX_VALUE; |
||||
|
double minLon = Double.MAX_VALUE; |
||||
|
double maxLon = -Double.MAX_VALUE; |
||||
|
|
||||
|
// 按网格聚合气体值
|
||||
|
Map<String, List<Float>> gridMap = new HashMap<>(); |
||||
|
|
||||
|
for (WaylineJobAtmosphereVo vo : atmosphereList) { |
||||
|
Float lat = vo.getLatitude(); |
||||
|
Float lon = vo.getLongitude(); |
||||
|
String airData = vo.getAirData(); |
||||
|
if (lat == null || lon == null || airData == null) continue; |
||||
|
|
||||
|
// 区域边界统计
|
||||
|
minLat = Math.min(minLat, lat); |
||||
|
maxLat = Math.max(maxLat, lat); |
||||
|
minLon = Math.min(minLon, lon); |
||||
|
maxLon = Math.max(maxLon, lon); |
||||
|
|
||||
|
JSONObject json = JSONUtil.parseObj(airData); |
||||
|
if (!json.containsKey(gasKey)) continue; |
||||
|
float value = json.getFloat(gasKey, 0f); |
||||
|
|
||||
|
// 全局更新点统计
|
||||
|
globalSum += value; |
||||
|
globalCount++; |
||||
|
pointMax = Math.max(pointMax, value); |
||||
|
pointMin = Math.min(pointMin, value); |
||||
|
|
||||
|
// 网格编号
|
||||
|
int gridX = (int) ((lon - baseLon) / lonGridSize); |
||||
|
int gridY = (int) ((lat - baseLat) / latGridSize); |
||||
|
String gridKey = gridX + "_" + gridY; |
||||
|
|
||||
|
gridMap.computeIfAbsent(gridKey, k -> new ArrayList<>()).add(value); |
||||
|
} |
||||
|
|
||||
|
float gridMax = Float.MIN_VALUE; |
||||
|
float gridMin = Float.MAX_VALUE; |
||||
|
|
||||
|
for (List<Float> values : gridMap.values()) { |
||||
|
float sum = 0; |
||||
|
for (float v : values) sum += v; |
||||
|
float avg = sum / values.size(); |
||||
|
gridMax = Math.max(gridMax, avg); |
||||
|
gridMin = Math.min(gridMin, avg); |
||||
|
} |
||||
|
|
||||
|
GridGasStatResult result = new GridGasStatResult(); |
||||
|
|
||||
|
|
||||
|
double areaLat = (minLat + maxLat) / 2.0; |
||||
|
double areaLon = (minLon + maxLon) / 2.0; |
||||
|
// 粗略估算:纬度 ≈ 111000 米/度,经度 ≈ 85000 * cos(纬度) 米/度
|
||||
|
double latLen = (maxLat - minLat) * 111000.0; |
||||
|
double lonLen = (maxLon - minLon) * 85000.0 * Math.cos(Math.toRadians(areaLat)); |
||||
|
double areaSize = latLen * lonLen; |
||||
|
|
||||
|
result.setAreaLat(areaLat); |
||||
|
result.setAreaLon(areaLon); |
||||
|
result.setAreaTotalSize(areaSize); |
||||
|
|
||||
|
result.setConcentrationAvag(globalCount == 0 ? null : globalSum / globalCount); |
||||
|
result.setConcentrationPointMax(pointMax == Float.MIN_VALUE ? null : pointMax); |
||||
|
result.setConcentrationPointMin(pointMin == Float.MAX_VALUE ? null : pointMin); |
||||
|
result.setConcentrationMax(gridMax == Float.MIN_VALUE ? null : gridMax); |
||||
|
result.setConcentrationMin(gridMin == Float.MAX_VALUE ? null : gridMin); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public static List<GridGasStatResult> computeStats(List<WaylineJobAtmosphereVo> atmosphereList, |
||||
|
double latGridSize, double lonGridSize, |
||||
|
List<String> gasKeys) { |
||||
|
if (atmosphereList == null || atmosphereList.isEmpty() || gasKeys == null || gasKeys.isEmpty()) { |
||||
|
return Collections.emptyList(); |
||||
|
} |
||||
|
|
||||
|
// 动态起点
|
||||
|
double baseLat = atmosphereList.stream() |
||||
|
.filter(vo -> vo.getLatitude() != null) |
||||
|
.mapToDouble(WaylineJobAtmosphereVo::getLatitude) |
||||
|
.min().orElse(0); |
||||
|
double baseLon = atmosphereList.stream() |
||||
|
.filter(vo -> vo.getLongitude() != null) |
||||
|
.mapToDouble(WaylineJobAtmosphereVo::getLongitude) |
||||
|
.min().orElse(0); |
||||
|
|
||||
|
// 区域边界初始化
|
||||
|
double minLat = Double.MAX_VALUE; |
||||
|
double maxLat = -Double.MAX_VALUE; |
||||
|
double minLon = Double.MAX_VALUE; |
||||
|
double maxLon = -Double.MAX_VALUE; |
||||
|
|
||||
|
// 每个 gasKey 的统计结构
|
||||
|
class GasStats { |
||||
|
float globalSum = 0; |
||||
|
int globalCount = 0; |
||||
|
float pointMax = Float.MIN_VALUE; |
||||
|
float pointMin = Float.MAX_VALUE; |
||||
|
Map<String, List<Float>> gridMap = new HashMap<>(); |
||||
|
} |
||||
|
|
||||
|
Map<String, GasStats> statsMap = new HashMap<>(); |
||||
|
for (String gasKey : gasKeys) { |
||||
|
statsMap.put(gasKey, new GasStats()); |
||||
|
} |
||||
|
|
||||
|
for (WaylineJobAtmosphereVo vo : atmosphereList) { |
||||
|
Float lat = vo.getLatitude(); |
||||
|
Float lon = vo.getLongitude(); |
||||
|
String airData = vo.getAirData(); |
||||
|
if (lat == null || lon == null || airData == null) continue; |
||||
|
|
||||
|
minLat = Math.min(minLat, lat); |
||||
|
maxLat = Math.max(maxLat, lat); |
||||
|
minLon = Math.min(minLon, lon); |
||||
|
maxLon = Math.max(maxLon, lon); |
||||
|
|
||||
|
JSONObject json = JSONUtil.parseObj(airData); |
||||
|
|
||||
|
for (String gasKey : gasKeys) { |
||||
|
if (!json.containsKey(gasKey)) continue; |
||||
|
|
||||
|
float value = json.getFloat(gasKey, 0f); |
||||
|
GasStats stats = statsMap.get(gasKey); |
||||
|
|
||||
|
// 全局统计
|
||||
|
stats.globalSum += value; |
||||
|
stats.globalCount++; |
||||
|
stats.pointMax = Math.max(stats.pointMax, value); |
||||
|
stats.pointMin = Math.min(stats.pointMin, value); |
||||
|
|
||||
|
// 网格编号
|
||||
|
int gridX = (int) ((lon - baseLon) / lonGridSize); |
||||
|
int gridY = (int) ((lat - baseLat) / latGridSize); |
||||
|
String gridKey = gridX + "_" + gridY; |
||||
|
|
||||
|
stats.gridMap.computeIfAbsent(gridKey, k -> new ArrayList<>()).add(value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 区域中心、面积计算
|
||||
|
double areaLat = (minLat + maxLat) / 2.0; |
||||
|
double areaLon = (minLon + maxLon) / 2.0; |
||||
|
double latLen = (maxLat - minLat) * 111000.0; |
||||
|
double lonLen = (maxLon - minLon) * 85000.0 * Math.cos(Math.toRadians(areaLat)); |
||||
|
double areaSize = latLen * lonLen; |
||||
|
|
||||
|
// 输出结果列表
|
||||
|
List<GridGasStatResult> resultList = new ArrayList<>(); |
||||
|
|
||||
|
for (String gasKey : gasKeys) { |
||||
|
GasStats stats = statsMap.get(gasKey); |
||||
|
|
||||
|
float gridMax = Float.MIN_VALUE; |
||||
|
float gridMin = Float.MAX_VALUE; |
||||
|
for (List<Float> values : stats.gridMap.values()) { |
||||
|
float sum = 0; |
||||
|
for (float v : values) sum += v; |
||||
|
float avg = sum / values.size(); |
||||
|
gridMax = Math.max(gridMax, avg); |
||||
|
gridMin = Math.min(gridMin, avg); |
||||
|
} |
||||
|
|
||||
|
GridGasStatResult result = new GridGasStatResult(); |
||||
|
result.setGasKey(gasKey); |
||||
|
result.setAreaLat(areaLat); |
||||
|
result.setAreaLon(areaLon); |
||||
|
result.setAreaTotalSize(areaSize); |
||||
|
result.setConcentrationAvag(stats.globalCount == 0 ? null : stats.globalSum / stats.globalCount); |
||||
|
result.setConcentrationPointMax(stats.pointMax == Float.MIN_VALUE ? null : stats.pointMax); |
||||
|
result.setConcentrationPointMin(stats.pointMin == Float.MAX_VALUE ? null : stats.pointMin); |
||||
|
result.setConcentrationMax(gridMax == Float.MIN_VALUE ? null : gridMax); |
||||
|
result.setConcentrationMin(gridMin == Float.MAX_VALUE ? null : gridMin); |
||||
|
|
||||
|
resultList.add(result); |
||||
|
} |
||||
|
|
||||
|
return resultList; |
||||
|
} |
||||
|
} |
@ -0,0 +1,101 @@ |
|||||
|
package org.dromara.sample.utils; |
||||
|
|
||||
|
import cn.hutool.extra.spring.SpringUtil; |
||||
|
import com.itextpdf.text.Document; |
||||
|
import com.itextpdf.text.DocumentException; |
||||
|
import com.itextpdf.text.Font; |
||||
|
import com.itextpdf.text.pdf.BaseFont; |
||||
|
import com.itextpdf.text.pdf.PdfWriter; |
||||
|
import com.itextpdf.tool.xml.XMLWorkerFontProvider; |
||||
|
import com.itextpdf.tool.xml.XMLWorkerHelper; |
||||
|
import freemarker.template.TemplateException; |
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; |
||||
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; |
||||
|
|
||||
|
import java.io.ByteArrayInputStream; |
||||
|
import java.io.ByteArrayOutputStream; |
||||
|
import java.io.IOException; |
||||
|
import java.net.URLEncoder; |
||||
|
import java.nio.charset.Charset; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* Html转换Pdf |
||||
|
* |
||||
|
* @author :Mall |
||||
|
* @date :Created in 2022-04-25 |
||||
|
*/ |
||||
|
public class HtmlConvertPdfHelper { |
||||
|
|
||||
|
/** |
||||
|
* Freemarker的配置类,模板目录默认 在 resources下的 templates |
||||
|
*/ |
||||
|
private static FreeMarkerConfigurer freeMarkerConfigurer = SpringUtil.getBean(FreeMarkerConfigurer.class); |
||||
|
|
||||
|
public static void renderTplFileToPDF(String fileName , String templateName, Map<String, Object> datas, HttpServletResponse response) { |
||||
|
try { |
||||
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); // 字符集编码
|
||||
|
response.setContentType("application/pdf;"); |
||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")); |
||||
|
response.addHeader("Access-Control-Allow-Origin", "*"); // 实现跨域
|
||||
|
byte[] bytes = htmlConvertPDF(datas, templateName); |
||||
|
// 将生成的文档写入到响应的输出流中
|
||||
|
response.reset(); // 重置响应
|
||||
|
response.getOutputStream().write(bytes); |
||||
|
response.getOutputStream().flush(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* freemarker转PDF |
||||
|
* |
||||
|
* @param templateName ftl文件名称,需要在resources/templates目录下 |
||||
|
* @return |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static byte[] htmlConvertPDF(Object map,String templateName) throws IOException, TemplateException, DocumentException { |
||||
|
String htmlText = FreeMarkerTemplateUtils.processTemplateIntoString(freeMarkerConfigurer.getConfiguration().getTemplate(templateName), map); |
||||
|
return htmlConvertPDF(htmlText); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 根据HTML内容转Image |
||||
|
* |
||||
|
* @param htmText HTML文本字符串 |
||||
|
*/ |
||||
|
public static byte[] htmlConvertPDF(String htmText) throws DocumentException, IOException { |
||||
|
//最终返回的byte流
|
||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
||||
|
//第一步,创建一个 iTextSharp.text.Document对象的实例:
|
||||
|
Document document = new Document(); |
||||
|
//第二步,为该Document创建一个Writer实例:
|
||||
|
PdfWriter writer = PdfWriter.getInstance(document, byteArrayOutputStream); |
||||
|
//第三步,打开当前Document
|
||||
|
document.open(); |
||||
|
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmText.getBytes()), null, Charset.defaultCharset(), new AsianFontProvider()); |
||||
|
document.close(); |
||||
|
return byteArrayOutputStream.toByteArray(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 用于中文显示的Provider |
||||
|
*/ |
||||
|
class AsianFontProvider extends XMLWorkerFontProvider { |
||||
|
@Override |
||||
|
public Font getFont(final String fontname, String encoding, float size, int style) { |
||||
|
try { |
||||
|
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); |
||||
|
return new Font(bfChinese, size, style); |
||||
|
} catch (Exception e) { |
||||
|
} |
||||
|
return super.getFont(fontname, encoding, size, style); |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,62 @@ |
|||||
|
package org.dromara.sample.wayline.domain.bo; |
||||
|
|
||||
|
import cn.hutool.json.JSONObject; |
||||
|
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
|
import io.github.linpeilie.annotations.AutoMapper; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import org.dromara.common.mybatis.core.domain.BaseEntity; |
||||
|
import org.dromara.sample.wayline.domain.WaylineJobAtmosphere; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 无人机任务-空气质量业务对象 wayline_job_atmosphere |
||||
|
* |
||||
|
* @author szs |
||||
|
* @date 2025-06-16 |
||||
|
*/ |
||||
|
@Data |
||||
|
public class WaylineJobAtmosphereData { |
||||
|
|
||||
|
private Long waylineJobId; //无人机任务ID
|
||||
|
private String serial; //序列号
|
||||
|
private String deviceSn;//机场SN
|
||||
|
|
||||
|
//{"SO2":0,"NO2":0,"Ox":0.058595,"PM1_0":39,"PM2_5":85,"PM10":108}
|
||||
|
private String atmosphereType;//NO2,NO2,0x,PM1_0,PM2_5
|
||||
|
private String atmosphereTypeStr;//NO2,NO2,0x,PM1_0,PM2_5
|
||||
|
|
||||
|
|
||||
|
private String deptDetectName;//和平街道大气监测
|
||||
|
private String companyName;//徐州市低空产业公司
|
||||
|
|
||||
|
private String startTime; |
||||
|
private String endTime; |
||||
|
|
||||
|
private String deviceName;//低空-徐州鼓楼琵琶街道
|
||||
|
private String deviceSerial;//37c12953
|
||||
|
private String deviceId;//100
|
||||
|
|
||||
|
private String analysisMethod;//分析方法:激光散射
|
||||
|
|
||||
|
private Integer analysisCount;//923
|
||||
|
|
||||
|
private Float areaWidth; //检测区域宽
|
||||
|
private Float areaLength; //检测区域长
|
||||
|
private Float areaSize; //检测区域平均面积
|
||||
|
private Float areaTotalSize; //检测区域总面积
|
||||
|
private Float areaLat; //检测区域维度
|
||||
|
private Float areaLon; //检测区域经度
|
||||
|
|
||||
|
private Float concentrationAvag; // 平均浓度
|
||||
|
private Float concentrationMax; // 最高值
|
||||
|
private Float concentrationMin; //最小值
|
||||
|
private Float concentrationPointMax; //单点最高值
|
||||
|
private Float concentrationPointMin; //单点最低值
|
||||
|
|
||||
|
private String imgUrl; |
||||
|
private String imgName; |
||||
|
|
||||
|
} |
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,101 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<title>SpiritSmell Record</title> |
||||
|
<style> |
||||
|
table, th, td { |
||||
|
border: 1px solid black; |
||||
|
border-collapse: collapse; |
||||
|
text-align: center; |
||||
|
} |
||||
|
h2 { |
||||
|
text-align: left; |
||||
|
margin-top: 30px; |
||||
|
margin-left: 60px; |
||||
|
} |
||||
|
p{ |
||||
|
margin-top: 3px; |
||||
|
margin-left: 60px; |
||||
|
} |
||||
|
table { |
||||
|
margin: 40px auto; |
||||
|
width: 100%; |
||||
|
} |
||||
|
/*h2 {*/ |
||||
|
/* color: #1b5aa1;*/ |
||||
|
/*}*/ |
||||
|
td { |
||||
|
word-wrap: break-word; |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
body{ |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body style="margin-top:30px;"> |
||||
|
|
||||
|
<!--<div style="display: flex;justify-content: space-between;">--> |
||||
|
<#--<div >--> |
||||
|
<#-- <div style="display:inline-block;width: 45%;">${deptDetectName?if_exists}</div>--> |
||||
|
<#-- <div style="display:inline-block;width: 45%;text-align: right">${companyName?if_exists}</div>--> |
||||
|
<#--</div>--> |
||||
|
|
||||
|
<#-- |
||||
|
<table style="width: 100%; border-collapse: collapse; border: none"> |
||||
|
<tr> |
||||
|
<td style="width: 50%; text-align: left; border-collapse: collapse; border: none "> |
||||
|
${deptDetectName?if_exists} |
||||
|
</td> |
||||
|
<td style="width: 50%; text-align: right;border-collapse: collapse; border: none "> |
||||
|
${companyName?if_exists} |
||||
|
</td> |
||||
|
</tr> |
||||
|
</table> |
||||
|
--> |
||||
|
|
||||
|
|
||||
|
<span style="display:inline-block;">${deptDetectName?if_exists} [${companyName?if_exists}]</span> |
||||
|
<span>分布情况:</span> |
||||
|
<#if (dataList?size gt 0) && dataList??> |
||||
|
<span>${deptDetectNameStr?if_exists}</span> |
||||
|
<#--<#list dataList as item>--> |
||||
|
<#-- <span>${item.atmosphereTypeStr?if_exists}</span>--> |
||||
|
<#--</#list>--> |
||||
|
</#if> |
||||
|
|
||||
|
<hr/> |
||||
|
|
||||
|
<p>检测时间: ${startTime?if_exists} 至 ${endTime?if_exists}</p> |
||||
|
<#--<p>监测设备: [${deviceName?if_exists}](${deviceSerial?if_exists}) 模块 ID: ${deviceId?if_exists}</p>--> |
||||
|
<p>监测设备: [${deviceName?if_exists}](${deviceSerial?if_exists}) </p> |
||||
|
<#--<p>${analysisMethod?if_exists}</p>--> |
||||
|
<p>采样点数量: ${analysisCount?if_exists}</p> |
||||
|
<p>检测区域网格平均尺寸: ${areaWidth?if_exists} 米 X ${areaLength?if_exists} 米 (${areaSize?if_exists} 平方米)</p> |
||||
|
<p>总检测区域网格面积: ${areaTotalSize?if_exists} (平方米)</p> |
||||
|
<p>检测区域中心点经纬度: ${areaLat?if_exists}, ${areaLon?if_exists}</p> |
||||
|
<hr/> |
||||
|
|
||||
|
|
||||
|
<#if (dataList?size gt 0) && dataList??> |
||||
|
<#list dataList as item> |
||||
|
|
||||
|
<h3>${item.atmosphereTypeStr?if_exists}浓度分布情况</h3> |
||||
|
<p>${item.atmosphereTypeStr?if_exists}检测区域平均浓度:${item.concentrationAvag?if_exists} μg/m³</p> |
||||
|
<p>${item.atmosphereTypeStr?if_exists}网格浓度最高值: ${item.concentrationMax?if_exists} μg/m³</p> |
||||
|
<p>${item.atmosphereTypeStr?if_exists}网格浓度最小值: ${item.concentrationMin?if_exists} μg/m³</p> |
||||
|
<p>${item.atmosphereTypeStr?if_exists}单点浓度最高值: ${item.concentrationPointMax?if_exists} μg/m³ ${item.concentrationPointMaxTime?if_exists}</p> |
||||
|
<p>${item.atmosphereTypeStr?if_exists}单点浓度最低值: ${item.concentrationPointMin?if_exists} μg/m³ ${item.concentrationPointMinTime?if_exists}</p> |
||||
|
|
||||
|
<div style="text-align: center"> |
||||
|
<img src="${item.imgUrl?if_exists}" alt="${item.imgName?if_exists}" /> |
||||
|
</div> |
||||
|
<div style="margin-top: 30px;"> |
||||
|
<hr/> |
||||
|
</div> |
||||
|
|
||||
|
</#list> |
||||
|
</#if> |
||||
|
|
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,81 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<title>SpiritSmell Record</title> |
||||
|
<style> |
||||
|
table, th, td { |
||||
|
border: 1px solid black; |
||||
|
border-collapse: collapse; |
||||
|
text-align: center; |
||||
|
} |
||||
|
h2 { |
||||
|
text-align: left; |
||||
|
margin-top: 40px; |
||||
|
margin-left: 60px; |
||||
|
} |
||||
|
p{ |
||||
|
margin-top: 10px; |
||||
|
margin-left: 60px; |
||||
|
} |
||||
|
table { |
||||
|
margin: 40px auto; |
||||
|
width: 100%; |
||||
|
} |
||||
|
/*h2 {*/ |
||||
|
/* color: #1b5aa1;*/ |
||||
|
/*}*/ |
||||
|
td { |
||||
|
word-wrap: break-word; |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
body{ |
||||
|
font-size: 18px; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body style="margin-top:30px;"> |
||||
|
|
||||
|
<!--<div style="display: flex;justify-content: space-between;">--> |
||||
|
<#--<div >--> |
||||
|
<#-- <div style="display:inline-block;width: 45%;">${deptDetectName?if_exists}</div>--> |
||||
|
<#-- <div style="display:inline-block;width: 45%;text-align: right">${companyName?if_exists}</div>--> |
||||
|
<#--</div>--> |
||||
|
|
||||
|
<#-- |
||||
|
<table style="width: 100%; border-collapse: collapse; border: none"> |
||||
|
<tr> |
||||
|
<td style="width: 50%; text-align: left; border-collapse: collapse; border: none "> |
||||
|
${deptDetectName?if_exists} |
||||
|
</td> |
||||
|
<td style="width: 50%; text-align: right;border-collapse: collapse; border: none "> |
||||
|
${companyName?if_exists} |
||||
|
</td> |
||||
|
</tr> |
||||
|
</table> |
||||
|
--> |
||||
|
|
||||
|
<h3 style="display:inline-block;">${deptDetectName?if_exists} [${companyName?if_exists}]</h3> |
||||
|
<hr/> |
||||
|
|
||||
|
<h3 >${atmosphereTypeStr?if_exists}浓度分布情况</h3> |
||||
|
|
||||
|
<p>检测时间: ${startTime?if_exists} 至 ${endTime?if_exists}</p> |
||||
|
<p>监测设备: [${deviceName?if_exists}](${deviceSerial?if_exists}) 模块 ID: ${deviceId?if_exists}</p> |
||||
|
<#--<p>${analysisMethod?if_exists}</p>--> |
||||
|
<p>采样点数量: ${analysisCount?if_exists}</p> |
||||
|
<p>检测区域网格平均尺寸: ${areaWidth?if_exists} 米 X ${areaLength?if_exists} 米 (${areaSize?if_exists} 平方米)</p> |
||||
|
<p>总检测区域网格面积: ${areaTotalSize?if_exists} (平方米)</p> |
||||
|
<p>检测区域中心点经纬度: ${areaLat?if_exists}, ${areaLon?if_exists}</p> |
||||
|
<p>${atmosphereTypeStr?if_exists}检测区域平均浓度:${concentrationAvag?if_exists} μg/m³</p> |
||||
|
<p>${atmosphereTypeStr?if_exists}网格浓度最高值: ${concentrationMax?if_exists} μg/m³</p> |
||||
|
<p>${atmosphereTypeStr?if_exists}网格浓度最小值: ${concentrationMin?if_exists} μg/m³</p> |
||||
|
<p>${atmosphereTypeStr?if_exists}单点浓度最高值: ${concentrationPointMax?if_exists} μg/m³ ${concentrationPointMaxTime?if_exists}</p> |
||||
|
<p>${atmosphereTypeStr?if_exists}单点浓度最低值: ${concentrationPointMin?if_exists} μg/m³ ${concentrationPointMinTime?if_exists}</p> |
||||
|
|
||||
|
|
||||
|
<div style="text-align: center"> |
||||
|
<img src="${imgUrl?if_exists}" alt="${imgName?if_exists}" style=""/> |
||||
|
</div> |
||||
|
|
||||
|
</body> |
||||
|
</html> |
After Width: | Height: | Size: 437 KiB |
@ -0,0 +1,141 @@ |
|||||
|
package org.dromara.system.controller; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Set; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
import cn.hutool.core.util.NumberUtil; |
||||
|
import com.alibaba.fastjson.JSON; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
import jakarta.validation.constraints.*; |
||||
|
import cn.dev33.satoken.annotation.SaCheckPermission; |
||||
|
import org.dromara.system.service.ISysSubmailConfigService; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
import org.springframework.validation.annotation.Validated; |
||||
|
import org.dromara.common.idempotent.annotation.RepeatSubmit; |
||||
|
import org.dromara.common.log.annotation.Log; |
||||
|
import org.dromara.common.web.core.BaseController; |
||||
|
import org.dromara.common.mybatis.core.page.PageQuery; |
||||
|
import org.dromara.common.core.domain.R; |
||||
|
import org.dromara.common.core.validate.AddGroup; |
||||
|
import org.dromara.common.core.validate.EditGroup; |
||||
|
import org.dromara.common.log.enums.BusinessType; |
||||
|
import org.dromara.common.excel.utils.ExcelUtil; |
||||
|
import org.dromara.system.domain.vo.SysMsgConfigUserVo; |
||||
|
import org.dromara.system.domain.bo.SysMsgConfigUserBo; |
||||
|
import org.dromara.system.service.ISysMsgConfigUserService; |
||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo; |
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户 |
||||
|
* 前端访问路由地址为:/system/msgConfigUser |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
@Validated |
||||
|
@RequiredArgsConstructor |
||||
|
@RestController |
||||
|
@RequestMapping("/msgConfigUser") |
||||
|
public class SysMsgConfigUserController extends BaseController { |
||||
|
|
||||
|
private final ISysMsgConfigUserService sysMsgConfigUserService; |
||||
|
|
||||
|
private final ISysSubmailConfigService sysSubmailConfigService; |
||||
|
|
||||
|
/** |
||||
|
* 查询系统短信发送配置用户列表 |
||||
|
*/ |
||||
|
@SaCheckPermission("system:msgConfigUser:list") |
||||
|
@GetMapping("/list") |
||||
|
public TableDataInfo<SysMsgConfigUserVo> list(SysMsgConfigUserBo bo, PageQuery pageQuery) { |
||||
|
return sysMsgConfigUserService.queryPageList(bo, pageQuery); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 导出系统短信发送配置用户列表 |
||||
|
*/ |
||||
|
@SaCheckPermission("system:msgConfigUser:export") |
||||
|
@Log(title = "系统短信发送配置用户", businessType = BusinessType.EXPORT) |
||||
|
@PostMapping("/export") |
||||
|
public void export(SysMsgConfigUserBo bo, HttpServletResponse response) { |
||||
|
List<SysMsgConfigUserVo> list = sysMsgConfigUserService.queryList(bo); |
||||
|
ExcelUtil.exportExcel(list, "系统短信发送配置用户", SysMsgConfigUserVo.class, response); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 短信消息发送 |
||||
|
* @param deviceSn |
||||
|
* @param taskType 1:手动飞行 2:航线飞行 |
||||
|
* @return |
||||
|
*/ |
||||
|
@GetMapping("/sendMsg/{deviceSn}/{taskType}") |
||||
|
public R<String> sendMsg( @PathVariable String deviceSn, @PathVariable int taskType) { |
||||
|
// sysMsgConfigUserService.queryById(id)
|
||||
|
SysMsgConfigUserBo bo = new SysMsgConfigUserBo(); |
||||
|
bo.setDeviceSn(deviceSn); |
||||
|
bo.setMsgSendType("drone_send_opt_user");//机场操作-提示运行人员
|
||||
|
List<SysMsgConfigUserVo> sysMsgConfigUserVoList = sysMsgConfigUserService.queryList(bo); |
||||
|
if(sysMsgConfigUserVoList.size() > 0) { |
||||
|
// remoteSubmailConfigService.remoteSendUser("smsMultixsend",List.of(Long.valueOf(completeTaskBo.getHandler())),noticeMap,"kKv7s3");
|
||||
|
|
||||
|
//构建推送信息
|
||||
|
Map<String, Object> noticeMap = new HashMap<>(); |
||||
|
noticeMap.put("dockName", sysMsgConfigUserVoList.get(0).getDeviceName()); |
||||
|
noticeMap.put("taskType", taskType == 1 ? "手动飞行" : "航线飞行"); |
||||
|
Set<String> phoneList = sysMsgConfigUserVoList.stream().map(SysMsgConfigUserVo::getPhonenumber).distinct().collect(Collectors.toSet()); |
||||
|
sysSubmailConfigService.sendPhone("smsMultixsend",phoneList, JSON.toJSONString(noticeMap),"JXtQI"); |
||||
|
} |
||||
|
return R.ok(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取系统短信发送配置用户详细信息 |
||||
|
* |
||||
|
* @param id 主键 |
||||
|
*/ |
||||
|
@SaCheckPermission("system:msgConfigUser:query") |
||||
|
@GetMapping("/{id}") |
||||
|
public R<SysMsgConfigUserVo> getInfo(@NotNull(message = "主键不能为空") |
||||
|
@PathVariable Long id) { |
||||
|
return R.ok(sysMsgConfigUserService.queryById(id)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 新增系统短信发送配置用户 |
||||
|
*/ |
||||
|
@SaCheckPermission("system:msgConfigUser:add") |
||||
|
@Log(title = "系统短信发送配置用户", businessType = BusinessType.INSERT) |
||||
|
@RepeatSubmit() |
||||
|
@PostMapping() |
||||
|
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysMsgConfigUserBo bo) { |
||||
|
return toAjax(sysMsgConfigUserService.insertByBo(bo)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 修改系统短信发送配置用户 |
||||
|
*/ |
||||
|
@SaCheckPermission("system:msgConfigUser:edit") |
||||
|
@Log(title = "系统短信发送配置用户", businessType = BusinessType.UPDATE) |
||||
|
@RepeatSubmit() |
||||
|
@PutMapping() |
||||
|
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysMsgConfigUserBo bo) { |
||||
|
return toAjax(sysMsgConfigUserService.updateByBo(bo)); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 删除系统短信发送配置用户 |
||||
|
* |
||||
|
* @param ids 主键串 |
||||
|
*/ |
||||
|
@SaCheckPermission("system:msgConfigUser:remove") |
||||
|
@Log(title = "系统短信发送配置用户", businessType = BusinessType.DELETE) |
||||
|
@DeleteMapping("/{ids}") |
||||
|
public R<Void> remove(@NotEmpty(message = "主键不能为空") |
||||
|
@PathVariable Long[] ids) { |
||||
|
return toAjax(sysMsgConfigUserService.deleteWithValidByIds(List.of(ids), true)); |
||||
|
} |
||||
|
} |
@ -0,0 +1,331 @@ |
|||||
|
package org.dromara.system.controller.system; |
||||
|
|
||||
|
import cn.dev33.satoken.annotation.SaCheckPermission; |
||||
|
import cn.hutool.http.HttpRequest; |
||||
|
import cn.hutool.json.JSONObject; |
||||
|
import cn.hutool.json.JSONUtil; |
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.dromara.common.core.domain.R; |
||||
|
import org.dromara.common.excel.utils.ExcelUtil; |
||||
|
import org.dromara.common.log.annotation.Log; |
||||
|
import org.dromara.common.log.enums.BusinessType; |
||||
|
import org.dromara.common.mybatis.core.page.PageQuery; |
||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo; |
||||
|
import org.dromara.common.web.core.BaseController; |
||||
|
import org.dromara.system.domain.bo.SysConfigBo; |
||||
|
import org.dromara.system.domain.vo.SysConfigVo; |
||||
|
import org.dromara.system.service.ISysConfigService; |
||||
|
import org.springframework.validation.annotation.Validated; |
||||
|
import org.springframework.web.bind.annotation.*; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 参数配置 信息操作处理 |
||||
|
* |
||||
|
* @author Lion Li |
||||
|
*/ |
||||
|
@Validated |
||||
|
@RequiredArgsConstructor |
||||
|
@RestController |
||||
|
@RequestMapping("/ysyApi") |
||||
|
public class YSYDeviceController extends BaseController { |
||||
|
|
||||
|
private final ISysConfigService configService; |
||||
|
|
||||
|
private static final String BASE_URL = "https://open.ys7.com"; |
||||
|
|
||||
|
//opt操作
|
||||
|
private static final String APP_TOKEN_GET = "/api/lapp/token/get"; |
||||
|
|
||||
|
|
||||
|
//设备信息
|
||||
|
private static final String DEVICE_LIST_API = "/api/lapp/device/list"; |
||||
|
private static final String DEVICE_INFO = "/api/lapp/device/info"; |
||||
|
private static final String DEVICE_CAMERA_LIST = "/api/lapp/device/camera/list"; |
||||
|
|
||||
|
|
||||
|
private static final String DEVICE_NAME_UPDATE = "/api/lapp/device/name/update"; |
||||
|
private static final String CAMERA_NAME_UPDATE = "/api/lapp/camera/name/update"; |
||||
|
|
||||
|
//云台控制
|
||||
|
private static final String DEVICE_PTZ_START = "/api/lapp/device/ptz/start"; |
||||
|
private static final String DEVICE_PTZ_STOP = "/api/lapp/device/ptz/stop"; |
||||
|
|
||||
|
//直播
|
||||
|
private static final String LIVE_ADDRESS_GET = "/api/lapp/v2/live/address/get"; |
||||
|
private static final String VIDEO_UNIFY_QUERY = "/api/v3/device/local/video/unify/query"; |
||||
|
|
||||
|
|
||||
|
|
||||
|
// @SaCheckPermission("system:config:list")
|
||||
|
// @GetMapping("/device/list")
|
||||
|
// public TableDataInfo<SysConfigVo> list(SysConfigBo config, PageQuery pageQuery) {
|
||||
|
// return configService.selectPageConfigList(config, pageQuery);
|
||||
|
// }
|
||||
|
|
||||
|
//--------------------------------------OPT操作---------------------------------------------
|
||||
|
|
||||
|
/** 获取accessToken https://open.ys7.com/help/81
|
||||
|
* https://open.ys7.com/api/lapp/token/get
|
||||
|
*/ |
||||
|
@PostMapping("/token/get") |
||||
|
public JSONObject tokenGet(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("appKey")){ return null; }; |
||||
|
if(!params.containsKey("appSecret")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("appKey", params.getStr("appKey")); |
||||
|
body.put("appSecret", params.getStr("appSecret")); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + APP_TOKEN_GET) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** 修改云端设备名称 https://open.ys7.com/help/667
|
||||
|
* https://open.ys7.com/api/lapp/device/name/update
|
||||
|
*/ |
||||
|
@PostMapping("/device/name/update") |
||||
|
public JSONObject deviceNameUpdate(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
if(!params.containsKey("deviceName")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getInt("deviceSerial")); |
||||
|
body.put("deviceName", params.getStr("deviceName")); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + DEVICE_NAME_UPDATE) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 修改云端通道名称 https://open.ys7.com/help/668
|
||||
|
* https://open.ys7.com/api/lapp/camera/name/update
|
||||
|
*/ |
||||
|
@PostMapping("/camera/name/update") |
||||
|
public JSONObject cameraNameUpdate(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
if(!params.containsKey("name")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getInt("deviceSerial")); |
||||
|
body.put("name", params.getStr("name")); |
||||
|
body.put("channelNo", params.getInt("channelNo",1)); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + CAMERA_NAME_UPDATE) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
//--------------------------------------设备信息---------------------------------------------
|
||||
|
|
||||
|
/** 设备分页查询 https://open.ys7.com/help/673
|
||||
|
* https://open.ys7.com/api/lapp/device/list
|
||||
|
* **/ |
||||
|
@PostMapping("/device/list") |
||||
|
public JSONObject deviceList(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("pageStart", params.getInt("pageStart",0)); |
||||
|
body.put("pageSize", params.getInt("pageSize",10)); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + DEVICE_LIST_API) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
/**获取单个设备信息 https://open.ys7.com/help/672
|
||||
|
* https://open.ys7.com/api/lapp/device/info
|
||||
|
*/ |
||||
|
@PostMapping("/device/info") |
||||
|
public JSONObject deviceInfo(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getStr("deviceSerial")); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + DEVICE_INFO) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
/**获取指定设备的通道信息 https://open.ys7.com/help/1478
|
||||
|
* https://open.ys7.com/api/lapp/device/camera/list
|
||||
|
*/ |
||||
|
@PostMapping("/device/camera/list") |
||||
|
public JSONObject deviceCameraList(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getStr("deviceSerial")); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + DEVICE_CAMERA_LIST) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
//--------------------------------------云台控制---------------------------------------------
|
||||
|
|
||||
|
/**开始云台控制 https://open.ys7.com/help/679
|
||||
|
* https://open.ys7.com/api/lapp/device/ptz/start
|
||||
|
*/ |
||||
|
@PostMapping("/device/ptz/start") |
||||
|
public JSONObject devicePTZStart(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
if(!params.containsKey("channelNo")){ return null; }; |
||||
|
if(!params.containsKey("direction")){ return null; }; |
||||
|
if(!params.containsKey("speed")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getStr("deviceSerial")); |
||||
|
body.put("channelNo", params.getInt("channelNo",1)); |
||||
|
body.put("direction", params.getInt("direction",16)); |
||||
|
body.put("speed", params.getInt("speed",1)); |
||||
|
|
||||
|
//先停止一遍
|
||||
|
String response_stop = HttpRequest.post(BASE_URL + DEVICE_PTZ_STOP) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + DEVICE_PTZ_START) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
/**停止云台控制 https://open.ys7.com/help/680
|
||||
|
* https://open.ys7.com/api/lapp/device/ptz/stop
|
||||
|
*/ |
||||
|
@PostMapping("/device/ptz/stop") |
||||
|
public JSONObject devicePTZStop(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
if(!params.containsKey("channelNo")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getStr("deviceSerial")); |
||||
|
body.put("channelNo", params.getInt("channelNo",1)); |
||||
|
body.put("direction", params.getInt("direction",16)); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + DEVICE_PTZ_STOP) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
//--------------------------------------播放---------------------------------------------
|
||||
|
|
||||
|
|
||||
|
/**获取播放地址(新) https://open.ys7.com/help/1414
|
||||
|
* https://open.ys7.com/api/lapp/v2/live/address/get
|
||||
|
* |
||||
|
* protocol Integer 流播放协议,1-ezopen、2-hls、3-rtmp、4-flv,默认为1 |
||||
|
* type String 地址的类型,1-预览,2-本地录像回放,3-云存储录像回放,非必选,默认为1;回放仅支持rtmp、ezopen、flv协议 |
||||
|
*/ |
||||
|
@PostMapping("/live/address/get") |
||||
|
public JSONObject liveAddressGet(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
if(!params.containsKey("type")){ return null; }; |
||||
|
// if(!params.containsKey("channelNo")){ return null; };
|
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
body.put("accessToken", params.getStr("accessToken")); |
||||
|
body.put("deviceSerial", params.getStr("deviceSerial")); |
||||
|
body.put("channelNo", params.getInt("channelNo",1)); |
||||
|
body.put("protocol", params.getInt("protocol",1)); //流播放协议,1-ezopen(默认)、2-hls、3-rtmp、4-flv,
|
||||
|
body.put("type", params.getInt("type",1)); //地址的类型,1-预览(默认),2-本地录像回放,3-云存储录像回放,回放仅支持rtmp、ezopen、flv协议
|
||||
|
body.put("expireTime", params.getInt("expireTime",300)); |
||||
|
body.put("quality", params.getInt("quality",2)); |
||||
|
body.put("startTime", params.getStr("startTime")); |
||||
|
body.put("stopTime", params.getStr("stopTime")); |
||||
|
|
||||
|
String response = HttpRequest.post(BASE_URL + LIVE_ADDRESS_GET) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**查询设备本地录像 https://open.ys7.com/help/3922
|
||||
|
* https://open.ys7.com/api/v3/device/local/video/unify/query
|
||||
|
*/ |
||||
|
@PostMapping("/video/unify/query") |
||||
|
public JSONObject videoUnifyQuery(@RequestBody JSONObject params) { |
||||
|
if(!params.containsKey("accessToken")){ return null; }; |
||||
|
if(!params.containsKey("deviceSerial")){ return null; }; |
||||
|
if(!params.containsKey("startTime")){ return null; }; |
||||
|
if(!params.containsKey("endTime")){ return null; }; |
||||
|
|
||||
|
Map<String, Object> body = new HashMap<>(); |
||||
|
// body.put("accessToken", params.getStr("accessToken"));
|
||||
|
// body.put("deviceSerial", params.getStr("deviceSerial"));
|
||||
|
// body.put("localIndex", params.getInt("localIndex",1));
|
||||
|
// body.put("recordType", params.getInt("recordType",1));
|
||||
|
body.put("startTime", params.getStr("startTime")); |
||||
|
body.put("endTime", params.getStr("endTime")); |
||||
|
body.put("pageSize", params.getInt("pageSize",50)); |
||||
|
|
||||
|
String response = HttpRequest.get(BASE_URL + VIDEO_UNIFY_QUERY) |
||||
|
.header("Content-Type", "application/x-www-form-urlencoded") |
||||
|
.header("accessToken", params.getStr("accessToken")) |
||||
|
.header("deviceSerial", params.getStr("deviceSerial")) |
||||
|
.header("localIndex", params.getStr("localIndex","1")) |
||||
|
.form(body) |
||||
|
.execute() |
||||
|
.body(); |
||||
|
return JSONUtil.parseObj(response); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
package org.dromara.system.domain; |
||||
|
|
||||
|
import org.dromara.common.tenant.core.TenantEntity; |
||||
|
import com.baomidou.mybatisplus.annotation.*; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
|
||||
|
import java.io.Serial; |
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户对象 sys_msg_config_user |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
@Data |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
@TableName("sys_msg_config_user") |
||||
|
public class SysMsgConfigUser extends TenantEntity { |
||||
|
|
||||
|
@Serial |
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
/** |
||||
|
* ID |
||||
|
*/ |
||||
|
@TableId(value = "id") |
||||
|
private Long id; |
||||
|
|
||||
|
/** |
||||
|
* 短信发送(字典) |
||||
|
*/ |
||||
|
private String msgSendType; |
||||
|
|
||||
|
/** |
||||
|
* 设备SN |
||||
|
*/ |
||||
|
private String deviceSn; |
||||
|
|
||||
|
/** |
||||
|
* 设备名称 |
||||
|
*/ |
||||
|
private String deviceName; |
||||
|
|
||||
|
/** |
||||
|
* 赛邮配置ID |
||||
|
*/ |
||||
|
private Long submailConfigId; |
||||
|
|
||||
|
/** |
||||
|
* 用户Id |
||||
|
*/ |
||||
|
private Long userId; |
||||
|
|
||||
|
/** |
||||
|
* 用户名称 |
||||
|
*/ |
||||
|
private String name; |
||||
|
|
||||
|
/** |
||||
|
* 手机号 |
||||
|
*/ |
||||
|
private String phonenumber; |
||||
|
|
||||
|
/** |
||||
|
* 备注 |
||||
|
*/ |
||||
|
private String remark; |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,74 @@ |
|||||
|
package org.dromara.system.domain.bo; |
||||
|
|
||||
|
import org.dromara.system.domain.SysMsgConfigUser; |
||||
|
import org.dromara.common.mybatis.core.domain.BaseEntity; |
||||
|
import org.dromara.common.core.validate.AddGroup; |
||||
|
import org.dromara.common.core.validate.EditGroup; |
||||
|
import io.github.linpeilie.annotations.AutoMapper; |
||||
|
import lombok.Data; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import jakarta.validation.constraints.*; |
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户业务对象 sys_msg_config_user |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
@Data |
||||
|
@EqualsAndHashCode(callSuper = true) |
||||
|
@AutoMapper(target = SysMsgConfigUser.class, reverseConvertGenerate = false) |
||||
|
public class SysMsgConfigUserBo extends BaseEntity { |
||||
|
|
||||
|
/** |
||||
|
* ID |
||||
|
*/ |
||||
|
@NotNull(message = "ID不能为空", groups = { EditGroup.class }) |
||||
|
private Long id; |
||||
|
|
||||
|
/** |
||||
|
* 短信发送(字典) |
||||
|
*/ |
||||
|
@NotBlank(message = "短信发送(字典)不能为空", groups = { AddGroup.class, EditGroup.class }) |
||||
|
private String msgSendType; |
||||
|
|
||||
|
/** |
||||
|
* 设备SN |
||||
|
*/ |
||||
|
private String deviceSn; |
||||
|
|
||||
|
/** |
||||
|
* 设备名称 |
||||
|
*/ |
||||
|
private String deviceName; |
||||
|
|
||||
|
/** |
||||
|
* 赛邮配置ID |
||||
|
*/ |
||||
|
private Long submailConfigId; |
||||
|
|
||||
|
/** |
||||
|
* 用户Id |
||||
|
*/ |
||||
|
@NotNull(message = "用户Id不能为空", groups = { AddGroup.class, EditGroup.class }) |
||||
|
private Long userId; |
||||
|
|
||||
|
/** |
||||
|
* 用户名称 |
||||
|
*/ |
||||
|
@NotBlank(message = "用户名称不能为空", groups = { AddGroup.class, EditGroup.class }) |
||||
|
private String name; |
||||
|
|
||||
|
/** |
||||
|
* 手机号 |
||||
|
*/ |
||||
|
@NotBlank(message = "手机号不能为空", groups = { AddGroup.class, EditGroup.class }) |
||||
|
private String phonenumber; |
||||
|
|
||||
|
/** |
||||
|
* 备注 |
||||
|
*/ |
||||
|
private String remark; |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,87 @@ |
|||||
|
package org.dromara.system.domain.vo; |
||||
|
|
||||
|
import org.dromara.system.domain.SysMsgConfigUser; |
||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
||||
|
import com.alibaba.excel.annotation.ExcelProperty; |
||||
|
import org.dromara.common.excel.annotation.ExcelDictFormat; |
||||
|
import org.dromara.common.excel.convert.ExcelDictConvert; |
||||
|
import io.github.linpeilie.annotations.AutoMapper; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.io.Serial; |
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户视图对象 sys_msg_config_user |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
@Data |
||||
|
@ExcelIgnoreUnannotated |
||||
|
@AutoMapper(target = SysMsgConfigUser.class) |
||||
|
public class SysMsgConfigUserVo implements Serializable { |
||||
|
|
||||
|
@Serial |
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
/** |
||||
|
* ID |
||||
|
*/ |
||||
|
@ExcelProperty(value = "ID") |
||||
|
private Long id; |
||||
|
|
||||
|
/** |
||||
|
* 短信发送(字典) |
||||
|
*/ |
||||
|
@ExcelProperty(value = "短信发送(字典)", converter = ExcelDictConvert.class) |
||||
|
@ExcelDictFormat(dictType = "msg_send_type") |
||||
|
private String msgSendType; |
||||
|
|
||||
|
/** |
||||
|
* 设备SN |
||||
|
*/ |
||||
|
@ExcelProperty(value = "设备SN") |
||||
|
private String deviceSn; |
||||
|
|
||||
|
/** |
||||
|
* 设备名称 |
||||
|
*/ |
||||
|
@ExcelProperty(value = "设备名称") |
||||
|
private String deviceName; |
||||
|
|
||||
|
/** |
||||
|
* 赛邮配置ID |
||||
|
*/ |
||||
|
@ExcelProperty(value = "赛邮配置ID") |
||||
|
private Long submailConfigId; |
||||
|
|
||||
|
/** |
||||
|
* 用户Id |
||||
|
*/ |
||||
|
@ExcelProperty(value = "用户Id") |
||||
|
private Long userId; |
||||
|
|
||||
|
/** |
||||
|
* 用户名称 |
||||
|
*/ |
||||
|
@ExcelProperty(value = "用户名称") |
||||
|
private String name; |
||||
|
|
||||
|
/** |
||||
|
* 手机号 |
||||
|
*/ |
||||
|
@ExcelProperty(value = "手机号") |
||||
|
private String phonenumber; |
||||
|
|
||||
|
/** |
||||
|
* 备注 |
||||
|
*/ |
||||
|
@ExcelProperty(value = "备注") |
||||
|
private String remark; |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package org.dromara.system.mapper; |
||||
|
|
||||
|
import org.dromara.system.domain.SysMsgConfigUser; |
||||
|
import org.dromara.system.domain.vo.SysMsgConfigUserVo; |
||||
|
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; |
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户Mapper接口 |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
public interface SysMsgConfigUserMapper extends BaseMapperPlus<SysMsgConfigUser, SysMsgConfigUserVo> { |
||||
|
|
||||
|
} |
@ -0,0 +1,69 @@ |
|||||
|
package org.dromara.system.service; |
||||
|
|
||||
|
import org.dromara.system.domain.SysMsgConfigUser; |
||||
|
import org.dromara.system.domain.vo.SysMsgConfigUserVo; |
||||
|
import org.dromara.system.domain.bo.SysMsgConfigUserBo; |
||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo; |
||||
|
import org.dromara.common.mybatis.core.page.PageQuery; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户Service接口 |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
public interface ISysMsgConfigUserService { |
||||
|
|
||||
|
/** |
||||
|
* 查询系统短信发送配置用户 |
||||
|
* |
||||
|
* @param id 主键 |
||||
|
* @return 系统短信发送配置用户 |
||||
|
*/ |
||||
|
SysMsgConfigUserVo queryById(Long id); |
||||
|
|
||||
|
/** |
||||
|
* 分页查询系统短信发送配置用户列表 |
||||
|
* |
||||
|
* @param bo 查询条件 |
||||
|
* @param pageQuery 分页参数 |
||||
|
* @return 系统短信发送配置用户分页列表 |
||||
|
*/ |
||||
|
TableDataInfo<SysMsgConfigUserVo> queryPageList(SysMsgConfigUserBo bo, PageQuery pageQuery); |
||||
|
|
||||
|
/** |
||||
|
* 查询符合条件的系统短信发送配置用户列表 |
||||
|
* |
||||
|
* @param bo 查询条件 |
||||
|
* @return 系统短信发送配置用户列表 |
||||
|
*/ |
||||
|
List<SysMsgConfigUserVo> queryList(SysMsgConfigUserBo bo); |
||||
|
|
||||
|
/** |
||||
|
* 新增系统短信发送配置用户 |
||||
|
* |
||||
|
* @param bo 系统短信发送配置用户 |
||||
|
* @return 是否新增成功 |
||||
|
*/ |
||||
|
Boolean insertByBo(SysMsgConfigUserBo bo); |
||||
|
|
||||
|
/** |
||||
|
* 修改系统短信发送配置用户 |
||||
|
* |
||||
|
* @param bo 系统短信发送配置用户 |
||||
|
* @return 是否修改成功 |
||||
|
*/ |
||||
|
Boolean updateByBo(SysMsgConfigUserBo bo); |
||||
|
|
||||
|
/** |
||||
|
* 校验并批量删除系统短信发送配置用户信息 |
||||
|
* |
||||
|
* @param ids 待删除的主键集合 |
||||
|
* @param isValid 是否进行有效性校验 |
||||
|
* @return 是否删除成功 |
||||
|
*/ |
||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); |
||||
|
} |
@ -0,0 +1,135 @@ |
|||||
|
package org.dromara.system.service.impl; |
||||
|
|
||||
|
import org.dromara.common.core.utils.MapstructUtils; |
||||
|
import org.dromara.common.core.utils.StringUtils; |
||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo; |
||||
|
import org.dromara.common.mybatis.core.page.PageQuery; |
||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.dromara.system.domain.bo.SysMsgConfigUserBo; |
||||
|
import org.dromara.system.domain.vo.SysMsgConfigUserVo; |
||||
|
import org.dromara.system.domain.SysMsgConfigUser; |
||||
|
import org.dromara.system.mapper.SysMsgConfigUserMapper; |
||||
|
import org.dromara.system.service.ISysMsgConfigUserService; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Collection; |
||||
|
|
||||
|
/** |
||||
|
* 系统短信发送配置用户Service业务层处理 |
||||
|
* |
||||
|
* @author yq |
||||
|
* @date 2025-07-15 |
||||
|
*/ |
||||
|
@RequiredArgsConstructor |
||||
|
@Service |
||||
|
public class SysMsgConfigUserServiceImpl implements ISysMsgConfigUserService { |
||||
|
|
||||
|
private final SysMsgConfigUserMapper baseMapper; |
||||
|
|
||||
|
/** |
||||
|
* 查询系统短信发送配置用户 |
||||
|
* |
||||
|
* @param id 主键 |
||||
|
* @return 系统短信发送配置用户 |
||||
|
*/ |
||||
|
@Override |
||||
|
public SysMsgConfigUserVo queryById(Long id){ |
||||
|
return baseMapper.selectVoById(id); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 分页查询系统短信发送配置用户列表 |
||||
|
* |
||||
|
* @param bo 查询条件 |
||||
|
* @param pageQuery 分页参数 |
||||
|
* @return 系统短信发送配置用户分页列表 |
||||
|
*/ |
||||
|
@Override |
||||
|
public TableDataInfo<SysMsgConfigUserVo> queryPageList(SysMsgConfigUserBo bo, PageQuery pageQuery) { |
||||
|
LambdaQueryWrapper<SysMsgConfigUser> lqw = buildQueryWrapper(bo); |
||||
|
Page<SysMsgConfigUserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); |
||||
|
return TableDataInfo.build(result); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查询符合条件的系统短信发送配置用户列表 |
||||
|
* |
||||
|
* @param bo 查询条件 |
||||
|
* @return 系统短信发送配置用户列表 |
||||
|
*/ |
||||
|
@Override |
||||
|
public List<SysMsgConfigUserVo> queryList(SysMsgConfigUserBo bo) { |
||||
|
LambdaQueryWrapper<SysMsgConfigUser> lqw = buildQueryWrapper(bo); |
||||
|
return baseMapper.selectVoList(lqw); |
||||
|
} |
||||
|
|
||||
|
private LambdaQueryWrapper<SysMsgConfigUser> buildQueryWrapper(SysMsgConfigUserBo bo) { |
||||
|
Map<String, Object> params = bo.getParams(); |
||||
|
LambdaQueryWrapper<SysMsgConfigUser> lqw = Wrappers.lambdaQuery(); |
||||
|
lqw.eq(StringUtils.isNotBlank(bo.getMsgSendType()), SysMsgConfigUser::getMsgSendType, bo.getMsgSendType()); |
||||
|
lqw.eq(StringUtils.isNotBlank(bo.getDeviceSn()), SysMsgConfigUser::getDeviceSn, bo.getDeviceSn()); |
||||
|
lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), SysMsgConfigUser::getDeviceName, bo.getDeviceName()); |
||||
|
lqw.eq(bo.getSubmailConfigId() != null, SysMsgConfigUser::getSubmailConfigId, bo.getSubmailConfigId()); |
||||
|
lqw.eq(bo.getUserId() != null, SysMsgConfigUser::getUserId, bo.getUserId()); |
||||
|
lqw.like(StringUtils.isNotBlank(bo.getName()), SysMsgConfigUser::getName, bo.getName()); |
||||
|
lqw.eq(StringUtils.isNotBlank(bo.getPhonenumber()), SysMsgConfigUser::getPhonenumber, bo.getPhonenumber()); |
||||
|
return lqw; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 新增系统短信发送配置用户 |
||||
|
* |
||||
|
* @param bo 系统短信发送配置用户 |
||||
|
* @return 是否新增成功 |
||||
|
*/ |
||||
|
@Override |
||||
|
public Boolean insertByBo(SysMsgConfigUserBo bo) { |
||||
|
SysMsgConfigUser add = MapstructUtils.convert(bo, SysMsgConfigUser.class); |
||||
|
validEntityBeforeSave(add); |
||||
|
boolean flag = baseMapper.insert(add) > 0; |
||||
|
if (flag) { |
||||
|
bo.setId(add.getId()); |
||||
|
} |
||||
|
return flag; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 修改系统短信发送配置用户 |
||||
|
* |
||||
|
* @param bo 系统短信发送配置用户 |
||||
|
* @return 是否修改成功 |
||||
|
*/ |
||||
|
@Override |
||||
|
public Boolean updateByBo(SysMsgConfigUserBo bo) { |
||||
|
SysMsgConfigUser update = MapstructUtils.convert(bo, SysMsgConfigUser.class); |
||||
|
validEntityBeforeSave(update); |
||||
|
return baseMapper.updateById(update) > 0; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 保存前的数据校验 |
||||
|
*/ |
||||
|
private void validEntityBeforeSave(SysMsgConfigUser entity){ |
||||
|
//TODO 做一些数据校验,如唯一约束
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 校验并批量删除系统短信发送配置用户信息 |
||||
|
* |
||||
|
* @param ids 待删除的主键集合 |
||||
|
* @param isValid 是否进行有效性校验 |
||||
|
* @return 是否删除成功 |
||||
|
*/ |
||||
|
@Override |
||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { |
||||
|
if(isValid){ |
||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
|
} |
||||
|
return baseMapper.deleteByIds(ids) > 0; |
||||
|
} |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
<?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="org.dromara.system.mapper.SysMsgConfigUserMapper"> |
||||
|
|
||||
|
</mapper> |
Loading…
Reference in new issue