修改图库接口,添加图片生成幻灯片功能

develop
username 1 month ago
parent c2bef66dac
commit a3d67c7ce5

@ -16,6 +16,17 @@
</description> </description>
<dependencies> <dependencies>
<!--JAVA使用javacv实现图片合成短视频相关JAR包-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.2</version>
</dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>

@ -54,7 +54,6 @@ public class CtGalleryCataController extends BaseController {
condition(queryWrapper,ctGalleryCata); condition(queryWrapper,ctGalleryCata);
List<CtGalleryCata> list = ctGalleryCataService.list(queryWrapper); List<CtGalleryCata> list = ctGalleryCataService.list(queryWrapper);
List<CtGalleryCata> ctGalleryCatas = buildTree(list); List<CtGalleryCata> ctGalleryCatas = buildTree(list);
return getDataTable(ctGalleryCatas); return getDataTable(ctGalleryCatas);
} }

@ -1,12 +1,10 @@
package com.bs.ct.controller; package com.bs.ct.controller;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -80,18 +78,115 @@ public class CtGalleryImagesController extends BaseController {
private ICtTaskInfoService ctTaskInfoService; private ICtTaskInfoService ctTaskInfoService;
@Resource @Resource
private ICtImagesFeedbackRefService ctImagesFeedbackRefService; private ICtImagesFeedbackRefService ctImagesFeedbackRefService;
@Resource
private ICtGalleryCataService ctGalleryCataService;
@Resource
private ICtTaskFeedbackService ctTaskFeedbackService;
/** /**
* *
*/ */
@ApiOperation("分页查询图库图片列表") @ApiOperation("分页查询图库图片列表")
@GetMapping("/pageList") @GetMapping("/pageList")
public TableDataInfo pageList(CtGalleryImages ctGalleryImages) { public TableDataInfo pageList(CtGalleryImages ctGalleryImages) {
startPage(); Integer pageNum = ctGalleryImages.getPageNum() != null ? ctGalleryImages.getPageNum() : 1;
Integer pageSize = ctGalleryImages.getPageSize() != null ? ctGalleryImages.getPageSize() : 10;
LambdaQueryWrapper<CtGalleryImages> queryWrapper = new LambdaQueryWrapper(); LambdaQueryWrapper<CtGalleryImages> queryWrapper = new LambdaQueryWrapper();
condition(queryWrapper,ctGalleryImages); if (Validator.isEmpty(ctGalleryImages.getImageTitle())) {
condition(queryWrapper,ctGalleryImages);
}
List<CtGalleryImages> list = ctGalleryImagesService.list(queryWrapper); List<CtGalleryImages> list = ctGalleryImagesService.list(queryWrapper);
setAll(list);
setFile(list); setFile(list);
return getDataTable(list); if (Validator.isNotEmpty(ctGalleryImages.getImageTitle())) {
list = filterByImageTitle(list,ctGalleryImages.getImageTitle());
}
Integer start = (pageNum - 1) * pageSize;
List<CtGalleryImages> result = list.stream()
.skip(start) // 跳过前4条数据
.limit(pageSize) // 最多取6条数据
.collect(Collectors.toList());
TableDataInfo data = getDataTable(result);
data.setTotal(list.size());
return data;
}
// 过滤方法
public static List<CtGalleryImages> filterByImageTitle(List<CtGalleryImages> list, String filterText) {
return list.stream()
.filter(image -> {
boolean matchImageName = image.getImageName() != null && image.getImageName().contains(filterText);
boolean matchImageTitle = image.getImageTitle() != null && image.getImageTitle().contains(filterText);
boolean matchKeyWords = image.getKeyWords() != null && image.getKeyWords().contains(filterText);
boolean matchCataName = image.getCataName() != null && image.getCataName().contains(filterText);
boolean matchTagNames = image.getTagNames() != null && image.getTagNames().stream().anyMatch(tag -> tag.contains(filterText));
boolean matchTaskTitles = image.getTaskTitles() != null && image.getTaskTitles().stream().anyMatch(task -> task.contains(filterText));
return matchImageName || matchImageTitle || matchKeyWords || matchCataName || matchTagNames || matchTaskTitles;
})
.collect(Collectors.toList());
}
private void setAll(List<CtGalleryImages> list) {
List<CtGalleryCata> ctGalleryCatas = ctGalleryCataService.list();
List<CtGalleryImagesTag> imagesTags = ctGalleryImagesTagService.list();
HashMap<Long, String> longStringHashMap = ctGalleryCatas.stream()
.collect(Collectors.toMap(
CtGalleryCata::getId,
CtGalleryCata::getCataName,
(existing, replacement) -> existing,
HashMap::new
));
Map<Long, List<String>> imageStringHashMap = imagesTags.stream()
.collect(Collectors.groupingBy(
CtGalleryImagesTag::getImageId,
Collectors.mapping(
CtGalleryImagesTag::getTagName,
Collectors.toList()
)
));
//查询相关任务名称
List<CtImagesFeedbackRef> imagesFeedbackRefs = ctImagesFeedbackRefService.list();
Map<Long, List<Long>> refMap = imagesFeedbackRefs.stream()
.collect(Collectors.groupingBy(
CtImagesFeedbackRef::getImageId, // 分组键imageId
Collectors.mapping(
CtImagesFeedbackRef::getFeedbackId, // 提取值feedbackId
Collectors.toList() // 收集为列表
)
));
List<CtTaskFeedback> ctTaskFeedbacks = ctTaskFeedbackService.list();
HashMap<Long, Long> feedbackIdsMap = ctTaskFeedbacks.stream()
.collect(Collectors.toMap(
CtTaskFeedback::getId, // 键id
CtTaskFeedback::getTaskId, // 值taskId
(existing, replacement) -> existing, // 处理键冲突:保留现有值
() -> new HashMap<>() // 指定 Map 实现类(可选)
));
List<CtTaskInfo> ctTaskInfos = ctTaskInfoService.list();
HashMap<Long, String> infoMap = ctTaskInfos.stream()
.collect(Collectors.toMap(
CtTaskInfo::getId,
CtTaskInfo::getTaskTitle,
(existing, replacement) -> existing,
HashMap::new
));
for (CtGalleryImages ctGalleryImage : list) {
Long cataId = ctGalleryImage.getCataId();
String cataName = longStringHashMap.get(cataId);
ctGalleryImage.setCataName(cataName);
List<String> tagNames = imageStringHashMap.get(ctGalleryImage.getId());
ctGalleryImage.setTagNames(tagNames);
List<Long> feedList = refMap.get(ctGalleryImage.getId());
List<String> taskTitles = new ArrayList<>();
if (null != feedList && feedList.size() > 0) {
for (Long feedId : feedList) {
Long taskInfoId = feedbackIdsMap.get(feedId);
String taskTitleName = infoMap.get(taskInfoId);
taskTitles.add(taskTitleName);
}
ctGalleryImage.setTaskTitles(taskTitles);
}
}
} }
private void setFile(List<CtGalleryImages> list) { private void setFile(List<CtGalleryImages> list) {
@ -141,12 +236,14 @@ public class CtGalleryImagesController extends BaseController {
List<CtGalleryImages> list = ctGalleryImagesService.list(new LambdaQueryWrapper<CtGalleryImages>() List<CtGalleryImages> list = ctGalleryImagesService.list(new LambdaQueryWrapper<CtGalleryImages>()
.in(CtGalleryImages::getId, imagesIds)); .in(CtGalleryImages::getId, imagesIds));
BufferedImage[] imgs = new BufferedImage[list.size()]; BufferedImage[] imgs = new BufferedImage[list.size()];
Map<Integer, File> imgMap = new HashMap<>();
int index = 0; int index = 0;
for (CtGalleryImages galleryImages : list) { for (CtGalleryImages galleryImages : list) {
String attachUrl = galleryImages.getImagePath().replace("/profile", ""); String attachUrl = galleryImages.getImagePath().replace("/profile", "");
String filePath = profile + attachUrl; String filePath = profile + attachUrl;
try { try {
imgs[index++] = OperateImageUtils.getBufferedImage(filePath); imgs[index++] = OperateImageUtils.getBufferedImage(filePath);
imgMap.put(index++, new File(filePath));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return AjaxResult.error("读取图片失败: " + filePath); return AjaxResult.error("读取图片失败: " + filePath);
@ -190,6 +287,12 @@ public class CtGalleryImagesController extends BaseController {
return AjaxResult.error("垂直合并需要至少2张图片"); return AjaxResult.error("垂直合并需要至少2张图片");
} }
break; break;
case "video":
int width = imgs[0].getWidth();
int height = imgs[0].getHeight();
String mp4SavePath = profile + UUIDUtils.generatorUUID() + "output.mp4";
OperateImageUtils.createMp4(mp4SavePath, imgMap, width, height);
break;
default: default:
return AjaxResult.error("不支持的图片类型: " + imageType); return AjaxResult.error("不支持的图片类型: " + imageType);
} }
@ -330,12 +433,6 @@ public class CtGalleryImagesController extends BaseController {
CtTaskInfo ctTaskInfo = new CtTaskInfo(); CtTaskInfo ctTaskInfo = new CtTaskInfo();
Long newId = System.currentTimeMillis() + new Random().nextInt(1000); Long newId = System.currentTimeMillis() + new Random().nextInt(1000);
ctTaskInfo.setId(newId); ctTaskInfo.setId(newId);
List<CtTaskBranch> branchList = ctTaskInfo.getBranchList();
for (CtTaskBranch sdTaskOtherBranch : branchList) {
sdTaskOtherBranch.setTaskId(ctTaskInfo.getId());
sdTaskOtherBranch.setType("机构");
ctTaskBranchService.saveOrUpdate(sdTaskOtherBranch);
}
//设置发起单位与部门 //设置发起单位与部门
LoginUser loginUser = getLoginUser(); LoginUser loginUser = getLoginUser();
Long deptId = loginUser.getDeptId(); Long deptId = loginUser.getDeptId();
@ -348,6 +445,20 @@ public class CtGalleryImagesController extends BaseController {
ctTaskInfo.setBranchCode(String.valueOf(parentDept.getDeptId())); ctTaskInfo.setBranchCode(String.valueOf(parentDept.getDeptId()));
ctTaskInfo.setBranchName(parentDept.getDeptName()); ctTaskInfo.setBranchName(parentDept.getDeptName());
} }
CtTaskBranch branch = new CtTaskBranch();
branch.setBranchCode(String.valueOf(deptId));
branch.setBranchName(sysDept.getDeptName());
branch.setTaskId(ctTaskInfo.getId());
branch.setType("机构");
ctTaskBranchService.saveOrUpdate(branch);
CtTaskBranch taskBranch = new CtTaskBranch();
taskBranch.setBranchCode(String.valueOf(deptId));
taskBranch.setUserName(loginUser.getUsername());
taskBranch.setUserId(String.valueOf(loginUser.getUserId()));
taskBranch.setTaskStatus("0");
taskBranch.setTaskId(ctTaskInfo.getId());
taskBranch.setType("人员");
ctTaskBranchService.saveOrUpdate(taskBranch);
} }
if ("1".equals(ctTaskInfo.getStatus())) { if ("1".equals(ctTaskInfo.getStatus())) {
ctTaskInfo.setTaskDate(new Date()); ctTaskInfo.setTaskDate(new Date());

@ -6,6 +6,7 @@ import javax.servlet.http.HttpServletResponse;
import com.bs.cm.domain.CmAttach; import com.bs.cm.domain.CmAttach;
import com.bs.cm.service.ICmAttachService; import com.bs.cm.service.ICmAttachService;
import com.bs.common.exception.ServiceException;
import com.bs.ct.domain.CtTaskInfo; import com.bs.ct.domain.CtTaskInfo;
import com.bs.ct.domain.CtTaskTemplateTag; import com.bs.ct.domain.CtTaskTemplateTag;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@ -111,6 +112,10 @@ public class CtTagController extends BaseController {
@Log(title = "标签信息新增", businessType = BusinessType.INSERT) @Log(title = "标签信息新增", businessType = BusinessType.INSERT)
@PostMapping @PostMapping
public AjaxResult add(@RequestBody CtTag ctTag) { public AjaxResult add(@RequestBody CtTag ctTag) {
List<CtTag> ctTags = ctTagService.list(new LambdaQueryWrapper<CtTag>().eq(CtTag::getTagName, ctTag.getTagName()));
if (null != ctTags && ctTags.size() > 0) {
throw new ServiceException("该标签名称已经存在");
}
updateFile(ctTag); updateFile(ctTag);
return toAjax(ctTagService.save(ctTag)); return toAjax(ctTagService.save(ctTag));
} }

@ -285,8 +285,6 @@ public class CtTaskBranchController extends BaseController {
taskOtherBranch.setTaskDate(byId.getTaskDate()); taskOtherBranch.setTaskDate(byId.getTaskDate());
taskOtherBranch.setSdTaskOther(byId); taskOtherBranch.setSdTaskOther(byId);
} }
List<CtTaskFeedback> feedbackListByCreateTime = ctTaskFeedbackService.list(new LambdaQueryWrapper<CtTaskFeedback>() List<CtTaskFeedback> feedbackListByCreateTime = ctTaskFeedbackService.list(new LambdaQueryWrapper<CtTaskFeedback>()
.eq(CtTaskFeedback::getTaskBranchId, taskOtherBranch.getId()) .eq(CtTaskFeedback::getTaskBranchId, taskOtherBranch.getId())
.ne(CtTaskFeedback::getStatus, 0) .ne(CtTaskFeedback::getStatus, 0)

@ -6,9 +6,12 @@ import javax.servlet.http.HttpServletResponse;
import com.bs.cm.domain.CmAttach; import com.bs.cm.domain.CmAttach;
import com.bs.cm.service.ICmAttachService; import com.bs.cm.service.ICmAttachService;
import com.bs.common.core.domain.entity.SysDept;
import com.bs.common.core.domain.entity.SysUser; import com.bs.common.core.domain.entity.SysUser;
import com.bs.common.core.domain.model.LoginUser;
import com.bs.ct.domain.*; import com.bs.ct.domain.*;
import com.bs.ct.service.*; import com.bs.ct.service.*;
import com.bs.system.service.ISysDeptService;
import com.bs.system.service.ISysUserService; import com.bs.system.service.ISysUserService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -57,6 +60,10 @@ public class CtTaskFeedbackController extends BaseController {
private ICtImagesFeedbackRefService ctImagesFeedbackRefService; private ICtImagesFeedbackRefService ctImagesFeedbackRefService;
@Resource @Resource
private ICtGalleryImagesService ctGalleryImagesService; private ICtGalleryImagesService ctGalleryImagesService;
@Resource
private ICtGalleryImagesTagService ctGalleryImagesTagService;
@Autowired
private ISysDeptService deptService;
/** /**
* *
*/ */
@ -76,7 +83,7 @@ public class CtTaskFeedbackController extends BaseController {
.eq(CtImagesFeedbackRef::getFeedbackId, ctFeedback.getId())); .eq(CtImagesFeedbackRef::getFeedbackId, ctFeedback.getId()));
if (null != ctImagesFeedbackRefs && ctImagesFeedbackRefs.size() > 0) { if (null != ctImagesFeedbackRefs && ctImagesFeedbackRefs.size() > 0) {
List<Long> imageIds = ctImagesFeedbackRefs.stream() List<Long> imageIds = ctImagesFeedbackRefs.stream()
.map(CtImagesFeedbackRef::getImageId) // 提取 imageId .map(CtImagesFeedbackRef::getImageId)
.collect(Collectors.toList()); .collect(Collectors.toList());
List<CtGalleryImages> galleryImages = ctGalleryImagesService.list(new LambdaQueryWrapper<CtGalleryImages>() List<CtGalleryImages> galleryImages = ctGalleryImagesService.list(new LambdaQueryWrapper<CtGalleryImages>()
.in(CtGalleryImages::getId, imageIds)); .in(CtGalleryImages::getId, imageIds));
@ -89,6 +96,70 @@ public class CtTaskFeedbackController extends BaseController {
} }
} }
//
/**
*
*/
@ApiOperation("通过图片新增任务反馈")
@Log(title = "通过图片新增任务反馈", businessType = BusinessType.INSERT)
@PostMapping("/addByImage")
public AjaxResult addByImage(@RequestBody CtTaskFeedback ctTaskFeedback) {
List<Long> imageIds = ctTaskFeedback.getImageIds();
Long taskId = ctTaskFeedback.getTaskId();
List<CtTaskTag> ctTaskTags = ctTaskTagService.list(new LambdaQueryWrapper<CtTaskTag>()
.eq(CtTaskTag::getTaskId, taskId));
List<String> tagNamesByTag = ctTaskTags.stream()
.map(CtTaskTag::getTagName)
.collect(Collectors.toList());
LoginUser loginUser = getLoginUser();
SysDept sysDept = deptService.selectDeptById(loginUser.getDeptId());
List<Long> notTags = new ArrayList<>();
Map<String, List<Long>> tagImageIdMap = new HashMap<>();
for (Long imageId : imageIds) {
List<CtGalleryImagesTag> ctGalleryImagesTags = ctGalleryImagesTagService.list(new LambdaQueryWrapper<CtGalleryImagesTag>()
.eq(CtGalleryImagesTag::getImageId, imageId));
List<String> tagNames = ctGalleryImagesTags.stream()
.map(CtGalleryImagesTag::getTagName)
.collect(Collectors.toList());
boolean hasMatch = false;
for (String tagName : tagNames) {
if (tagNamesByTag.contains(tagName)) {
tagImageIdMap.computeIfAbsent(tagName, k -> new ArrayList<>()).add(imageId);
hasMatch = true;
}
}
if (!hasMatch) {
notTags.add(imageId);
}
}
// 为每个标签组创建反馈任务
for (Map.Entry<String, List<Long>> entry : tagImageIdMap.entrySet()) {
String tagName = entry.getKey();
List<Long> groupImageIds = entry.getValue();
Optional<CtTaskTag> firstMatch = ctTaskTags.stream()
.filter(tag -> tagName.equals(tag.getTagName()))
.findFirst();
if (firstMatch.isPresent()) {
CtTaskTag tag = firstMatch.get();
CtTaskFeedback feedback = new CtTaskFeedback();
feedback.setTaskId(taskId);
feedback.setTaskTagId(tag.getId());
feedback.setImageIds(groupImageIds);
feedback.setFeedbackTime(new Date());
feedback.setUserId(String.valueOf(loginUser.getUserId()));
feedback.setUserName(loginUser.getUsername());
feedback.setBranchCode(String.valueOf(loginUser.getDeptId()));
feedback.setUserDept(sysDept.getDeptName());
boolean save = ctTaskFeedbackService.save(feedback);
if (save) {
saveRef(feedback);
}
}
}
return success(notTags);
}
/** /**
* *
*/ */

@ -121,6 +121,35 @@ public class CtGalleryImages extends BaseEntity{
@TableField(exist = false) @TableField(exist = false)
private Long feedbackId; private Long feedbackId;
/**
* nineGrid
* fourGrid
* horizontalMerge
* verticalMerge
* video
* */
@TableField(exist = false) @TableField(exist = false)
private String imageType; private String imageType;
/** 目录名称 */
@TableField(exist = false)
private String cataName;
/** 标签名称 */
@TableField(exist = false)
private List<String> tagNames;
/** 标签名称 */
@TableField(exist = false)
private List<String> taskTitles;
@TableField(exist = false)
private Integer pageNum;
@TableField(exist = false)
private Integer pageSize;
} }

@ -1,9 +1,16 @@
package com.bs.ct.utils; package com.bs.ct.utils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.FrameRecorder;
import org.bytedeco.javacv.Java2DFrameConverter;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
/** /**
@ -112,9 +119,11 @@ public class OperateImageUtils {
return DestImage; return DestImage;
} }
/** /**
* @param isHorizontal truefasle *
* @param imgs *
* @param isHorizontal truefalse
* @param imgs
* @return * @return
* @throws IOException * @throws IOException
*/ */
@ -130,11 +139,9 @@ public class OperateImageUtils {
if (img.getWidth() > allwMax) { if (img.getWidth() > allwMax) {
allwMax = img.getWidth(); allwMax = img.getWidth();
} }
;
if (img.getHeight() > allhMax) { if (img.getHeight() > allhMax) {
allhMax = img.getHeight(); allhMax = img.getHeight();
} }
;
} }
// 创建新图片 // 创建新图片
if (isHorizontal) { if (isHorizontal) {
@ -165,6 +172,7 @@ public class OperateImageUtils {
/** /**
* *
*
* @param rows * @param rows
* @param cols * @param cols
* @param imgs * @param imgs
@ -205,12 +213,73 @@ public class OperateImageUtils {
return destImage; return destImage;
} }
public static void createMp4(String mp4SavePath, Map<Integer, File> imgMap, int width, int height) throws FrameRecorder.Exception {
// 调整宽度和高度为偶数
width = width % 2 == 0 ? width : width + 1;
height = height % 2 == 0 ? height : height + 1;
// 视频宽高最好是按照常见的视频的宽高 169 或者 916
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(mp4SavePath, width, height);
// 设置视频编码层模式
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
// 设置视频为25帧每秒
recorder.setFrameRate(25);
// 设置视频图像数据格式
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFormat("mp4");
try {
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
// 录制一个22秒的视频,22秒为自定义的一个视频时间长度,图片少则在22秒内,多则到22秒停止
for (int i = 0; i < 22; i++) {
if (imgMap.containsKey(i)) {
BufferedImage read = ImageIO.read(imgMap.get(i));
// 调整图片尺寸为偶数
read = resizeToEven(read);
// 转换图像颜色模式为 TYPE_3BYTE_BGR
BufferedImage bgrImage = new BufferedImage(read.getWidth(), read.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
java.awt.Graphics g = bgrImage.getGraphics();
g.drawImage(read, 0, 0, null);
g.dispose();
// 一秒是25帧 所以要记录25次
for (int j = 0; j < 25; j++) {
recorder.record(converter.getFrame(bgrImage));
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 最后一定要结束并释放资源
recorder.stop();
recorder.release();
}
}
public static BufferedImage resizeToEven(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
width = width % 2 == 0 ? width : width + 1;
height = height % 2 == 0 ? height : height + 1;
java.awt.Image tmp = image.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
java.awt.Graphics2D g2d = resized.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return resized;
}
public static void main(String[] args) { public static void main(String[] args) {
try { try {
// 读取待合并的文件 // 读取待合并的文件
BufferedImage[] imgs = new BufferedImage[9]; BufferedImage[] imgs = new BufferedImage[9];
Map<Integer, File> imgMap = new HashMap<>();
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
imgs[i] = getBufferedImage("D:\\edge下载\\下载\\1_2019年-2024年数据\\" + (i + 1) + ".jpg"); imgs[i] = getBufferedImage("D:\\edge下载\\下载\\1_2019年-2024年数据\\" + (i + 1) + ".jpg");
imgMap.put(i, new File("D:\\edge下载\\下载\\1_2019年-2024年数据\\" + (i + 1) + ".jpg"));
} }
// 合并成九宫格 // 合并成九宫格
@ -245,6 +314,13 @@ public class OperateImageUtils {
saveImage(multiVerticalMergedImg, "D:\\edge下载\\下载\\1_2019年-2024年数据\\", "multiVerticalMerge.jpg", "jpg"); saveImage(multiVerticalMergedImg, "D:\\edge下载\\下载\\1_2019年-2024年数据\\", "multiVerticalMerge.jpg", "jpg");
System.out.println("多张图片垂直合并完毕!"); System.out.println("多张图片垂直合并完毕!");
// 测试图片转视频
int width = imgs[0].getWidth();
int height = imgs[0].getHeight();
String mp4SavePath = "D:\\edge下载\\下载\\1_2019年-2024年数据\\output.mp4";
createMp4(mp4SavePath, imgMap, width, height);
System.out.println("MP4视频生成完毕!");
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

@ -90,6 +90,11 @@
<dict-tag :options="dict.type.sys_yes_no" :value="scope.row.isPhoto"/> <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.isPhoto"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="标签类型" align="center" prop="tagType" sortable='custom'>
<template slot-scope="scope">
<dict-tag :options="dict.type.tag_type" :value="scope.row.tagType"/>
</template>
</el-table-column>
<el-table-column label="拍照数量要求" align="center" prop="photoNum" sortable='custom'/> <el-table-column label="拍照数量要求" align="center" prop="photoNum" sortable='custom'/>
<el-table-column label="照片存放目录" align="center" prop="saveDir" sortable='custom'> <el-table-column label="照片存放目录" align="center" prop="saveDir" sortable='custom'>
<template slot-scope="scope"> <template slot-scope="scope">
@ -131,38 +136,64 @@
<!-- 添加或修改标签信息对话框 --> <!-- 添加或修改标签信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="70%" append-to-body :close-on-click-modal="false"> <el-dialog :title="title" :visible.sync="open" width="70%" append-to-body :close-on-click-modal="false">
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-row :gutter="20"> <el-row :gutter="24">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="标签名称" prop="tagName"> <el-form-item label="标签名称" prop="tagName">
<el-input v-model="form.tagName" placeholder="请输入标签名称"/> <el-input
v-model="form.tagName"
placeholder="请输入标签名称"
clearable
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="是否需要拍照" prop="isPhoto"> <el-form-item label="是否需要拍照" prop="isPhoto">
<el-radio-group v-model="form.isPhoto"> <el-radio-group v-model="form.isPhoto" class="radio-group">
<el-radio <el-radio
v-for="dict in dict.type.sys_yes_no" v-for="dict in dict.type.sys_yes_no"
:key="dict.value" :key="dict.value"
:label="dict.value" :label="dict.value"
>{{dict.label}}</el-radio> style="margin-right: 16px;"
>{{ dict.label }}</el-radio>
</el-radio-group> </el-radio-group>
<!-- <el-input v-model="form.isPhoto" placeholder="请输入是否需要拍照"/>-->
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <!-- 标签类型 + 拍照数量要求 -->
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="标签类型">
<el-select
v-model="form.tagType"
placeholder="请选择"
clearable
filterable
style="width: 100%;"
>
<el-option
v-for="dict in dict.type.tag_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="拍照数量要求" prop="photoNum"> <el-form-item label="拍照数量要求" prop="photoNum">
<el-input-number <el-input-number
v-model="form.photoNum" v-model="form.photoNum"
style="width: 100%;"
placeholder="请输入拍照数量要求" placeholder="请输入拍照数量要求"
:min="0" :min="0"
:step="1" :step="1"
style="width: 100%;"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> </el-row>
<!-- 照片存放目录单独一行 span=24 -->
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="照片存放目录" prop="saveDir"> <el-form-item label="照片存放目录" prop="saveDir">
<treeselect <treeselect
v-model="form.saveDir" v-model="form.saveDir"
@ -170,31 +201,45 @@
:normalizer="normalizer" :normalizer="normalizer"
placeholder="选择照片存放目录" placeholder="选择照片存放目录"
:allow-empty="true" :allow-empty="true"
style="width: 100%;"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <!-- 标签说明文本域单独一行 -->
<el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="标签说明" prop="tagDesc"> <el-form-item label="标签说明" prop="tagDesc">
<el-input v-model="form.tagDesc" type="textarea" placeholder="请输入内容"/> <el-input
v-model="form.tagDesc"
type="textarea"
placeholder="请输入内容"
:rows="3"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <!-- 备注文本域单独一行 -->
<el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remarks"> <el-form-item label="备注" prop="remarks">
<el-input v-model="form.remarks" type="textarea" placeholder="请输入内容"/> <el-input
v-model="form.remarks"
type="textarea"
placeholder="请输入内容"
:rows="3"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <!-- 附件单独一行 -->
<el-row :gutter="24">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="附件" prop="files"> <el-form-item label="附件" prop="files">
<FileUpload <FileUpload
v-model="form.files" v-model="form.files"
accept=".xls,.xlsx,.doc,.docx,.pdf,.png,.jpg,.jpeg,.gif,.ppt,.pptx" accept=".xls,.xlsx,.doc,.docx,.pdf,.png,.jpg,.jpeg,.gif,.ppt,.pptx"
></FileUpload> />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -237,7 +282,7 @@ export default {
Treeselect Treeselect
}, },
name: "Tag", name: "Tag",
dicts: ['sys_yes_no'], dicts: ['sys_yes_no','tag_type'],
data() { data() {
return { return {
// //
@ -285,7 +330,6 @@ export default {
}, },
created() { created() {
this.getList(); this.getList();
listCata().then(res => { listCata().then(res => {
const list = res.data || []; const list = res.data || [];
this.cates = list; this.cates = list;
@ -377,14 +421,14 @@ export default {
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
const api = this.form.id != null ? updateTag : addTag; const api = this.form.id != null? updateTag : addTag;
api(this.form) api(this.form)
.then(response => { .then(response => {
this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功"); this.$modal.msgSuccess(this.form.id != null? "修改成功" : "新增成功");
this.open = false; this.open = false;
this.getList(); this.getList();
}) })
.catch(this.handleApiError); .catch();
} }
}); });
}, },

@ -3,7 +3,7 @@
:close-on-click-modal="false" :close-on-click-modal="false"
:close-on-press-escape="false" :close-on-press-escape="false"
:visible.sync="dialogVisible" :visible.sync="dialogVisible"
:title="`我的任务${isAudit ? '审核':'反馈'}`" :title="`任务${isAudit ? '审核':'反馈'}`"
width="80%" width="80%"
> >
<div style="height: 70vh;width:100%;overflow-y: scroll;overflow-x: hidden;" v-loading="loading"> <div style="height: 70vh;width:100%;overflow-y: scroll;overflow-x: hidden;" v-loading="loading">

@ -37,7 +37,7 @@
:value="dict.value" :value="dict.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="12"> <el-col :span="12">
@ -73,7 +73,7 @@
> >
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-button <el-button
v-if="editAble" v-if="editAble"
type="primary" type="primary"
@ -134,7 +134,7 @@
> >
<el-link type="warning" slot="reference">移除</el-link> <el-link type="warning" slot="reference">移除</el-link>
</el-popconfirm> </el-popconfirm>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -294,7 +294,7 @@ export default {
startDate: null, startDate: null,
endDate: null, endDate: null,
}, },
title: "其他任务", title: "任务",
updateApi: updateInfo, updateApi: updateInfo,
addApi: addInfo, addApi: addInfo,
}, },

Loading…
Cancel
Save