feat(portal): 新增人员编制功能

- 添加人员编制相关的实体类和BO
- 实现人员编制数据的获取和解析
- 新增满编率计算功能- 优化员工基本信息展示
- 添加PAPI接口调用工具类
This commit is contained in:
dxfeng 2025-07-28 16:56:16 +08:00
parent 172a53cca9
commit 2582e7f8b8
20 changed files with 436 additions and 17 deletions

View File

@ -6,10 +6,7 @@ import com.weaver.seconddev.portal.entity.po.PortalPO;
import com.weaver.seconddev.portal.service.LeaderCockpitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@ -49,8 +46,8 @@ public class LeaderCockpitController {
}
@PostMapping("/getFullStaffingRate")
private WeaResult<List<PortalPO>> getFullStaffingRate(@RequestBody Map<String, String> params) {
return leaderCockpitService.getFullStaffingRate(params);
private WeaResult<List<PortalPO>> getFullStaffingRate(@RequestHeader Map<String, String> header,@RequestBody Map<String, String> params) {
return leaderCockpitService.getFullStaffingRate(header,params);
}
@PostMapping("/getEmploymentStatus")

View File

@ -0,0 +1,41 @@
package com.weaver.seconddev.portal.entity.bo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.weaver.seconddev.portal.entity.po.cfg.EmployeeStaff;
import java.util.List;
/**
* @author:dxfeng
* @createTime: 2025/07/23
* @version: 1.0
*/
public class EmployeeStaffBo {
public static List<EmployeeStaff> mapEmployeeStaffData(String responseJson) {
// 解析接口返回的 JSON 数据
JSONObject responseObj = JSON.parseObject(responseJson);
// 判断接口是否响应成功
if (responseObj.containsKey("code") && responseObj.getIntValue("code") == 200 && responseObj.containsKey("status") && responseObj.getBooleanValue("status")) {
// 判断是否存在 data displayData 字段
if (responseObj.containsKey("data")) {
JSONObject dataObj = responseObj.getJSONObject("data");
if (dataObj.containsKey("displayData")) {
// 解析 displayData 对象集合
return dataObj.getJSONArray("displayData").toJavaList(EmployeeStaff.class);
} else {
// displayData 字段不存在
throw new IllegalArgumentException("displayData 字段不存在");
}
} else {
// data 字段不存在
throw new IllegalArgumentException("data 字段不存在");
}
} else {
// 接口响应失败
String errorMsg = responseObj.getString("msg");
throw new RuntimeException("接口调用失败: " + errorMsg);
}
}
}

View File

@ -3,8 +3,6 @@ package com.weaver.seconddev.portal.entity.po;
import com.weaver.teams.domain.user.Avatar;
import lombok.Data;
import java.util.Date;
/**
* @author:dxfeng
* @createTime: 2025/07/14
@ -30,10 +28,11 @@ public class EmployeeBasicInfoPo {
* 公司名称
*/
private String companyName;
private String departmentName;
/**
* 入职日期
*/
private Date hireDate;
private String hireDate;
/**
* 人员状态
*/

View File

@ -0,0 +1,95 @@
package com.weaver.seconddev.portal.entity.po.cfg;
import lombok.Data;
/**
* @author:dxfeng
* @createTime: 2025/07/23
* @version: 1.0
*/
@Data
public class EmployeeStaff {
/**
* 主键id
*/
private String id;
/**
* 组织ID
*/
private String orgId;
/**
* 组织
*/
private String orgName;
/**
* 组织全名
*/
private String orgFullName;
private String isParent;
/**
* 编制方案ID
*/
private String planId;
/**
* 编制方案名称
*/
private String planName;
/**
* 年份
*/
private Integer year;
/**
* 超编管控
*/
private String overCtrl;
/**
* 编制数含下级
*/
private Integer estCountWithSub;
/**
* 编制数本级
*/
private Integer estCount;
/**
* 在编数本级
*/
private Integer numberingCount;
/**
* 在编数含下级
*/
private Integer numberingCountWithSub;
/**
* 预增数本级
*/
private Integer preAddEmpCount;
/**
* 预增数含下级
*/
private Integer preAddEmpCountWithSub;
/**
* 预减数本级
*/
private Integer preSubEmpCount;
/**
* 预减数含下级
*/
private Integer preSubEmpCountWithSub;
/**
* 缺编数本级
*/
private Integer estLackCount;
/**
* 缺编数含下级
*/
private Integer estLackCountWithSub;
/**
* 超编数本级
*/
private Integer estOverCount;
/**
* 超编数含下级
*/
private Integer estOverCountWithSub;
private Integer hasLink;
private Integer hasDc;
}

View File

@ -0,0 +1,28 @@
package com.weaver.seconddev.portal.entity.po.cfg;
/**
* @author: dxfeng
* @createTime: 2025/07/23
* @version: 1.0
*/
public class FormDatas {
private FormDatasDetail formDatas;
private QuickSearchDatas quickSearchDatas;
// Getters and Setters
public FormDatasDetail getFormDatas() {
return formDatas;
}
public void setFormDatas(FormDatasDetail formDatas) {
this.formDatas = formDatas;
}
public QuickSearchDatas getQuickSearchDatas() {
return quickSearchDatas;
}
public void setQuickSearchDatas(QuickSearchDatas quickSearchDatas) {
this.quickSearchDatas = quickSearchDatas;
}
}

View File

@ -0,0 +1,34 @@
package com.weaver.seconddev.portal.entity.po.cfg;
import java.util.List;
public class FormDatasDetail {
private List<OrgWrapper> org;
private List<OverCtrlWrapper> overCtrl;
private List<MonthWrapper> month;
// Getters and Setters
public List<OrgWrapper> getOrg() {
return org;
}
public void setOrg(List<OrgWrapper> org) {
this.org = org;
}
public List<OverCtrlWrapper> getOverCtrl() {
return overCtrl;
}
public void setOverCtrl(List<OverCtrlWrapper> overCtrl) {
this.overCtrl = overCtrl;
}
public List<MonthWrapper> getMonth() {
return month;
}
public void setMonth(List<MonthWrapper> month) {
this.month = month;
}
}

View File

@ -0,0 +1,14 @@
package com.weaver.seconddev.portal.entity.po.cfg;
public class MonthWrapper {
private String month;
// Getters and Setters
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
}

View File

@ -0,0 +1,14 @@
package com.weaver.seconddev.portal.entity.po.cfg;
public class OrgItem {
private String id;
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@ -0,0 +1,16 @@
package com.weaver.seconddev.portal.entity.po.cfg;
import java.util.List;
public class OrgWrapper {
private List<OrgItem> org;
// Getters and Setters
public List<OrgItem> getOrg() {
return org;
}
public void setOrg(List<OrgItem> org) {
this.org = org;
}
}

View File

@ -0,0 +1,14 @@
package com.weaver.seconddev.portal.entity.po.cfg;
public class OverCtrlWrapper {
private String overCtrl;
// Getters and Setters
public String getOverCtrl() {
return overCtrl;
}
public void setOverCtrl(String overCtrl) {
this.overCtrl = overCtrl;
}
}

View File

@ -0,0 +1,4 @@
package com.weaver.seconddev.portal.entity.po.cfg;
public class QuickSearchDatas {
}

View File

@ -42,4 +42,12 @@ public interface EbuilderBaseMapper {
* @return
*/
List<FormdataTemplateDetails> getFormdataTemplateDetails(@Param("param") BaseParam param, @Param("templateId") long templateId);
/**
* 根据表名获取对象ID
* @param param
* @param tableName
* @return
*/
Long getObjIdByTableName(@Param("param") BaseParam param, @Param("tableName") String tableName);
}

View File

@ -51,9 +51,10 @@ public interface LeaderCockpitService {
* 获取满编率
*
* @param params
* @param header
* @return
*/
WeaResult<List<PortalPO>> getFullStaffingRate(Map<String, String> params);
WeaResult<List<PortalPO>> getFullStaffingRate(Map<String, String> header, Map<String, String> params);
/**
* 获取入职情况

View File

@ -13,12 +13,12 @@ import com.weaver.seconddev.portal.enums.PersonnelStatusEnum;
import com.weaver.seconddev.portal.mapper.PortalMapper;
import com.weaver.seconddev.portal.service.EmployeePortalService;
import com.weaver.seconddev.portal.util.DateUtil;
import com.weaver.teams.domain.department.SimpleDepartment;
import com.weaver.teams.domain.user.Avatar;
import com.weaver.teams.domain.user.SimpleEmployee;
import com.weaver.teams.security.context.UserContext;
import com.weaver.teams.security.user.User;
import com.weaver.workflow.common.cfg.org.service.DepartMentService;
import com.weaver.workflow.common.entity.org.WeaDepartMent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -70,14 +70,16 @@ public class EmployeePortalServiceImpl implements EmployeePortalService {
employeeBasicInfoPo.setEmployeeId(currentUser.getEmployeeId());
SimpleEmployee byId = hrmCommonEmployeeDao.getById(currentUser.getEmployeeId());
SimpleDepartment department = byId.getDepartment();
Avatar avatar = byId.getAvatar();
employeeBasicInfoPo.setAvatar(avatar);
employeeBasicInfoPo.setUserName(byId.getUsername());
employeeBasicInfoPo.setWorkCode(byId.getJobNum());
WeaDepartMent departmentById = departMentService.getDepartMentById(byId.getDepartmentId());
employeeBasicInfoPo.setCompanyName(null != departmentById ? departmentById.getDepartMentName() : "");
//WeaDepartMent departmentById = departMentService.getDepartMentById(byId.getDepartmentId());
//employeeBasicInfoPo.setCompanyName(null != departmentById ? departmentById.getDepartMentName() : "");
employeeBasicInfoPo.setDepartmentName(null==department?"":department.getName());
employeeBasicInfoPo.setHireDate(byId.getHiredate());
employeeBasicInfoPo.setHireDate(cn.hutool.core.date.DateUtil.formatDate(byId.getHiredate()));
employeeBasicInfoPo.setEmployeeStatus(PersonnelStatusEnum.getShowNameByValue(byId.getPersonnelStatus()));
SimpleEmployee superior = byId.getSuperior();

View File

@ -1,12 +1,15 @@
package com.weaver.seconddev.portal.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.weaver.common.base.entity.result.WeaResult;
import com.weaver.common.hrm.dao.HrmCommonEmployeeDao;
import com.weaver.seconddev.portal.entity.bo.EmployeeStaffBo;
import com.weaver.seconddev.portal.entity.param.SearchConditionParam;
import com.weaver.seconddev.portal.entity.po.PortalData;
import com.weaver.seconddev.portal.entity.po.PortalPO;
import com.weaver.seconddev.portal.entity.po.cfg.*;
import com.weaver.seconddev.portal.mapper.LeaderCockpitMapper;
import com.weaver.seconddev.portal.service.LeaderCockpitService;
import com.weaver.seconddev.portal.util.DateUtil;
@ -86,10 +89,54 @@ public class LeaderCockpitServiceImpl implements LeaderCockpitService {
}
@Override
public WeaResult<List<PortalPO>> getFullStaffingRate(Map<String, String> params) {
public WeaResult<List<PortalPO>> getFullStaffingRate(Map<String, String> header, Map<String, String> params) {
String origin = header.get("origin");
// 人员编制
String employeeStaffUrl = origin + "/api/bs/hr/est/cfg/table";
// 人员编制具体信息
String getEmployeeDetailUrl = origin + "/api/bs/hr/est/cfg/emp/table";
String beginDate = DateUtil.getFirstDayOfMonth();
String endDate = DateUtil.getLastDayOfMonth();
SearchConditionParam searchConditionParam = new SearchConditionParam();
initSearchConditionParam(searchConditionParam, params, null);
log.error("searchConditionParam===" + JSON.toJSONString(searchConditionParam));
//postEmployeeStaff(employeeStaffUrl, header, searchConditionParam.getDepartmentIdList(), month);
return null;
}
private void postEmployeeStaff(String employeeStaffUrl,Map<String, String> header, Set<Long> departmentIdList, String month) {
FormDatas formDatas = new FormDatas();
FormDatasDetail formDatasDetail = new FormDatasDetail();
formDatas.setFormDatas(formDatasDetail);
List<OrgItem> orgItemList = new ArrayList<>();
for (Long aLong : departmentIdList) {
OrgItem orgItem = new OrgItem();
orgItem.setId(aLong + "");
orgItemList.add(orgItem);
}
OrgWrapper orgWrapper = new OrgWrapper();
orgWrapper.setOrg(orgItemList);
formDatasDetail.setOrg(Collections.singletonList(orgWrapper));
MonthWrapper monthWrapper = new MonthWrapper();
monthWrapper.setMonth(month);
formDatasDetail.setMonth(Collections.singletonList(monthWrapper));
OverCtrlWrapper overCtrlWrapper = new OverCtrlWrapper();
overCtrlWrapper.setOverCtrl("all");
formDatasDetail.setOverCtrl(Collections.singletonList(overCtrlWrapper));
String resultStr = HttpRequest.post(employeeStaffUrl).headerMap(header, true)
.body(JSON.toJSONString(formDatas)).execute().body();
List<EmployeeStaff> employeeStaffs = EmployeeStaffBo.mapEmployeeStaffData(resultStr);
}
@Override
public WeaResult<Map<String, Object>> getEmploymentStatus(Map<String, String> params) {
SearchConditionParam searchConditionParam = new SearchConditionParam();
@ -177,7 +224,7 @@ public class LeaderCockpitServiceImpl implements LeaderCockpitService {
String firstDayOfMonthStr = DateUtil.getFirstDayOfPreviousMonthStr(searchConditionParam.getStartDate());
String lastDayOfMonthStr = DateUtil.getLastDayOfPreviousMonthStr(searchConditionParam.getEndDate());
// 个月
// 个月
for (int i = 1; i < 7; i++) {
allDataMap.put(DateUtil.formatToYearMonth_ZH(firstDayOfMonthStr), leaderCockpitMapper.getResignCount(searchConditionParam, searchConditionParam.getDepartmentIdList(), firstDayOfMonthStr, lastDayOfMonthStr));
keyDataMap.put(DateUtil.formatToYearMonth_ZH(firstDayOfMonthStr), leaderCockpitMapper.getKeyResignCount(searchConditionParam, searchConditionParam.getDepartmentIdList(), firstDayOfMonthStr, lastDayOfMonthStr));

View File

@ -279,7 +279,7 @@ public class ManagerPortalServiceImpl implements ManagerPortalService {
if (CollectionUtils.isNotEmpty(allDepartmentIdList)) {
andCondition.add(" t1.department in (" + StringUtils.join(allDepartmentIdList, ",") + ") ");
}
andCondition.add(" ( ( DATE_FORMAT(t1.hiredate, '%m-%d') between DATE_FORMAT(CURDATE(), '%m-%d') and DATE_FORMAT(DATE_ADD(CURDATE(), interval 7 day), '%m-%d') ) or ( DATE_FORMAT(CURDATE(), '%m-%d') & gt; DATE_FORMAT(DATE_ADD(CURDATE(), interval 7 day), '%m-%d') and ( DATE_FORMAT(t1.hiredate, '%m-%d') & gt; = DATE_FORMAT(CURDATE(), '%m-%d') or DATE_FORMAT(t1.hiredate, '%m-%d') & lt; = DATE_FORMAT(DATE_ADD(CURDATE(), interval 7 day), '%m-%d') ) ) ) ");
andCondition.add(" ( ( DATE_FORMAT(t1.hiredate, '%m-%d') between DATE_FORMAT(CURDATE(), '%m-%d') and DATE_FORMAT(DATE_ADD(CURDATE(), interval 7 day), '%m-%d') ) or ( DATE_FORMAT(CURDATE(), '%m-%d') &gt; DATE_FORMAT(DATE_ADD(CURDATE(), interval 7 day), '%m-%d') and ( DATE_FORMAT(t1.hiredate, '%m-%d') &gt;= DATE_FORMAT(CURDATE(), '%m-%d') or DATE_FORMAT(t1.hiredate, '%m-%d') &lt;= DATE_FORMAT(DATE_ADD(CURDATE(), interval 7 day), '%m-%d') ) ) ) ");
break;
default:
break;

View File

@ -72,6 +72,13 @@ public class DateUtil {
return date.format(DEFAULT_DATE_FORMATTER);
}
public static String formatDate(LocalDateTime dateTime) {
if (dateTime == null) {
return null;
}
return dateTime.format(DEFAULT_DATE_FORMATTER);
}
/**
* 格式化LocalDateTime为字符串
*/

View File

@ -0,0 +1,66 @@
package com.weaver.seconddev.portal.util;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import constant.ApplicationConfigConstant;
/**
* @author:dxfeng
* @createTime: 2025/07/28
* @version: 1.0
*/
public class PapiUtil {
/**
* 获取papi授权码
*
* @param url
* @param corpId
* @param state
* @return
*/
public static String getPapiCode(String url, String corpId, String state) {
JSONObject bodyJson = new JSONObject();
bodyJson.put("corpid", corpId);
bodyJson.put("response_type", "code");
bodyJson.put("state", state);
String resultStr = HttpRequest.post(url + "/papi/openapi/oauth2/authorize")
.body(bodyJson.toJSONString())
.execute()
.body();
JSONObject jsonObject = JSONObject.parseObject(resultStr);
return jsonObject.getString("code");
}
/**
* 获取papi token
*
* @param url
* @param appKey
* @param appSecret
* @param code
* @return
*/
public static String getPapiToken(String url, String appKey, String appSecret, String code) {
JSONObject bodyJson = new JSONObject();
bodyJson.put("app_key", appKey);
bodyJson.put("app_secret", appSecret);
bodyJson.put("grant_type", "authorization_code");
bodyJson.put("code", code);
String resultStr = HttpRequest.post(url + "/papi/openapi/oauth2/access_token")
.header("Content-Type", "application/x-www-form-urlencoded")
.body(bodyJson.toJSONString())
.execute()
.body();
JSONObject jsonObject = JSONObject.parseObject(resultStr);
return jsonObject.getString("accessToken");
}
public static void main(String[] args) {
String papiCode = getPapiCode(ApplicationConfigConstant.APP_URL, ApplicationConfigConstant.CORP_ID, "A1a");
System.out.println("papiCode==" + papiCode);
String papiToken = getPapiToken(ApplicationConfigConstant.APP_URL, ApplicationConfigConstant.ORGANIZATION_APP_KEY, ApplicationConfigConstant.ORGANIZATION_APP_SECRET, papiCode);
System.out.println("papiToken==" + papiToken);
}
}

View File

@ -0,0 +1,26 @@
package constant;
/**
* @author:dxfeng
* @createTime: 2025/07/28
* @version: 1.0
*/
public class ApplicationConfigConstant {
/**
* 应用端URL
*/
public static final String APP_URL = "http://10.60.4.124:30609";
/**
* Corp id
*/
public static final String CORP_ID = "ec7de918480e79abe774982cf075c045";
/**
* 组织中心APP Key
*/
public static final String ORGANIZATION_APP_KEY = "c003f58a174a12abebb9fdfa5ba800c2";
/**
* 组织中心APP Secret
*/
public static final String ORGANIZATION_APP_SECRET = "332ed6328a15f6189efa4d2ac5935bc1";
}

View File

@ -22,4 +22,10 @@
order by t.`order`
</select>
<select id="getObjIdByTableName" resultType="java.lang.Long">
select t.id from ${param.e10_common}.ebdf_obj t where
t.tenant_key = #{param.tenantKey} and t.delete_type = 0
and t.table_name = #{tableName}
</select>
</mapper>