智能配图代码编写,新增删除修改查询功能等
This commit is contained in:
parent
5063540d75
commit
6b93fe145e
@ -0,0 +1,69 @@
|
||||
package com.yfd.platform.common.utils;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Base64 转 MultipartFile 的适配器实现
|
||||
* 用于将前端传来的 Base64 字符串伪装成标准文件对象
|
||||
*/
|
||||
public class Base64MultipartFile implements MultipartFile {
|
||||
|
||||
private final byte[] content;
|
||||
private final String name;
|
||||
private final String originalFilename;
|
||||
private final String contentType;
|
||||
|
||||
public Base64MultipartFile(byte[] content, String name, String originalFilename, String contentType) {
|
||||
this.content = content;
|
||||
this.name = name;
|
||||
this.originalFilename = originalFilename;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return content == null || content.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return content != null ? content.length : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
try (FileOutputStream fos = new FileOutputStream(dest)) {
|
||||
fos.write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,6 +84,7 @@ public class SecurityConfig {
|
||||
// .requestMatchers("/mapLegend/**").permitAll()
|
||||
// .requestMatchers("/base/msalongb/**").permitAll()
|
||||
// .requestMatchers("/base/msalongdetb/**").permitAll()
|
||||
// .requestMatchers("/smartImage/**").permitAll()
|
||||
.requestMatchers("/sms/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/").permitAll()
|
||||
.requestMatchers(HttpMethod.GET,
|
||||
|
||||
@ -202,6 +202,14 @@ public class SwaggerConfig {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi groupEnvSmartImageApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("3.11 智能配图-首页(si)")
|
||||
.packagesToScan("com.yfd.platform.qgc_env.si.controller")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
package com.yfd.platform.qgc_env.si.controller;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.common.utils.UserNameFillHelper;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.qgc_env.si.entity.vo.SmartImageVo;
|
||||
|
||||
import com.yfd.platform.qgc_env.si.service.ISmartImageService;
|
||||
import com.yfd.platform.utils.DataSourceRequestUtil;
|
||||
import com.yfd.platform.utils.DictCodeToNameConverter;
|
||||
import com.yfd.platform.utils.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 智能配图控制器
|
||||
*
|
||||
* @author migration
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/smartImage")
|
||||
@Tag(name = "智能配图控制器")
|
||||
public class SmartImageController {
|
||||
|
||||
@Resource
|
||||
private ISmartImageService smartImageService;
|
||||
|
||||
@Resource
|
||||
private UserNameFillHelper userNameFillHelper;
|
||||
|
||||
@Resource
|
||||
private DictCodeToNameConverter dictCodeToNameConverter;
|
||||
/**
|
||||
* 条件过滤数据列表
|
||||
*/
|
||||
@Operation(summary = "条件过滤数据列表")
|
||||
@PostMapping("/GetKendoList")
|
||||
public ResponseResult getKendoList( @RequestBody DataSourceRequest request) {
|
||||
Page<SmartImageVo> pushConfigPage = DataSourceRequestUtil.executeQuery(request, SmartImageVo.class, smartImageService);
|
||||
userNameFillHelper.fillUserNames(pushConfigPage.getRecords());
|
||||
return ResponseResult.successData(pushConfigPage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新增或修改
|
||||
*/
|
||||
@Operation(summary = "新增或修改")
|
||||
@PostMapping("/save")
|
||||
public ResponseResult save(@RequestBody SmartImageVo smartImage) {
|
||||
if (smartImage == null) {
|
||||
return ResponseResult.error("智能配图信息不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(smartImage.getPeituName())) {
|
||||
throw new BizException("配图名称(peituName)不能为空.");
|
||||
}
|
||||
if (StrUtil.isBlank(smartImage.getConfig())) {
|
||||
throw new BizException("配图配置(config)不能为空.");
|
||||
}
|
||||
|
||||
// 新增时设置创建信息
|
||||
if (StrUtil.isBlank(smartImage.getId())) {
|
||||
smartImage.setCreatedAt(new Date());
|
||||
smartImage.setRecordUser(SecurityUtils.getUserId());
|
||||
smartImage.setIsDeleted(0);
|
||||
}
|
||||
|
||||
// 设置操作人、操作时间、更新信息
|
||||
smartImage.setOperator(SecurityUtils.getUserId());
|
||||
smartImage.setOperateTime(new Date());
|
||||
smartImage.setModifyUser(SecurityUtils.getUserId());
|
||||
smartImage.setModifyTime(new Date());
|
||||
|
||||
|
||||
smartImageService.saveWithAttachment(smartImage);
|
||||
return ResponseResult.successData(smartImage.getId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
@Operation(summary = "删除")
|
||||
@PostMapping("/delete")
|
||||
public ResponseResult delete(@RequestBody List<String> ids) {
|
||||
smartImageService.deleteByIds(ids);
|
||||
return ResponseResult.success("删除成功.");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.yfd.platform.qgc_env.si.entity.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.yfd.platform.annotation.UserIdField;
|
||||
import com.yfd.platform.annotation.UserNameField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 智能配图表
|
||||
*
|
||||
* @author migration
|
||||
*/
|
||||
|
||||
@Data
|
||||
@TableName("SD_SMART_IMAGE")
|
||||
@Schema(description = "智能配图表")
|
||||
public class SmartImageVo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
private String id;
|
||||
|
||||
/** 配图名称 */
|
||||
@TableField("PEITU_NAME")
|
||||
private String peituName;
|
||||
|
||||
/** 操作人,关联SYS_USER.ID */
|
||||
@TableField("OPERATOR")
|
||||
@UserIdField
|
||||
private String operator;
|
||||
|
||||
/** 操作人名称(非数据库字段) */
|
||||
@TableField(exist = false)
|
||||
@UserNameField
|
||||
private String operatorName;
|
||||
|
||||
/** 配图操作时间 */
|
||||
@TableField("OPERATE_TIME")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date operateTime;
|
||||
|
||||
/** 配图配置,存储JSON格式长文本 */
|
||||
@TableField("CONFIG")
|
||||
private String config;
|
||||
|
||||
/** 图片在服务器存储的KEY */
|
||||
@TableField("IMAGE_KEY")
|
||||
private String imageKey;
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField("CREATED_AT")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date createdAt;
|
||||
|
||||
/** 创建人,关联SYS_USER.ID */
|
||||
@TableField("RECORD_USER")
|
||||
private String recordUser;
|
||||
|
||||
/** 创建人名称(非数据库字段) */
|
||||
@TableField(exist = false)
|
||||
private String recordUserName;
|
||||
|
||||
/** 更新人,关联SYS_USER.ID */
|
||||
@TableField("MODIFY_USER")
|
||||
private String modifyUser;
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField("MODIFY_TIME")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date modifyTime;
|
||||
|
||||
/** 是否已删除:0=未删除,1=已删除 */
|
||||
@TableField("IS_DELETED")
|
||||
private Integer isDeleted;
|
||||
|
||||
/** 删除人,关联SYS_USER.ID */
|
||||
@TableField("DELETE_USER")
|
||||
private String deleteUser;
|
||||
|
||||
/** 删除时间 */
|
||||
@TableField("DELETE_TIME")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date deleteTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String bsfile;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String fileName;
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.yfd.platform.qgc_env.si.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yfd.platform.qgc_env.si.entity.vo.SmartImageVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SmartImageMapper extends BaseMapper<SmartImageVo> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.yfd.platform.qgc_env.si.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.qgc_env.si.entity.vo.SmartImageVo;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 智能配图表 Service 接口
|
||||
*
|
||||
* @author migration
|
||||
*/
|
||||
public interface ISmartImageService extends IService<SmartImageVo> {
|
||||
|
||||
/**
|
||||
* 条件过滤数据列表(Kendo 数据源)
|
||||
*
|
||||
* @param dataSourceRequest 数据源请求
|
||||
* @return 数据源结果
|
||||
*/
|
||||
DataSourceResult<SmartImageVo> getKendoList(DataSourceRequest dataSourceRequest);
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids 主键ID列表
|
||||
*/
|
||||
void deleteByIds(List<String> ids);
|
||||
|
||||
/**
|
||||
* 保存或更新(含附件上传)
|
||||
*
|
||||
* @param smartImage 智能配图实体
|
||||
*/
|
||||
void saveWithAttachment(SmartImageVo smartImage);
|
||||
}
|
||||
@ -0,0 +1,207 @@
|
||||
package com.yfd.platform.qgc_env.si.service.impl;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.yfd.platform.common.DataSourceLoadOptionsBase;
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.common.utils.Base64MultipartFile;
|
||||
import com.yfd.platform.qgc_data.service.AttachmentUploadService;
|
||||
import com.yfd.platform.qgc_env.si.entity.vo.SmartImageVo;
|
||||
import com.yfd.platform.qgc_env.si.mapper.SmartImageMapper;
|
||||
import com.yfd.platform.qgc_env.si.service.ISmartImageService;
|
||||
import com.yfd.platform.utils.DataSourceRequestUtil;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 智能配图表 Service 实现类
|
||||
*
|
||||
* @author migration
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class SmartImageServiceImpl extends ServiceImpl<SmartImageMapper, SmartImageVo> implements ISmartImageService {
|
||||
|
||||
@Resource
|
||||
private AttachmentUploadService attachmentUploadService;
|
||||
@Override
|
||||
public DataSourceResult<SmartImageVo> getKendoList(DataSourceRequest dataSourceRequest) {
|
||||
// 1. 构建查询条件
|
||||
QueryWrapper<SmartImageVo> wrapper = DataSourceRequestUtil.buildQueryWrapper(
|
||||
dataSourceRequest, SmartImageVo.class);
|
||||
|
||||
// 默认按创建时间倒序
|
||||
wrapper.orderByDesc("CREATED_AT");
|
||||
|
||||
// 2. 分页参数处理
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
Page<SmartImageVo> page = loadOptions == null ? null
|
||||
: (Page<SmartImageVo>) QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake());
|
||||
|
||||
// 3. 执行查询
|
||||
Page<SmartImageVo> resultPage;
|
||||
if (page != null) {
|
||||
resultPage = this.page(page, wrapper);
|
||||
} else {
|
||||
List<SmartImageVo> list = this.list(wrapper);
|
||||
resultPage = new Page<>();
|
||||
resultPage.setRecords(list);
|
||||
resultPage.setTotal(list.size());
|
||||
}
|
||||
|
||||
// 4. 构建结果
|
||||
DataSourceResult<SmartImageVo> dataSourceResult = new DataSourceResult<>();
|
||||
dataSourceResult.setData(resultPage.getRecords());
|
||||
dataSourceResult.setTotal(resultPage.getTotal());
|
||||
return dataSourceResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveWithAttachment(SmartImageVo smartImage) {
|
||||
// 3. 将 Base64 转换为 MultipartFile
|
||||
MultipartFile file = null;
|
||||
if (StrUtil.isNotBlank(smartImage.getBsfile())) {
|
||||
try {
|
||||
file = convertBase64ToMultipartFile(smartImage.getBsfile(), smartImage.getFileName());
|
||||
} catch (Exception e) {
|
||||
log.error("Base64 文件转换失败", e);
|
||||
throw new BizException("文件解析失败,请检查 Base64 格式是否正确");
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有附件,上传并获取 attachmentId
|
||||
if (file != null || !file.isEmpty()) {
|
||||
try {
|
||||
List<MultipartFile> files = new ArrayList<>();
|
||||
files.add(file);
|
||||
List<String> attachmentIds = attachmentUploadService.uploadMultipartFiles(files);
|
||||
if (attachmentIds != null && !attachmentIds.isEmpty()) {
|
||||
//如果是一条
|
||||
smartImage.setImageKey(attachmentIds.get(0));
|
||||
//如果是多条
|
||||
//smartImage.setImageKey(String.valueOf(attachmentIds));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("附件上传失败", e);
|
||||
}
|
||||
}
|
||||
this.saveOrUpdate(smartImage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将 Base64 字符串转换为 MultipartFile
|
||||
*
|
||||
* @param base64 Base64 字符串(可带 data:image/png;base64, 前缀)
|
||||
* @param fileName 文件名(可空)
|
||||
* @return MultipartFile 对象
|
||||
*/
|
||||
private MultipartFile convertBase64ToMultipartFile(String base64, String fileName) {
|
||||
try {
|
||||
// 1. 去除 Base64 前缀(如果有)
|
||||
String[] parts = base64.split(",");
|
||||
String base64Data = parts.length > 1 ? parts[1] : parts[0];
|
||||
|
||||
// 2. 解码为字节数组
|
||||
byte[] fileBytes = Base64.getDecoder().decode(base64Data);
|
||||
|
||||
// 3. 处理文件名
|
||||
String originalFilename = fileName;
|
||||
if (StrUtil.isBlank(originalFilename)) {
|
||||
// 自动检测文件扩展名
|
||||
String ext = detectExtension(base64);
|
||||
originalFilename = System.currentTimeMillis() + (ext != null ? "." + ext : ".bin");
|
||||
}
|
||||
|
||||
// 4. 检测 MIME 类型
|
||||
String contentType = detectContentType(base64);
|
||||
if (contentType == null) {
|
||||
contentType = "application/octet-stream";
|
||||
}
|
||||
|
||||
// 5. 返回自定义 MultipartFile 实现
|
||||
return new Base64MultipartFile(
|
||||
fileBytes,
|
||||
"file", // 表单字段名
|
||||
originalFilename,
|
||||
contentType
|
||||
);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("Base64 解码失败,可能数据不合法", e);
|
||||
throw new BizException("Base64 编码数据格式错误,请检查");
|
||||
} catch (Exception e) {
|
||||
log.error("转换 MultipartFile 失败", e);
|
||||
throw new BizException("文件转换失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Base64 前缀检测文件扩展名
|
||||
*/
|
||||
private String detectExtension(String base64) {
|
||||
if (base64.startsWith("data:image/jpeg") || base64.startsWith("data:image/jpg")) {
|
||||
return "jpg";
|
||||
} else if (base64.startsWith("data:image/png")) {
|
||||
return "png";
|
||||
} else if (base64.startsWith("data:image/gif")) {
|
||||
return "gif";
|
||||
} else if (base64.startsWith("data:image/bmp")) {
|
||||
return "bmp";
|
||||
} else if (base64.startsWith("data:application/pdf")) {
|
||||
return "pdf";
|
||||
} else if (base64.startsWith("data:application/msword")) {
|
||||
return "doc";
|
||||
} else if (base64.startsWith("data:application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
|
||||
return "docx";
|
||||
}
|
||||
return null; // 默认无扩展名
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Base64 前缀检测 MIME 类型
|
||||
*/
|
||||
private String detectContentType(String base64) {
|
||||
if (base64.startsWith("data:image/jpeg") || base64.startsWith("data:image/jpg")) {
|
||||
return "image/jpeg";
|
||||
} else if (base64.startsWith("data:image/png")) {
|
||||
return "image/png";
|
||||
} else if (base64.startsWith("data:image/gif")) {
|
||||
return "image/gif";
|
||||
} else if (base64.startsWith("data:image/bmp")) {
|
||||
return "image/bmp";
|
||||
} else if (base64.startsWith("data:application/pdf")) {
|
||||
return "application/pdf";
|
||||
} else if (base64.startsWith("data:application/msword")) {
|
||||
return "application/msword";
|
||||
} else if (base64.startsWith("data:application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
|
||||
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByIds(List<String> ids) {
|
||||
List<SmartImageVo> list = this.listByIds(ids);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
for (SmartImageVo entity : list) {
|
||||
attachmentUploadService.deleteFile(entity.getImageKey());
|
||||
}
|
||||
for (String id : ids) {
|
||||
this.removeById(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user