zqy vor 2 Wochen
Ursprung
Commit
7cee26dad4

+ 251 - 0
doc/接口开发.md

@@ -0,0 +1,251 @@
+### 一.获取组织信息接口
+服务名:getOrgInfoOsfService
+
+参数:
+
+| 字段名 | 类型 | 必填 | 说明 | 示例 |
+| :--- | :--- | :--- | :--- | :--- |
+| layerType | String | 否 | 组织类型(精确匹配) | 公司 |
+| modifyDate | String | 否 | 最后修改日期(>= 该日期) | yyyy-MM-dd |
+| name | String | 否 | 组织名称(左模糊匹配) | 业务部 |
+| code | String | 否 | 组织编号(精确匹配) | 010056 |
+| size | int | 否 | 每页条数(默认100,最大1000) | 100 |
+| page | int | 否 | 页码(默认1) | 1 |
+
+字段:
+
+| 描述 | 接口字段 | 类型 | 说明 |
+| --- | --- | --- | --- |
+| 组织名称 | name | String |  |
+| 组织全称 | fullname | String |  |
+| 组织编号 | code | String |  |
+| 上级组织 | parent | String | 区分大小写的字符串uuid |
+| 组织全编码 | fullnumber | String | 根据”!”分割,前一数字是上级组织编号 |
+| 显示顺序 | disporder | String | 根据”!”分割,前一数字是上级组织排序码 |
+| 是否启用 | status | String | 1(有效);0(封存),与DB字段fissealup取反 |
+| 主键 | id | String | 区分大小写的字符串uuid |
+| 备注 | description | String |  |
+| 修改日期 | modifyDate | String | 当前版本不返回此字段 |
+| 组织类型 | layerType | String | 公司 / 部门 / 集团 / 子中心 / 中心 / 公司(新) |
+
+返回说明:
+
+| 字段名 | 类型 | 说明 |
+| :--- | :--- | :--- |
+| code | String | 状态码(200:成功, 500:异常) |
+| msg | String | 提示信息 |
+| page | int | 当前页码 |
+| size | int | 每页条数 |
+| data | Array | 组织列表,结构见”字段”表 |
+
+使用sdk调用示例(Java)
+
+| OSFWSClient osfwsClient = new OSFWSClient();<br/>String shrAddr = “[http://192.168.1.250:6888/shr](http://192.168.1.250:6888/shr)”;<br/>Map<String, Object> map = new HashMap();<br/>map.put(“modifyDate”, “2025-01-01”);<br/>map.put(“layerType”, “部门”);<br/>map.put(“page”, 1);<br/>map.put(“size”, 100);<br/>String result = osfwsClient.proceedOSF(shrAddr, “getOrgInfoOsfService”, map);<br/>System.out.println(result); |
+| :--- |
+
+
+### 二.获取岗位信息接口
+服务名:getPosInfoOsfService
+
+参数:
+
+| 字段名 | 类型 | 必填 | 说明 | 示例 |
+| :--- | :--- | :--- | :--- | :--- |
+| modifyDate | String | 否 | 修改日期(范围过滤:岗位或人员职位 >= 该日期) | yyyy-MM-dd |
+| name | String | 否 | 岗位名称(左模糊匹配) | 经理 |
+| code | String | 否 | 岗位编号(精确匹配) | 010056 |
+| size | int | 否 | 每页条数(默认100,最大1000) | 100 |
+| page | int | 否 | 页码(默认1) | 1 |
+
+字段:
+
+| 描述 | 接口字段 | 类型 | 说明 |
+| --- | --- | --- | --- |
+| 是否负责人岗 | isrespposition | String | 1(是),0(否) |
+| 岗位名称 | name | String |  |
+| 岗位编号 | code | String |  |
+| 显示顺序 | disporder | String |  |
+| 所属组织ID | department | String | 区分大小写的字符串uuid |
+| 上级岗位 | parent | String | 区分大小写的字符串uuid |
+| 部门副职 | vice | String | 1(是),0(否) |
+| 备注 | description | String |  |
+| 主键 | id | String | 区分大小写的字符串uuid |
+
+返回说明:
+
+| 字段名 | 类型 | 说明 |
+| :--- | :--- | :--- |
+| code | String | 状态码(200:成功, 500:异常) |
+| msg | String | 提示信息 |
+| page | int | 当前页码 |
+| size | int | 每页条数 |
+| data | Array | 岗位列表,结构见”字段”表 |
+
+使用sdk调用示例(Java)
+
+| OSFWSClient osfwsClient = new OSFWSClient();<br/>String shrAddr = “[http://192.168.1.250:6888/shr](http://192.168.1.250:6888/shr)”;<br/>Map<String, Object> map = new HashMap();<br/>map.put(“modifyDate”, “2025-01-01”);<br/>map.put(“name”, “经理”);<br/>map.put(“page”, 1);<br/>map.put(“size”, 100);<br/>String result = osfwsClient.proceedOSF(shrAddr, “getPosInfoOsfService”, map);<br/>System.out.println(result); |
+| :--- |
+
+
+### 三.人员接口
+参数:
+
+| 字段名 | 类型 | 必填 | 说明 | 示例 |
+| :--- | :--- | :--- | :--- | :--- |
+| modifyTime | String | 否 | 修改时间 | yyyy-MM-dd |
+
+
+字段:
+
+| 描述 | 接口字段 | 类型 | 示例 |
+| --- | --- | --- | --- |
+| <font style="color:#FF0000;">姓名</font> | <font style="color:#FF0000;">username</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">邮箱</font> | <font style="color:#FF0000;">email</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">上级</font> | <font style="color:#FF0000;">superior</font> | Array[String] | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">手机</font> | <font style="color:#FF0000;">mobile</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">性别</font> | <font style="color:#FF0000;">sex</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">工号</font> | <font style="color:#FF0000;">job_num</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">所属组织</font> | <font style="color:#FF0000;">department</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">岗位</font> | <font style="color:#FF0000;">position</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">状态</font> | <font style="color:#FF0000;">personnel_status</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">登录名</font> | <font style="color:#FF0000;">loginid</font> | string | <font style="color:#FF0000;"></font> |
+| <font style="color:#FF0000;">办公电话</font> | <font style="color:#FF0000;">telephone</font> | string | <font style="color:#FF0000;"></font> |
+| 其他上级 | other_superior | Array[String] |  |
+| 别名 | alias | string |  |
+| 入职时间 | hiredate | string |  |
+| 职级 | grade | string |  |
+| 办公地点 | location | string |  |
+| 身份证 | id_no | string |  |
+| 出生日期 | birthday | string |  |
+| 年龄 | age | string |  |
+| 毕业日期 | graduate_date | string |  |
+| 毕业院校 | graduate_school | string |  |
+| 学位 | degree | string |  |
+| 学历学历 | education | string |  |
+| 婚姻状况 | marital_status | string |  |
+| 籍贯 | native_place | string |  |
+| 民族 | nation | string |  |
+| 户口类型 | household_type | string |  |
+| 政治面貌 | politics_status | string |  |
+| 现居住地 | residence_place | string |  |
+| 家庭联系方式 | family_contact | string |  |
+| 首次参加工作日期 | first_work_date | string |  |
+| 个人工龄(年) | work_year | string |  |
+| 子女状态 | child_status | string |  |
+| 仅人员新增有效;不允许修改。(该字段仅可以传递 手机号码或者邮箱) | account | string |  |
+| 密码 | password | string |  |
+| 安全级别 | sec_level | string |  |
+| 密级 | classification | string |  |
+| 第三方主键 | outkey | string |  |
+
+
+### 四.分管领导接口
+服务名:getRoleSupervisorInfoOsfService
+
+参数:
+
+| 字段名 | 类型 | 必填 | 说明 | 示例 |
+| :--- | :--- | :--- | :--- | :--- |
+| modifyDate | String | 否 | 修改日期(范围过滤:角色或人员-角色关联 >= 该日期) | yyyy-MM-dd |
+| name | String | 否 | 角色名称(左模糊匹配) | 分管领导 |
+| code | String | 否 | 角色编号(精确匹配) | 010056 |
+| size | int | 否 | 每页条数(默认100,最大1000) | 100 |
+| page | int | 否 | 页码(默认1) | 1 |
+
+字段:
+
+| 描述 | 接口字段 | 类型 | 说明                                 |
+| --- | --- | --- |------------------------------------|
+| 主键 | id | String | 区分大小写的字符串uuid(人员-角色关联表主键)          |
+| 角色ID | roleid | String | 区分大小写的字符串uuid(关联 T_WFR_WFROLE.FID) |
+| 组织ID | orgid | String | 区分大小写的字符串uuid                      |
+| 人员ID | personid | String | 区分大小写的字符串uuid                      |
+| 是否包含下级 | isinclude | String | 1(是),0(否)                          |
+| 是否委托 | isdele | String | 1(是),0(否)                          |
+| 委托操作人 | deleperson | String | 区分大小写的字符串uuid                      |
+| 角色名称 | rolename | String |                                    |
+| 角色编号 | rolenumber | String |                                    |
+| 角色描述 | roledescribe | String |                                    |
+| 角色类型 | roletype | String | 0  (职员角色),1  (职位角色),2  (组织角色)      |
+| 角色状态 | state | String | 1  (启用),0(禁用)                      |
+
+返回说明:
+
+| 字段名 | 类型 | 说明 |
+| :--- | :--- | :--- |
+| code | String | 状态码(200:成功, 500:异常) |
+| msg | String | 提示信息 |
+| page | int | 当前页码 |
+| size | int | 每页条数 |
+| data | Array | 角色成员列表,结构见"字段"表 |
+
+使用sdk调用示例(Java)
+
+| OSFWSClient osfwsClient = new OSFWSClient();<br/>String shrAddr = "[http://192.168.1.250:6888/shr](http://192.168.1.250:6888/shr)";<br/>Map<String, Object> map = new HashMap();<br/>map.put("modifyDate", "2025-01-01");<br/>map.put("name", "分管领导");<br/>map.put("page", 1);<br/>map.put("size", 100);<br/>String result = osfwsClient.proceedOSF(shrAddr, "getRoleSupervisorInfoOsfService", map);<br/>System.out.println(result); |
+| :--- |
+
+
+
+
+
+
+### 五:人员兼职接口
+参数:
+
+| 字段名 | 类型 | 必填 | 说明 | 示例 |
+| :--- | :--- | :--- | :--- | :--- |
+| modifyTime | String | 否 | 修改时间 | yyyy-MM-dd |
+
+
+字段:
+
+| 描述 | 接口字段 | 类型 | 示例 |
+| --- | --- | --- | --- |
+| <font style="color:#FF0000;">主身份人员id</font> | <font style="color:#FF0000;">id</font> | String | |
+| <font style="color:#FF0000;">兼职部门或者分部</font> | <font style="color:#FF0000;">departmentId</font> | String | |
+| <font style="color:#FF0000;">兼职岗位</font> | <font style="color:#FF0000;">positionId</font> | String | |
+| <font style="color:#FF0000;">兼职上级</font> | <font style="color:#FF0000;">superior</font> | Array[String] | |
+| <font style="color:#FF0000;">兼职开始时间</font> | <font style="color:#FF0000;">start_date</font> | String | |
+| <font style="color:#FF0000;">兼职结束时间</font> | <font style="color:#FF0000;">end_date</font> | String | |
+| 备注 | remark | String | |
+
+
+### 六.保存打卡记录接口
+服务名:savePunchCardRecords
+
+参数:
+
+| 字段名 | 类型 | 必填 | 说明 | 示例            |
+| :--- | :--- | :--- | :--- |:--------------|
+| EquNo | String | 是	 | 打卡来源 | OA            |
+| CardId	 | String | 是		 | 员工工号 | 904213        |
+| RecDate | String | 是 | 打卡日期 | 2025-11-07 		 |
+| RecTime | String | 是  | 打卡时间 | 09:00:00      |
+| Address	 | String 		 | 是 | 打卡地点 | 广东惠州          |
+
+
+返回说明:
+
+| 字段名 | 类型 | 说明 |
+| :--- | :--- | :--- |
+| recordCtn	 | int | 总数 |
+| successCtn | int | 成功数 |
+| formatErrorRecords | Array | 格式化失败打卡记录列表 |
+| notExistRecords	 | Array | 获取人员信息失败打卡记录列表 |
+| duplicateRecords | Array | 重复打卡记录列表 |
+
+
+使用sdk调用示例(Java)
+
+| OSFWSClient osfwsClient = new OSFWSClient();<br/>String shrAddr = "[<u>http://192.168.1.250:6888/shr</u>](http://192.168.1.250:6888/shr)";<br/>Map<String, String> paramMap = new HashMap();<br/>paramMap.put("EquNo","OA001");<br/>paramMap.put("CardId","980132");<br/>paramMap.put("RecDate","2026-06-15");<br/>paramMap.put("RecTime","09:00");<br/>list.add(paramMap);<br/>Gson gson =new Gson();<br/>param.put("records",gson.toJson(list));<br/>String result = osfwsClient.proceedOSF(shrAddr, "savePunchCardRecords", map);<br/>System.out.println(result); |
+| :--- |
+
+
+
+
+### 七:单点登录集成
+
+
+
+
+### 八:待办集成

+ 236 - 0
websrc/com/kingdee/eas/custom/szpgm/osf/service/GetOrgInfoOsfService.java

@@ -0,0 +1,236 @@
+package com.kingdee.eas.custom.szpgm.osf.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import org.apache.commons.lang3.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 获取组织信息接口
+ * <p>
+ * 根据组织类型、最后修改日期、组织名称、组织编号等条件分页查询组织基础信息,
+ * 包含组织名称、编号、上下级关系、状态等字段。
+ * </p>
+ *
+ * <h3>入参说明</h3>
+ * <pre>
+ * layerType  - 组织类型(如:公司、部门、集团、中心、子中心、公司(新))
+ * modifyDate - 最后修改日期(yyyy-MM-dd)
+ * name       - 组织名称(左模糊匹配)
+ * code       - 组织编号(精确匹配)
+ * size       - 每页条数(可选,默认100,最大1000)
+ * page       - 页码(可选,默认1)
+ * </pre>
+ *
+ * <h3>返回值说明</h3>
+ * <pre>
+ * code    - 状态码(200:成功, 500:异常)
+ * msg     - 提示信息
+ * page    - 当前页码
+ * size    - 每页条数
+ * data    - 组织列表,每项包含:
+ *   id          - 主键
+ *   name        - 组织名称
+ *   fullname    - 组织全称
+ *   code        - 组织编号
+ *   parent      - 上级组织ID
+ *   fullnumber  - 组织全编码
+ *   disporder   - 显示顺序
+ *   status      - 是否启用(1:有效, 0:封存,与数据库fissealup取反)
+ *   description - 备注
+ *   modifyDate  - 修改日期(yyyy-MM-dd,当前版本不返回此字段)
+ *   layerType   - 组织类型
+ * </pre>
+ *
+ * @author szpgm
+ * @since 1.0.0
+ */
+public class GetOrgInfoOsfService implements IHRMsfService {
+
+    /**
+     * 处理组织信息查询请求
+     *
+     * @param context 上下文对象
+     * @param map     入参,支持以下 key:
+     *                <ul>
+     *                  <li><b>layerType</b>  - 组织类型(可选,精确匹配)</li>
+     *                  <li><b>modifyDate</b> - 最后修改日期(可选,yyyy-MM-dd)</li>
+     *                  <li><b>name</b>       - 组织名称(可选,左模糊匹配)</li>
+     *                  <li><b>code</b>       - 组织编号(可选,精确匹配)</li>
+     *                  <li><b>page</b>       - 页码(可选,默认1)</li>
+     *                  <li><b>size</b>       - 每页条数(可选,默认100,最大1000)</li>
+     *                </ul>
+     * @return Map&lt;String, Object&gt;,包含 code、msg、page、size、data 字段
+     * @throws EASBizException 业务异常
+     * @throws BOSException    平台异常
+     */
+    @Override
+    public Object process(Context context, Map map) throws EASBizException, BOSException {
+        Map<String, Object> result = new HashMap<String, Object>();
+        List<Map<String, Object>> list = new ArrayList<>();
+
+        // ---------- 入参解析 ----------
+        String layerType = (String) map.get("layerType");
+        String modifyDate = (String) map.get("modifyDate");
+        String name = (String) map.get("name");
+        String code = (String) map.get("code");
+
+        // 每页条数(默认100,上限1000)
+        int maxSize = 1000;
+        int size = 100;
+        if (map.get("size") != null) {
+            if (map.get("size") instanceof Integer) {
+                size = (int) map.get("size");
+            } else if (map.get("size") instanceof String) {
+                size = Integer.parseInt((String) map.get("size"));
+            }
+            size = Math.min(maxSize, size);
+        }
+
+        // 页码(默认1)
+        int page = 1;
+        if (map.get("page") != null) {
+            if (map.get("page") instanceof Integer) {
+                page = (int) map.get("page");
+            } else if (map.get("page") instanceof String) {
+                page = Integer.parseInt((String) map.get("page"));
+            }
+        }
+
+        // ---------- 查询数据 ----------
+        try {
+            result.put("msg", "成功");
+            result.put("code", "200");
+            result.put("page", page);
+            result.put("size", size);
+            result.put("data", list);
+
+            // 构建基础SQL并动态追加过滤条件
+            StringBuilder sql = getSql();
+            List<Object> paramArr = new ArrayList<>();
+
+            // 修改日期过滤:组织最后修改时间 >= 指定日期
+            if (StringUtils.isNotBlank(modifyDate)) {
+                sql.append(" and org.flastupdatetime >= ? ");
+                paramArr.add(modifyDate);
+            }
+
+            // 组织类型精确匹配
+            if (StringUtils.isNotBlank(layerType)) {
+                sql.append(" and lt.fname_l2 = ? ");
+                paramArr.add(layerType);
+            }
+
+            // 组织名称左模糊匹配
+            if (StringUtils.isNotBlank(name)) {
+                sql.append(" and org.fname_l2 like ? ");
+                paramArr.add(name + "%");
+            }
+
+            // 组织编号精确匹配
+            if (StringUtils.isNotBlank(code)) {
+                sql.append(" and org.fnumber = ? ");
+                paramArr.add(code);
+            }
+
+            // 分页:LIMIT 条数 OFFSET 偏移量
+            sql.append(" LIMIT ? OFFSET ? ");
+            paramArr.add(size);
+            paramArr.add(((page - 1) * size));
+
+            // 执行查询
+            IRowSet rs = DbUtil.executeQuery(context, sql.toString(), paramArr.toArray());
+
+            // 日期格式化器(yyyy-MM-dd)
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            while (rs.next()) {
+                Map<String, Object> params = new HashMap<String, Object>();
+
+                // 组织名称
+                params.put("name", rs.getString("name"));
+                // 组织全称
+                params.put("fullname", rs.getString("fullname"));
+                // 组织编号
+                params.put("code", rs.getString("code"));
+                // 上级组织ID
+                params.put("parent", rs.getString("parent"));
+                // 组织全编码(长编码路径)
+                params.put("fullnumber", rs.getString("fullnumber"));
+                // 显示顺序
+                params.put("disporder", rs.getString("disporder"));
+                // 是否启用(DB字段fissealup: 1=封存,0=有效 → 取反后: 1=有效,0=封存)
+                int statusVal = rs.getInt("status");
+                params.put("status", statusVal == 1 ? "0" : "1");
+                // 主键ID
+                params.put("id", rs.getString("id"));
+                // 备注
+                params.put("description", rs.getString("description"));
+                // 修改日期(当前版本不返回此字段,如需返回请取消注释)
+                //Date modifyDateVal = rs.getTimestamp("modifyDate");
+                //params.put("modifyDate", modifyDateVal != null ? sdf.format(modifyDateVal) : "");
+                // 组织类型(公司 / 部门 / 集团 / 子中心 / 中心 / 公司(新))
+                params.put("layerType", rs.getString("layerType"));
+                list.add(params);
+            }
+        } catch (Exception e) {
+            // 异常时返回错误信息
+            e.printStackTrace();
+            result.put("msg", e.getMessage());
+            result.put("code", "500");
+        }
+        return result;
+    }
+
+    /**
+     * 构建组织信息查询SQL
+     * <p>
+     * 从 t_org_admin(组织管理表)左连 T_Org_LayerType(组织类型表)
+     * 查询组织基础信息,按修改日期、组织类型、名称、编号过滤,支持分页。
+     * </p>
+     *
+     * @return 含占位符的基础SQL(where 1=1),过滤条件和分页参数由调用方动态追加
+     */
+    private static StringBuilder getSql() {
+        StringBuilder sql = new StringBuilder();
+        sql.append(" /*dialect*/ select ");
+        // 组织名称
+        sql.append(" org.fname_l2 \"name\", ");
+        // 组织全称(显示名)
+        sql.append(" org.fdisplayname_l2 fullname, ");
+        // 组织编号
+        sql.append(" org.fnumber code, ");
+        // 上级组织ID
+        sql.append(" org.fparentid parent, ");
+        // 组织长编码(层级路径)
+        sql.append(" org.flongNumber fullnumber, ");
+        // 显示排序号
+        sql.append(" org.fsortcode disporder, ");
+        // 是否封存(1=封存, 0=有效,接口层取反)
+        sql.append(" org.fissealup status, ");
+        // 主键
+        sql.append(" org.fid id, ");
+        // 备注说明
+        sql.append(" org.fdescription_l2 description, ");
+        // 最后修改时间
+        sql.append(" org.flastupdatetime modifyDate, ");
+        // 组织类型名称
+        sql.append(" lt.fname_l2 layerType ");
+        // 组织管理表
+        sql.append(" from t_org_admin org ");
+        // 左连组织类型表
+        sql.append(" left join T_Org_LayerType lt on lt.fid = org.flayertypeid ");
+        sql.append(" where 1=1 ");
+
+        return sql;
+    }
+}

+ 209 - 0
websrc/com/kingdee/eas/custom/szpgm/osf/service/GetPosInfoOsfService.java

@@ -0,0 +1,209 @@
+package com.kingdee.eas.custom.szpgm.osf.service;
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import org.apache.commons.lang3.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * 获取岗位信息接口
+ * <p>
+ * 根据修改日期、岗位名称、岗位编号等条件分页查询岗位基础信息,
+ * 包含岗位名称、编号、所属组织、上级岗位、是否负责人岗等字段。
+ * </p>
+ *
+ * <h3>入参说明</h3>
+ * <pre>
+ * modifyDate - 修改日期(可选,yyyy-MM-dd,范围过滤:岗位或人员职位 >= 该日期)
+ * name       - 岗位名称(可选,左模糊匹配)
+ * code       - 岗位编号(可选,精确匹配)
+ * size       - 每页条数(可选,默认100,最大1000)
+ * page       - 页码(可选,默认1)
+ * </pre>
+ *
+ * <h3>返回值说明</h3>
+ * <pre>
+ * code    - 状态码(200:成功, 500:异常)
+ * msg     - 提示信息
+ * page    - 当前页码
+ * size    - 每页条数
+ * data    - 岗位列表,每项包含:
+ *   id              - 主键
+ *   name            - 岗位名称
+ *   code            - 岗位编号
+ *   department      - 所属组织ID
+ *   parent          - 上级岗位ID
+ *   vice            - 部门副职(1:是, 0:否)
+ *   disporder       - 显示顺序
+ *   description     - 备注
+ *   isrespposition  - 是否负责人岗(1:是, 0:否)
+ * </pre>
+ *
+ * @author szpgm
+ * @since 1.0.0
+ */
+public class GetPosInfoOsfService  implements IHRMsfService {
+
+    /**
+     * 处理岗位信息查询请求
+     *
+     * @param context 上下文对象
+     * @param map     入参,支持以下 key:
+     *                <ul>
+     *                  <li><b>modifyDate</b> - 最后修改日期(可选,yyyy-MM-dd,范围过滤岗位/人员职位 >= 该日期)</li>
+     *                  <li><b>name</b>       - 岗位名称(可选,左模糊匹配)</li>
+     *                  <li><b>code</b>       - 岗位编号(可选,精确匹配)</li>
+     *                  <li><b>page</b>       - 页码(可选,默认1)</li>
+     *                  <li><b>size</b>       - 每页条数(可选,默认100,最大1000)</li>
+     *                </ul>
+     * @return Map&lt;String, Object&gt;,包含 code、msg、page、size、data 字段
+     * @throws EASBizException 业务异常
+     * @throws BOSException    平台异常
+     */
+    @Override
+    public Object process(Context context, Map map) throws EASBizException, BOSException {
+        Map<String, Object> result = new HashMap<String, Object>();
+        List<Map<String, Object>> list = new ArrayList<>();
+
+        // ---------- 入参解析 ----------
+        String modifyDate = (String) map.get("modifyDate");
+        String name = (String) map.get("name");
+        String code = (String) map.get("code");
+
+        // 每页条数(默认100,上限1000)
+        int maxSize = 1000;
+        int size = 100;
+        if (map.get("size") != null) {
+            if (map.get("size") instanceof Integer) {
+                size = (int) map.get("size");
+            } else if (map.get("size") instanceof String) {
+                size = Integer.parseInt((String) map.get("size"));
+            }
+            size = Math.min(maxSize, size);
+        }
+
+        // 页码(默认1)
+        int page = 1;
+        if (map.get("page") != null) {
+            if (map.get("page") instanceof Integer) {
+                page = (int) map.get("page");
+            } else if (map.get("page") instanceof String) {
+                page = Integer.parseInt((String) map.get("page"));
+            }
+        }
+
+        // ---------- 查询数据 ----------
+        try {
+            result.put("msg", "成功");
+            result.put("code", "200");
+            result.put("page", page);
+            result.put("size", size);
+            result.put("data", list);
+
+            // 构建基础SQL并动态追加过滤条件
+            StringBuilder sql = getSql();
+            List<Object> paramArr = new ArrayList<>();
+
+            // 修改日期过滤:岗位或人员职位最后修改时间 >= 指定日期
+            if (StringUtils.isNotBlank(modifyDate)) {
+                sql.append("and (pos.flastupdatetime >= ? or pp.flastupdatetime >= ? ) ");
+                paramArr.add(modifyDate);
+                paramArr.add(modifyDate);
+            }
+
+            // 岗位名称左模糊匹配
+            if (StringUtils.isNotBlank(name)) {
+                sql.append(" and pos.fname_l2 like ? ");
+                paramArr.add(name + "%");
+            }
+            // 岗位编号精确匹配
+            if (StringUtils.isNotBlank(code)) {
+                sql.append(" and pos.fnumber = ? ");
+                paramArr.add(code);
+            }
+
+            // 分页:LIMIT 条数 OFFSET 偏移量
+            sql.append(" LIMIT ? OFFSET ? ");
+            paramArr.add(size);
+            paramArr.add(((page - 1) * size));
+
+            // 执行查询
+            IRowSet rs = DbUtil.executeQuery(context, sql.toString(), paramArr.toArray());
+            while (rs.next()) {
+                String id = rs.getString("id");
+                Map<String, Object> params = new HashMap<>();
+                // 是否负责人岗(1:是, 0:否)
+                params.put("isrespposition", rs.getString("isrespposition"));
+                // 岗位名称
+                params.put("name", rs.getString("name"));
+                // 所属组织ID
+                params.put("department", rs.getString("department"));
+                // 岗位编号
+                params.put("code", rs.getString("code"));
+                // 上级岗位ID
+                params.put("parent", rs.getString("parent"));
+                // 部门副职(1:是, 0:否)
+                params.put("vice", rs.getString("vice"));
+                // 显示顺序
+                params.put("disporder", rs.getString("disporder"));
+                // 主键ID
+                params.put("id", rs.getString("id"));
+                // 备注
+                params.put("description", rs.getString("description"));
+                list.add(params);
+            }
+            // 以 list 覆盖 result 中的 data(确保引用一致)
+            result.put("data", list);
+        } catch (Exception e) {
+            // 异常时返回错误信息
+            e.printStackTrace();
+            result.put("msg", e.getMessage());
+            result.put("code", "500");
+        }
+        return result;
+    }
+
+    /**
+     * 构建岗位信息查询SQL
+     * <p>
+     * 从 t_org_position(岗位表)查询岗位基础信息,
+     * 按修改日期、岗位名称、岗位编号过滤,支持分页。
+     * 以 {@code where 1=1} 结尾,便于动态追加 AND 条件。
+     * </p>
+     *
+     * @return 含占位符的基础SQL(where 1=1),过滤条件和分页参数由调用方动态追加
+     */
+    private static StringBuilder getSql() {
+        StringBuilder sql = new StringBuilder();
+        sql.append(" /*dialect*/ select ");
+        // 岗位名称
+        sql.append(" pos.fname_l2 \"name\", ");
+        // 岗位编号
+        sql.append(" pos.fnumber code, ");
+        // 显示顺序
+        sql.append(" pos.findex disporder, ");
+        // 所属组织ID
+        sql.append(" pos.fadminorgunitid department, ");
+        // 上级岗位ID
+        sql.append(" pos.fparentid parent, ");
+        // 部门副职(1:是, 0:否)
+        sql.append(" pos.cfsffz1 vice, ");
+        // 备注
+        sql.append(" pos.fdescription_l2 description, ");
+        // 主键
+        sql.append(" pos.fid id, ");
+        // 是否负责人岗(1:是, 0:否)
+        sql.append(" pos.fisrespposition isrespposition ");
+        // 岗位表
+        sql.append(" from t_org_position pos ");
+        sql.append(" where 1=1 ");
+
+        return sql;
+    }
+}

+ 232 - 0
websrc/com/kingdee/eas/custom/szpgm/osf/service/GetRoleSupervisorInfoOsfService.java

@@ -0,0 +1,232 @@
+package com.kingdee.eas.custom.szpgm.osf.service;
+
+
+import com.kingdee.bos.BOSException;
+import com.kingdee.bos.Context;
+import com.kingdee.bos.bsf.service.app.IHRMsfService;
+import com.kingdee.eas.common.EASBizException;
+import com.kingdee.eas.util.app.DbUtil;
+import com.kingdee.jdbc.rowset.IRowSet;
+import org.apache.commons.lang3.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 获取角色/角色成员信息接口(分管领导接口)
+ * <p>
+ * 根据修改日期、角色名称、角色编号等条件分页查询角色成员-角色关联信息,
+ * 包含角色名称、编号、类型、状态以及人员关联关系等字段。
+ * </p>
+ *
+ * <h3>入参说明</h3>
+ * <pre>
+ * modifyDate - 最后修改日期(yyyy-MM-dd),同时过滤角色-角色成员关联的最后修改时间
+ * name       - 成员名称(左模糊匹配)
+ * code       - 角色编号(精确匹配)
+ * size       - 每页条数(可选,默认100,最大1000)
+ * page       - 页码(可选,默认1)
+ * </pre>
+ *
+ * <h3>返回值说明</h3>
+ * <pre>
+ * code    - 状态码(200:成功, 500:异常)
+ * msg     - 提示信息
+ * page    - 当前页码
+ * size    - 每页条数
+ * data    - 角色负责人列表,每项包含:
+ *   id          - 主键(人员-角色关联表主键)
+ *   roleid      - 角色ID(关联 T_WFR_WFROLE.FID)
+ *   orgid       - 组织ID
+ *   personid    - 人员ID
+ *   isinclude   - 是否包含下级
+ *   isdele      - 是否委托
+ *   deleperson  - 委托操作人
+ *   rolename    - 角色名称
+ *   rolenumber  - 角色编号
+ *   roledescribe- 角色描述
+ *   roletype    - 角色类型
+ *   state       - 角色状态
+ * </pre>
+ *
+ * @author szpgm
+ * @since 1.0.0
+ */
+public class GetRoleSupervisorInfoOsfService  implements IHRMsfService {
+
+    /**
+     * 处理角色-角色成员信息查询请求
+     *
+     * @param context 上下文对象
+     * @param map     入参,支持以下 key:
+     *                <ul>
+     *                  <li><b>modifyDate</b> - 最后修改日期(可选,yyyy-MM-dd)</li>
+     *                  <li><b>name</b>       - 角色名称(可选,左模糊匹配)</li>
+     *                  <li><b>code</b>       - 角色编号(可选,精确匹配)</li>
+     *                  <li><b>page</b>       - 页码(可选,默认1)</li>
+     *                  <li><b>size</b>       - 每页条数(可选,默认100,最大1000)</li>
+     *                </ul>
+     * @return Map&lt;String, Object&gt;,包含 code、msg、page、size、data 字段
+     * @throws EASBizException 业务异常
+     * @throws BOSException    平台异常
+     */
+    @Override
+    public Object process(Context context, Map map) throws EASBizException, BOSException {
+        Map<String, Object> result = new HashMap<String, Object>();
+        List<Map<String, Object>> list = new ArrayList<>();
+
+        // ---------- 入参解析 ----------
+        String modifyDate = (String) map.get("modifyDate");
+        String name = (String) map.get("name");
+        String code = (String) map.get("code");
+
+        // 每页条数(默认100,上限1000)
+        int maxSize = 1000;
+        int size = 100;
+        if (map.get("size") != null) {
+            if (map.get("size") instanceof Integer) {
+                size = (int) map.get("size");
+            } else if (map.get("size") instanceof String) {
+                size = Integer.parseInt((String) map.get("size"));
+            }
+            size = Math.min(maxSize, size);
+        }
+
+        // 页码(默认1)
+        int page = 1;
+        if (map.get("page") != null) {
+            if (map.get("page") instanceof Integer) {
+                page = (int) map.get("page");
+            } else if (map.get("page") instanceof String) {
+                page = Integer.parseInt((String) map.get("page"));
+            }
+        }
+
+        // ---------- 查询数据 ----------
+        try {
+            result.put("msg", "成功");
+            result.put("code", "200");
+            result.put("page", page);
+            result.put("size", size);
+            result.put("data", list);
+
+            // 构建基础SQL并动态追加过滤条件
+            StringBuilder sql = getSql();
+            List<Object> paramArr = new ArrayList<>();
+
+            // 修改日期过滤:角色或角色成员-关联最后修改时间 >= 指定日期
+            if (StringUtils.isNotBlank(modifyDate)) {
+                sql.append(" and (role.flastupdatetime >= ? or prole.flastupdatetime >= ? ) ");
+                paramArr.add(modifyDate);
+                paramArr.add(modifyDate);
+            }
+
+            // 角色名称左模糊匹配
+            if (StringUtils.isNotBlank(name)) {
+                sql.append(" and role.frolename_l2 like ? ");
+                paramArr.add(name + "%");
+            }
+
+            // 角色编号精确匹配
+            if (StringUtils.isNotBlank(code)) {
+                sql.append(" and role.fnumber = ? ");
+                paramArr.add(code);
+            }
+
+            // 分页:LIMIT 条数 OFFSET 偏移量
+            sql.append(" LIMIT ? OFFSET ? ");
+            paramArr.add(size);
+            paramArr.add(((page - 1) * size));
+
+            IRowSet rs = DbUtil.executeQuery(context, sql.toString(), paramArr.toArray());
+
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+            while (rs.next()) {
+                Map<String, Object> params = new HashMap<String, Object>();
+
+                // 主键(人员-角色关联表主键)
+                params.put("id", rs.getString("id"));
+                // 角色ID
+                params.put("roleid", rs.getString("roleid"));
+                // 组织ID
+                params.put("orgid", rs.getString("orgid"));
+                // 人员ID
+                params.put("personid", rs.getString("personid"));
+                // 是否包含
+                params.put("isinclude", rs.getString("isinclude"));
+                // 是否删除
+                params.put("isdele", rs.getString("isdele"));
+                // 删除操作人
+                params.put("deleperson", rs.getString("deleperson"));
+                // 角色名称
+                params.put("rolename", rs.getString("rolename"));
+                // 角色编号
+                params.put("rolenumber", rs.getString("rolenumber"));
+                // 角色描述
+                params.put("roledescribe", rs.getString("roledescribe"));
+                // 角色类型
+                params.put("roletype", rs.getString("roletype"));
+                // 角色状态
+                params.put("state", rs.getString("state"));
+                // 修改日期(格式化为 yyyy-MM-dd)
+                //Date modifyDateVal = rs.getTimestamp("modifyDate");
+                //params.put("modifyDate", modifyDateVal != null ? sdf.format(modifyDateVal) : "");
+
+                list.add(params);
+            }
+        } catch (Exception e) {
+            // 异常时返回错误信息
+            e.printStackTrace();
+            result.put("msg", e.getMessage());
+            result.put("code", "500");
+        }
+        return result;
+    }
+
+    /**
+     * 构建角色负责人信息查询SQL
+     * <p>
+     * 从 T_WFR_PERSONROLE(人员-角色关联表)左连 T_WFR_WFROLE(工作流角色表)
+     * 查询角色与角色成员的关联信息,按修改日期、岗位名称、岗位编号过滤,支持分页。
+     * </p>
+     *
+     * @return 含占位符的SQL,参数顺序: modifyDate(×2), name, code, limit, offset
+     */
+    private static StringBuilder getSql() {
+        StringBuilder sql = new StringBuilder();
+        sql.append(" /*dialect*/ select ");
+        // 人员-角色关联主键
+        sql.append(" prole.fid id, ");
+        // 角色ID
+        sql.append(" prole.froleid roleid, ");
+        // 组织ID
+        sql.append(" prole.forgid orgid, ");
+        // 人员ID
+        sql.append(" prole.fpsersonid personid, ");
+        // 是否包含子组织
+        sql.append(" prole.fisinclude isinclude, ");
+        // 是否已删除
+        sql.append(" prole.fisdele isdele, ");
+        // 删除操作人ID
+        sql.append(" prole.fdelepersonid deleperson, ");
+        // 角色名称
+        sql.append(" role.frolename_l2 rolename, ");
+        // 角色编号
+        sql.append(" role.fnumber rolenumber, ");
+        // 角色描述
+        sql.append(" role.froledescribe_l2 roledescribe, ");
+        // 角色类型
+        sql.append(" role.froletype roletype, ");
+        // 角色状态
+        sql.append(" role.fstate state ");
+        sql.append(" from T_WFR_PERSONROLE prole ");
+        sql.append(" LEFT JOIN T_WFR_WFROLE role on prole.FROLEID = role.FID ");
+        sql.append(" where 1=1 ");
+
+        return sql;
+    }
+}

+ 1 - 0
websrc/com/kingdee/eas/custom/szpgm/osf/service/TransmitPunchCardRecordExService.java

@@ -18,6 +18,7 @@ public class TransmitPunchCardRecordExService extends TransmitPunchCardRecordSer
 
     public Object process(Context ctx, Map param) throws EASBizException, BOSException {
         String records = (String)param.get("records");
+        System.out.println(records);
         JSONArray recordsJson = JSON.parseArray(records);
         CardToShrOSFService cardToShrOSFService = new CardToShrOSFService();
         return cardToShrOSFService.saveCards(ctx,recordsJson);

+ 2 - 1
websrc/com/kingdee/eas/custom/szpgm/osf/task/CardToShrOSFService.java

@@ -180,6 +180,7 @@ public class CardToShrOSFService implements IHRMsfService {
                             }
 
                             try {
+                                System.out.println(recordsJson.toJSONString());
                                 Map<String, Object> ret = this.saveCards(ctx, recordsJson);
                                 successCtn += (Integer)ret.get("successCtn");
                                 formatErrorRecords.addAll((JSONArray)ret.get("formatErrorRecords"));
@@ -276,7 +277,7 @@ public class CardToShrOSFService implements IHRMsfService {
                     cardInfo.setHrOrgUnit(attendanceFileInfo.getHrOrgUnit());
                     cardInfo.setAdminOrgUnit(attendanceFileInfo.getAdminOrgUnit());
                     cardInfo.setAdminOrgUnit(attendanceFileInfo.getAttAdminOrgUnit());
-
+                    cardInfo.setDescription(cardInfo.getEquipmentNum());
                     try {
                         cardInfo.setCreator((UserInfo)ctx.get("UserInfo"));
                         cardInfo.setLastUpdateUser((UserInfo)ctx.get("UserInfo"));