|
@@ -0,0 +1,474 @@
|
|
|
|
|
+package com.kingdee.shr.cmpdesign.web.handler.v2;
|
|
|
|
|
+
|
|
|
|
|
+import com.kingdee.bos.BOSException;
|
|
|
|
|
+import com.kingdee.bos.Context;
|
|
|
|
|
+import com.kingdee.bos.metadata.entity.*;
|
|
|
|
|
+import com.kingdee.bos.metadata.query.util.CompareType;
|
|
|
|
|
+import com.kingdee.eas.base.permission.UserInfo;
|
|
|
|
|
+import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
|
|
|
|
|
+import com.kingdee.eas.basedata.org.PositionInfo;
|
|
|
|
|
+import com.kingdee.eas.basedata.person.PersonInfo;
|
|
|
|
|
+import com.kingdee.eas.hr.ats.AtsUtil;
|
|
|
|
|
+import com.kingdee.eas.hr.ats.util.AtsDateUtils;
|
|
|
|
|
+import com.kingdee.eas.hr.emp.*;
|
|
|
|
|
+import com.kingdee.eas.util.app.ContextUtil;
|
|
|
|
|
+import com.kingdee.eas.util.app.DbUtil;
|
|
|
|
|
+import com.kingdee.jdbc.rowset.IRowSet;
|
|
|
|
|
+import com.kingdee.shr.base.syssetting.context.SHRContext;
|
|
|
|
|
+import com.kingdee.shr.base.syssetting.exception.SHRWebException;
|
|
|
|
|
+import com.kingdee.shr.base.syssetting.web.dynamic.util.DynamicUtil;
|
|
|
|
|
+import com.kingdee.shr.base.syssetting.web.dynamic.util.MD5;
|
|
|
|
|
+import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
|
|
|
|
|
+import com.kingdee.shr.base.syssetting.web.util.UserUtil;
|
|
|
|
|
+import com.kingdee.shr.cmpdesign.app.v2.bill.*;
|
|
|
|
|
+import com.kingdee.shr.cmpdesign.web.handler.utils.AdvancedZipUtils;
|
|
|
|
|
+import com.kingdee.util.DateTimeUtils;
|
|
|
|
|
+import org.apache.log4j.Logger;
|
|
|
|
|
+import org.apache.poi.xwpf.usermodel.*;
|
|
|
|
|
+import org.springframework.ui.ModelMap;
|
|
|
|
|
+
|
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
+import javax.servlet.http.HttpSession;
|
|
|
|
|
+import java.io.*;
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.math.RoundingMode;
|
|
|
|
|
+import java.nio.file.Files;
|
|
|
|
|
+import java.nio.file.Paths;
|
|
|
|
|
+import java.sql.SQLException;
|
|
|
|
|
+import java.text.MessageFormat;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @Title: AdjustSalaryApplyListHandlerEx
|
|
|
|
|
+ * @Author 青梧
|
|
|
|
|
+ * @Package com.kingdee.shr.cmpdesign.web.handler.v2
|
|
|
|
|
+ * @Date 2026/1/14 15:37
|
|
|
|
|
+ * @description: 套打
|
|
|
|
|
+ */
|
|
|
|
|
+public class AdjustSalaryApplyListHandlerEx extends AdjustSalaryApplyListHandler {
|
|
|
|
|
+ private Context ctx = SHRContext.getInstance().getContext();
|
|
|
|
|
+ private static Logger logger = Logger.getLogger(AdjustSalaryApplyListHandlerEx.class);
|
|
|
|
|
+ // 定义薪资项编码常量
|
|
|
|
|
+ private static final String BASIC_SALARY = "SCY002"; // 基本工资标准
|
|
|
|
|
+ private static final String OVERTIME_SALARY = "SCY005"; // 加班工资标准
|
|
|
|
|
+ private static final String SKILL_SALARY = "SCY003"; // 技能工资标准
|
|
|
|
|
+ private static final String POST_ALLOWANCE = "SCY004"; // 岗位补助工资标准
|
|
|
|
|
+ private static final String EDU_ALLOWANCE = "SCY006"; // 学历补助标准
|
|
|
|
|
+ private static final String EXPENSE_ALLOWANCE = "SCY073"; // 费用补助标准
|
|
|
|
|
+ private static final String TOTAL_SALARY = "SCY001"; // 标准薪资合计
|
|
|
|
|
+ // 所有需要查询的薪资项编码
|
|
|
|
|
+ private static final String[] SALARY_ITEM_CODES = {BASIC_SALARY, OVERTIME_SALARY, SKILL_SALARY, POST_ALLOWANCE, EDU_ALLOWANCE, EXPENSE_ALLOWANCE, TOTAL_SALARY};
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 定调薪申请单套打
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param request
|
|
|
|
|
+ * @param response
|
|
|
|
|
+ * @param modelMap
|
|
|
|
|
+ * @throws SHRWebException
|
|
|
|
|
+ */
|
|
|
|
|
+ public void customPrintAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException, BOSException {
|
|
|
|
|
+ try {
|
|
|
|
|
+ String billId = this.getBillId(request);
|
|
|
|
|
+ //获取临时地址
|
|
|
|
|
+ HttpSession session = request.getSession();
|
|
|
|
|
+ String tempFilePath = UserUtil.getUserTempDirAbsolutePath(session); //存放
|
|
|
|
|
+ File tempFile = new File(tempFilePath);
|
|
|
|
|
+ if (!tempFile.exists()) {
|
|
|
|
|
+ tempFile.mkdirs();
|
|
|
|
|
+ }
|
|
|
|
|
+ Map map = new HashMap();
|
|
|
|
|
+ Map<String, byte[]> files = new HashMap();
|
|
|
|
|
+ //人员ID集合
|
|
|
|
|
+ Map<String, Object> PersonMap = getAdjustSalaryApplyPersonIds(billId);
|
|
|
|
|
+ Set personSet = (Set) PersonMap.get("personSet");
|
|
|
|
|
+ //查询定调薪申请单
|
|
|
|
|
+ SelectorItemCollection sic = new SelectorItemCollection();
|
|
|
|
|
+ sic.add("*");
|
|
|
|
|
+ sic.add("person.*");
|
|
|
|
|
+ sic.add("primaryPosition.*");
|
|
|
|
|
+ sic.add("personDep.*");
|
|
|
|
|
+ FilterInfo filterInfo = new FilterInfo();
|
|
|
|
|
+ FilterItemCollection filterItems = filterInfo.getFilterItems();
|
|
|
|
|
+ filterItems.add(new FilterItemInfo("person.id", personSet, CompareType.INCLUDE));
|
|
|
|
|
+ EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
|
|
|
|
|
+ //查询人员信息
|
|
|
|
|
+ IPersonPosition iPersonPosition = PersonPositionFactory.getLocalInstance(ctx);
|
|
|
|
|
+ PersonPositionCollection personPositionCollection = iPersonPosition.getPersonPositionCollection(entityViewInfo);
|
|
|
|
|
+ for (int i = 0; i < personPositionCollection.size(); i++) {
|
|
|
|
|
+ String fileName = "定调薪套打.docx";
|
|
|
|
|
+ String txtNameHash = MD5.md5Hash(fileName);
|
|
|
|
|
+ String realFileName = getEncryRealFileName(ctx, txtNameHash);
|
|
|
|
|
+ String txtPath = tempFilePath + File.separator + realFileName;
|
|
|
|
|
+ // String fileStr = txtNameHash;
|
|
|
|
|
+ // 1. 配置文件路径
|
|
|
|
|
+ String templatePath = System.getProperty("EAS_HOME") + "/server/properties/templatePrint/dtxtdmb.docx";
|
|
|
|
|
+ String pdfOutputPath = txtPath + ".docx";
|
|
|
|
|
+ PersonPositionInfo personPositionInfo = personPositionCollection.get(i);
|
|
|
|
|
+ //人员
|
|
|
|
|
+ PersonInfo person = personPositionInfo.getPerson();
|
|
|
|
|
+ //职位
|
|
|
|
|
+ PositionInfo primaryPosition = personPositionInfo.getPrimaryPosition();
|
|
|
|
|
+ //部门
|
|
|
|
|
+ AdminOrgUnitInfo personDep = personPositionInfo.getPersonDep();
|
|
|
|
|
+ // 2. 定义占位符-实际数据映射(同之前方案,可动态获取)
|
|
|
|
|
+ Map<String, String> dataMap = new HashMap<>();
|
|
|
|
|
+ String personId = person.getId().toString();
|
|
|
|
|
+ //获取人员基本信息
|
|
|
|
|
+ Map<String, String> personBaseMap = getPersonBaseInfo(personId);
|
|
|
|
|
+ // 基础信息
|
|
|
|
|
+ //人员分类
|
|
|
|
|
+ dataMap.put("N", personBaseMap.getOrDefault("clName", "0")); // 员工类型(表格标题)
|
|
|
|
|
+ //定调薪单据-单据来源
|
|
|
|
|
+ Map<String, String> data = (Map<String, String>) PersonMap.get(personId);
|
|
|
|
|
+ dataMap.put("T", data.get("billSource")); // 异动类型
|
|
|
|
|
+ //定调薪单据编码
|
|
|
|
|
+ dataMap.put("X", "SCY-R-HR-262-A/0"); // 编码
|
|
|
|
|
+ // 员工个人信息
|
|
|
|
|
+ dataMap.put("q", person.getName()); // 员工姓名
|
|
|
|
|
+ dataMap.put("w", person.getNumber()); // 工号
|
|
|
|
|
+ dataMap.put("e", AtsDateUtils.dateShortFormatToStr(person.getHireDate())); // 入职日期
|
|
|
|
|
+ //教育经历
|
|
|
|
|
+ dataMap.put("r", personBaseMap.getOrDefault("diplomaName", "0")); // 学历
|
|
|
|
|
+ dataMap.put("t", personBaseMap.getOrDefault("caName", "0")); // 管理类别
|
|
|
|
|
+
|
|
|
|
|
+ dataMap.put("y", personDep.getName()); // 所属组织
|
|
|
|
|
+ dataMap.put("u", primaryPosition.getName()); // 职位
|
|
|
|
|
+ dataMap.put("i", personBaseMap.getOrDefault("rankName", "0")); // 职级
|
|
|
|
|
+ dataMap.put("I", personBaseMap.get("schemeName")+"制"); // 工资类型
|
|
|
|
|
+ Map<String, BigDecimal> adjustSalaryInfo = getAdjustSalaryInfo(personId);
|
|
|
|
|
+ // 工资结构
|
|
|
|
|
+ dataMap.put("A", adjustSalaryInfo.get(BASIC_SALARY).toString()); // 基本工资
|
|
|
|
|
+ dataMap.put("B", adjustSalaryInfo.get(OVERTIME_SALARY).toString());// 加班工资
|
|
|
|
|
+ dataMap.put("C", adjustSalaryInfo.get(SKILL_SALARY).toString()); // 技能工资
|
|
|
|
|
+ dataMap.put("J", adjustSalaryInfo.get(POST_ALLOWANCE).toString()); // 岗位补贴
|
|
|
|
|
+ dataMap.put("E", adjustSalaryInfo.get(EDU_ALLOWANCE).toString()); // 学历补贴
|
|
|
|
|
+ dataMap.put("G", adjustSalaryInfo.get(TOTAL_SALARY).toString()); // 月薪合计
|
|
|
|
|
+ dataMap.put("F", adjustSalaryInfo.get(EXPENSE_ALLOWANCE).toString());// 费用补贴
|
|
|
|
|
+ // 生效日期
|
|
|
|
|
+ dataMap.put("YYYYHHDD", data.get("stateDate"));
|
|
|
|
|
+ // 执行流程:替换占位符 → 转 PDF
|
|
|
|
|
+ batchReplaceWordPlaceholders(templatePath, pdfOutputPath, dataMap);
|
|
|
|
|
+// convertWordToPdf(pdfOutputPath, pdfOutputPath);
|
|
|
|
|
+
|
|
|
|
|
+ File file = new File(pdfOutputPath);
|
|
|
|
|
+ byte[] fileBytes = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
|
|
|
|
|
+ files.put(person.getName() + "_定调薪套打.docx", fileBytes);
|
|
|
|
|
+ }
|
|
|
|
|
+ UserInfo currentUserInfo = ContextUtil.getCurrentUserInfo(ctx);
|
|
|
|
|
+ String downloadZipName = System.currentTimeMillis() + "print.zip";
|
|
|
|
|
+ String zipName = downloadZipName + "_" + MD5.md5Hash(currentUserInfo.getId().toString());
|
|
|
|
|
+ File userPathFile = new File(tempFilePath);
|
|
|
|
|
+ if (!userPathFile.exists()) {
|
|
|
|
|
+ userPathFile.mkdirs();
|
|
|
|
|
+ }
|
|
|
|
|
+ String zipPath = tempFilePath + File.separator + zipName;
|
|
|
|
|
+ AdvancedZipUtils.createZipFromMultipleFiles(files, zipPath);
|
|
|
|
|
+ Map<String, String> param = new HashMap<String, String>();
|
|
|
|
|
+ param.put("method", "tmp");
|
|
|
|
|
+ param.put("file", downloadZipName);
|
|
|
|
|
+ param.put("filename", "AdjustSalaryApplyPrint.zip");
|
|
|
|
|
+ String link = DynamicUtil.assembleUrl("/shr/downloadfile.do", param).replaceAll("\\+", "%20");
|
|
|
|
|
+ map.put("msgType", "1");
|
|
|
|
|
+ map.put("link", link);
|
|
|
|
|
+ map.put("msg", "下载成功");
|
|
|
|
|
+ // 可选:删除临时 Word 文件(如需保留可注释)
|
|
|
|
|
+// File tempWordFile = new File(pdfOutputPath);
|
|
|
|
|
+// if (tempWordFile.exists()) {
|
|
|
|
|
+// tempWordFile.delete();
|
|
|
|
|
+// System.out.println("临时 Word 文件已删除");
|
|
|
|
|
+// }
|
|
|
|
|
+ JSONUtils.SUCCESS(map);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ System.err.println("执行失败:" + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ public Map<String, BigDecimal> getAdjustSalaryInfo(String personId) {
|
|
|
|
|
+ // 1. 初始化Map,预设所有薪资项的默认值为"0"
|
|
|
|
|
+ Map<String, BigDecimal> salaryMap = new HashMap<>();
|
|
|
|
|
+ for (String code : SALARY_ITEM_CODES) {
|
|
|
|
|
+ salaryMap.put(code, BigDecimal.ZERO);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 2. 构建参数化SQL(避免SQL注入)
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ sb.append("select salary.FMoney as money ,item.fname_l2 as name ,item.fnumber as number\n");
|
|
|
|
|
+ sb.append("from T_HR_SFixAdjustSalary salary\n");
|
|
|
|
|
+ sb.append("left join T_HR_SCmpItem item on item.fid = salary.FCmpItemID\n");
|
|
|
|
|
+ sb.append("where FPersonID = ? and FLeffectDay = ?");
|
|
|
|
|
+ String sql = sb.toString();
|
|
|
|
|
+ logger.error("getAdjustSalaryInfo--sql---" + sql);
|
|
|
|
|
+ Object[] param = new Object[]{personId, "2199-12-31 00:00:00"};
|
|
|
|
|
+ logger.error("getAdjustSalaryInfo--param---" + param);
|
|
|
|
|
+ // 3. 执行查询(使用参数化方式,自动关闭资源)
|
|
|
|
|
+ IRowSet iRowSet = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 假设DbUtil支持参数化查询,传入参数数组(替换原有的字符串拼接)
|
|
|
|
|
+ iRowSet = DbUtil.executeQuery(ctx, sql, param);
|
|
|
|
|
+ while (iRowSet.next()) {
|
|
|
|
|
+ String number = iRowSet.getString("number");
|
|
|
|
|
+ BigDecimal money = iRowSet.getBigDecimal("money").setScale(2, RoundingMode.HALF_UP);
|
|
|
|
|
+ // 4. 只更新存在的薪资项,不存在的保持默认值0
|
|
|
|
|
+ if (salaryMap.containsKey(number)) {
|
|
|
|
|
+ // 处理money为空的情况,确保不会存入null
|
|
|
|
|
+ salaryMap.put(number, money == null ? BigDecimal.ZERO : money);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (SQLException | BOSException e) {
|
|
|
|
|
+ logger.error("查询薪资信息失败", e);
|
|
|
|
|
+ // 异常时返回默认值(所有项都是0)
|
|
|
|
|
+ return salaryMap;
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ // 确保资源关闭(根据实际的IRowSet实现,添加关闭逻辑)
|
|
|
|
|
+ if (iRowSet != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ iRowSet.close();
|
|
|
|
|
+ } catch (SQLException e) {
|
|
|
|
|
+ logger.error("关闭IRowSet失败", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return salaryMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取人员基本信息
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param personId
|
|
|
|
|
+ */
|
|
|
|
|
+ public Map getPersonBaseInfo(String personId) throws BOSException, SQLException {
|
|
|
|
|
+ Map baseMap = new HashMap();
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ sb.append("").append("\n");
|
|
|
|
|
+ sb.append("select").append("\n");
|
|
|
|
|
+ sb.append(" salaryScheme.fname_l2 as schemeName,").append("\n");
|
|
|
|
|
+ sb.append(" rank.fname_l2 as rankName,").append("\n");
|
|
|
|
|
+ sb.append(" degree.diplomaName as diplomaName ,").append("\n");
|
|
|
|
|
+ sb.append(" ca.fname_l2 as caName,").append("\n");
|
|
|
|
|
+ sb.append("cl.fname_l2 as clName").append("\n");
|
|
|
|
|
+ sb.append("from").append("\n");
|
|
|
|
|
+ sb.append(" T_BD_person person").append("\n");
|
|
|
|
|
+ sb.append(" left join CT_MP_SalaryScheme salaryScheme on salaryScheme.fid = person.CFSalarySchemeID").append("\n");
|
|
|
|
|
+ sb.append(" left join (").append("\n");
|
|
|
|
|
+ sb.append(" select").append("\n");
|
|
|
|
|
+ sb.append(" FPERSONID,").append("\n");
|
|
|
|
|
+ sb.append(" jonGrade.fname_l2").append("\n");
|
|
|
|
|
+ sb.append(" from").append("\n");
|
|
|
|
|
+ sb.append(" T_HR_EmpPostRank rank").append("\n");
|
|
|
|
|
+ sb.append(" left join T_HR_JobGrade jonGrade on rank.FJOBGRADEID = jonGrade.fid").append("\n");
|
|
|
|
|
+ sb.append(" where").append("\n");
|
|
|
|
|
+ sb.append(" FPERSONID = '" + personId + "'").append("\n");
|
|
|
|
|
+ sb.append(" and FIsLatest = 1").append("\n");
|
|
|
|
|
+ sb.append(" ) rank on rank.FPERSONID = person.fid").append("\n");
|
|
|
|
|
+ sb.append(" left join (").append("\n");
|
|
|
|
|
+ sb.append(" select").append("\n");
|
|
|
|
|
+ sb.append(" degree.FPERSONID personId,").append("\n");
|
|
|
|
|
+ sb.append(" diploma.FNAME_l2 as diplomaName").append("\n");
|
|
|
|
|
+ sb.append(" from").append("\n");
|
|
|
|
|
+ sb.append(" T_HR_PersonDegree degree").append("\n");
|
|
|
|
|
+ sb.append(" left join T_BD_HRDiploma diploma on degree.FDiploma = diploma.fid").append("\n");
|
|
|
|
|
+ sb.append(" where").append("\n");
|
|
|
|
|
+ sb.append(" degree.fpersonid = '" + personId + "'").append("\n");
|
|
|
|
|
+ sb.append(" and FIsSingle = 1").append("\n");
|
|
|
|
|
+ sb.append(" ) degree on degree.personId = person.fid").append("\n");
|
|
|
|
|
+ sb.append(" left join CT_MP_ManageCa ca on ca.fid = person.CFManageCaID").append("\n");
|
|
|
|
|
+ sb.append("left join CT_MP_PersonnelCl cl on cl.fid = person.CFPersonnelClID").append("\n");
|
|
|
|
|
+ sb.append("where").append("\n");
|
|
|
|
|
+ sb.append(" person.fid = '" + personId + "'").append("\n");
|
|
|
|
|
+ logger.error("getPersonBaseInfo--sql---" + sb.toString());
|
|
|
|
|
+ IRowSet iRowSet = DbUtil.executeQuery(ctx, sb.toString());
|
|
|
|
|
+ while (iRowSet.next()) {
|
|
|
|
|
+ //工作类型
|
|
|
|
|
+ baseMap.put("schemeName", iRowSet.getString("schemeName"));
|
|
|
|
|
+ //职级
|
|
|
|
|
+ baseMap.put("rankName", iRowSet.getString("rankName"));
|
|
|
|
|
+ //学历
|
|
|
|
|
+ baseMap.put("diplomaName", iRowSet.getString("diplomaName"));
|
|
|
|
|
+ //人员分类
|
|
|
|
|
+ baseMap.put("clName", iRowSet.getString("clName"));
|
|
|
|
|
+ //管理类别
|
|
|
|
|
+ baseMap.put("caName", iRowSet.getString("caName"));
|
|
|
|
|
+ }
|
|
|
|
|
+ return baseMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /******
|
|
|
|
|
+ * 获取定调薪申请人员ID
|
|
|
|
|
+ * @param billId
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public Map<String, Object> getAdjustSalaryApplyPersonIds(String billId) throws BOSException, SQLException {
|
|
|
|
|
+ Map<String, Object> map = new HashMap<String, Object>();
|
|
|
|
|
+ //套打人员ID
|
|
|
|
|
+ Set set = new HashSet();
|
|
|
|
|
+ //查询定调薪申请单
|
|
|
|
|
+ FilterInfo filterInfo = new FilterInfo();
|
|
|
|
|
+ FilterItemCollection filterItems = filterInfo.getFilterItems();
|
|
|
|
|
+ filterItems.add(new FilterItemInfo("id", AtsUtil.toSet(billId), CompareType.INCLUDE));
|
|
|
|
|
+ EntityViewInfo entityViewInfo = EntityViewInfo.getInstance(filterInfo, null, null);
|
|
|
|
|
+ IAdjustSalaryApply iAdjustSalaryApply = AdjustSalaryApplyFactory.getLocalInstance(ctx);
|
|
|
|
|
+ AdjustSalaryApplyCollection adjustSalaryApplyCollection = iAdjustSalaryApply.getAdjustSalaryApplyCollection(entityViewInfo);
|
|
|
|
|
+ for (int i = 0; i < adjustSalaryApplyCollection.size(); i++) {
|
|
|
|
|
+ AdjustSalaryApplyInfo adjustSalaryApplyInfo = adjustSalaryApplyCollection.get(i);
|
|
|
|
|
+ String sql = "SELECT FPersonID as personId,FEffectDate as stateDate FROM T_HR_SAdjApplyEntry02cmp where FBillID = '" + adjustSalaryApplyInfo.getId() + "'";
|
|
|
|
|
+ IRowSet iRowSet = DbUtil.executeQuery(ctx, sql);
|
|
|
|
|
+ while (iRowSet.next()) {
|
|
|
|
|
+ String personId = iRowSet.getString("personId");
|
|
|
|
|
+ Date stateDate = iRowSet.getDate("stateDate");
|
|
|
|
|
+ set.add(personId);
|
|
|
|
|
+ Map dataMap = new HashMap();
|
|
|
|
|
+ dataMap.put("billSource", adjustSalaryApplyInfo.getBillSource().getAlias());
|
|
|
|
|
+ dataMap.put("stateDate", DateTimeUtils.format(stateDate, "yyyy年hh月dd日"));
|
|
|
|
|
+ map.put(personId, dataMap);
|
|
|
|
|
+ map.put("personSet", set);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return map;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // -------------- 第一步:批量替换 Word 占位符 --------------
|
|
|
|
|
+ public static void batchReplaceWordPlaceholders(String templatePath, String tempWordPath, Map<String, String> dataMap) throws IOException {
|
|
|
|
|
+ FileInputStream fis = new FileInputStream(templatePath);
|
|
|
|
|
+ XWPFDocument document = new XWPFDocument(fis);
|
|
|
|
|
+
|
|
|
|
|
+ // 替换段落和表格中的占位符
|
|
|
|
|
+ replaceAllParagraphs(document, dataMap);
|
|
|
|
|
+ replaceAllTables(document, dataMap);
|
|
|
|
|
+
|
|
|
|
|
+ // 保存临时 Word 文档(替换后的 Word)
|
|
|
|
|
+ FileOutputStream fos = new FileOutputStream(tempWordPath);
|
|
|
|
|
+ document.write(fos);
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭资源
|
|
|
|
|
+ fos.close();
|
|
|
|
|
+ document.close();
|
|
|
|
|
+ fis.close();
|
|
|
|
|
+ System.out.println("Word 占位符替换完成,临时文件:" + tempWordPath);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 替换文档中所有段落的占位符
|
|
|
|
|
+ private static void replaceAllParagraphs(XWPFDocument document, Map<String, String> dataMap) {
|
|
|
|
|
+ for (XWPFParagraph para : document.getParagraphs()) {
|
|
|
|
|
+ replacePlaceholdersInParagraph(para, dataMap);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 替换文档中所有表格的占位符
|
|
|
|
|
+ private static void replaceAllTables(XWPFDocument document, Map<String, String> dataMap) {
|
|
|
|
|
+ for (XWPFTable table : document.getTables()) {
|
|
|
|
|
+ for (XWPFTableRow row : table.getRows()) {
|
|
|
|
|
+ for (XWPFTableCell cell : row.getTableCells()) {
|
|
|
|
|
+ for (XWPFParagraph para : cell.getParagraphs()) {
|
|
|
|
|
+ replacePlaceholdersInParagraph(para, dataMap);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 替换单个段落中的所有占位符
|
|
|
|
|
+ private static void replacePlaceholdersInParagraph(XWPFParagraph para, Map<String, String> dataMap) {
|
|
|
|
|
+ List<XWPFRun> runs = para.getRuns();
|
|
|
|
|
+ if (runs == null || runs.isEmpty()) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 拼接段落文本
|
|
|
|
|
+ StringBuilder paraText = new StringBuilder();
|
|
|
|
|
+ for (XWPFRun run : runs) {
|
|
|
|
|
+ String text = run.getText(0);
|
|
|
|
|
+ if (text != null) paraText.append(text);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String original = paraText.toString();
|
|
|
|
|
+ String replaced = original;
|
|
|
|
|
+
|
|
|
|
|
+ // 批量替换所有占位符
|
|
|
|
|
+ for (Map.Entry<String, String> entry : dataMap.entrySet()) {
|
|
|
|
|
+ replaced = replaced.replace(entry.getKey(), entry.getValue());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 更新段落内容(保留格式)
|
|
|
|
|
+ if (!replaced.equals(original)) {
|
|
|
|
|
+ for (XWPFRun run : runs) run.setText("", 0);
|
|
|
|
|
+ runs.get(0).setText(replaced, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // -------------- 第二步:Word 转 PDF --------------
|
|
|
|
|
+// public static void convertWordToPdf(String wordPath, String pdfPath) throws Exception {
|
|
|
|
|
+// FileInputStream fis = new FileInputStream(pdfPath);
|
|
|
|
|
+// // 加载 Word 文档
|
|
|
|
|
+// com.aspose.words.Document doc = new com.aspose.words.Document();
|
|
|
|
|
+// // 配置 PDF 保存选项(可选,优化格式)
|
|
|
|
|
+// PdfSaveOptions saveOptions = new PdfSaveOptions();
|
|
|
|
|
+// saveOptions.setCompliance(PdfCompliance.PDF_A_1_B); // 兼容 PDF 标准
|
|
|
|
|
+// saveOptions.setExportGeneratorName(true); // 保留页眉页脚
|
|
|
|
|
+// // 保存为 PDF
|
|
|
|
|
+// doc.save(pdfPath, saveOptions);
|
|
|
|
|
+// System.out.println("PDF 转换完成,输出文件:" + pdfPath);
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 9.9版本 下载url
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param ctx
|
|
|
|
|
+ * @param realFileName
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String getEncryRealFileName(Context ctx, String realFileName) {
|
|
|
|
|
+ UserInfo currentUserInfo = ContextUtil.getCurrentUserInfo(ctx);
|
|
|
|
|
+ return MessageFormat.format("{0}_{1}", realFileName, MD5.md5Hash(currentUserInfo.getId().toString()));
|
|
|
|
|
+ }
|
|
|
|
|
+ // -------------- 测试方法(一站式执行)--------------
|
|
|
|
|
+// public static void main(String[] args) {
|
|
|
|
|
+// // 1. 配置文件路径
|
|
|
|
|
+// String templatePath = "F:\\test/定调薪套打模板.docx"; // 原模板路径
|
|
|
|
|
+// String pdfOutputPath = "F:\\test/替换后的薪酬核定表PDF.pdf"; // 输出路径
|
|
|
|
|
+// // 2. 定义占位符-实际数据映射(同之前方案,可动态获取)
|
|
|
|
|
+// Map<String, String> dataMap = new HashMap<>();
|
|
|
|
|
+// // 基础信息
|
|
|
|
|
+// dataMap.put("T", "平级调薪"); // 异动类型
|
|
|
|
|
+// dataMap.put("X", "45602"); // 编码
|
|
|
|
|
+// dataMap.put("N", "技术岗"); // 员工类型(表格标题)
|
|
|
|
|
+// // 员工个人信息
|
|
|
|
|
+// dataMap.put("q", "李四"); // 员工姓名
|
|
|
|
|
+// dataMap.put("w", "EMP2024002"); // 工号
|
|
|
|
|
+// dataMap.put("e", "2024-02-20"); // 入职日期
|
|
|
|
|
+// dataMap.put("r", "大专"); // 学历
|
|
|
|
|
+// dataMap.put("t", "管理岗"); // 管理类别
|
|
|
|
|
+// dataMap.put("y", "研发二部"); // 所属组织
|
|
|
|
|
+// dataMap.put("u", "工程师"); // 职位
|
|
|
|
|
+// dataMap.put("i", "P4"); // 职级
|
|
|
|
|
+// // 工资结构
|
|
|
|
|
+// dataMap.put("A", "4000"); // 基本工资
|
|
|
|
|
+// dataMap.put("B", "1500"); // 加班工资
|
|
|
|
|
+// dataMap.put("C", "900"); // 技能工资
|
|
|
|
|
+// dataMap.put("J", "600"); // 岗位补贴
|
|
|
|
|
+// dataMap.put("E", "350"); // 学历补贴
|
|
|
|
|
+// dataMap.put("G", "10000"); // 月薪合计
|
|
|
|
|
+// dataMap.put("I", "月薪制"); // 工资类型
|
|
|
|
|
+// dataMap.put("F", "月薪制"); // 费用补贴
|
|
|
|
|
+// // 生效日期
|
|
|
|
|
+// dataMap.put("YYYYHHDD", "2024年08月15日");
|
|
|
|
|
+// try {
|
|
|
|
|
+// // 执行流程:替换占位符 → 转 PDF
|
|
|
|
|
+// batchReplaceWordPlaceholders(templatePath, pdfOutputPath, dataMap);
|
|
|
|
|
+// convertWordToPdf(pdfOutputPath, pdfOutputPath);
|
|
|
|
|
+//
|
|
|
|
|
+// // 可选:删除临时 Word 文件(如需保留可注释)
|
|
|
|
|
+//// File tempWordFile = new File(pdfOutputPath);
|
|
|
|
|
+//// if (tempWordFile.exists()) {
|
|
|
|
|
+//// tempWordFile.delete();
|
|
|
|
|
+//// System.out.println("临时 Word 文件已删除");
|
|
|
|
|
+//// }
|
|
|
|
|
+// } catch (Exception e) {
|
|
|
|
|
+// e.printStackTrace();
|
|
|
|
|
+// System.err.println("执行失败:" + e.getMessage());
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+}
|