20251125GET指定任务的所有Media
This commit is contained in:
@@ -0,0 +1,878 @@
|
||||
package cn.edu.whu.boot.lydcextend.controller;
|
||||
|
||||
import cn.edu.whu.boot.collection.service.IBaseService;
|
||||
import cn.edu.whu.boot.common.domain.CommonConstant;
|
||||
import cn.edu.whu.boot.common.domain.ResultMessage;
|
||||
import cn.edu.whu.boot.common.domain.SqlStringConstant;
|
||||
import cn.edu.whu.boot.common.utils.collection.OtherUtil;
|
||||
import cn.edu.whu.boot.common.utils.collection.PostgreSqlUtil;
|
||||
import cn.edu.whu.boot.common.utils.collection.TableOperationUtil;
|
||||
import cn.edu.whu.boot.xml.domain.Task;
|
||||
import cn.edu.whu.boot.xml.service.ITaskService;
|
||||
import cn.edu.whu.boot.xml.xmlreader.bean.Config;
|
||||
import cn.edu.whu.boot.xml.xmlreader.bean.Field;
|
||||
import cn.edu.whu.boot.xml.xmlreader.bean.Table;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 照片和媒体路径导出控制器
|
||||
* 根据 taskId 遍历任务的所有表:
|
||||
* 1. 对于以 _media 为后缀的表,提取表名、id、media_id、media_path 以及位置和相机相关字段
|
||||
* 2. 对于其他表,如果包含 photo 和 parentID 字段,则提取表名、ID、parentID 和 photo 字段
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("lydcextend")
|
||||
public class PhotoMediaExportController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PhotoMediaExportController.class);
|
||||
|
||||
private final ITaskService taskService;
|
||||
private final IBaseService baseService;
|
||||
|
||||
@Autowired
|
||||
public PhotoMediaExportController(ITaskService taskService, IBaseService baseService) {
|
||||
this.taskService = taskService;
|
||||
this.baseService = baseService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取照片和媒体路径数据
|
||||
* 根据 taskId 遍历任务的所有表:
|
||||
* 1. 对于以 _media 为后缀的表,提取表名、id、media_id、media_path 以及位置和相机相关字段
|
||||
* 2. 对于其他表,如果包含 photo 和 parentID 字段,则提取表名、ID、parentID 和 photo 字段
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @return 照片和媒体数据列表(包含 relationsource 字段)
|
||||
*/
|
||||
@RequestMapping(value = "getPhotoMedia", produces = "text/html;charset=UTF-8")
|
||||
public String getPhotoMedia(@RequestParam Integer taskId) {
|
||||
try {
|
||||
// 获取任务
|
||||
Task task = taskService.getTaskById(taskId);
|
||||
if (task == null) {
|
||||
return ResultMessage.failed("任务不存在").toString();
|
||||
}
|
||||
|
||||
// 收集所有需要返回的数据
|
||||
List<Map<String, Object>> dataList = new ArrayList<>();
|
||||
String schemaName = task.getDatabaseName();
|
||||
|
||||
// 缓存任务名、用户名和姓名,避免重复查询
|
||||
Map<Integer, String> taskNameCache = new HashMap<>();
|
||||
Map<Integer, String> userNameCache = new HashMap<>();
|
||||
Map<Integer, String> realNameCache = new HashMap<>();
|
||||
|
||||
// 从数据库直接查询 schema 中的所有表
|
||||
String getAllTablesSql = "SELECT table_name FROM information_schema.tables " +
|
||||
"WHERE table_schema = '" + schemaName + "' AND table_type = 'BASE TABLE' " +
|
||||
"ORDER BY table_name";
|
||||
List<Map<String, Object>> allTablesResult = baseService.selectData(getAllTablesSql);
|
||||
|
||||
if (allTablesResult == null || allTablesResult.isEmpty()) {
|
||||
return ResultMessage.failed("schema 中没有找到表").toString();
|
||||
}
|
||||
|
||||
// 解析配置获取表配置(用于字段检查)
|
||||
Config config = JSON.toJavaObject(JSON.parseObject(task.getConfig()), Config.class);
|
||||
Map<String, Table> tableMap = config.getTables() != null ? config.getTables() : new HashMap<>();
|
||||
String configString = task.getConfig();
|
||||
|
||||
// 遍历数据库中的所有表
|
||||
for (Map<String, Object> tableRow : allTablesResult) {
|
||||
String tableName = (String) tableRow.get("table_name");
|
||||
if (tableName == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 从配置中获取表信息(如果存在)
|
||||
Table table = tableMap.get(tableName);
|
||||
|
||||
// 如果表名以 _media 为后缀,获取相关字段
|
||||
if (tableName.endsWith("_media")) {
|
||||
// 查询表数据
|
||||
String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
|
||||
String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
|
||||
List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);
|
||||
|
||||
if (tableDataList != null && !tableDataList.isEmpty()) {
|
||||
// 处理每条数据
|
||||
for (Map<String, Object> rowData : tableDataList) {
|
||||
Map<String, Object> dataRow = new HashMap<>();
|
||||
dataRow.put("schema名称", schemaName);
|
||||
dataRow.put("表名", tableName);
|
||||
|
||||
// id(父表ID)
|
||||
Object idValue = rowData.get("id");
|
||||
dataRow.put("ID", idValue != null ? idValue.toString() : "");
|
||||
|
||||
// media_id
|
||||
Object mediaIdValue = rowData.get("media_id");
|
||||
dataRow.put("media_id", mediaIdValue != null ? mediaIdValue.toString() : "");
|
||||
|
||||
// media_path
|
||||
Object mediaPathValue = rowData.get("media_path");
|
||||
dataRow.put("media_path", mediaPathValue != null ? mediaPathValue.toString() : "");
|
||||
|
||||
// longitude(经度)
|
||||
Object longitudeValue = rowData.get("longitude");
|
||||
dataRow.put("longitude", longitudeValue != null ? longitudeValue.toString() : "");
|
||||
|
||||
// latitude(纬度)
|
||||
Object latitudeValue = rowData.get("latitude");
|
||||
dataRow.put("latitude", latitudeValue != null ? latitudeValue.toString() : "");
|
||||
|
||||
// altitude(高程)
|
||||
Object altitudeValue = rowData.get("altitude");
|
||||
dataRow.put("altitude", altitudeValue != null ? altitudeValue.toString() : "");
|
||||
|
||||
// accuracy
|
||||
Object accuracyValue = rowData.get("accuracy");
|
||||
dataRow.put("accuracy", accuracyValue != null ? accuracyValue.toString() : "");
|
||||
|
||||
// camera_angle
|
||||
Object cameraAngleValue = rowData.get("camera_angle");
|
||||
dataRow.put("camera_angle", cameraAngleValue != null ? cameraAngleValue.toString() : "");
|
||||
|
||||
// camera_pitch
|
||||
Object cameraPitchValue = rowData.get("camera_pitch");
|
||||
dataRow.put("camera_pitch", cameraPitchValue != null ? cameraPitchValue.toString() : "");
|
||||
|
||||
// camera_roll
|
||||
Object cameraRollValue = rowData.get("camera_roll");
|
||||
dataRow.put("camera_roll", cameraRollValue != null ? cameraRollValue.toString() : "");
|
||||
|
||||
// 非 _media 表的字段设为空
|
||||
dataRow.put("parentID", "");
|
||||
dataRow.put("photo", "");
|
||||
|
||||
// 解析任务名、账号和姓名
|
||||
String mediaPathStr = mediaPathValue != null ? mediaPathValue.toString() : "";
|
||||
parseAndSetTaskAndUser(dataRow, mediaPathStr, taskNameCache, userNameCache, realNameCache);
|
||||
|
||||
// 构建 relationsource(对于 _media 表,id 是父表ID)
|
||||
Object parentIdForMedia = idValue;
|
||||
String relationsource = buildRelationSource(schemaName, tableName, parentIdForMedia,
|
||||
tableMap, configString, baseService);
|
||||
dataRow.put("relationsource", relationsource);
|
||||
|
||||
dataList.add(dataRow);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 其他表:检查表是否有 photo 和 parentID 字段
|
||||
// 先从数据库查询表的列信息
|
||||
List<String> tableColumns = baseService.getTableColumns(schemaName, tableName);
|
||||
boolean hasPhoto = tableColumns != null && tableColumns.contains("photo");
|
||||
|
||||
// 从配置中获取 parentID 字段名(如果配置存在)
|
||||
String parentIdFieldName = null;
|
||||
if (table != null) {
|
||||
parentIdFieldName = TableOperationUtil.getParentID(table);
|
||||
} else {
|
||||
// 如果配置中没有,尝试从数据库列中查找(通常 parentID 字段名可能不同)
|
||||
if (tableColumns != null) {
|
||||
for (String col : tableColumns) {
|
||||
if (col.toLowerCase().contains("parent") || col.toLowerCase().contains("parentid")) {
|
||||
parentIdFieldName = col;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPhoto && parentIdFieldName != null) {
|
||||
// 查询表数据
|
||||
String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
|
||||
String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
|
||||
List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);
|
||||
|
||||
if (tableDataList != null && !tableDataList.isEmpty()) {
|
||||
// 获取主键字段名
|
||||
String primaryKey = null;
|
||||
if (table != null) {
|
||||
primaryKey = TableOperationUtil.getPrimaryKey(table);
|
||||
}
|
||||
|
||||
// 如果配置中没有主键信息,尝试从数据库查询
|
||||
if (primaryKey == null && tableColumns != null) {
|
||||
// 查询主键信息
|
||||
String getPrimaryKeySql = "SELECT a.attname " +
|
||||
"FROM pg_index i " +
|
||||
"JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) " +
|
||||
"WHERE i.indrelid = '\"" + schemaName + "\".\"" + tableName + "\"'::regclass " +
|
||||
"AND i.indisprimary " +
|
||||
"LIMIT 1";
|
||||
List<Map<String, Object>> pkResult = baseService.selectData(getPrimaryKeySql);
|
||||
if (pkResult != null && !pkResult.isEmpty()) {
|
||||
primaryKey = (String) pkResult.get(0).get("attname");
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryKey == null) {
|
||||
logger.warn("表 {} 没有主键,跳过", tableName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 处理每条数据
|
||||
for (Map<String, Object> rowData : tableDataList) {
|
||||
Map<String, Object> dataRow = new HashMap<>();
|
||||
dataRow.put("schema名称", schemaName);
|
||||
dataRow.put("表名", tableName);
|
||||
|
||||
// ID(主键)
|
||||
Object idValue = rowData.get(primaryKey);
|
||||
dataRow.put("ID", idValue != null ? idValue.toString() : "");
|
||||
|
||||
// parentID
|
||||
Object parentIdValue = rowData.get(parentIdFieldName);
|
||||
dataRow.put("parentID", parentIdValue != null ? parentIdValue.toString() : "");
|
||||
|
||||
// photo
|
||||
Object photoValue = rowData.get("photo");
|
||||
dataRow.put("photo", photoValue != null ? photoValue.toString() : "");
|
||||
|
||||
// 非 _media 表,相关字段设为空
|
||||
dataRow.put("media_id", "");
|
||||
dataRow.put("media_path", "");
|
||||
dataRow.put("longitude", "");
|
||||
dataRow.put("latitude", "");
|
||||
dataRow.put("altitude", "");
|
||||
dataRow.put("accuracy", "");
|
||||
dataRow.put("camera_angle", "");
|
||||
dataRow.put("camera_pitch", "");
|
||||
dataRow.put("camera_roll", "");
|
||||
|
||||
// 解析任务名、账号和姓名(从 photo 字段)
|
||||
String photoStr = photoValue != null ? photoValue.toString() : "";
|
||||
parseAndSetTaskAndUser(dataRow, photoStr, taskNameCache, userNameCache, realNameCache);
|
||||
|
||||
// 构建 relationsource
|
||||
String relationsource = buildRelationSource(schemaName, tableName, parentIdValue,
|
||||
tableMap, configString, baseService);
|
||||
dataRow.put("relationsource", relationsource);
|
||||
|
||||
dataList.add(dataRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dataList.isEmpty()) {
|
||||
return ResultMessage.failed("没有找到符合条件的数据").toString();
|
||||
}
|
||||
|
||||
return ResultMessage.success(dataList).toString();
|
||||
} catch (Exception e) {
|
||||
logger.error("获取照片和媒体数据失败", e);
|
||||
return ResultMessage.failed("获取照片和媒体数据失败: " + e.getMessage()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出照片和媒体路径数据到 Excel
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @param response HTTP响应对象
|
||||
* @return 操作结果
|
||||
*/
|
||||
@RequestMapping(value = "exportPhotoMedia", produces = "text/html;charset=UTF-8")
|
||||
public String exportPhotoMedia(@RequestParam Integer taskId, HttpServletResponse response) throws IOException {
|
||||
// 获取任务
|
||||
Task task = taskService.getTaskById(taskId);
|
||||
if (task == null) {
|
||||
return ResultMessage.failed("任务不存在").toString();
|
||||
}
|
||||
|
||||
// 收集所有需要导出的数据
|
||||
List<Map<String, Object>> exportDataList = new ArrayList<>();
|
||||
String schemaName = task.getDatabaseName();
|
||||
|
||||
// 缓存任务名、用户名和姓名,避免重复查询
|
||||
Map<Integer, String> taskNameCache = new HashMap<>();
|
||||
Map<Integer, String> userNameCache = new HashMap<>();
|
||||
Map<Integer, String> realNameCache = new HashMap<>();
|
||||
|
||||
// 从数据库直接查询 schema 中的所有表
|
||||
String getAllTablesSql = "SELECT table_name FROM information_schema.tables " +
|
||||
"WHERE table_schema = '" + schemaName + "' AND table_type = 'BASE TABLE' " +
|
||||
"ORDER BY table_name";
|
||||
List<Map<String, Object>> allTablesResult = baseService.selectData(getAllTablesSql);
|
||||
|
||||
if (allTablesResult == null || allTablesResult.isEmpty()) {
|
||||
return ResultMessage.failed("schema 中没有找到表").toString();
|
||||
}
|
||||
|
||||
// 解析配置获取表配置(用于字段检查)
|
||||
Config config = JSON.toJavaObject(JSON.parseObject(task.getConfig()), Config.class);
|
||||
Map<String, Table> tableMap = config.getTables() != null ? config.getTables() : new HashMap<>();
|
||||
String configString = task.getConfig();
|
||||
|
||||
// 遍历数据库中的所有表
|
||||
for (Map<String, Object> tableRow : allTablesResult) {
|
||||
String tableName = (String) tableRow.get("table_name");
|
||||
if (tableName == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 从配置中获取表信息(如果存在)
|
||||
Table table = tableMap.get(tableName);
|
||||
|
||||
// 如果表名以 _media 为后缀,获取相关字段
|
||||
if (tableName.endsWith("_media")) {
|
||||
// 查询表数据
|
||||
String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
|
||||
String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
|
||||
List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);
|
||||
|
||||
if (tableDataList != null && !tableDataList.isEmpty()) {
|
||||
// 处理每条数据
|
||||
for (Map<String, Object> rowData : tableDataList) {
|
||||
Map<String, Object> exportRow = new HashMap<>();
|
||||
exportRow.put("schema名称", schemaName);
|
||||
exportRow.put("表名", tableName);
|
||||
|
||||
// id(父表ID)
|
||||
Object idValue = rowData.get("id");
|
||||
exportRow.put("ID", idValue != null ? idValue.toString() : "");
|
||||
|
||||
// media_id
|
||||
Object mediaIdValue = rowData.get("media_id");
|
||||
exportRow.put("media_id", mediaIdValue != null ? mediaIdValue.toString() : "");
|
||||
|
||||
// media_path
|
||||
Object mediaPathValue = rowData.get("media_path");
|
||||
exportRow.put("media_path", mediaPathValue != null ? mediaPathValue.toString() : "");
|
||||
|
||||
// longitude(经度)
|
||||
Object longitudeValue = rowData.get("longitude");
|
||||
exportRow.put("longitude", longitudeValue != null ? longitudeValue.toString() : "");
|
||||
|
||||
// latitude(纬度)
|
||||
Object latitudeValue = rowData.get("latitude");
|
||||
exportRow.put("latitude", latitudeValue != null ? latitudeValue.toString() : "");
|
||||
|
||||
// altitude(高程)
|
||||
Object altitudeValue = rowData.get("altitude");
|
||||
exportRow.put("altitude", altitudeValue != null ? altitudeValue.toString() : "");
|
||||
|
||||
// accuracy
|
||||
Object accuracyValue = rowData.get("accuracy");
|
||||
exportRow.put("accuracy", accuracyValue != null ? accuracyValue.toString() : "");
|
||||
|
||||
// camera_angle
|
||||
Object cameraAngleValue = rowData.get("camera_angle");
|
||||
exportRow.put("camera_angle", cameraAngleValue != null ? cameraAngleValue.toString() : "");
|
||||
|
||||
// camera_pitch
|
||||
Object cameraPitchValue = rowData.get("camera_pitch");
|
||||
exportRow.put("camera_pitch", cameraPitchValue != null ? cameraPitchValue.toString() : "");
|
||||
|
||||
// camera_roll
|
||||
Object cameraRollValue = rowData.get("camera_roll");
|
||||
exportRow.put("camera_roll", cameraRollValue != null ? cameraRollValue.toString() : "");
|
||||
|
||||
// 非 _media 表的字段设为空
|
||||
exportRow.put("parentID", "");
|
||||
exportRow.put("photo", "");
|
||||
|
||||
// 解析任务名、账号和姓名
|
||||
String mediaPathStr = mediaPathValue != null ? mediaPathValue.toString() : "";
|
||||
parseAndSetTaskAndUser(exportRow, mediaPathStr, taskNameCache, userNameCache, realNameCache);
|
||||
|
||||
// 构建 relationsource(对于 _media 表,id 是父表ID)
|
||||
Object parentIdForMedia = idValue;
|
||||
String relationsource = buildRelationSource(schemaName, tableName, parentIdForMedia,
|
||||
tableMap, configString, baseService);
|
||||
exportRow.put("relationsource", relationsource);
|
||||
|
||||
exportDataList.add(exportRow);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 其他表:检查表是否有 photo 和 parentID 字段
|
||||
// 先从数据库查询表的列信息
|
||||
List<String> tableColumns = baseService.getTableColumns(schemaName, tableName);
|
||||
boolean hasPhoto = tableColumns != null && tableColumns.contains("photo");
|
||||
|
||||
// 从配置中获取 parentID 字段名(如果配置存在)
|
||||
String parentIdFieldName = null;
|
||||
if (table != null) {
|
||||
parentIdFieldName = TableOperationUtil.getParentID(table);
|
||||
} else {
|
||||
// 如果配置中没有,尝试从数据库列中查找(通常 parentID 字段名可能不同)
|
||||
// 这里可以根据实际情况调整查找逻辑
|
||||
if (tableColumns != null) {
|
||||
for (String col : tableColumns) {
|
||||
if (col.toLowerCase().contains("parent") || col.toLowerCase().contains("parentid")) {
|
||||
parentIdFieldName = col;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPhoto && parentIdFieldName != null) {
|
||||
// 查询表数据
|
||||
String tableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, tableName, false, false);
|
||||
String selectSql = MessageFormat.format(SqlStringConstant.SELECT_ALLDATA_SQL, tableNameInDb);
|
||||
List<Map<String, Object>> tableDataList = baseService.selectData(selectSql);
|
||||
|
||||
if (tableDataList != null && !tableDataList.isEmpty()) {
|
||||
// 获取主键字段名
|
||||
String primaryKey = null;
|
||||
if (table != null) {
|
||||
primaryKey = TableOperationUtil.getPrimaryKey(table);
|
||||
}
|
||||
|
||||
// 如果配置中没有主键信息,尝试从数据库查询
|
||||
if (primaryKey == null && tableColumns != null) {
|
||||
// 查询主键信息
|
||||
String getPrimaryKeySql = "SELECT a.attname " +
|
||||
"FROM pg_index i " +
|
||||
"JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey) " +
|
||||
"WHERE i.indrelid = '\"" + schemaName + "\".\"" + tableName + "\"'::regclass " +
|
||||
"AND i.indisprimary " +
|
||||
"LIMIT 1";
|
||||
List<Map<String, Object>> pkResult = baseService.selectData(getPrimaryKeySql);
|
||||
if (pkResult != null && !pkResult.isEmpty()) {
|
||||
primaryKey = (String) pkResult.get(0).get("attname");
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryKey == null) {
|
||||
logger.warn("表 {} 没有主键,跳过", tableName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 处理每条数据
|
||||
for (Map<String, Object> rowData : tableDataList) {
|
||||
Map<String, Object> exportRow = new HashMap<>();
|
||||
exportRow.put("schema名称", schemaName);
|
||||
exportRow.put("表名", tableName);
|
||||
|
||||
// ID(主键)
|
||||
Object idValue = rowData.get(primaryKey);
|
||||
exportRow.put("ID", idValue != null ? idValue.toString() : "");
|
||||
|
||||
// parentID
|
||||
Object parentIdValue = rowData.get(parentIdFieldName);
|
||||
exportRow.put("parentID", parentIdValue != null ? parentIdValue.toString() : "");
|
||||
|
||||
// photo
|
||||
Object photoValue = rowData.get("photo");
|
||||
exportRow.put("photo", photoValue != null ? photoValue.toString() : "");
|
||||
|
||||
// 非 _media 表,相关字段设为空
|
||||
exportRow.put("media_id", "");
|
||||
exportRow.put("media_path", "");
|
||||
exportRow.put("longitude", "");
|
||||
exportRow.put("latitude", "");
|
||||
exportRow.put("altitude", "");
|
||||
exportRow.put("accuracy", "");
|
||||
exportRow.put("camera_angle", "");
|
||||
exportRow.put("camera_pitch", "");
|
||||
exportRow.put("camera_roll", "");
|
||||
|
||||
// 解析任务名、账号和姓名(从 photo 字段)
|
||||
String photoStr = photoValue != null ? photoValue.toString() : "";
|
||||
parseAndSetTaskAndUser(exportRow, photoStr, taskNameCache, userNameCache, realNameCache);
|
||||
|
||||
// 构建 relationsource
|
||||
String relationsource = buildRelationSource(schemaName, tableName, parentIdValue,
|
||||
tableMap, configString, baseService);
|
||||
exportRow.put("relationsource", relationsource);
|
||||
|
||||
exportDataList.add(exportRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exportDataList.isEmpty()) {
|
||||
return ResultMessage.failed("没有找到符合条件的数据").toString();
|
||||
}
|
||||
|
||||
// 生成 Excel 文件
|
||||
String exportDir = CommonConstant.TEMP_FILE_PATHNAME + "/" + System.currentTimeMillis();
|
||||
File exportDirFile = new File(exportDir);
|
||||
exportDirFile.mkdirs();
|
||||
|
||||
String excelFileName = task.getTaskName() + "_照片媒体导出.xlsx";
|
||||
File excelFile = new File(exportDir, excelFileName);
|
||||
|
||||
try {
|
||||
createExcelFile(exportDataList, excelFile);
|
||||
|
||||
// 设置响应头
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.addHeader("Content-Disposition",
|
||||
"attachment;fileName=" + new String(excelFileName.getBytes(StandardCharsets.UTF_8), "iso-8859-1"));
|
||||
|
||||
// 将文件写入响应
|
||||
String result = OtherUtil.uploadFileByResponse(excelFile, response);
|
||||
|
||||
// 清理临时文件
|
||||
FileUtils.deleteDirectory(exportDirFile);
|
||||
|
||||
return CommonConstant.FAILED.equals(result)
|
||||
? ResultMessage.failed("导出失败").toString()
|
||||
: ResultMessage.success(null).toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("导出 Excel 文件失败", e);
|
||||
FileUtils.deleteDirectory(exportDirFile);
|
||||
return ResultMessage.failed("导出失败:" + e.getMessage()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 Excel 文件
|
||||
*/
|
||||
private void createExcelFile(List<Map<String, Object>> dataList, File excelFile) throws IOException {
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("照片媒体数据");
|
||||
|
||||
// 创建样式
|
||||
// 表头样式:居中、加粗、有边框
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
headerStyle.setBorderTop(BorderStyle.THIN);
|
||||
headerStyle.setBorderBottom(BorderStyle.THIN);
|
||||
headerStyle.setBorderLeft(BorderStyle.THIN);
|
||||
headerStyle.setBorderRight(BorderStyle.THIN);
|
||||
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
// 数据样式:居中、有边框
|
||||
CellStyle dataStyle = workbook.createCellStyle();
|
||||
dataStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
dataStyle.setBorderTop(BorderStyle.THIN);
|
||||
dataStyle.setBorderBottom(BorderStyle.THIN);
|
||||
dataStyle.setBorderLeft(BorderStyle.THIN);
|
||||
dataStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
// 创建表头
|
||||
Row headerRow = sheet.createRow(0);
|
||||
String[] headers = {"schema名称", "表名", "ID", "parentID", "photo", "media_id", "media_path",
|
||||
"longitude", "latitude", "altitude", "accuracy", "camera_angle", "camera_pitch", "camera_roll",
|
||||
"任务名", "账号", "姓名", "relationsource"};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
cell.setCellStyle(headerStyle);
|
||||
}
|
||||
|
||||
// 写入数据
|
||||
int rowNum = 1;
|
||||
for (Map<String, Object> rowData : dataList) {
|
||||
Row row = sheet.createRow(rowNum++);
|
||||
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
String header = headers[i];
|
||||
Object value = rowData.get(header);
|
||||
Cell cell = row.createCell(i);
|
||||
cell.setCellStyle(dataStyle);
|
||||
|
||||
if (value == null) {
|
||||
cell.setBlank();
|
||||
} else if (value instanceof Number) {
|
||||
cell.setCellValue(((Number) value).doubleValue());
|
||||
} else if (value instanceof Boolean) {
|
||||
cell.setCellValue((Boolean) value);
|
||||
} else {
|
||||
cell.setCellValue(value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自动调整列宽
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
sheet.autoSizeColumn(i);
|
||||
// 设置最小列宽
|
||||
int columnWidth = sheet.getColumnWidth(i);
|
||||
if (columnWidth < 2000) {
|
||||
sheet.setColumnWidth(i, 2000);
|
||||
} else if (columnWidth > 15000) {
|
||||
sheet.setColumnWidth(i, 15000);
|
||||
}
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
try (FileOutputStream fos = new FileOutputStream(excelFile)) {
|
||||
workbook.write(fos);
|
||||
} finally {
|
||||
workbook.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 media_path 或 photo 字段解析任务ID和用户ID,并查询数据库获取任务名、账号和姓名
|
||||
*/
|
||||
private void parseAndSetTaskAndUser(Map<String, Object> exportRow, String pathStr,
|
||||
Map<Integer, String> taskNameCache, Map<Integer, String> userNameCache,
|
||||
Map<Integer, String> realNameCache) {
|
||||
String taskName = "";
|
||||
String userName = "";
|
||||
String realName = "";
|
||||
|
||||
if (pathStr != null && !pathStr.isEmpty()) {
|
||||
// 按 / 拆分路径
|
||||
String[] parts = pathStr.split("/");
|
||||
|
||||
Integer taskId = null;
|
||||
Integer userId = null;
|
||||
|
||||
// 查找 task_ 和 user_ 后的ID
|
||||
for (String part : parts) {
|
||||
if (part.startsWith("task_")) {
|
||||
try {
|
||||
String taskIdStr = part.substring(5); // 去掉 "task_" 前缀
|
||||
taskId = Integer.parseInt(taskIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("无法解析任务ID: {}", part);
|
||||
}
|
||||
} else if (part.startsWith("user_")) {
|
||||
try {
|
||||
String userIdStr = part.substring(5); // 去掉 "user_" 前缀
|
||||
userId = Integer.parseInt(userIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("无法解析用户ID: {}", part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询任务名
|
||||
if (taskId != null) {
|
||||
if (taskNameCache.containsKey(taskId)) {
|
||||
taskName = taskNameCache.get(taskId);
|
||||
} else {
|
||||
String queryTaskSql = "SELECT task_name FROM public.task WHERE id = " + taskId;
|
||||
List<Map<String, Object>> taskResult = baseService.selectData(queryTaskSql);
|
||||
if (taskResult != null && !taskResult.isEmpty()) {
|
||||
Object taskNameObj = taskResult.get(0).get("task_name");
|
||||
taskName = taskNameObj != null ? taskNameObj.toString() : "";
|
||||
taskNameCache.put(taskId, taskName);
|
||||
} else {
|
||||
taskNameCache.put(taskId, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询用户名和姓名
|
||||
if (userId != null) {
|
||||
if (userNameCache.containsKey(userId) && realNameCache.containsKey(userId)) {
|
||||
userName = userNameCache.get(userId);
|
||||
realName = realNameCache.get(userId);
|
||||
} else {
|
||||
String queryUserSql = "SELECT username, real_name FROM public.user_staff WHERE id = " + userId;
|
||||
List<Map<String, Object>> userResult = baseService.selectData(queryUserSql);
|
||||
if (userResult != null && !userResult.isEmpty()) {
|
||||
Map<String, Object> userRow = userResult.get(0);
|
||||
Object userNameObj = userRow.get("username");
|
||||
userName = userNameObj != null ? userNameObj.toString() : "";
|
||||
userNameCache.put(userId, userName);
|
||||
|
||||
Object realNameObj = userRow.get("real_name");
|
||||
realName = realNameObj != null ? realNameObj.toString() : "";
|
||||
realNameCache.put(userId, realName);
|
||||
} else {
|
||||
userNameCache.put(userId, "");
|
||||
realNameCache.put(userId, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exportRow.put("任务名", taskName);
|
||||
exportRow.put("账号", userName);
|
||||
exportRow.put("姓名", realName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建表层次关系JSON字符串
|
||||
*
|
||||
* @param schemaName schema名称
|
||||
* @param currentTableName 当前表名
|
||||
* @param parentIdValue 父表ID值(可能为null)
|
||||
* @param tableMap 表配置映射
|
||||
* @param configString 配置字符串
|
||||
* @param baseService 数据库服务
|
||||
* @return JSON格式的层次关系字符串
|
||||
*/
|
||||
private String buildRelationSource(String schemaName, String currentTableName, Object parentIdValue,
|
||||
Map<String, Table> tableMap, String configString, IBaseService baseService) {
|
||||
try {
|
||||
// 如果 parentID 为空,说明是根表,返回空对象
|
||||
if (parentIdValue == null || parentIdValue.toString().trim().isEmpty()) {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
// 查找当前表的父表
|
||||
String parentTableName = findParentTableName(currentTableName, tableMap);
|
||||
if (parentTableName == null) {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
// 构建当前层的关系
|
||||
Map<String, Object> relationMap = new HashMap<>();
|
||||
relationMap.put("parentTableName", parentTableName);
|
||||
relationMap.put("parentID", parentIdValue.toString());
|
||||
|
||||
// 递归查找父表的父表
|
||||
Table parentTable = tableMap.get(parentTableName);
|
||||
if (parentTable != null) {
|
||||
String parentParentIdField = TableOperationUtil.getParentID(parentTable);
|
||||
if (parentParentIdField != null) {
|
||||
// 查询父表记录,获取其 parentID
|
||||
String parentTableNameInDb = PostgreSqlUtil.buildTableNameString(schemaName, parentTableName, false, false);
|
||||
String parentPrimaryKey = TableOperationUtil.getPrimaryKey(parentTable);
|
||||
if (parentPrimaryKey != null) {
|
||||
// 获取主键字段的数据库类型
|
||||
String parentPrimaryKeyDbType = null;
|
||||
Map<String, Field> parentFields = parentTable.getFields();
|
||||
if (parentFields != null) {
|
||||
Field primaryKeyField = parentFields.get(parentPrimaryKey);
|
||||
if (primaryKeyField != null) {
|
||||
parentPrimaryKeyDbType = primaryKeyField.getDbType();
|
||||
}
|
||||
}
|
||||
|
||||
// 构建安全的SQL查询,根据字段类型处理
|
||||
String parentPrimaryKeyTransformed = PostgreSqlUtil.transformString(parentPrimaryKey);
|
||||
String parentParentIdFieldTransformed = PostgreSqlUtil.transformString(parentParentIdField);
|
||||
String parentIdValueStr = parentIdValue.toString();
|
||||
|
||||
// 根据字段类型构建WHERE子句
|
||||
String whereClause;
|
||||
if (parentPrimaryKeyDbType != null &&
|
||||
(parentPrimaryKeyDbType.toLowerCase().equals("integer") ||
|
||||
parentPrimaryKeyDbType.toLowerCase().equals("long") ||
|
||||
parentPrimaryKeyDbType.toLowerCase().equals("bigint") ||
|
||||
parentPrimaryKeyDbType.toLowerCase().equals("double") ||
|
||||
parentPrimaryKeyDbType.toLowerCase().equals("numeric"))) {
|
||||
// 数字类型,不需要引号
|
||||
whereClause = parentPrimaryKeyTransformed + " = " + parentIdValueStr;
|
||||
} else {
|
||||
// 字符串或其他类型,需要加引号并转义单引号
|
||||
String escapedValue = parentIdValueStr.replace("'", "''");
|
||||
whereClause = parentPrimaryKeyTransformed + " = '" + escapedValue + "'";
|
||||
}
|
||||
String selectParentSql = "SELECT " + parentParentIdFieldTransformed + " FROM " + parentTableNameInDb + " WHERE " + whereClause;
|
||||
List<Map<String, Object>> parentResult = baseService.selectData(selectParentSql);
|
||||
|
||||
if (parentResult != null && !parentResult.isEmpty()) {
|
||||
Object parentParentIdValue = parentResult.get(0).get(parentParentIdField);
|
||||
if (parentParentIdValue != null && !parentParentIdValue.toString().trim().isEmpty()) {
|
||||
// 递归构建父表的父表关系
|
||||
String parentParentRelation = buildRelationSource(schemaName, parentTableName,
|
||||
parentParentIdValue, tableMap, configString, baseService);
|
||||
if (!parentParentRelation.equals("{}")) {
|
||||
relationMap.put("parentParent", JSON.parseObject(parentParentRelation));
|
||||
} else {
|
||||
relationMap.put("parentParent", new HashMap<>());
|
||||
}
|
||||
} else {
|
||||
relationMap.put("parentParent", new HashMap<>());
|
||||
}
|
||||
} else {
|
||||
relationMap.put("parentParent", new HashMap<>());
|
||||
}
|
||||
} else {
|
||||
relationMap.put("parentParent", new HashMap<>());
|
||||
}
|
||||
} else {
|
||||
relationMap.put("parentParent", new HashMap<>());
|
||||
}
|
||||
} else {
|
||||
relationMap.put("parentParent", new HashMap<>());
|
||||
}
|
||||
|
||||
return JSON.toJSONString(relationMap);
|
||||
} catch (Exception e) {
|
||||
logger.error("构建 relationsource 失败: {}", e.getMessage(), e);
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定表的父表名
|
||||
* 通过遍历所有表,找到哪些表的 associate 或 collection 字段指向当前表
|
||||
* 对于 _media 表,父表名就是去掉 _media 后缀的表名
|
||||
*
|
||||
* @param childTableName 子表名
|
||||
* @param tableMap 表配置映射
|
||||
* @return 父表名,如果找不到返回 null
|
||||
*/
|
||||
private String findParentTableName(String childTableName, Map<String, Table> tableMap) {
|
||||
if (childTableName == null || childTableName.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 对于 _media 表,父表名就是去掉 _media 后缀的表名
|
||||
if (childTableName.endsWith("_media")) {
|
||||
String parentTableName = childTableName.substring(0, childTableName.length() - 6); // 去掉 "_media"
|
||||
// 验证父表是否存在于配置中
|
||||
if (tableMap != null && tableMap.containsKey(parentTableName)) {
|
||||
return parentTableName;
|
||||
}
|
||||
}
|
||||
|
||||
if (tableMap == null || tableMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 遍历所有表,查找哪些表的 associate 或 collection 字段指向当前表
|
||||
for (Map.Entry<String, Table> entry : tableMap.entrySet()) {
|
||||
Table table = entry.getValue();
|
||||
if (table == null || table.getFields() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查该表的字段中是否有 associate 或 collection 指向当前表
|
||||
for (Map.Entry<String, Field> fieldEntry : table.getFields().entrySet()) {
|
||||
Field field = fieldEntry.getValue();
|
||||
if (field == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查 associate 字段
|
||||
String associate = field.getAssociate();
|
||||
if (associate != null && !associate.trim().isEmpty() && associate.equals(childTableName)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
|
||||
// 检查 collection 字段
|
||||
String collection = field.getCollection();
|
||||
if (collection != null && !collection.trim().isEmpty() && collection.equals(childTableName)) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,6 +335,35 @@ public class TaskManagementController{
|
||||
return ResultMessage.success(result).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 网页端任务管理模块根据关键词模糊查找任务相关信息
|
||||
* 可以根据任务名称或数据库名中包含keyword的任务
|
||||
*/
|
||||
@RequestMapping(value = "selectAllWithKeyword", produces = "text/html;charset=UTF-8")
|
||||
public String selectAllWithKeyword(String keyword){
|
||||
List<Task> allTaskList = taskService.getAllTask();
|
||||
List<Task> filteredTaskList = new ArrayList<>();
|
||||
|
||||
// 如果keyword为空或null,返回所有任务
|
||||
if(keyword == null || keyword.trim().isEmpty()){
|
||||
String result = getTaskInfo(allTaskList);
|
||||
return ResultMessage.success(result).toString();
|
||||
}
|
||||
|
||||
// 模糊匹配任务名称或数据库名
|
||||
String lowerKeyword = keyword.toLowerCase().trim();
|
||||
for(Task task : allTaskList){
|
||||
String taskName = task.getTaskName() != null ? task.getTaskName().toLowerCase() : "";
|
||||
String databaseName = task.getDatabaseName() != null ? task.getDatabaseName().toLowerCase() : "";
|
||||
if(taskName.contains(lowerKeyword) || databaseName.contains(lowerKeyword)){
|
||||
filteredTaskList.add(task);
|
||||
}
|
||||
}
|
||||
|
||||
String result = getTaskInfo(filteredTaskList);
|
||||
return ResultMessage.success(result).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 网页端决策管理模块获取任务相关信息,有任务名称、数据库名、任务下所有根表名
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user