20251125GET指定任务的所有Media

This commit is contained in:
wxlong
2025-11-25 18:08:41 +08:00
parent 73760b7eb8
commit f9064be39b
2 changed files with 907 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}
/**
* 网页端决策管理模块获取任务相关信息,有任务名称、数据库名、任务下所有根表名
*/