Merge remote-tracking branch 'origin/main'

This commit is contained in:
haozq 2025-09-11 13:56:30 +08:00
commit 4d35e32ed5
25 changed files with 1345 additions and 266 deletions

View File

@ -14,7 +14,7 @@ PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
<!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="logImpl" value="SLF4J" />
<!-- 使用驼峰命名法转换字段 -->
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>

View File

@ -0,0 +1,144 @@
package com.bonus.business.controller;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.domain.WebFileDto;
import com.bonus.business.service.ITbPromotionMaterialService;
import com.bonus.common.utils.FastJsonHelper;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.bonus.common.annotation.Log;
import com.bonus.common.core.controller.BaseController;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.enums.BusinessType;
import com.bonus.common.utils.poi.ExcelUtil;
import com.bonus.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
/**
* 宣传物料信息Controller
*
* @author ruoyi
* @date 2025-09-10
*/
@RestController
@RequestMapping("/system/material")
public class MaterialController extends BaseController {
@Resource
private ITbPromotionMaterialService service;
/**
* 查询宣传物料信息列表
*/
// @PreAuthorize("@ss.hasPermi('system:material:list')")
@GetMapping("/list")
public TableDataInfo list(TbPromotionMaterial tbPromotionMaterial) {
try {
startPage();
List<TbPromotionMaterial> list = service.selectTbPromotionMaterialList(tbPromotionMaterial);
return getDataTable(list);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return getDataTable(new ArrayList<>());
}
}
/**
* 获取宣传物料信息详细信息
*/
// @PreAuthorize("@ss.hasPermi('system:material:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
try {
return success(service.selectTbPromotionMaterialById(id));
} catch (Exception e) {
logger.error(e.getMessage(), e);
return error("系统异常,请联系管理员");
}
}
/**
* 新增宣传物料信息
*/
// @PreAuthorize("@ss.hasPermi('system:material:add')")
@Log(title = "新增宣传物料信息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestParam(value = "files") MultipartFile[] files,@RequestParam(value = "fileMsg") String fileMsg, @RequestParam(value = "params")String params) {
try {
List<WebFileDto> listFile = FastJsonHelper.jsonArrStrToBeanList(fileMsg, WebFileDto.class);
// 验证对应关系
if (listFile.size() != files.length || files.length != 2) {
return error("文件信息与文件数量不匹配或文件缺失");
}
//先将数据对应关系处理
for (int i = 0; i < listFile.size(); i++) {
listFile.get(i).setFile(files[i]);
}
TbPromotionMaterial tbPromotionMaterial = FastJsonHelper.jsonStrToBean(params, TbPromotionMaterial.class);
return toAjax(service.insertTbPromotionMaterial(tbPromotionMaterial,listFile));
} catch (Exception e) {
logger.error(e.getMessage(), e);
return error("系统异常,请联系管理员");
}
}
/**
* 修改宣传物料信息
*/
// @PreAuthorize("@ss.hasPermi('system:material:edit')")
@Log(title = "修改宣传物料信息", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
public AjaxResult edit(@RequestParam(value = "files") MultipartFile[] files,@RequestParam(value = "fileMsg") String fileMsg, @RequestParam(value = "params")String params) {
try {
List<WebFileDto> listFile = FastJsonHelper.jsonArrStrToBeanList(fileMsg, WebFileDto.class);
// 验证对应关系
if (listFile.size() != files.length || files.length != 2) {
return error("文件信息与文件数量不匹配或文件缺失");
}
//先将数据对应关系处理
for (int i = 0; i < listFile.size(); i++) {
listFile.get(i).setFile(files[i]);
}
TbPromotionMaterial tbPromotionMaterial = FastJsonHelper.jsonStrToBean(params, TbPromotionMaterial.class);
return toAjax(service.updateTbPromotionMaterial(tbPromotionMaterial,listFile));
} catch (Exception e) {
logger.error(e.getMessage(), e);
return error("系统异常,请联系管理员");
}
}
/**
* 删除宣传物料信息
*/
// @PreAuthorize("@ss.hasPermi('system:material:remove')")
@Log(title = "宣传物料信息", businessType = BusinessType.DELETE)
@PostMapping("/{id}")
public AjaxResult remove(@PathVariable Long id) {
try {
return toAjax(service.deleteTbPromotionMaterialById(id));
} catch (Exception e) {
logger.error(e.getMessage(), e);
return error("系统异常,请联系管理员");
}
}
/**
* 导出宣传物料信息列表
*/
// @PreAuthorize("@ss.hasPermi('system:material:export')")
@Log(title = "导出宣传物料信息列表", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, TbPromotionMaterial tbPromotionMaterial) {
List<TbPromotionMaterial> list = service.selectTbPromotionMaterialList(tbPromotionMaterial);
ExcelUtil<TbPromotionMaterial> util = new ExcelUtil<TbPromotionMaterial>(TbPromotionMaterial.class);
util.exportExcel(response, list, "宣传物料信息数据");
}
}

View File

@ -0,0 +1,33 @@
package com.bonus.business.controller;
import com.bonus.business.domain.TbProduct;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.service.MaterialScreenService;
import com.bonus.business.service.ProductScreenService;
import com.bonus.common.core.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 产品大屏
*/
@RestController
@RequestMapping("/screen/material/")
public class MaterialScreenController {
@Autowired
private MaterialScreenService service;
/**
* 展示中心查询
* @param o
* @return
*/
@PostMapping("/getMaterialList")
public AjaxResult getMaterialList(TbPromotionMaterial o ){
return service.getMaterialList(o) ;
}
}

View File

@ -0,0 +1,40 @@
package com.bonus.business.controller;
import com.bonus.business.domain.MapBeanPo;
import com.bonus.business.service.SelectService;
import com.bonus.common.core.controller.BaseController;
import com.bonus.common.core.domain.AjaxResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @Description: 公用下拉框控制器
* @Author: fly
* @Date: 2025/9/10
*/
@RestController
@RequestMapping("/select")
public class SelectController extends BaseController {
@Resource
private SelectService service;
/**
* 查询产品列表
* @param po
* @return
*/
@PostMapping("/selectProduct")
public AjaxResult selectProduct(MapBeanPo po){
try{
return service.selectProduct(po);
}catch (Exception e){
logger.error(e.toString(),e);
}
return AjaxResult.error("查询产品下拉框失败");
}
}

View File

@ -0,0 +1,25 @@
package com.bonus.business.domain;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class MapBeanPo {
private Integer id;
private String name;
private Integer subComId;
private Integer proId;
private Integer subId;
public MapBeanPo(Integer id, String name) {
this.id = id;
this.name = name;
}
}

View File

@ -0,0 +1,25 @@
package com.bonus.business.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MapBeanVo {
private String key;
private String value;
private Integer id;
private String name;
public MapBeanVo(String key, String value){
this.value = value;
this.key = key;
}
}

View File

@ -1,16 +1,23 @@
package com.bonus.business.domain;
import com.bonus.common.core.domain.BaseEntity;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.bonus.common.annotation.Excel;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 宣传物料信息对象 tb_promotion_material
*
* @author ruoyi
* @date 2025-09-10
*/
@Data
public class TbPromotionMaterial extends BaseEntity
{
private static final long serialVersionUID = 1L;
@ -50,139 +57,56 @@ public class TbPromotionMaterial extends BaseEntity
@Excel(name = "修改人")
private Long updateUser;
/** 删除状态 */
private String delFlag;
/** 产品名称(通过,拼接) */
@Excel(name = "产品名称(通过,拼接)")
private String productName;
public void setId(Long id)
{
private String productId;
/** 删除状态 */
private String delFlag;
/** 文件类型 0 视频 1文档 */
private String fileType;
/** 文件地址 */
private String filePath;
/** 文件 */
private List<TbPromotionMaterialFiles> files;
// 构造函数
public TbPromotionMaterial() {}
public TbPromotionMaterial(Long id, String productName, String productId) {
this.id = id;
}
public Long getId()
{
return id;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setTypeId(Long typeId)
{
this.typeId = typeId;
}
public Long getTypeId()
{
return typeId;
}
public void setTypeName(String typeName)
{
this.typeName = typeName;
}
public String getTypeName()
{
return typeName;
}
public void setImage(String image)
{
this.image = image;
}
public String getImage()
{
return image;
}
public void setVersion(String version)
{
this.version = version;
}
public String getVersion()
{
return version;
}
public void setDescription(String description)
{
this.description = description;
}
public String getDescription()
{
return description;
}
public void setCreateUser(Long createUser)
{
this.createUser = createUser;
}
public Long getCreateUser()
{
return createUser;
}
public void setUpdateUser(Long updateUser)
{
this.updateUser = updateUser;
}
public Long getUpdateUser()
{
return updateUser;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
public void setProductName(String productName)
{
this.productName = productName;
this.productId = productId;
}
public String getProductName()
{
return productName;
/**
* 将单个 TbPromotionMaterial 拆分为多个对象
*/
public List<TbPromotionMaterial> split(TbPromotionMaterial source) {
if (source == null || source.getProductName() == null || source.getProductId() == null) {
return Collections.emptyList();
}
String[] names = source.getProductName().split(",");
String[] ids = source.getProductId().split(",");
// 检查长度是否一致
if (names.length != ids.length) {
throw new IllegalArgumentException("productName 和 productId 的数量不匹配");
}
return IntStream.range(0, names.length)
.mapToObj(i -> {
TbPromotionMaterial item = new TbPromotionMaterial();
item.setId(source.getId());
item.setProductName(names[i].trim()); // 去除空格
item.setProductId(ids[i].trim());
return item;
})
.collect(Collectors.toList());
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("name", getName())
.append("typeId", getTypeId())
.append("typeName", getTypeName())
.append("image", getImage())
.append("version", getVersion())
.append("description", getDescription())
.append("createUser", getCreateUser())
.append("createTime", getCreateTime())
.append("updateUser", getUpdateUser())
.append("updateTime", getUpdateTime())
.append("delFlag", getDelFlag())
.append("productName", getProductName())
.toString();
}
}

View File

@ -1,6 +1,8 @@
package com.bonus.business.domain;
import com.bonus.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.bonus.common.annotation.Excel;
@ -11,6 +13,8 @@ import com.bonus.common.annotation.Excel;
* @author ruoyi
* @date 2025-09-10
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class TbPromotionMaterialFiles extends BaseEntity
{
private static final long serialVersionUID = 1L;
@ -35,152 +39,26 @@ public class TbPromotionMaterialFiles extends BaseEntity
private String fileType;
/** 文件前缀 */
@Excel(name = "文件前缀")
private String folderPath;
@Excel(name = "桶名称")
private String bucketName;
/** 原文件名称 */
@Excel(name = "原文件名称")
private String originalName;
/** 文件大小 */
@Excel(name = "文件大小")
private String fileSize;
/** 文件名称 */
@Excel(name = "文件名称")
private String fileName;
/** 访问路径=前缀+文件名 */
@Excel(name = "访问路径=前缀+文件名")
@Excel(name = "访问路径")
private String filePath;
/** 文件大小 */
@Excel(name = "文件大小")
private String fileSize;
/** 删除状态 */
private String delFlag;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setMaterialId(Long materialId)
{
this.materialId = materialId;
}
public Long getMaterialId()
{
return materialId;
}
public void setTypeId(Long typeId)
{
this.typeId = typeId;
}
public Long getTypeId()
{
return typeId;
}
public void setTypeName(String typeName)
{
this.typeName = typeName;
}
public String getTypeName()
{
return typeName;
}
public void setFileType(String fileType)
{
this.fileType = fileType;
}
public String getFileType()
{
return fileType;
}
public void setFolderPath(String folderPath)
{
this.folderPath = folderPath;
}
public String getFolderPath()
{
return folderPath;
}
public void setOriginalName(String originalName)
{
this.originalName = originalName;
}
public String getOriginalName()
{
return originalName;
}
public void setFileSize(String fileSize)
{
this.fileSize = fileSize;
}
public String getFileSize()
{
return fileSize;
}
public void setFileName(String fileName)
{
this.fileName = fileName;
}
public String getFileName()
{
return fileName;
}
public void setFilePath(String filePath)
{
this.filePath = filePath;
}
public String getFilePath()
{
return filePath;
}
public void setDelFlag(String delFlag)
{
this.delFlag = delFlag;
}
public String getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("materialId", getMaterialId())
.append("typeId", getTypeId())
.append("typeName", getTypeName())
.append("fileType", getFileType())
.append("folderPath", getFolderPath())
.append("originalName", getOriginalName())
.append("fileSize", getFileSize())
.append("fileName", getFileName())
.append("filePath", getFilePath())
.append("delFlag", getDelFlag())
.toString();
}
}

View File

@ -0,0 +1,27 @@
package com.bonus.business.domain;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
/**
* @author: fly
* @date: 2025/08/14
*/
@Data
public class WebFileDto {
/**
* 文件类型名称
*/
private String name;
/**
* 文件类型下级编号
*/
private String type;
private MultipartFile file;
private String base64File;
}

View File

@ -0,0 +1,14 @@
package com.bonus.business.mapper;
import com.bonus.business.domain.TbProduct;
import com.bonus.business.domain.TbPromotionMaterial;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MaterialScreenMapper {
List<TbPromotionMaterial> getMaterialList(TbPromotionMaterial product);
}

View File

@ -0,0 +1,21 @@
package com.bonus.business.mapper;
import com.bonus.business.domain.MapBeanPo;
import com.bonus.business.domain.MapBeanVo;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.common.core.domain.AjaxResult;
import java.util.List;
/**
* 宣传物料信息Mapper接口
*
* @author ruoyi
* @date 2025-09-10
*/
public interface SelectMapper {
List<MapBeanVo> selectProduct(MapBeanPo po);
}

View File

@ -0,0 +1,93 @@
package com.bonus.business.mapper;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.domain.TbPromotionMaterialFiles;
import java.util.List;
/**
* 宣传物料信息Mapper接口
*
* @author ruoyi
* @date 2025-09-10
*/
public interface TbPromotionMaterialMapper {
/**
* 查询宣传物料信息
*
* @param id 宣传物料信息主键
* @return 宣传物料信息
*/
public TbPromotionMaterial selectTbPromotionMaterialById(Long id);
/**
* 查询宣传物料信息列表
*
* @param tbPromotionMaterial 宣传物料信息
* @return 宣传物料信息集合
*/
public List<TbPromotionMaterial> selectTbPromotionMaterialList(TbPromotionMaterial tbPromotionMaterial);
/**
* 新增宣传物料信息
*
* @param tbPromotionMaterial 宣传物料信息
* @return 结果
*/
public int insertTbPromotionMaterial(TbPromotionMaterial tbPromotionMaterial);
/**
* 修改宣传物料信息
*
* @param tbPromotionMaterial 宣传物料信息
* @return 结果
*/
public int updateTbPromotionMaterial(TbPromotionMaterial tbPromotionMaterial);
/**
* 删除宣传物料信息
*
* @param id 宣传物料信息主键
* @return 结果
*/
public int deleteTbPromotionMaterialById(Long id);
/**
* 批量新增文件
*
* @param materialFile 宣传物料信息
* @return 结果
*/
int insertMaterialFile(TbPromotionMaterialFiles materialFile);
/**
* 根据id查询文件
* @param o 数据id
* @return 文件列表
*/
List<TbPromotionMaterialFiles> getFileMaterialId(TbPromotionMaterial o);
/**
* 批量新增物料与产品的关联
*
* @param split 宣传物料信息
* @return 影响行数
*/
int insertMaterialProductRelevance(List<TbPromotionMaterial> split);
/**
* 删除物料与产品的关联
*
* @param id 宣传物料信息id
* @return 影响行数
*/
int deleteMaterialProductRelevance(Long id);
/**
* 修改物料封面
*
* @param bean 宣传物料信息
*/
void updateCover(TbPromotionMaterial bean);
}

View File

@ -0,0 +1,56 @@
package com.bonus.business.service;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.domain.WebFileDto;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 宣传物料信息Service接口
*
* @author ruoyi
* @date 2025-09-10
*/
public interface ITbPromotionMaterialService
{
/**
* 查询宣传物料信息
*
* @param id 宣传物料信息主键
* @return 宣传物料信息
*/
public TbPromotionMaterial selectTbPromotionMaterialById(Long id);
/**
* 查询宣传物料信息列表
*
* @param tbPromotionMaterial 宣传物料信息
* @return 宣传物料信息集合
*/
public List<TbPromotionMaterial> selectTbPromotionMaterialList(TbPromotionMaterial tbPromotionMaterial);
/**
* 新增宣传物料信息
*
* @param tbPromotionMaterial 宣传物料信息
* @return 结果
*/
public int insertTbPromotionMaterial(TbPromotionMaterial tbPromotionMaterial, List<WebFileDto> listFiles);
/**
* 修改宣传物料信息
*
* @param tbPromotionMaterial 宣传物料信息
* @return 结果
*/
public int updateTbPromotionMaterial(TbPromotionMaterial tbPromotionMaterial,List<WebFileDto> listFiles);
/**
* 删除宣传物料信息信息
*
* @param id 宣传物料信息主键
* @return 结果
*/
public int deleteTbPromotionMaterialById(Long id);
}

View File

@ -0,0 +1,15 @@
package com.bonus.business.service;
import com.bonus.business.domain.TbProduct;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.common.core.domain.AjaxResult;
public interface MaterialScreenService {
/**
* 查询展示中心
* @param o
* @return
*/
AjaxResult getMaterialList(TbPromotionMaterial o);
}

View File

@ -0,0 +1,19 @@
package com.bonus.business.service;
import com.bonus.business.domain.MapBeanPo;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.common.core.domain.AjaxResult;
import java.util.List;
/**
* 宣传物料信息Service接口
*
* @author ruoyi
* @date 2025-09-10
*/
public interface SelectService
{
AjaxResult selectProduct(MapBeanPo po);
}

View File

@ -0,0 +1,52 @@
package com.bonus.business.service.impl;
import com.bonus.business.domain.ProductCaseImage;
import com.bonus.business.domain.TbProduct;
import com.bonus.business.domain.TbProductCase;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.mapper.MaterialScreenMapper;
import com.bonus.business.mapper.ProductMapper;
import com.bonus.business.mapper.ProductScreenMapper;
import com.bonus.business.service.MaterialScreenService;
import com.bonus.business.service.ProductScreenService;
import com.bonus.common.config.MinioConfig;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class MaterialScreenServiceImpl implements MaterialScreenService {
@Autowired
private MaterialScreenMapper mapper;
@Resource
private MinioConfig minioConfig;
@Override
public AjaxResult getMaterialList(TbPromotionMaterial o) {
try{
List<TbPromotionMaterial> list = mapper.getMaterialList(o);
if(StringUtils.isNotEmpty(list)){
list.forEach(vo->{
vo.setImage(minioConfig.getUrl()+"/"+minioConfig.getBucketName()+vo.getImage());
vo.setFilePath(minioConfig.getUrl()+"/"+minioConfig.getBucketName()+vo.getFilePath());
});
}
return AjaxResult.success(list);
}catch (Exception e){
log.error(e.toString());
}
return AjaxResult.success(new ArrayList<TbPromotionMaterial>());
}
}

View File

@ -0,0 +1,34 @@
package com.bonus.business.service.impl;
import com.bonus.business.domain.MapBeanPo;
import com.bonus.business.domain.MapBeanVo;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.mapper.SelectMapper;
import com.bonus.business.mapper.TbPromotionMaterialMapper;
import com.bonus.business.service.ITbPromotionMaterialService;
import com.bonus.business.service.SelectService;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.utils.DateUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* 宣传物料信息Service业务层处理
*
* @author ruoyi
* @date 2025-09-10
*/
@Service
public class SelectServiceImpl implements SelectService
{
@Resource
private SelectMapper mapper;
@Override
public AjaxResult selectProduct(MapBeanPo po) {
List<MapBeanVo> list =mapper.selectProduct(po);
return AjaxResult.success(list);
}
}

View File

@ -0,0 +1,203 @@
package com.bonus.business.service.impl;
import java.util.List;
import java.util.Objects;
import com.bonus.business.domain.ProductCaseImage;
import com.bonus.business.domain.TbPromotionMaterial;
import com.bonus.business.domain.TbPromotionMaterialFiles;
import com.bonus.business.domain.WebFileDto;
import com.bonus.business.mapper.TbPromotionMaterialMapper;
import com.bonus.business.service.ITbPromotionMaterialService;
import com.bonus.common.config.MinioConfig;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.utils.DateUtils;
import com.bonus.common.utils.SecurityUtils;
import com.bonus.common.utils.StringUtils;
import com.bonus.common.utils.file.FileTypeUtils;
import com.bonus.file.config.SysFile;
import com.bonus.file.service.FileUploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
/**
* 宣传物料信息Service业务层处理
*
* @author ruoyi
* @date 2025-09-10
*/
@Service
public class TbPromotionMaterialServiceImpl implements ITbPromotionMaterialService
{
@Resource
private TbPromotionMaterialMapper mapper;
@Autowired
private MinioConfig minioConfig;
@Resource
private FileUploadService fileUploadService;
public String day= DateUtils.getCurrentYear();
public String month=DateUtils.getCurrentMonth();
public String year=DateUtils.getCurrentYear();
/**
* 查询宣传物料信息列表
*
* @param tbPromotionMaterial 宣传物料信息
* @return 宣传物料信息
*/
@Override
public List<TbPromotionMaterial> selectTbPromotionMaterialList(TbPromotionMaterial tbPromotionMaterial)
{
List<TbPromotionMaterial> tbPromotionMaterials = mapper.selectTbPromotionMaterialList(tbPromotionMaterial);
for (TbPromotionMaterial bean : tbPromotionMaterials) {
//查询附件
bean.setTypeId(2L);
List<TbPromotionMaterialFiles> files = mapper.getFileMaterialId(bean);
//拼接个访问前缀
for (TbPromotionMaterialFiles o: files) {
o.setFilePath(minioConfig.getUrl()+"/"+minioConfig.getBucketName() + o.getFilePath());
}
bean.setFiles(files);
}
return tbPromotionMaterials;
}
/**
* 查询宣传物料信息
*
* @param id 宣传物料信息主键
* @return 宣传物料信息
*/
@Override
public TbPromotionMaterial selectTbPromotionMaterialById(Long id)
{
TbPromotionMaterial bean = mapper.selectTbPromotionMaterialById(id);
//查询所有文件
List<TbPromotionMaterialFiles> files = mapper.getFileMaterialId(bean);
//拼接个访问前缀
for (TbPromotionMaterialFiles o: files) {
o.setFilePath(minioConfig.getUrl()+"/"+minioConfig.getBucketName() + o.getFilePath());
}
bean.setFiles(files);
return bean;
}
/**
* 新增宣传物料信息
*
* @param tbPromotionMaterial 宣传物料信息
* @return 结果
*/
@Override
public int insertTbPromotionMaterial(TbPromotionMaterial tbPromotionMaterial, List<WebFileDto> listFiles)
{
tbPromotionMaterial.setCreateUser(SecurityUtils.getUserId());
tbPromotionMaterial.setCreateTime(DateUtils.getNowDate());
int i = mapper.insertTbPromotionMaterial(tbPromotionMaterial);
if (i > 0) {
//删除以前的关联关系
int x = mapper.deleteMaterialProductRelevance(tbPromotionMaterial.getId());
//将产品与物料关系存到另一张表
List<TbPromotionMaterial> split = tbPromotionMaterial.split(tbPromotionMaterial);
int n = mapper.insertMaterialProductRelevance(split);
//将物料文件上传
int m = uploadFile(listFiles, "tb_promotion_material_files", tbPromotionMaterial.getId());
}
return i;
}
/**
* 修改宣传物料信息
*
* @param tbPromotionMaterial 宣传物料信息
* @return 结果
*/
@Override
public int updateTbPromotionMaterial(TbPromotionMaterial tbPromotionMaterial,List<WebFileDto> listFiles)
{
tbPromotionMaterial.setUpdateUser(SecurityUtils.getUserId());
tbPromotionMaterial.setUpdateTime(DateUtils.getNowDate());
int i = mapper.updateTbPromotionMaterial(tbPromotionMaterial);
if (i > 0) {
//将产品与物料关系存到另一张表
List<TbPromotionMaterial> split = tbPromotionMaterial.split(tbPromotionMaterial);
int n = mapper.insertMaterialProductRelevance(split);
//将物料文件上传
int m = uploadFile(listFiles, "tb_promotion_material_files", tbPromotionMaterial.getId());
}
return i;
}
/**
* 删除宣传物料信息信息
*
* @param id 宣传物料信息主键
* @return 结果
*/
@Override
public int deleteTbPromotionMaterialById(Long id)
{
//删除以前的关联关系
int x = mapper.deleteMaterialProductRelevance(id);
return mapper.deleteTbPromotionMaterialById(id);
}
/**
* 上传附件
* @param
* @return
*/
public int uploadFile(List<WebFileDto> listFiles, String tableId, Long sourceId){
int i = 0;
for (WebFileDto fileData: listFiles) {
MultipartFile file = fileData.getFile();
boolean videoFile = FileTypeUtils.isVideoFile(file);
String uuid = StringUtils.randomUUID();
String originFileName = file.getOriginalFilename();
String suffix=StringUtils.substringAfterLast(originFileName, ".");
//产品 封面
String filePath = "/material" + "/" +
year + "/" + month + "/" + day + "/" + uuid + "." + suffix;
SysFile sysFile = fileUploadService.uploadLargeFile(file, filePath);
TbPromotionMaterialFiles materialFile=new TbPromotionMaterialFiles();
materialFile.setMaterialId(sourceId);
materialFile.setTypeId(Long.valueOf(fileData.getType()));
materialFile.setTypeName(Objects.equals(fileData.getType(), "1") ?"封面":"附件");
materialFile.setFileType(videoFile?"0":"1");
materialFile.setBucketName(minioConfig.getBucketName());
materialFile.setOriginalName(originFileName);
materialFile.setFileName(uuid+"." + suffix);
materialFile.setFilePath(filePath);
// 获取文件大小字节
long sizeInBytes = file.getSize();
// 转换为可读格式如KB/MB
String humanReadableSize = convertToHumanReadable(sizeInBytes);
materialFile.setFileSize(humanReadableSize);
i += mapper.insertMaterialFile(materialFile);
//如果是封面存入主表
if (Objects.equals(fileData.getType(), "1")) {
TbPromotionMaterial bean = new TbPromotionMaterial();
bean.setId(sourceId);
bean.setImage(filePath);
mapper.updateCover(bean);
}
}
return i==listFiles.size()?1:0;
}
// 辅助方法字节转可读格式
private String convertToHumanReadable(long bytes) {
if (bytes < 1024) return bytes + " B";
else if (bytes < 1024 * 1024) return String.format("%.2f KB", bytes / 1024.0);
else return String.format("%.2f MB", bytes / (1024 * 1024.0));
}
}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.business.mapper.MaterialScreenMapper">
<select id="getMaterialList" resultType="com.bonus.business.domain.TbPromotionMaterial">
select
aaa.name,
aaa.image,
aaa.version,
aaa.description,
bbb.file_type,
bbb.file_path
from tb_promotion_material aaa
left join tb_promotion_material_files bbb on aaa.id = bbb.material_id and bbb.type_id = '2' and bbb.del_flag = '0'
where aaa.del_flag = '0'
<if test="name != null and name != ''">
and aaa.name like concat('%',#{name},'%')
</if>
<if test="typeId != null and typeId != ''">
and aaa.type_id = #{typeId}
</if>
<if test="fileType != null and fileType != ''">
and bbb.file_type = #{fileType}
</if>
</select>
</mapper>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.business.mapper.SelectMapper">
<select id="selectProduct" resultType="com.bonus.business.domain.MapBeanVo">
select id,name from tb_product
<where>
del_flag = 0
<if test="name != null and name != ''">
and name like '%${name}%'
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bonus.business.mapper.TbPromotionMaterialMapper">
<resultMap type="TbPromotionMaterial" id="TbPromotionMaterialResult">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="typeId" column="type_id" />
<result property="typeName" column="type_name" />
<result property="image" column="image" />
<result property="version" column="version" />
<result property="description" column="description" />
<result property="createUser" column="create_user" />
<result property="createTime" column="create_time" />
<result property="updateUser" column="update_user" />
<result property="updateTime" column="update_time" />
<result property="delFlag" column="del_flag" />
<result property="productName" column="product_name" />
</resultMap>
<sql id="selectTbPromotionMaterialVo">
select id, name, type_id, type_name, image, version, description, create_user, create_time, update_user, update_time, del_flag, product_name from tb_promotion_material
</sql>
<select id="selectTbPromotionMaterialList" parameterType="TbPromotionMaterial" resultMap="TbPromotionMaterialResult">
<include refid="selectTbPromotionMaterialVo"/>
<where>
<if test="name != null and name != ''"> and name like concat('%', #{name}, '%')</if>
<if test="typeId != null "> and type_id = #{typeId}</if>
<if test="typeName != null and typeName != ''"> and type_name like concat('%', #{typeName}, '%')</if>
</where>
</select>
<select id="selectTbPromotionMaterialById" parameterType="Long" resultMap="TbPromotionMaterialResult">
<include refid="selectTbPromotionMaterialVo"/>
where id = #{id}
</select>
<insert id="insertTbPromotionMaterial" parameterType="TbPromotionMaterial" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into tb_promotion_material
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="name != null">name,</if>
<if test="typeId != null">type_id,</if>
<if test="typeName != null">type_name,</if>
<if test="image != null">image,</if>
<if test="version != null">version,</if>
<if test="description != null">description,</if>
<if test="createUser != null">create_user,</if>
<if test="createTime != null">create_time,</if>
<if test="updateUser != null">update_user,</if>
<if test="updateTime != null">update_time,</if>
<if test="delFlag != null">del_flag,</if>
<if test="productName != null">product_name,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="name != null">#{name},</if>
<if test="typeId != null">#{typeId},</if>
<if test="typeName != null">#{typeName},</if>
<if test="image != null">#{image},</if>
<if test="version != null">#{version},</if>
<if test="description != null">#{description},</if>
<if test="createUser != null">#{createUser},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateUser != null">#{updateUser},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="productName != null">#{productName},</if>
</trim>
</insert>
<update id="updateTbPromotionMaterial" parameterType="TbPromotionMaterial">
update tb_promotion_material
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">name = #{name},</if>
<if test="typeId != null">type_id = #{typeId},</if>
<if test="typeName != null">type_name = #{typeName},</if>
<if test="image != null">image = #{image},</if>
<if test="version != null">version = #{version},</if>
<if test="description != null">description = #{description},</if>
<if test="createUser != null">create_user = #{createUser},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateUser != null">update_user = #{updateUser},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="productName != null">product_name = #{productName},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteTbPromotionMaterialById" parameterType="Long">
update tb_promotion_material set del_flag = 1 where id = #{id}
</delete>
<insert id="insertMaterialFile">
insert into tb_promotion_material_files
(material_id, type_id, type_name, file_type, bucket_name, original_name, file_size, file_name, file_path)
values (#{materialId}, #{typeId}, #{typeName}, #{fileType}, #{bucketName}, #{originalName}, #{fileSize}, #{fileName}, #{filePath})
</insert>
<select id="getFileMaterialId" resultType="com.bonus.business.domain.TbPromotionMaterialFiles">
select * from tb_promotion_material_files where material_id = #{id}
<if test="typeId != null">and type_id = #{typeId}</if>
</select>
<insert id="insertMaterialProductRelevance">
insert into tb_promotion_material_product
(material_id, product_id,product_name)
values
<foreach collection="list" item="item" separator=",">
(#{item.id}, #{item.productId}, #{item.productName})
</foreach>
</insert>
<delete id="deleteMaterialProductRelevance">
delete from tb_promotion_material_product where material_id = #{id}
</delete>
<update id="updateCover">
update tb_promotion_material set image = #{image} where id = #{id}
</update>
</mapper>

View File

@ -139,10 +139,9 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
*
* @param endDate 结束日期
* @param startDate 开始日期
* @param separator 自定义拼接符
* @return 时间差字符串
*/
public static String timeDistance(Date endDate, Date startDate, String separator) {
public static String timeDistance(Date endDate, Date startDate,String separator) {
long duration = endDate.getTime() - startDate.getTime();
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration) % 24;

View File

@ -0,0 +1,186 @@
package com.bonus.common.utils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import java.util.List;
/**
* @author fly
* @version 1
* json与jsonArray所有自定义bean嵌套的相关操作
* 将fast json 简单的封装和添加注释而成
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>fastjson</artifactId>
* <version>1.2.47</version>
* </dependency>
*修改时间:2021-09-30
*/
public class FastJsonHelper {
/**
* JSONArray : 相当于 List<Object>
* JSONObject: 相当于 Map<String,Object>
* public static final Object parse(String text); // 把JSON文本parse为JSONObject或者JSONArray
* public static final JSONObject parseObject(String text); // 把JSON文本parse成JSONObject
* public static final <T> T parseObject(String text, Class<T> clazz); // 把JSON文本parse为JavaBean
* public static final JSONArray parseArray(String text); // 把JSON文本parse成JSONArray
* public static final <T> List< > parseArray(String text, Class<T> clazz); //把JSON文本parse成JavaBean集合
* public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本 || JSONObject转成JSON文本
* public static final String toJSONString(Object object, boolean prettyFormat); // 将JavaBean序列化为带格式的JSON文本
* public static final Object toJSON(Object javaObject); //将JavaBean转换为JSONObject或者JSONArray
*/
/**
* 将任意bean转换成json字符串
* fast json
* @param bean
* @param <T>
* @return
*/
public static <T> String beanToJsonStr(T bean) {
String jsonStr = JSON.toJSONString(bean);
return jsonStr;
}
/**
* 把一个json字符串转换成bean对象
* fast json
* @param str
* @param <T>
* @return
*/
public static <T> T jsonStrToBean(String str, Class<T> clazz) {
T bean = JSON.parseObject(str, clazz);
return bean;
}
/**
* 把一个jsonObj转换成bean对象
* fast json
* @param jsonObj
* @param <T>
* @return
*/
public static <T> T jsonObjToBean(JSONObject jsonObj, Class<T> clazz) {
String s = jsonObj.toJSONString();
T bean = JSON.parseObject(s, clazz);
return bean;
}
/**
* 把一个bean对象转换成jsonObj
* fast json
* @param bean
* @param <T>
* @return
*/
public static <T> JSONObject beanToJsonObj(T bean) {
Object o = JSON.toJSON(bean);
return (JSONObject) o;
}
/**
* 把一个jsonStr转换成jsonObj
* fast json
* @param str
* @return
*/
public static JSONObject jsonStrToJsonObj(String str) {
Object o = JSON.parseObject(str);
return (JSONObject) o;
}
/**
* 把一个jsonObj转换成jsonStr
* fast json
* @param jsonObj
* @return
*/
public static String jsonObjToJsonStr(JSONObject jsonObj) {
String s = jsonObj.toJSONString();
return s;
}
/**
* 把一个beanList对象转换成jsonArrStr
* fast json
* @param beanList
* @param <T>
* @return
*/
public static <T> String beanListToJsonArrStr(List<T> beanList) {
JSONArray o = (JSONArray)JSON.toJSON(beanList);
String s = JSON.toJSONString(o);
return s;
}
/**
* 把一个jsonArrStr转换成beanList对象
* fast json
* @param jsonArrStr
* @param <T>
* @return
*/
public static <T> List<T> jsonArrStrToBeanList(String jsonArrStr, Class<T> clazz) {
List<T> ts = JSON.parseArray(jsonArrStr, clazz);
return ts;
}
/**
* 把一个JsonArr转换成JsonArrStr
* fast json
* @param jsonArr
* @return
*/
public static String jsonArrToJsonArrStr(JSONArray jsonArr) {
String s = JSON.toJSONString(jsonArr);
return s;
}
/**
* 把一个JsonArrStr文本转换成JsonArr
* fast json
* @param jsonArrStr
* @return
*/
public static JSONArray jsonArrStrToJsonArr(String jsonArrStr) {
Object o = JSON.parse(jsonArrStr);
return (JSONArray) o;
}
/**
* 把一个JsonArr转换成beanList
* fast json
* @param jsonArr
* @return
*/
public static <T> List<T> jsonArrToBeanList(JSONArray jsonArr, Class<T> clazz) {
String s = JSON.toJSONString(jsonArr);
List<T> ts = JSON.parseArray(s, clazz);
return ts;
}
/**
* 把一个beanList文本转换成JsonArr
* fast json
* @param beanList
* @return
*/
public static <T> JSONArray beanListToJsonArr(List<T> beanList) {
Object o = JSON.toJSON(beanList);
return (JSONArray) o;
}
}

View File

@ -1,7 +1,11 @@
package com.bonus.common.utils.file;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件类型工具类
@ -10,6 +14,35 @@ import org.apache.commons.lang3.StringUtils;
*/
public class FileTypeUtils
{
// 常见视频文件的文件头十六进制
private static final String[] VIDEO_HEADER_PREFIXES = {
"000001BA", // MPEG
"000001B3", // MPEG
"66747970", // MP4
"464C56", // FLV
"494433", // MP3 (音频可排除)
"89504E47", // PNG (图片)
"47494638", // GIF
"25504446", // PDF
"FFD8FFE0", // JPEG
"52494646", // WebP / AVI (RIFF 容器)
"4D5A" // EXE (危险文件)
};
// 真正的视频 MIME 类型
private static final String[] VIDEO_CONTENT_TYPES = {
"video/mp4",
"video/avi",
"video/x-msvideo",
"video/mpeg",
"video/quicktime",
"video/x-flv",
"video/webm",
"video/3gpp",
"video/ogg"
};
/**
* 获取文件类型
* <p>
@ -73,4 +106,72 @@ public class FileTypeUtils
}
return strFileExtendName;
}
/**
* 判断 MultipartFile 是否为视频文件Java 8 兼容版
*/
public static boolean isVideoFile(MultipartFile file) {
if (file == null || file.isEmpty()) {
return false;
}
String contentType = file.getContentType();
if (contentType == null) {
return false;
}
// 先用 MIME 类型快速判断备用方案
boolean isVideoByMimeType = Arrays.stream(VIDEO_CONTENT_TYPES)
.anyMatch(contentType::startsWith);
try {
byte[] headerBytes = new byte[12];
int read = file.getInputStream().read(headerBytes);
if (read < 4) {
return false;
}
String headerHex = bytesToHex(headerBytes, Math.min(read, 8)).toUpperCase();
boolean isVideo = false; // 用一个变量保存结果
switch (headerHex) {
case "66747970": // MP4
case "000001BA": // MPEG
case "000001B3": // MPEG
case "464C56": // FLV
isVideo = true;
break;
case "52494646": // RIFF (AVI, WebM)
// 进一步判断子类型AVI WebM
if (read >= 12) {
String subType = bytesToHex(Arrays.copyOfRange(headerBytes, 8, 12)).toUpperCase();
isVideo = "41564920".equals(subType) || "5745424D".equals(subType); // "AVI " "WEBM"
}
break;
default:
// 文件头不匹配降级使用 MIME 类型判断
isVideo = isVideoByMimeType;
break;
}
return isVideo;
} catch (IOException e) {
// 读取出错降级使用 MIME 类型判断
return isVideoByMimeType;
}
}
/**
* 将字节数组转为十六进制字符串
*/
private static String bytesToHex(byte[] bytes, int len) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
sb.append(String.format("%02X", bytes[i] & 0xFF));
}
return sb.toString();
}
/**
* 获取字节数组的十六进制表示完整
*/
private static String bytesToHex(byte[] bytes) {
return bytesToHex(bytes, bytes.length);
}
}

View File

@ -41,14 +41,30 @@ public class FileUploadService {
* @param filePath
*/
public void delFile(String filePath) {
try{
boolean isCz=minioUtil.isObjectExist(minioConfig.getBucketName(),filePath);
if(isCz){
minioUtil.removeFile(minioConfig.getBucketName(),filePath);
try {
boolean isCz = minioUtil.isObjectExist(minioConfig.getBucketName(), filePath);
if (isCz) {
minioUtil.removeFile(minioConfig.getBucketName(), filePath);
}
} catch (Exception e) {
log.error(e.toString(), e);
}
}
/**
* 上传文件
* @param file
* @return
*/
public SysFile uploadLargeFile(MultipartFile file,String path) {
try{
return minioUtil.uploadFile(file, path);
}catch (Exception e){
log.error(e.toString(),e);
}
return null;
}
}