增加3D倾斜模型功能

This commit is contained in:
sdy 2026-06-08 11:47:58 +08:00
parent 4f4a110765
commit b7e2733345
16 changed files with 604 additions and 13 deletions

View File

@ -91,6 +91,8 @@ public interface BusinessConstant {
String FILE_PATH = "file/"; String FILE_PATH = "file/";
String IMAGE_PATH = "image/"; String IMAGE_PATH = "image/";
String VIDEO_PATH = "video/"; String VIDEO_PATH = "video/";
String GEO_MODEL_DIR = "/geo/model";
String GEO_MODEL_DISK_UPLOAD_PATH = "/geo_model";
String VIDEO_COVER_SUFFIX = "_cover.jpeg"; String VIDEO_COVER_SUFFIX = "_cover.jpeg";
String DJI_SIGN = "DJI"; String DJI_SIGN = "DJI";
} }

View File

@ -1,11 +1,14 @@
package com.multictrl.common.utils.kmz; package com.multictrl.common.utils.kmz;
import com.multictrl.common.exception.RenException;
import com.multictrl.modules.business.dto.RouteDTO; import com.multictrl.modules.business.dto.RouteDTO;
import java.io.ByteArrayOutputStream; import java.io.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
/** /**
@ -46,4 +49,51 @@ public class KmzUtils {
zos.write(content.getBytes(StandardCharsets.UTF_8)); zos.write(content.getBytes(StandardCharsets.UTF_8));
zos.closeEntry(); zos.closeEntry();
} }
/**
* zip 输入流解压到目标目录完整保留 zip 内的目录结构
*
* @param zipStream zip 输入流调用方负责关闭外层流
* @param destDir 目标目录
* @throws IOException 解压失败
*/
public static void unzipToDirectory(InputStream zipStream, Path destDir) throws IOException {
// 确保目标目录存在已存在时不会重复创建
Files.createDirectories(destDir);
// 获取规范化的目标目录路径用于安全校验
Path normalizedDest = destDir.toAbsolutePath().normalize();
try (ZipInputStream zis = new ZipInputStream(zipStream)) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
String entryName = entry.getName();
// 拼接并规范化目标文件路径
Path targetPath = normalizedDest.resolve(entryName).normalize();
// 防止 Zip Slip 攻击确保解压路径仍在目标目录内
if (!targetPath.startsWith(normalizedDest)) {
throw new IOException("非法路径:" + entryName);
}
if (entry.isDirectory()) {
Files.createDirectories(targetPath);
} else {
// 创建父目录如果不存在
Path parent = targetPath.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
// 使用 NIO 方式将 zip 条目内容写入文件
try (OutputStream out = Files.newOutputStream(targetPath)) {
byte[] buffer = new byte[8192];
int len;
while ((len = zis.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
}
}
zis.closeEntry();
}
}
}
} }

View File

@ -0,0 +1,117 @@
package com.multictrl.modules.business.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson2.JSONObject;
import com.multictrl.common.annotation.ApiOrder;
import com.multictrl.common.annotation.LogOperation;
import com.multictrl.common.constant.Constant;
import com.multictrl.common.exception.ErrorCode;
import com.multictrl.common.page.PageData;
import com.multictrl.common.utils.Result;
import com.multictrl.common.validator.AssertUtils;
import com.multictrl.modules.business.dto.GeoPhotoDTO;
import com.multictrl.modules.business.service.GeoPhotoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 地理照片模型
*
* @author Sdy
* @since 1.0.0 2026-06-05
*/
@RestController
@RequestMapping("business/geophoto")
@Tag(name = "地理模型")
@ApiOrder(13)
@RequiredArgsConstructor
public class GeoPhotoController {
private final GeoPhotoService geoPhotoService;
@GetMapping("page")
@Operation(summary = "分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码从1开始"),
@Parameter(name = Constant.LIMIT, description = "每页显示记录数"),
@Parameter(name = "type", description = "类型 1正射 2倾斜")
})
@RequiresPermissions("bus:geophoto:page")
public Result<PageData<GeoPhotoDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
PageData<GeoPhotoDTO> page = geoPhotoService.pageList(params);
return new Result<PageData<GeoPhotoDTO>>().ok(page);
}
@PostMapping
@Operation(summary = "上传地理资源")
@LogOperation("上传地理资源")
@RequiresPermissions("bus:geophoto:upload")
public Result<Object> upload(@Parameter(description = "模型类型{1:正射2:倾斜}")
@RequestParam("type") String type,
@RequestParam("file") MultipartFile file) {
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
Map<String, String> typeSuffixMap = Map.of("1", "tif", "2", "zip");
String expectedSuffix = typeSuffixMap.get(type);
if (expectedSuffix == null) {
return new Result<>().error(ErrorCode.PARAMS_ERROR, "模型类型");
}
if (!expectedSuffix.equals(suffix)) {
return new Result<>().error(ErrorCode.FILE_FORMAT_ERROR, expectedSuffix);
}
geoPhotoService.upload(type, file);
return new Result<>();
}
@GetMapping
@Operation(summary = "获取地理资源")
public Result<List<GeoPhotoDTO>> get(@Parameter(description = "类型{1:正射2:倾斜}")
@RequestParam("type") String type) {
List<GeoPhotoDTO> layerInfo = geoPhotoService.getGeoList(type);
return new Result<List<GeoPhotoDTO>>().ok(layerInfo);
}
@DeleteMapping
@Operation(summary = "删除")
@LogOperation("删除")
@RequiresPermissions("bus:geophoto:delete")
public Result<Object> delete(@RequestParam Long id) {
geoPhotoService.remove(id);
return new Result<>();
}
@GetMapping("/getDiskModel")
@Operation(summary = "获取磁盘模型")
@LogOperation("获取磁盘模型")
@RequiresPermissions("bus:geophoto:getDiskModel")
public Result<List<GeoPhotoDTO>> getDiskModel() {
List<GeoPhotoDTO> diskData = geoPhotoService.getDiskMap();
return new Result<List<GeoPhotoDTO>>().ok(diskData);
}
@PostMapping("/uploadModelDisk")
@Operation(summary = "磁盘上传模型")
@LogOperation("磁盘上传模型")
@RequiresPermissions("bus:geophoto:uploadModelDisk")
public Result<List<GeoPhotoDTO>> uploadModelDisk(@RequestBody List<String> names) {
AssertUtils.isListEmpty(names, "模型名称");
geoPhotoService.uploadModelDisk(names);
return new Result<>();
}
}

View File

@ -0,0 +1,16 @@
package com.multictrl.modules.business.dao;
import com.multictrl.common.dao.BaseDao;
import com.multictrl.modules.business.entity.GeoPhotoEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* 地理照片模型
*
* @author Sdy
* @since 1.0.0 2026-06-05
*/
@Mapper
public interface GeoPhotoDao extends BaseDao<GeoPhotoEntity> {
}

View File

@ -0,0 +1,43 @@
package com.multictrl.modules.business.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 地理照片模型
*
* @author Sdy
* @since 1.0.0 2026-06-05
*/
@Data
@Schema(name = "地理照片模型")
public class GeoPhotoDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "标识")
private Long id;
@Schema(description = "名称")
private String geoName;
@Schema(description = "大小")
private String geoSize;
@Schema(description = "类型 1正射 2倾斜")
private String geoType;
@Schema(description = "状态 0进行中 1完成 2失败")
private String status;
@Schema(description = "时间")
private Date createDate;
@Schema(description = "资源地址")
private String url;
}

View File

@ -0,0 +1,51 @@
package com.multictrl.modules.business.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 地理照片模型
*
* @author Sdy
* @since 1.0.0 2026-06-05
*/
@Data
@TableName("bus_geo_photo")
public class GeoPhotoEntity {
/**
* 标识
*/
@TableId
private Long id;
/**
* 名称
*/
private String geoName;
/**
* 大小
*/
private String geoSize;
/**
* 类型 1正射 2倾斜
*/
private String geoType;
/**
* 状态 0进行中 1完成 2失败
*/
private String status;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
private Long creator;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createDate;
}

View File

@ -0,0 +1,38 @@
package com.multictrl.modules.business.service;
import com.multictrl.common.page.PageData;
import com.multictrl.common.service.CrudService;
import com.multictrl.modules.business.dto.GeoPhotoDTO;
import com.multictrl.modules.business.entity.GeoPhotoEntity;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* 地理照片模型
*
* @author Sdy
* @since 1.0.0 2026-06-05
*/
public interface GeoPhotoService extends CrudService<GeoPhotoEntity, GeoPhotoDTO> {
//分页列表
PageData<GeoPhotoDTO> pageList(Map<String, Object> params);
//上传地理资源
void upload(String type, MultipartFile file);
//获取地理资源
List<GeoPhotoDTO> getGeoList(String type);
//删除地理资源
void remove(Long id);
//获取磁盘地图
List<GeoPhotoDTO> getDiskMap();
//磁盘上传模型
void uploadModelDisk(List<String> names);
}

View File

@ -0,0 +1,232 @@
package com.multictrl.modules.business.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.exception.ErrorCode;
import com.multictrl.common.exception.RenException;
import com.multictrl.common.page.PageData;
import com.multictrl.common.service.impl.CrudServiceImpl;
import com.multictrl.common.utils.ConvertUtils;
import com.multictrl.common.utils.Utils;
import com.multictrl.common.utils.kmz.KmzUtils;
import com.multictrl.modules.business.dao.GeoPhotoDao;
import com.multictrl.modules.business.dto.GeoPhotoDTO;
import com.multictrl.modules.business.entity.GeoPhotoEntity;
import com.multictrl.modules.business.service.GeoPhotoService;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
/**
* 地理照片模型
*
* @author Sdy
* @since 1.0.0 2026-06-05
*/
@Slf4j
@Service
public class GeoPhotoServiceImpl extends CrudServiceImpl<GeoPhotoDao, GeoPhotoEntity, GeoPhotoDTO> implements GeoPhotoService {
@Override
public QueryWrapper<GeoPhotoEntity> getWrapper(Map<String, Object> params) {
String id = (String) params.get("id");
String geoType = (String) params.get("type");
QueryWrapper<GeoPhotoEntity> wrapper = new QueryWrapper<>();
wrapper.eq(StrUtil.isNotBlank(id), "id", id);
wrapper.eq(StrUtil.isNotBlank(geoType), "geo_type", geoType);
wrapper.orderByDesc("create_date");
return wrapper;
}
@Override
public PageData<GeoPhotoDTO> pageList(Map<String, Object> params) {
PageData<GeoPhotoDTO> page = page(params);
for (GeoPhotoDTO dto : page.getList()) {
String geoSize = dto.getGeoSize();
if (StrUtil.isNotBlank(geoSize)) {
dto.setGeoSize(Utils.formatBytes(Long.parseLong(geoSize)));
}
}
return page;
}
@Override
public void upload(String type, MultipartFile file) {
GeoPhotoEntity geoPhotoEntity = new GeoPhotoEntity();
geoPhotoEntity.setGeoName(FileUtil.mainName(file.getOriginalFilename()));
geoPhotoEntity.setGeoSize(file.getSize() + "");
geoPhotoEntity.setGeoType(type);
geoPhotoEntity.setStatus("0");
baseDao.insert(geoPhotoEntity);
if ("1".equals(type)) {//正射
return;
} else {//倾斜
uploadMode(geoPhotoEntity, file);
}
}
@Override
public List<GeoPhotoDTO> getGeoList(String type) {
QueryWrapper<GeoPhotoEntity> wrapper = new QueryWrapper<>();
wrapper.eq("geo_type", type);
wrapper.eq("status", "1");
wrapper.orderByDesc("create_date");
List<GeoPhotoEntity> list = baseDao.selectList(wrapper);
if ("1".equals(type)) {//正射
return List.of();
} else {//倾斜
List<GeoPhotoDTO> dtoList = ConvertUtils.sourceToTarget(list, GeoPhotoDTO.class);
for (GeoPhotoDTO dto : dtoList) {
String geoName = dto.getGeoName();
if (StrUtil.isNotBlank(geoName)) {
dto.setUrl(BusinessConstant.GEO_MODEL_DIR + "/" + geoName + "/tileset.json");
}
}
return dtoList;
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void remove(Long id) {
try {
GeoPhotoEntity geoPhotoEntity = selectById(id);
if ("1".equals(geoPhotoEntity.getGeoType())) {
return;
} else {
//删除数据
deleteById(id);
//删除文件
File file = new File(BusinessConstant.GEO_MODEL_DIR + "/" + geoPhotoEntity.getGeoName());
if (file.exists()) {
FileUtil.del(file);
}
}
} catch (Exception e) {
throw new RenException(ErrorCode.DELETE_FAIL, "地理资源");
}
}
@Override
public List<GeoPhotoDTO> getDiskMap() {
List<GeoPhotoDTO> list = new ArrayList<>();
File directory = new File(BusinessConstant.GEO_MODEL_DISK_UPLOAD_PATH);
if (directory.exists() && directory.isDirectory()) {
for (File file : Objects.requireNonNull(directory.listFiles())) {
String name = file.getName();
String extName = FileUtil.extName(name);
GeoPhotoDTO dto = new GeoPhotoDTO();
dto.setGeoName(name);
dto.setGeoSize(Utils.formatBytes(file.length()));
if ("tif".equals(extName)) {
dto.setGeoType("1");
list.add(dto);
} else if ("zip".equals(extName)) {
dto.setGeoType("2");
list.add(dto);
}
}
}
return list;
}
@Override
public void uploadModelDisk(List<String> names) {
for (String name : names) {
String sourceFile = BusinessConstant.GEO_MODEL_DISK_UPLOAD_PATH + File.separator + name;
String extName = FileUtil.extName(name);
if ("tif".equals(extName)) {
return;
} else if ("zip".equals(extName)) {
File file = new File(sourceFile);
if (file.exists()) {
GeoPhotoEntity entity = new GeoPhotoEntity();
entity.setGeoName(FileUtil.mainName(name));
entity.setGeoSize(file.length() + "");
entity.setGeoType("2");
entity.setStatus("0");
baseDao.insert(entity);
//解压文件
CompletableFuture.runAsync(() -> {
try (FileInputStream fis = new FileInputStream(file)) {
KmzUtils.unzipToDirectory(fis, Paths.get(BusinessConstant.GEO_MODEL_DIR));
entity.setStatus("1");
} catch (Exception e) {
entity.setStatus("2");
log.error("模型压缩文件解压失败,文件名称: {}", name, e);
} finally {
baseDao.updateById(entity);
// 删除临时文件
if (file.exists()) {
boolean delete = file.delete();
}
}
}).exceptionally(throwable -> {
log.error("模型压缩文件解压失败,文件名称: {}", name, throwable);
entity.setStatus("2");
baseDao.updateById(entity);
if (file.exists()) {
boolean delete = file.delete();
}
return null;
});
}
}
}
}
//上传倾斜模型
private void uploadMode(GeoPhotoEntity geoPhotoEntity, MultipartFile file) {
// 创建临时文件
File tempFile;
try {
tempFile = File.createTempFile("upload_geo_photo_" + System.currentTimeMillis(), ".zip");
file.transferTo(tempFile);
} catch (Exception e) {
log.error("创建临时文件失败", e);
geoPhotoEntity.setStatus("2");
baseDao.updateById(geoPhotoEntity);
return;
}
//解压文件
File finalTempFile = tempFile;
CompletableFuture.runAsync(() -> {
try (FileInputStream fis = new FileInputStream(finalTempFile)) {
KmzUtils.unzipToDirectory(fis, Paths.get(BusinessConstant.GEO_MODEL_DIR));
geoPhotoEntity.setStatus("1");
} catch (Exception e) {
geoPhotoEntity.setStatus("2");
log.error("模型压缩文件解压失败,文件名称: {}", file.getOriginalFilename(), e);
} finally {
baseDao.updateById(geoPhotoEntity);
// 删除临时文件
if (finalTempFile.exists()) {
boolean delete = finalTempFile.delete();
}
}
}).exceptionally(throwable -> {
log.error("模型压缩文件解压失败,文件名称: {}", file.getOriginalFilename(), throwable);
geoPhotoEntity.setStatus("2");
baseDao.updateById(geoPhotoEntity);
if (finalTempFile.exists()) {
boolean delete = finalTempFile.delete();
}
return null;
});
}
}

View File

@ -78,6 +78,6 @@ influx:
org: dj org: dj
host: host:
ip: 192.168.1.193 ip: 223.108.157.174
port: 61620 port: 61620
is-ssl: false is-ssl: false

View File

@ -36,8 +36,8 @@ spring:
matching-strategy: ANT_PATH_MATCHER matching-strategy: ANT_PATH_MATCHER
servlet: servlet:
multipart: multipart:
max-file-size: 500MB max-file-size: 2GB
max-request-size: 500MB max-request-size: 2GB
enabled: true enabled: true
data: data:
redis: redis:

View File

@ -67,4 +67,6 @@ public interface ErrorCode {
int UAV_LIGHT_INDEX_NOT_EXIST = 20026; int UAV_LIGHT_INDEX_NOT_EXIST = 20026;
int DICT_NOT_DELETE = 20027; int DICT_NOT_DELETE = 20027;
int DICT_EXIST = 20028; int DICT_EXIST = 20028;
int FILE_FORMAT_ERROR = 20029;
int DELETE_FAIL = 20030;
} }

View File

@ -29,7 +29,7 @@
10030=\u5220\u9664\u6587\u4EF6\u5931\u8D25{0} 10030=\u5220\u9664\u6587\u4EF6\u5931\u8D25{0}
#business #business
20001=\u822a\u7ebf\u5df2\u5b58\u5728 20001=\u822a\u7ebf\u5df2\u5b58\u5728
20002=\u53C2\u6570\u9519\u8BEF 20002={0}\u53C2\u6570\u9519\u8BEF
20003=\u8BF7\u6C42\u8D85\u65F6\uFF0C\u672A\u6536\u5230\u673A\u573A\u56DE\u590D 20003=\u8BF7\u6C42\u8D85\u65F6\uFF0C\u672A\u6536\u5230\u673A\u573A\u56DE\u590D
20004=\u673A\u573A\u6267\u884C\u6210\u529F 20004=\u673A\u573A\u6267\u884C\u6210\u529F
20005=\u673A\u5E93\u89C6\u9891\u6807\u8BC6\u672A\u83B7\u53D6\uFF0C\u8BF7\u5C1D\u8BD5\u91CD\u542F\u673A\u5E93\u6216\u8005\u8C03\u8BD5\u6A21\u5F0F\u98DE\u673A\u5F00\u5173\u673A 20005=\u673A\u5E93\u89C6\u9891\u6807\u8BC6\u672A\u83B7\u53D6\uFF0C\u8BF7\u5C1D\u8BD5\u91CD\u542F\u673A\u5E93\u6216\u8005\u8C03\u8BD5\u6A21\u5F0F\u98DE\u673A\u5F00\u5173\u673A
@ -55,4 +55,6 @@
20025={0}\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E 20025={0}\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u8DEF\u5F84\u662F\u5426\u6B63\u786E
20026=\u98DE\u673A\u63A2\u7167\u706F\u8D1F\u8F7D\u4F4D\u7F6E\u672A\u83B7\u53D6\uFF0C\u8BF7\u68C0\u67E5\u98DE\u673A\u662F\u5426\u5F00\u673A 20026=\u98DE\u673A\u63A2\u7167\u706F\u8D1F\u8F7D\u4F4D\u7F6E\u672A\u83B7\u53D6\uFF0C\u8BF7\u68C0\u67E5\u98DE\u673A\u662F\u5426\u5F00\u673A
20027={0}\u5B57\u5178\u7981\u6B62\u5220\u9664 20027={0}\u5B57\u5178\u7981\u6B62\u5220\u9664
20028={0}\u5B57\u5178\u5DF2\u7ECF\u5B58\u5728 20028={0}\u5B57\u5178\u5DF2\u7ECF\u5B58\u5728
20029=\u8bf7\u4e0a\u4f20{0}\u683c\u5f0f\u6587\u4ef6
20030=\u5220\u9664{0}\u5931\u8D25\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458

View File

@ -55,6 +55,8 @@ cp ./file/wait/wait-for-it.sh /root/dj_multictrl_data/wait/wait-for-it.sh
mkdir -p /root/dj_multictrl_data/mongodb/data mkdir -p /root/dj_multictrl_data/mongodb/data
mkdir -p /geo_model
mkdir -p /root/dj_multictrl_data/script mkdir -p /root/dj_multictrl_data/script
mkdir -p /root/dj_multictrl_data/script/logs mkdir -p /root/dj_multictrl_data/script/logs
cp ./file/script/cleanup_srs_record_videos.sh /root/dj_multictrl_data/script/ cp ./file/script/cleanup_srs_record_videos.sh /root/dj_multictrl_data/script/

View File

@ -28,6 +28,7 @@ services:
- /data/dj_multictrl_data/minio/data:/data - /data/dj_multictrl_data/minio/data:/data
- /data/dj_multictrl_data/live_record:/data/live_record - /data/dj_multictrl_data/live_record:/data/live_record
- /data/dj_multictrl_data/geoserver:/data/geoserver - /data/dj_multictrl_data/geoserver:/data/geoserver
- /data/dj_multictrl_data/geo/model:/data/geo/model
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
dj-multictrl-pgsql: dj-multictrl-pgsql:
@ -174,8 +175,10 @@ services:
- /data/dj_multictrl_data/live_record:/live_record - /data/dj_multictrl_data/live_record:/live_record
- /root/dj_multictrl_data/ffmpeg/ffmpeg:/usr/bin/ffmpeg - /root/dj_multictrl_data/ffmpeg/ffmpeg:/usr/bin/ffmpeg
- /data/dj_multictrl_data/minio/data:/minio_data - /data/dj_multictrl_data/minio/data:/minio_data
- /data/dj_multictrl_data/geo/model:/geo/model
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- /root/dj_multictrl_data/api/tmp:/tmp - /root/dj_multictrl_data/api/tmp:/tmp
- /geo_model:/geo_model
command: command:
- /bin/bash - /bin/bash
- -c - -c

View File

@ -36,12 +36,12 @@ http {
proxy_pass http://dj-multictrl-api:8080/api/; proxy_pass http://dj-multictrl-api:8080/api/;
} }
#location ~* /live_record/(.+)$ { location /geo/model {
# add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Origin *;
# add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
# add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
# alias /live_record/$1; root /data;
#} }
location ~* /video/(.+)$ { location ~* /video/(.+)$ {
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Origin *;

View File

@ -2144,6 +2144,39 @@ INSERT INTO "public"."sys_dict_data" ("id", "dict_type_id", "dict_label", "dict_
VALUES (2060253516358848514, 2060253239434121218, 'Ars550', 'Ars550', '', 0, 1067246875800000001, VALUES (2060253516358848514, 2060253239434121218, 'Ars550', 'Ars550', '', 0, 1067246875800000001,
'2026-05-29 14:54:50.617', 1067246875800000001, '2026-05-29 14:54:50.617', 'source-material/Ars550.png'); '2026-05-29 14:54:50.617', 1067246875800000001, '2026-05-29 14:54:50.617', 'source-material/Ars550.png');
--2026/6/5
DROP TABLE IF EXISTS "public"."bus_geo_photo";
CREATE TABLE "public"."bus_geo_photo"
(
"id" int8 NOT NULL,
"geo_name" varchar(255) COLLATE "pg_catalog"."default",
"geo_size" varchar(50) COLLATE "pg_catalog"."default",
"geo_type" char(1) COLLATE "pg_catalog"."default",
"status" char(1) COLLATE "pg_catalog"."default",
"creator" int8,
"create_date" timestamp(6)
)
;
COMMENT
ON COLUMN "public"."bus_geo_photo"."id" IS '标识';
COMMENT
ON COLUMN "public"."bus_geo_photo"."geo_name" IS '名称';
COMMENT
ON COLUMN "public"."bus_geo_photo"."geo_size" IS '大小';
COMMENT
ON COLUMN "public"."bus_geo_photo"."geo_type" IS '类型 1正射 2倾斜';
COMMENT
ON COLUMN "public"."bus_geo_photo"."status" IS '状态 0进行中 1完成 2失败';
COMMENT
ON TABLE "public"."bus_geo_photo" IS '地理照片模型';
-- ----------------------------
-- Primary Key structure for table bus_geo_photo
-- ----------------------------
ALTER TABLE "public"."bus_geo_photo"
ADD CONSTRAINT "uav_mode_pkey" PRIMARY KEY ("id");
-- 20260605 aros 蛙跳 by zhangchuang -- 20260605 aros 蛙跳 by zhangchuang