package com.kingdee.eas.custom.perfweb.handler; import com.kingdee.bos.BOSException; import com.kingdee.bos.Context; import com.kingdee.bos.ctrl.swing.StringUtils; import com.kingdee.jdbc.rowset.IRowSet; import com.kingdee.eas.custom.perfweb.util.ReportFilterUtil; import com.kingdee.eas.custom.perfweb.util.ReportOrgUtil; import com.kingdee.eas.util.app.DbUtil; import com.kingdee.shr.base.syssetting.context.SHRContext; import com.kingdee.shr.base.syssetting.exception.SHRWebException; import com.kingdee.shr.base.syssetting.json.GridDataEntity; import com.kingdee.shr.base.syssetting.web.handler.ListHandler; import org.apache.log4j.Logger; import org.springframework.ui.ModelMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 类名称: PersonnelStructureDashboardHandler * 功能描述: 人员结构看板报表(按公司统计在职人数及占比) * 创建日期: 2026-06-05 * 作 者: 青梧 * 版 本: 1.0 * * 返回字段说明: * companyCode - 公司编码(FNUMBER) * companyName - 公司名称(合计行显示"合计") * personCount - 公司在职人数(FIsOnTheStrength=1) * percentage - 人数占全公司合计的百分比 */ public class PersonnelStructureDashboardHandler extends ListHandler { private static Logger logger = Logger.getLogger(PersonnelStructureDashboardHandler.class); Context ctx = SHRContext.getInstance().getContext(); /** * 列表查询入口:遍历二级公司,统计各公司在职人数及占比,末尾追加合计行。 */ @Override protected GridDataEntity getGridRequestData(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException { logger.error("PersonnelStructureDashboardHandler getGridRequestData------------"); GridDataEntity gridDataEntity = new GridDataEntity(); try { List companyList = getCompanyList(); int totalCount = 0; List> dataList = new ArrayList<>(); for (CompanyData company : companyList) { int count = getActivePersonCount(company.getId()); // 人数为0的公司不展示 if (count == 0) { continue; } totalCount += count; Map row = new HashMap<>(); row.put("companyCode", company.getCode()); // companyCode: 公司编码 row.put("companyName", company.getName()); // companyName: 公司名称 row.put("personCount", count); // personCount: 在职人数 row.put("percentage", 0.0); // percentage: 占比(第二遍回填) dataList.add(row); } // 按总人数计算各公司占比 for (Map row : dataList) { int count = (Integer) row.get("personCount"); double percentage = totalCount > 0 ? (count * 100.0 / totalCount) : 0.0; row.put("percentage", String.format("%.2f", percentage) + "%"); } Map totalRow = new HashMap<>(); totalRow.put("companyCode", ""); // companyCode: 合计行留空 totalRow.put("companyName", "合计"); // companyName: 合计标识 totalRow.put("personCount", totalCount); // personCount: 全公司在职合计 totalRow.put("percentage", totalCount > 0 ? "100.00%" : "0.00%"); // percentage: 100% dataList.add(totalRow); gridDataEntity.setRows(dataList); gridDataEntity.setTotal(dataList.size()); gridDataEntity.setPage(1); gridDataEntity.setRecords(dataList.size()); logger.error("人员结构看板报表数据查询成功,总记录数: " + dataList.size()); } catch (SQLException e) { logger.error("数据库查询失败", e); throw new SHRWebException("数据查询失败: " + e.getMessage()); } catch (BOSException e) { logger.error("业务异常", e); throw new SHRWebException("业务处理失败: " + e.getMessage()); } catch (Exception e) { logger.error("未知异常", e); throw new SHRWebException("系统异常: " + e.getMessage()); } ReportFilterUtil.applyGridUserData(request, gridDataEntity); return gridDataEntity; } /** * 查询二级公司列表(FLevel=2, 未封存)。 */ private List getCompanyList() throws BOSException, SQLException { List companyList = new ArrayList<>(); StringBuilder sql = new StringBuilder(); sql.append("SELECT FID, FNUMBER, FNAME_L2 FROM T_ORG_Admin "); sql.append("WHERE FLAYERTYPEID = '00000000-0000-0000-0000-00000000000262824988' "); sql.append("AND FIsSealUp = 0 "); sql.append("AND FLevel = 2 "); // 排除国际公司130及其下级 sql.append("AND FNUMBER <> '").append(ReportOrgUtil.EXCLUDED_ORG_NUMBER).append("' "); ReportOrgUtil.appendExcludeOrg130(sql, "T_ORG_Admin", ctx); logger.error("查询公司列表SQL: " + sql.toString()); IRowSet rs = DbUtil.executeQuery(ctx, sql.toString()); while (rs.next()) { String id = rs.getString("FID"); if (StringUtils.isEmpty(id)) { continue; } String code = rs.getString("FNUMBER"); String name = rs.getString("FNAME_L2"); companyList.add(new CompanyData(id, code, name)); } logger.error("查询到公司数量: " + companyList.size()); return companyList; } /** * 统计指定公司在职人数(FIsOnTheStrength=1),对应字段 personCount。 */ private int getActivePersonCount(String companyId) throws BOSException, SQLException { if (StringUtils.isEmpty(companyId)) { return 0; } StringBuilder sql = new StringBuilder(); sql.append("SELECT COUNT(*) as personCount "); sql.append("FROM T_BD_PERSON person "); sql.append("LEFT JOIN T_HR_PersonPosition personPos ON person.FID = personPos.FPERSONID "); sql.append("LEFT JOIN T_HR_BDEmployeeType type ON type.FID = person.FEMPLOYEETYPEID "); sql.append("WHERE type.FIsOnTheStrength = 1 "); sql.append("AND personPos.FCompanyID = ? "); ReportOrgUtil.appendExcludeOrg130ById(sql, "personPos.FPersonDep", ctx); logger.error("查询公司在职人数SQL,companyId: " + companyId); IRowSet rs = DbUtil.executeQuery(ctx, sql.toString(), new Object[]{companyId}); int count = 0; if (rs.next()) { count = rs.getInt("personCount"); } return count; } /** 公司基础信息(id/code/name) */ private static class CompanyData { private String id; private String code; private String name; public CompanyData(String id, String code, String name) { this.id = id; this.code = code; this.name = name; } public String getId() { return id; } public String getCode() { return code; } public String getName() { return name; } } }