ruoyi-tpl 文件模板打印后台

This commit is contained in:
lizhengwei 2026-01-04 17:05:56 +08:00
parent 4031270b81
commit 4453b470a7
9 changed files with 421 additions and 58 deletions

View File

@ -0,0 +1,13 @@
package com.lizhw.tpl.module.docx.api.vo;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
@Getter
@Setter
public class TplConfigExportReq {
private Long tplId;
private Map<String, Object> params;
}

View File

@ -0,0 +1,86 @@
package com.lizhw.tpl.module.docx.controller;
import com.lizhw.tpl.module.docx.api.vo.TplConfigExportReq;
import com.lizhw.tpl.module.docx.model.TplConfig;
import com.lizhw.tpl.module.docx.service.ITplConfigService;
import lombok.RequiredArgsConstructor;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 模板配置控制器
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/tpl/config")
public class TplConfigController {
private final ITplConfigService tplConfigService;
/**
* 查询模板配置列表
*/
@GetMapping("/list")
public TableDataInfo<TplConfig> list(TplConfig tplConfig, PageQuery pageQuery) {
List<TplConfig> list = tplConfigService.selectTplConfigList(tplConfig);
return TableDataInfo.build(list);
}
/**
* 查询模板配置列表分页
*/
@PostMapping("/page")
public TableDataInfo<TplConfig> pageList(@RequestBody TplConfig tplConfig, PageQuery pageQuery) {
return tplConfigService.selectPageTplConfigList(tplConfig, pageQuery);
}
/**
* 导出模板填充key值
*/
@PostMapping("/export")
public String export(@RequestBody TplConfigExportReq req) {
return tplConfigService.export(req);
}
/**
* 获取模板配置详细信息
*
* @param id 主键
*/
@GetMapping("/getInfoById")
public TplConfig getInfo(@RequestParam("id") Long id) {
return tplConfigService.selectTplConfigById(id);
}
/**
* 新增模板配置
*/
@PostMapping
public Boolean add(@RequestBody TplConfig tplConfig) {
return tplConfigService.insertTplConfig(tplConfig);
}
/**
* 修改模板配置
*/
@PostMapping("edit")
public Boolean edit(@RequestBody TplConfig tplConfig) {
return tplConfigService.updateTplConfig(tplConfig);
}
/**
* 删除模板配置
*
* @param ids 主键
*/
@PostMapping("remove")
public Integer remove(@RequestBody List<Long> ids) {
return tplConfigService.deleteTplConfigByIds(ids);
}
}

View File

@ -0,0 +1,13 @@
package com.lizhw.tpl.module.docx.dao;
import com.lizhw.tpl.module.docx.model.TplConfig;
import org.apache.ibatis.annotations.Mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 模板配置Mapper接口
*/
@Mapper
public interface TplConfigMapper extends BaseMapperPlus<TplConfig, TplConfig> {
}

View File

@ -0,0 +1,49 @@
package com.lizhw.tpl.module.docx.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import org.dromara.common.tenant.core.TenantEntity;
import java.time.LocalDateTime;
/**
* 模板配置实体
*/
@Getter
@Setter
@TableName("tpl_config")
public class TplConfig extends TenantEntity {
/**
* 主键
*/
@TableId(value = "id")
private Long id;
/**
* 模板名称
*/
private String tplName;
/**
* 模板名称
*/
private String tplUploadName;
/**
* 模板路径
*/
private String tplUrl;
private LocalDateTime createTime;
private LocalDateTime updateTime;
/**
* 状态
*/
private Boolean deleted;
}

View File

@ -1,23 +0,0 @@
//package com.lizhw.tpl.module.classroom.service;
//
//import com.baomidou.mybatisplus.core.metadata.IPage;
//import com.lizhw.tpl.module.classroom.model.dto.ClassroomPageQuery;
//import com.lizhw.tpl.module.classroom.model.dto.ClassroomSaveDTO;
//import com.lizhw.tpl.module.classroom.model.vo.ClassroomListVO;
//
//import java.util.List;
//
//public interface ClassroomService {
//
// IPage<ClassroomListVO> pageCourse(ClassroomPageQuery pageQuery);
//
// List<ClassroomListVO> refList();
//
// ClassroomListVO getCourseById(Long id);
//
// boolean saveCourse(ClassroomSaveDTO saveDTO);
//
// boolean updateCourseById(Long id, ClassroomSaveDTO saveDTO);
//
// boolean updateCourseEnableStateById(Long id, Integer enableState);
//}

View File

@ -0,0 +1,65 @@
package com.lizhw.tpl.module.docx.service;
import com.lizhw.tpl.module.docx.api.vo.TplConfigExportReq;
import com.lizhw.tpl.module.docx.model.TplConfig;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import java.util.List;
/**
* 模板配置服务层
*/
public interface ITplConfigService {
TableDataInfo<TplConfig> selectPageTplConfigList(TplConfig tplConfig, PageQuery pageQuery);
/**
* 查询模板配置信息
*
* @param id 模板配置ID
* @return 模板配置信息
*/
TplConfig selectTplConfigById(Long id);
/**
* 查询模板配置列表
*
* @param req 模板配置信息
* @return 模板配置集合
*/
List<TplConfig> selectTplConfigList(TplConfig req);
/**
* 新增模板配置
*
* @param tplConfig 模板配置信息
* @return 结果
*/
Boolean insertTplConfig(TplConfig tplConfig);
/**
* 修改模板配置
*
* @param tplConfig 模板配置信息
* @return 结果
*/
Boolean updateTplConfig(TplConfig tplConfig);
/**
* 批量删除模板配置信息
*
* @param ids 需要删除的模板配置ID
*/
int deleteTplConfigByIds(List<Long> ids);
/**
* 校验模板配置键名是否唯一
*
* @param tplConfig 模板配置信息
* @return 结果
*/
boolean checkTplConfigUnique(TplConfig tplConfig);
String export(TplConfigExportReq req);
}

View File

@ -0,0 +1,153 @@
package com.lizhw.tpl.module.docx.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lizhw.tpl.module.docx.api.vo.TplConfigExportReq;
import com.lizhw.tpl.module.docx.dao.TplConfigMapper;
import com.lizhw.tpl.module.docx.model.TplConfig;
import com.lizhw.tpl.module.docx.service.ITplConfigService;
import com.lizhw.tpl.module.docx.ttt.NiceDoc;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* 模板配置服务层实现
*/
@RequiredArgsConstructor
@Service
public class TplConfigServiceImpl implements ITplConfigService {
private final TplConfigMapper baseMapper;
@Override
public TableDataInfo<TplConfig> selectPageTplConfigList(TplConfig tplConfig, PageQuery pageQuery) {
LambdaQueryWrapper<TplConfig> lqw = buildQueryWrapper(tplConfig);
Page<TplConfig> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(page);
}
/**
* 查询模板配置信息
*
* @param id 模板配置ID
* @return 模板配置信息
*/
@Override
public TplConfig selectTplConfigById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 查询模板配置列表
*
* @param tplConfig 模板配置信息
* @return 模板配置集合
*/
@Override
public List<TplConfig> selectTplConfigList(TplConfig tplConfig) {
LambdaQueryWrapper<TplConfig> lqw = buildQueryWrapper(tplConfig);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<TplConfig> buildQueryWrapper(TplConfig tplConfig) {
Map<String, Object> params = tplConfig.getParams();
LambdaQueryWrapper<TplConfig> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(tplConfig.getTplName()), TplConfig::getTplName, tplConfig.getTplName());
lqw.like(StringUtils.isNotBlank(tplConfig.getDescription()), TplConfig::getDescription, tplConfig.getDescription());
lqw.eq(StringUtils.isNotBlank(tplConfig.getStatus()), TplConfig::getStatus, tplConfig.getStatus());
lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
TplConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
lqw.orderByAsc(TplConfig::getId);
return lqw;
}
/**
* 新增模板配置
*
* @param tplConfig 模板配置信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertTplConfig(TplConfig tplConfig) {
int insert = baseMapper.insert(tplConfig);
return insert > 0;
}
/**
* 修改模板配置
*
* @param tplConfig 模板配置信息
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateTplConfig(TplConfig tplConfig) {
int update = baseMapper.updateById(tplConfig);
return update > 0;
}
/**
* 批量删除模板配置信息
*
* @param ids 需要删除的模板配置ID
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int deleteTplConfigByIds(List<Long> ids) {
if (CollUtil.isEmpty(ids)) {
throw new ServiceException("请选择要删除的数据");
}
return baseMapper.deleteByIds(ids);
}
/**
* 校验模板配置键名是否唯一
*
* @param tplConfig 模板配置信息
* @return 结果
*/
@Override
public boolean checkTplConfigUnique(TplConfig tplConfig) {
long id = ObjectUtil.isNull(tplConfig.getId()) ? -1L : tplConfig.getId();
TplConfig info = baseMapper.selectOne(new LambdaQueryWrapper<TplConfig>()
.eq(TplConfig::getTplName, tplConfig.getTplName()));
if (ObjectUtil.isNotNull(info) && info.getId() != id) {
return false;
}
return true;
}
@Override
public String export(TplConfigExportReq req) {
TplConfig tplConfig = selectTplConfigById(req.getTplId());
String tplUrl = tplConfig.getTplUrl();
//下载文件
NiceDoc niceDoc = null;
try {
niceDoc = new NiceDoc(tplUrl);
} catch (IOException e) {
throw new RuntimeException(e);
}
niceDoc.pushLabels(req.getParams());
niceDoc.save("", UUID.randomUUID() + ".docx");
return "";
}
}

View File

@ -1,5 +1,7 @@
package com.lizhw.tpl.module.docx.ttt;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
@ -9,7 +11,10 @@ import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
/**
@ -18,11 +23,12 @@ import java.util.regex.Matcher;
* <p>
* by miracleren@gmail.com
*/
public class NiceDoc {
//private HWPFDocument doc;
private XWPFDocument docx;
@Slf4j
public class NiceDoc implements Closeable {
private int status = 0;
@Getter
private XWPFDocument docx = null;
private final List<XWPFTable> allTables = new ArrayList<>();
/**
@ -30,25 +36,27 @@ public class NiceDoc {
*
* @param path
*/
public NiceDoc(String path) {
if (!path.endsWith(".docx")) System.out.println("无效文档后缀当前只支持docx格式word文档模板。");
FileInputStream in;
try {
in = new FileInputStream(path);
docx = new XWPFDocument(in);
public NiceDoc(String path) throws IOException {
if (!path.endsWith(".docx")) log.error("无效文档后缀当前只支持docx格式word文档模板。");
try (FileInputStream in = new FileInputStream(path)) {
this.docx = new XWPFDocument(in);
//遍历段落生加载表格列表
this.allTables.addAll(docx.getTables());
this.allTables.addAll(this.docx.getTables());
pushLabels(new HashMap<>());
status = 1;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (docx == null) docx = new XWPFDocument();
}
}
public NiceDoc(FileInputStream in) throws IOException {
if (in == null) throw new RuntimeException("请传入文件流");
this.docx = new XWPFDocument(in);
//遍历段落生加载表格列表
this.allTables.addAll(docx.getTables());
pushLabels(new HashMap<>());
status = 1;
}
/**
* 往模板填充标签值
* {{labelName}}
@ -534,21 +542,18 @@ public class NiceDoc {
* @param name
*/
public void save(String path, String name) {
try {
try (FileOutputStream outStream = new FileOutputStream(path + name)) {
//removeNullParagraphs();
FileOutputStream outStream = new FileOutputStream(path + name);
docx.write(outStream);
outStream.close();
} catch (Exception e) {
e.printStackTrace();
log.error("保存文件失败!", e);
}
}
/**
* 获取docx实体
*/
public XWPFDocument getDocx() {
return this.docx;
@Override
public void close() throws IOException {
if (docx != null) {
docx.close();
}
}
}

View File

@ -1,5 +1,6 @@
package com.lizhw.tpl.module.docx.ttt;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.*;
@ -15,8 +16,6 @@ public class TestTemplate {
* 测试示例模板生成word
*/
public static void buildTestDocx() {
//测试示例模板生成word
NiceDoc docx = new NiceDoc(path + "test.docx");
Map<String, Object> labels = new HashMap<>();
//值标签
@ -45,7 +44,6 @@ public class TestTemplate {
//添加头像
labels.put("headImg", path + "head.png");
docx.pushLabels(labels);
//表格
List<Map<String, Object>> books = new ArrayList<>();
@ -57,11 +55,15 @@ public class TestTemplate {
book2.put("name", "中国小说史略");
book2.put("time", "1923年12月上册1924年6月下册");
books.add(book2);
docx.pushTable("books", books);
//生成文档
docx.save(path, UUID.randomUUID() + ".docx");
//测试示例模板生成word
try (NiceDoc docx = new NiceDoc(path + "test.docx")){
docx.pushLabels(labels);
docx.pushTable("books", books);
//生成文档
docx.save(path, UUID.randomUUID() + ".docx");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**