许鹏程
2023-08-04 a26fbe729817216bcf53b13945fe6300caa89997
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
package com.product.print.service;
 
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.product.common.lang.StringUtils;
import com.product.core.cache.DataPoolCacheImpl;
import com.product.core.config.Global;
import com.product.core.entity.DataTableEntity;
import com.product.core.entity.FieldSetEntity;
import com.product.core.exception.BaseException;
import com.product.core.service.support.AbstractBaseService;
import com.product.file.service.FileManagerService;
import com.product.file.util.PdfConcurrenceUtil;
import com.product.print.config.CmnCode;
import com.product.print.config.CmnConst;
import com.product.print.service.ide.IPrintRealizeService;
import com.product.print.util.DynamicTableRenderPolicy;
import com.product.tool.flow.service.FlowDetailService;
import com.product.util.BaseUtil;
 
import com.product.util.SystemParamReplace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
 
 
/**
 * @ClassName PrintRealizeService
 * @Description 打印实现 业务层
 * @Author cheng
 * @Date 2021/12/1 9:50
 */
@Service
public class PrintRealizeService extends AbstractBaseService implements IPrintRealizeService {
 
 
    @Autowired
    FileManagerService fileManagerService;
 
    /**
     * word打印复选框处理
     *
     * @param fse
     */
    public static void dataConvertCheckedData(FieldSetEntity fse) {
 
        TextRenderData selSymbol = new TextRenderData(CmnConst.PRINT_CHECKED_CHAR, new Style(CmnConst.PRINT_FONT, 14));
        TextRenderData unselSymbol = new TextRenderData(CmnConst.PRINT_UNCHECKED_CHAR, new Style(CmnConst.PRINT_FONT, 14));
 
        //获取表单字段
        Object[] fields = fse.getMeta().getFields();
        if (fields == null) {
            return;
        }
        for (int i = 0; i < fields.length; ++i) {
            //获取保存的数据值
            String dataSaveValue = fse.getString(fields[i] + CmnConst._SAVE_VALUE);
            if (BaseUtil.strIsNull(dataSaveValue)) {
                continue;
            }
            //获取每个字段的meta信息
            FieldSetEntity meta = fse.getMeta().getFieldMeta(fields[i].toString());
            if (meta == null || meta.getString(CmnConst.FIELD_REFERECE) == null || meta.getString(CmnConst.FIELD_REFERECE).indexOf("《") == -1) {
                continue;
            }
            //数据对应参照信息
            DataTableEntity dictInfos = getMetaAndCacheDictInfo(meta);
            if (BaseUtil.dataTableIsEmpty(dictInfos)) {
                continue;
            }
            for (int j = 0; j < dictInfos.getRows(); j++) {
                //获取每个参照对应值
                String dict_value = dictInfos.getFieldSetEntity(j).getString(CmnConst.DICT_VALUE);
                if (dataSaveValue.indexOf(dict_value) > -1) {
                    fse.setValue(fields[i] + "_" + dict_value, selSymbol);
                    continue;
                }
                fse.setValue(fields[i] + "_" + dict_value, unselSymbol);
            }
        }
    }
 
    /**
     * 获取字段对应数据字典信息
     *
     * @param fieldMate
     * @return
     */
    public static DataTableEntity getMetaAndCacheDictInfo(FieldSetEntity fieldMate) {
        if (fieldMate != null && fieldMate.getString(CmnConst.FIELD_REFERECE) != null) {
            int a = fieldMate.getString(CmnConst.FIELD_REFERECE).indexOf("《");
            int b = fieldMate.getString(CmnConst.FIELD_REFERECE).indexOf("》");
            if (b > 1 && a == 0) {
                return DataPoolCacheImpl.getInstance().getCacheData("数据字典配置信息", new String[]{fieldMate.getString(CmnConst.FIELD_REFERECE).substring(a + 1, b)});
            }
        }
        return null;
    }
 
 
    /**
     * 打印传输pdf流到前端
     *
     * @param fse          打印数据
     * @param response     响应
     * @param isConvertPdf 是否转换为pdf
     * @throws BaseException
     */
    @Override
    public void print(FieldSetEntity fse, HttpServletResponse response, boolean isConvertPdf) throws BaseException {
        //打印配置
        FieldSetEntity printConfig = getPrintConfig(fse.getString("~" + CmnConst.PRINT_TEMP + "~"));
        //获取到替换后的文件路径 (pdf文件或者word文件)
        String tempPdfFilePath = replaceTemplateFileOut(printConfig, fse, isConvertPdf);
        //获取文件名
        String fileName = BaseUtil.ifNull(printConfig.getString(CmnConst.PRINT_FILE_NAME), printConfig.getString(CmnConst.PRINT_NAME));
        if (isConvertPdf) {
            fileName = fileName + ".pdf";
        } else {
            fileName = fileName + ".docx";
        }
        //设置响应
        response.setContentType("application/octet-stream;charset=UTF-8");
        // 将响应头中的Content-Disposition暴露出来,不然前端获取不到
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        // 设置自定义头Content-Disposition
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncodeUtil.encode(fileName));
 
        try (
                OutputStream out = response.getOutputStream();
        ) {
            FileUtil.writeToStream(new File(tempPdfFilePath), out);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(CmnCode.PRINT_CONTENT_FAIL, e);
        } finally {
            //删除pdf临时文件
            FileUtil.del(tempPdfFilePath);
        }
 
    }
 
    /**
     * 获取打印配置
     *
     * @param uuid 打印配置uuid
     * @return
     * @throws BaseException
     */
    public FieldSetEntity getPrintConfig(String uuid) throws BaseException {
        //查询打印配置
        FieldSetEntity fieldSetEntity = getBaseDao().getFieldSetEntity(CmnConst.TABLE_PRINT_CONFIG, uuid, false);
        if (fieldSetEntity == null || StringUtils.isEmpty(fieldSetEntity.getString(CmnConst.PRINT_TEMPLATE))) {
            throw new BaseException(CmnCode.PRINT_CONFIG_NOT_EXIST.getValue(), CmnCode.PRINT_CONFIG_NOT_EXIST.getText());
        }
 
        return fieldSetEntity;
    }
 
    /**
     * 替换模板文件并输出
     *
     * @param printConf    打印配置
     * @param fse          替换数据
     * @param isConvertPdf 是否转换为pdf
     * @return 替换后的文件路径
     * @throws BaseException 异常
     */
    private String replaceTemplateFileOut(FieldSetEntity printConf, FieldSetEntity fse, boolean isConvertPdf) throws BaseException {
 
        Object[] fields = fse.getFields();
        for (int i = 0; i < fields.length; i++) {
            String field = fields[i].toString();
            FieldSetEntity metaEntity = fse.getMeta().getFieldMeta(field);
            String fieldType = metaEntity.getString("field_type");
            //判断是否拥有流程标识
            if ("flowsign".equals(fieldType)) {
                if (StringUtils.equalsAny(fse.getString(field), "1", "2")) {
                    //流程办理中或办结 获取流程意见
                    FieldSetEntity flowTask = getBaseDao().getFieldSetByFilter("product_sys_flow_task", "table_name=? and record_uuid=?", new Object[]{fse.getTableName(), fse.getUUID()}, false);
                    if (flowTask != null) {
                        String taskUuid = flowTask.getString(CmnConst.UUID);
                        //获取流程意见
                        FlowDetailService flowDetailService = SpringUtil.getBean(FlowDetailService.class);
                        JSONArray opinion = flowDetailService.getHistoryInfo(taskUuid);
                        fse.setValue("~flow_opinion~", opinion);
                    }
                }
                break;
            }
        }
 
        // 打印模板附件uuid
        String template_uuid = printConf.getString(CmnConst.PRINT_TEMPLATE);
        // 获取打印模板
        File file = getTemplateFile(template_uuid);
        // 加载参照 打印时使用显示值 而不是实际值
        getBaseDao().loadPromptData(fse);
        // 文件名前缀部分
        Object tempKey = UUID.randomUUID();
        // 替换后的word临时路径
        String localTempPathWord = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".docx";
        replaceWord(localTempPathWord, file.getPath(), fse);
        file.delete();
 
        String replaceParams = SystemParamReplace.replaceParams(printConf.getString(CmnConst.PRINT_FILE_NAME), fse);
        printConf.setValue(CmnConst.PRINT_FILE_NAME, replaceParams);
        if (isConvertPdf) {
            try {
                // 替换后的pdf临时路径
                String localTempPathPdf = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".pdf";
                //检查文件是否存在不存则创建
                FileUtil.touch(localTempPathPdf);
                // 转换pdf
                PdfConcurrenceUtil.convertToPdf(localTempPathWord, localTempPathPdf, "docx");
                // 删除word临时文件
                File wordTemp = new File(localTempPathWord);
                if (wordTemp.exists()) {
                    wordTemp.delete();
                }
                return localTempPathPdf;
            } catch (Exception e) {
                throw new BaseException(CmnCode.CONVERT_PDF_ERROR, e);
            } finally {
                FileUtil.del(localTempPathWord);
            }
        }
        return localTempPathWord;
    }
 
    /**
     * 替换word模板
     *
     * @param outPath      输出路径
     * @param templatePath 模板路径
     * @param dataFse      替换数据
     */
    public static void replaceWord(String outPath, String templatePath, FieldSetEntity dataFse) {
        JSONArray flowOpinion = (JSONArray) dataFse.getObject("~flow_opinion~");
        if (flowOpinion != null) {
            dataFse.remove("~flow_opinion~");
        }
        //转换数据为复选框
        dataConvertCheckedData(dataFse);
        //克隆一份values
        Map<String, Object> cloneValues = new HashMap(dataFse.getValues());
        //获取子表数据
        Map<String, DataTableEntity> subDataMap = dataFse.getSubData();
        ConfigureBuilder config = Configure.createDefault().builder();
        if (!CollectionUtil.isEmpty(subDataMap)) {
            for (Map.Entry<String, DataTableEntity> entry : subDataMap.entrySet()) {
                cloneValues.put(entry.getKey(), entry.getValue().getData().stream().map(item -> (Map<String, Object>) ((Map) item.getValues())).collect(Collectors.toList()));
                config.bind(entry.getKey(), new DynamicTableRenderPolicy(entry.getKey()));
            }
        }
        if(flowOpinion!=null && flowOpinion.size()>0){
            cloneValues.put("lx_flow_opinion", flowOpinion);
            config.bind("lx_flow_opinion", new DynamicTableRenderPolicy("lx_flow_opinion"));
        }
        try {
            //检查输出文件是否存在,不存在则创建
            FileUtil.touch(outPath);
            System.out.println(cloneValues);
            XWPFTemplate.compile(templatePath, config.build()).render(cloneValues).writeToFile(outPath);
        } catch (Exception e) {
            e.printStackTrace();
            FileUtil.del(outPath);
            throw new BaseException(CmnCode.REPLACE_TEMPLATE_CONTENT_ERROR, e);
        }
    }
 
    /**
     * 获取模板附件
     *
     * @param templateUid 模板附件uuid
     * @return
     * @throws BaseException
     */
    private File getTemplateFile(String templateUid) throws BaseException {
        try {
            return fileManagerService.getFile(templateUid);
        } catch (BaseException e) {
            e.printStackTrace();
            //获取打印模板错误
            throw new BaseException(CmnCode.GET_PRINT_TEMPLATE_FILE_FAIL.getValue(), CmnCode.GET_PRINT_TEMPLATE_FILE_FAIL.getText());
        }
    }
}