Explorar o código

Merge remote-tracking branch 'origin/master'

徐滕 hai 1 mes
pai
achega
7f4888c0df

+ 5 - 0
pom.xml

@@ -1067,6 +1067,11 @@
             <version>2.1.87</version>
             <classifier>sources</classifier>
         </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
+            <version>2.0.0</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 13 - 0
src/main/java/com/jeeplus/modules/workstaff/dao/WorkStaffBasicInfoDao.java

@@ -90,4 +90,17 @@ public interface WorkStaffBasicInfoDao extends CrudDao<WorkStaffBasicInfo> {
      * @return
      */
     int freeze(WorkStaffBasicInfo workStaffBasicInfo);
+
+    /**
+     *获取全部员工登记数据
+     * @return
+     */
+    List<WorkStaffBasicInfo> findAllUserList();
+
+    /**
+     *根据id更新dd数据
+     * @return
+     */
+    void updateDdInfo(@Param("userId") String userId, @Param("ddId") String ddId, @Param("ddType") String ddType);
+
 }

+ 132 - 0
src/main/java/com/jeeplus/modules/workstaff/entity/DingTalkUser.java

@@ -0,0 +1,132 @@
+package com.jeeplus.modules.workstaff.entity;
+
+import com.jeeplus.common.persistence.DataEntity;
+
+public class DingTalkUser extends DataEntity<DingTalkUser> {
+    private String userid;
+    private String name;
+    private String mobile;
+    private boolean hideMobile;
+    private String telephone;
+    private String jobNumber;
+    private String title;
+    private String email;
+    private String orgEmail;
+    private String orgEmailType;
+    private String workPlace;
+    private String remark;
+    private String deptIdList; // 部门 ID 列表
+    private Long hiredDate;
+
+    public String getUserid() {
+        return userid;
+    }
+
+    public void setUserid(String userid) {
+        this.userid = userid;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = mobile;
+    }
+
+    public boolean isHideMobile() {
+        return hideMobile;
+    }
+
+    public void setHideMobile(boolean hideMobile) {
+        this.hideMobile = hideMobile;
+    }
+
+    public String getTelephone() {
+        return telephone;
+    }
+
+    public void setTelephone(String telephone) {
+        this.telephone = telephone;
+    }
+
+    public String getJobNumber() {
+        return jobNumber;
+    }
+
+    public void setJobNumber(String jobNumber) {
+        this.jobNumber = jobNumber;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getOrgEmail() {
+        return orgEmail;
+    }
+
+    public void setOrgEmail(String orgEmail) {
+        this.orgEmail = orgEmail;
+    }
+
+    public String getOrgEmailType() {
+        return orgEmailType;
+    }
+
+    public void setOrgEmailType(String orgEmailType) {
+        this.orgEmailType = orgEmailType;
+    }
+
+    public String getWorkPlace() {
+        return workPlace;
+    }
+
+    public void setWorkPlace(String workPlace) {
+        this.workPlace = workPlace;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+
+    public String getDeptIdList() {
+        return deptIdList;
+    }
+
+    public void setDeptIdList(String deptIdList) {
+        this.deptIdList = deptIdList;
+    }
+
+    public Long getHiredDate() {
+        return hiredDate;
+    }
+
+    public void setHiredDate(Long hiredDate) {
+        this.hiredDate = hiredDate;
+    }
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 546 - 519
src/main/java/com/jeeplus/modules/workstaff/entity/WorkStaffBasicInfo.java


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 387 - 264
src/main/java/com/jeeplus/modules/workstaff/service/WorkStaffBasicInfoService.java


+ 263 - 0
src/main/java/com/jeeplus/modules/workstaff/utils/DingTalkUtils.java

@@ -0,0 +1,263 @@
+package com.jeeplus.modules.workstaff.utils;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.*;
+import com.dingtalk.api.response.*;
+import com.jeeplus.common.config.Global;
+import com.jeeplus.common.utils.StringUtils;
+import com.jeeplus.modules.workcalendar.service.WorkCalendarTaskService;
+import com.jeeplus.modules.workstaff.dao.WorkStaffBasicInfoDao;
+import com.jeeplus.modules.workstaff.entity.DingTalkUser;
+import com.jeeplus.modules.workstaff.entity.WorkStaffBasicInfo;
+import com.taobao.api.ApiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.*;
+
+@Component
+public class DingTalkUtils {
+
+    //会计钉钉配置
+    private String appKey = Global.getConfig("appKey");
+
+    private String appSecret  = Global.getConfig("appSecret");
+
+    @Autowired
+    private WorkStaffBasicInfoDao workStaffBasicInfoDao;
+    private Logger logger = LoggerFactory.getLogger(DingTalkUtils.class);
+    private final static String dingFlag = Global.getConfig("dingFlag");
+
+    /**
+     * 获取钉钉token
+     */
+    public  String getToken() throws ApiException {
+        // 创建钉钉客户端
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+        // 配置请求参数
+        OapiGettokenRequest req = new OapiGettokenRequest();
+        req.setAppkey( appKey); // 确保 appKey 已正确初始化
+        req.setAppsecret(appSecret); // 确保 appSecret 已正确初始化
+        req.setHttpMethod("GET");
+        // 执行请求,获取响应
+        OapiGettokenResponse rsp = client.execute(req);
+        String accessToken = rsp.getAccessToken();
+        return accessToken;
+    }
+
+
+    /**
+     * 获取部门列表
+     */
+    public List<OapiV2DepartmentListsubResponse.DeptBaseResponse> deptList() throws ApiException {
+        List<OapiV2DepartmentListsubResponse.DeptBaseResponse> allDepartments = new ArrayList<>();
+        Long rootDeptId = 1L;
+        String token = getToken();
+        fetchAllDepartments(rootDeptId, allDepartments,token);
+        return allDepartments;
+    }
+
+    // 假设有一个方法可以调用 API 获取子部门列表
+    public  List<OapiV2DepartmentListsubResponse.DeptBaseResponse> getSubDepartments(Long parentDeptId,String token) {
+        try {
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
+            OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
+            // 检查 deptId 是否为空
+            if (parentDeptId != null) {
+                req.setDeptId(parentDeptId);
+            }
+            OapiV2DepartmentListsubResponse rsp = client.execute(req, token);
+            List<OapiV2DepartmentListsubResponse.DeptBaseResponse> result = rsp.getResult();
+            // 返回 JSON 响应
+            return result;
+        } catch (Exception e) {
+            e.printStackTrace(); // 打印错误日志(开发调试用)
+            return null;
+        }
+    }
+
+
+    // 递归获取所有子部门
+    public  void fetchAllDepartments(Long parentDeptId, List<OapiV2DepartmentListsubResponse.DeptBaseResponse> allDepts,String token) throws ApiException {
+        List<OapiV2DepartmentListsubResponse.DeptBaseResponse> subDepts = getSubDepartments(parentDeptId,token);
+        for (OapiV2DepartmentListsubResponse.DeptBaseResponse dept : subDepts) {
+            allDepts.add(dept); // 先添加当前部门
+            fetchAllDepartments(dept.getDeptId(), allDepts,token); // 递归获取子部门
+        }
+    }
+
+
+    /**
+     * 创建用户
+     */
+    public OapiV2UserCreateResponse addUser(DingTalkUser addUserDTO) {
+        try {
+            String token = getToken();
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/create");
+            OapiV2UserCreateRequest req = new OapiV2UserCreateRequest();
+            String name = addUserDTO.getName();
+            String mobile = addUserDTO.getMobile();
+            String deptIdList = addUserDTO.getDeptIdList();
+            String userid = addUserDTO.getUserid();
+            req.setName(name);
+            req.setDeptIdList(deptIdList);
+            req.setHideMobile(false);
+            req.setMobile(mobile);
+            req.setUserid(userid);
+            OapiV2UserCreateResponse rsp = client.execute(req, token);
+            // 返回 JSON 响应
+            return rsp;
+        } catch (Exception e) {
+            throw  new RuntimeException(e.getMessage());
+        }
+    }
+
+    public OapiV2UserUpdateResponse updateUser(DingTalkUser addUserDTO) {
+        try {
+            String token = getToken();
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/update");
+            OapiV2UserUpdateRequest req = new OapiV2UserUpdateRequest();
+            String name = addUserDTO.getName();
+            String mobile = addUserDTO.getMobile();
+            String deptIdList = addUserDTO.getDeptIdList();
+            String userId = addUserDTO.getUserid();
+            req.setUserid(userId);
+            req.setName(name);
+            req.setDeptIdList(deptIdList);
+            req.setHideMobile(false);
+            req.setMobile(mobile);
+            OapiV2UserUpdateResponse rsp = client.execute(req, token);
+            // 返回 JSON 响应
+            return rsp;
+        } catch (Exception e) {
+            throw  new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 获取用户信息
+     * @param id
+     * @return
+     */
+    public  OapiV2UserGetResponse.UserGetResponse selectUserById(String id) {
+        try {
+            String token = getToken();
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
+            OapiV2UserGetRequest req = new OapiV2UserGetRequest();
+            req.setUserid(id);
+            req.setLanguage("zh_CN");
+            OapiV2UserGetResponse rsp = client.execute(req, token);
+            OapiV2UserGetResponse.UserGetResponse result = rsp.getResult();
+            // 返回 JSON 响应
+            return result;
+        } catch (Exception e) {
+            throw  new RuntimeException(e.getMessage());
+        }
+    }
+
+    public  OapiV2UserDeleteResponse deleteUser(DingTalkUser dingTalkUser) {
+        try {
+            String token = getToken();
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/delete");
+            OapiV2UserDeleteRequest req = new OapiV2UserDeleteRequest();
+            req.setUserid(dingTalkUser.getUserid());
+            OapiV2UserDeleteResponse rsp = client.execute(req, token);
+            // 返回 JSON 响应
+            return rsp;
+        } catch (Exception e) {
+            throw  new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 根据手机号获取用户信息
+     * @param mobile
+     * @return
+     */
+    public  OapiV2UserGetbymobileResponse selectUserByMobile(String mobile) {
+        try {
+            String token = getToken();
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile");
+            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
+            req.setMobile(mobile);
+            String body = client.execute(req, token).getBody();
+            OapiV2UserGetbymobileResponse rsp = client.execute(req, token);
+            // 返回 JSON 响应
+            return rsp;
+        } catch (Exception e) {
+            throw  new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * 同步钉钉数据,定时任务
+     *
+     * @throws ApiException
+     */
+    //@Scheduled(cron = "0 */1 * * * ?")//一分钟一次
+    //@Scheduled(cron = "0 0 3 * * ?")//每天凌晨3点执行
+    public void syncDingTalkData() throws ApiException {
+        logger.info("钉钉数据同步开始");
+        if ("true".equals(dingFlag)) {
+            List<WorkStaffBasicInfo> allList = workStaffBasicInfoDao.findAllUserList();
+            // 创建线程池,最多允许3个钉钉并发请求
+            ExecutorService executorService = Executors.newFixedThreadPool(3);
+            CompletionService<WorkStaffBasicInfo> completionService = new ExecutorCompletionService<>(executorService);
+
+            // 提交任务
+            for (WorkStaffBasicInfo staff : allList) {
+                if (StringUtils.isBlank(staff.getMobile()) || StringUtils.isNotBlank(staff.getDdId())) {
+                    continue;
+                }
+
+                completionService.submit(() -> {
+                    OapiV2UserGetbymobileResponse response = selectUserByMobile(staff.getMobile());
+                    String body = response.getBody();
+                    JSONObject jsonObject = JSONUtil.parseObj(body);
+
+                    String ddUserId = "";
+                    WorkStaffBasicInfo workStaffBasicInfo = new WorkStaffBasicInfo();
+                    workStaffBasicInfo.setId(staff.getId());
+                    if ("0".equals(jsonObject.getStr("errcode"))) {
+                        ddUserId = jsonObject.getJSONObject("result").getStr("userid");
+                        workStaffBasicInfo.setDdId(ddUserId);
+                        workStaffBasicInfo.setDdType("1");
+                    } else {
+                        workStaffBasicInfo.setDdType("0");
+                    }
+
+                    return workStaffBasicInfo;
+                });
+            }
+
+            // 处理任务结果
+            int taskCount = allList.size();
+            for (int i = 0; i < taskCount; i++) {
+                try {
+                    Future<WorkStaffBasicInfo> future = completionService.take();
+                    WorkStaffBasicInfo result = future.get();
+                    if (result != null) {
+                        workStaffBasicInfoDao.updateDdInfo(result.getId(),result.getDdId(),result.getDdType());
+                    }
+                } catch (InterruptedException | ExecutionException e) {
+                    e.printStackTrace();
+                    logger.error("-------------钉钉同步---解析信息发生异常-------------");
+                }
+            }
+
+            // 关闭线程池
+            executorService.shutdown();
+            logger.info("钉钉数据同步结束");
+        }
+    }
+
+}

+ 5 - 5
src/main/java/com/jeeplus/modules/workstaff/web/WorkStaffBasicInfoController.java

@@ -30,15 +30,13 @@ import com.jeeplus.modules.workprojectnotify.entity.WorkProjectNotify;
 import com.jeeplus.modules.workprojectnotify.service.WorkProjectNotifyService;
 import com.jeeplus.modules.workreceiptsregister.entity.ResponseEntity;
 import com.jeeplus.modules.workrelationship.entity.WorkRelationship;
-import com.jeeplus.modules.workstaff.entity.WorkStaffBasicInfo;
-import com.jeeplus.modules.workstaff.entity.WorkStaffBasicInfoExcel;
-import com.jeeplus.modules.workstaff.entity.WorkStaffCertificate;
-import com.jeeplus.modules.workstaff.entity.WorkStaffCertificateImport;
+import com.jeeplus.modules.workstaff.entity.*;
 import com.jeeplus.modules.workstaff.service.WorkStaffBasicInfoService;
 import com.jeeplus.modules.workstaff.service.WorkStaffCertificateService;
 import com.jeeplus.modules.workstaffachiveslog.dao.WorkStaffAchivesLogDao;
 import com.jeeplus.modules.workstaffachiveslog.entity.WorkStaffAchivesLog;
 import com.jeeplus.modules.workstaffachiveslog.service.WorkStaffAchivesLogService;
+import com.taobao.api.ApiException;
 import org.apache.shiro.authz.annotation.Logical;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -89,6 +87,7 @@ public class WorkStaffBasicInfoController extends BaseController {
     @Autowired
 	private WorkStaffCertificateService workStaffCertificateService;
 
+
 	@ModelAttribute
 	public WorkStaffBasicInfo get(@RequestParam(required=false) String id) {
 		WorkStaffBasicInfo entity = null;
@@ -317,6 +316,7 @@ public class WorkStaffBasicInfoController extends BaseController {
 //			WeChatUser weChatUser = AddressBookUtil.replaceUser(workStaffBasicInfo,weChatId);
 //			AddressBookUtil.updateUser(accessToken,weChatUser);
 		}else{//新增表单保存
+
 			workStaffBasicInfoService.save(workStaffBasicInfo,request);//保存
 //			String officeId = workStaffBasicInfo.getOffice().getId();
 //			Integer weChatId = 1;
@@ -947,7 +947,7 @@ public class WorkStaffBasicInfoController extends BaseController {
 	 */
 	@RequiresPermissions("workstaff:workStaffBasicInfo:freeze")
 	@RequestMapping(value = "freeze")
-	public String freeze(WorkStaffBasicInfo workStaffBasicInfo, RedirectAttributes redirectAttributes) {
+	public String freeze(WorkStaffBasicInfo workStaffBasicInfo, RedirectAttributes redirectAttributes) throws Exception {
 		workStaffBasicInfoService.freeze(workStaffBasicInfo);
 		addMessage(redirectAttributes, "员工登录权限更新成功");
 		return "redirect:"+Global.getAdminPath()+"/workstaff/workStaffBasicInfo/?repage";

+ 6 - 0
src/main/resources/jeeplus.properties

@@ -148,6 +148,12 @@ projectPath=C\:\\test
 #aliyunUrl=http://gangwan-app.oss-cn-hangzhou.aliyuncs.com
 aliyunUrl=http://oss.gangwaninfo.com
 aliyunDownloadUrl=http://cdn.gangwaninfo.com
+
+#????
+appKey=dingtk0peibzdlxdmojz
+appSecret=NWFAu2fcfKlW3GxlvrGEwMjvJ7jyCPq0Q70XzptUsxE5PYs9cx5wTBWL0wjxKBtf
+dingFlag=false
+
 oSSUrl=http://cdn.gangwaninfo.com/jeeplus-resource-data/static
 endpoint=http://oss-cn-hangzhou.aliyuncs.com
 accessKeyId=LTAI5tKa6kzGr5EyPWJB4EcD

+ 28 - 5
src/main/resources/mappings/modules/workstaff/WorkStaffBasicInfoDao.xml

@@ -61,7 +61,9 @@
 		a.individual_resume AS "individualResume",
 		a.highest_education As "highestEducation",
 		a.hand_signature As "handSignature",
-		a.other_service_flag As "otherServiceFlag"
+		a.other_service_flag As "otherServiceFlag",
+		a.dd_id As "ddId",
+		a.dd_type As "ddType"
 <!--		ur.role_id AS "roleId",-->
 <!--		r.name AS "roleName"-->
 	</sql>
@@ -80,7 +82,8 @@
 		SELECT
 			<include refid="workStaffBasicInfoColumns"/>
 			,suo.area_remark as "areaRemark"
-			,suo.area_principal as "areaPrincipal"
+			,suo.area_principal as "areaPrincipal",
+		suo.login_flag as "userLoginFlag"
 		FROM work_staff_basic_info a
 		<include refid="workStaffBasicInfoJoins"/>
 		WHERE a.id = #{id}
@@ -391,7 +394,9 @@
 			individual_resume,
 			highest_education,
 			hand_signature,
-			other_service_flag
+			other_service_flag,
+		    dd_id,
+		    dd_type
 		) VALUES (
 			#{id},
 			#{createBy.id},
@@ -443,7 +448,9 @@
 			#{individualResume},
 			#{highestEducation},
 			#{handSignature},
-			#{otherServiceFlag}
+			#{otherServiceFlag},
+			#{ddId},
+			#{ddType}
 		)
 	</insert>
 
@@ -535,10 +542,12 @@
 		o.name as "office.name",
 		jg.name AS "jobGrade.name",
 		jg.id  AS "jobGrade.id",
-		jg.pay AS "salary"
+		jg.pay AS "salary",
+		u.login_flag AS "userLoginFlag"
 		FROM work_staff_basic_info  a
 		LEFT JOIN sys_office o on o.id=a.office_id
 		LEFT JOIN work_job_grade jg ON jg.id = a.job_grade
+		LEFT JOIN sys_user u ON u.id = a.user_id
 		where a.user_id=#{userId,jdbcType=VARCHAR}
 	</select>
 
@@ -732,4 +741,18 @@
 		where id = #{userId}
 	</update>
 
+	<select id="findAllUserList" resultType="WorkStaffBasicInfo">
+		SELECT a.*
+		FROM work_staff_basic_info a
+		LEFT JOIN sys_user b on b.id = a.user_id
+		WHERE a.del_flag = 0
+	</select>
+
+	<update id="updateDdInfo">
+		update work_staff_basic_info
+		set dd_id = #{ddId}, dd_type = #{ddType}
+		where id = #{userId}
+	</update>
+
+
 </mapper>

+ 82 - 51
src/main/webapp/webpage/modules/workstaff/workStaffBasicInfoList.jsp

@@ -357,6 +357,7 @@
                         return ''
                     }}*/
                 ,{field:'status',align:'center', title: '员工状态', minWidth:80}
+                ,{field:'ddType',align:'center', title: '是否已加入钉钉', minWidth:80}
                 ,{field:'entryDate', align:'center',sort:true,title: '入职日期',width:100}
                 ,{field:'op',align:'center',title:"操作",width:260,templet:function(d){
                         ////对操作进行初始化
@@ -394,63 +395,93 @@
                 <c:forEach items="${page.list}" var="workStaffBasicInfo" varStatus="index">
                 <c:if test="${index.index != 0}">,</c:if>
                 {
-                    "index":"${index.index+1}"
-                    ,"id":"${workStaffBasicInfo.id}"
-                    ,"auditUserId":"${workStaffBasicInfo.auditUserId}"
-                    ,"auditUserName":"${workStaffBasicInfo.auditUserName}"
-                    ,"role":"${workStaffBasicInfo.roleName}"
-                    ,"userLoginFlag":"${workStaffBasicInfo.userLoginFlag}"
-                    ,"no":"<c:out value="${workStaffBasicInfo.no}" escapeXml="true"/>"
-                    ,"name":"<c:out value="${workStaffBasicInfo.name}" escapeXml="false"/>"
-                    ,"idCard":"<c:out value="${workStaffBasicInfo.idCard}" escapeXml="true"/>"
-                    ,'mobile':"<c:out value="${workStaffBasicInfo.mobile}" escapeXml="true"/>"
-                    ,'office':"<c:out value="${workStaffBasicInfo.office.showName}" escapeXml="true"/>"
-                    ,'jobGrade':"<c:out value="${workStaffBasicInfo.jobGrade.name}" escapeXml="true"/>"
-                    ,'status':"<c:out value="${workStaffBasicInfo.status}" escapeXml="true"/>"
-                    ,"userId":"${workStaffBasicInfo.userId}"
-                    ,'highestEducation':"<c:out value="${workStaffBasicInfo.highestEducation}"/>"
-                    ,"entryDate":"<fmt:formatDate value="${workStaffBasicInfo.entryDate}" pattern="yyyy-MM-dd"/>"
-                    <shiro:hasPermission name="workstaff:workStaffBasicInfo:edit">,"canedit":"1"</shiro:hasPermission>
-                    <shiro:hasPermission name="workstaff:workStaffBasicInfo:freeze">,"freeze":"1"</shiro:hasPermission>
-                    <shiro:hasPermission name="workstaff:workStaffBasicInfo:del">,"candelete":"1"</shiro:hasPermission>
+                    "index": "${index.index+1}"
+                    ,
+                    "id": "${workStaffBasicInfo.id}"
+                    ,
+                    "auditUserId": "${workStaffBasicInfo.auditUserId}"
+                    ,
+                    "auditUserName": "${workStaffBasicInfo.auditUserName}"
+                    ,
+                    "role": "${workStaffBasicInfo.roleName}"
+                    ,
+                    "userLoginFlag": "${workStaffBasicInfo.userLoginFlag}"
+                    ,
+                    "no": "<c:out value="${workStaffBasicInfo.no}" escapeXml="true"/>"
+                    ,
+                    "name": "<c:out value="${workStaffBasicInfo.name}" escapeXml="false"/>"
+                    ,
+                    "idCard": "<c:out value="${workStaffBasicInfo.idCard}" escapeXml="true"/>"
+                    ,
+                    'mobile': "<c:out value="${workStaffBasicInfo.mobile}" escapeXml="true"/>"
+                    ,
+                    'office': "<c:out value="${workStaffBasicInfo.office.showName}" escapeXml="true"/>"
+                    ,
+                    'jobGrade': "<c:out value="${workStaffBasicInfo.jobGrade.name}" escapeXml="true"/>"
+                    ,
+                    'status': "<c:out value="${workStaffBasicInfo.status}" escapeXml="true"/>"
+                    ,
+                    "userId": "${workStaffBasicInfo.userId}"
+                    ,
+                    'highestEducation': "<c:out value="${workStaffBasicInfo.highestEducation}"/>"
+                    <%--,'ddType':"<c:out value="${workStaffBasicInfo.ddType}"/>"--%>
+                    <c:choose>
+                    <c:when test="${workStaffBasicInfo.ddType == '1'}">
+                    ,
+                    "ddType": "已加入"
+                    </c:when>
+                    <c:otherwise>
+                    ,
+                    "ddType": "未加入"
+                    </c:otherwise>
+                    </c:choose>
+
+                    ,
+                    "entryDate": "<fmt:formatDate value="${workStaffBasicInfo.entryDate}" pattern="yyyy-MM-dd"/>"
+                    <shiro:hasPermission name="workstaff:workStaffBasicInfo:edit">,
+                    "canedit": "1"</shiro:hasPermission>
+                    <shiro:hasPermission name="workstaff:workStaffBasicInfo:freeze">,
+                    "freeze": "1"</shiro:hasPermission>
+                    <shiro:hasPermission name="workstaff:workStaffBasicInfo:del">,
+                    "candelete": "1"</shiro:hasPermission>
                 }
                 </c:forEach>
                 </c:if>
             ]
         }).config.cols;
 
-       /* /!**
-         * 参数cols是table.render({})中的cols属性值
-         * aop代理是基于event点击事件进行操作的,
-         * 因此cols中务必开启event点击事件!
-         **!/
-        var aopTable = tableEdit.aopObj(cols); //获取一个aop对象
-        /!**
-         * 注意:
-         * 1、 aopTable.on('tool(xxx)',function (obj) {})
-         * 2、 table.on('tool(yyy)',function (obj) {})
-         * 如果1中的xxx与2中的yyy字符串相同时,
-         * 不能同时用,用了会造成后调用者覆盖前调用者。
-         * 应该直接用1来代替2,因为1中包含了2中的事件。
-         * 如果不相同,则可以同时使用。
-         **!/
-        aopTable.on('tool(tableEvent)',function (obj) {
-            var field = obj.field; //单元格字段
-            console.log(field);
-            var value = obj.value; //修改后的值
-            console.log(value);
-            var data = obj.data; //当前行旧数据
-            console.log(data);
-            var event = obj.event; //当前单元格事件属性值
-            console.log(event);
-            var update = {};
-            update[field] = value;
-            //把value更新到行中
-            obj.update(update);
-
-            $.ajax({
-                type:'post',
-                url:"${ctx}/workstaff/workStaffBasicInfo/updateAuditUser",
+        /* /!**
+          * 参数cols是table.render({})中的cols属性值
+          * aop代理是基于event点击事件进行操作的,
+          * 因此cols中务必开启event点击事件!
+          **!/
+         var aopTable = tableEdit.aopObj(cols); //获取一个aop对象
+         /!**
+          * 注意:
+          * 1、 aopTable.on('tool(xxx)',function (obj) {})
+          * 2、 table.on('tool(yyy)',function (obj) {})
+          * 如果1中的xxx与2中的yyy字符串相同时,
+          * 不能同时用,用了会造成后调用者覆盖前调用者。
+          * 应该直接用1来代替2,因为1中包含了2中的事件。
+          * 如果不相同,则可以同时使用。
+          **!/
+         aopTable.on('tool(tableEvent)',function (obj) {
+             var field = obj.field; //单元格字段
+             console.log(field);
+             var value = obj.value; //修改后的值
+             console.log(value);
+             var data = obj.data; //当前行旧数据
+             console.log(data);
+             var event = obj.event; //当前单元格事件属性值
+             console.log(event);
+             var update = {};
+             update[field] = value;
+             //把value更新到行中
+             obj.update(update);
+
+             $.ajax({
+                 type:'post',
+                 url:"${ctx}/workstaff/workStaffBasicInfo/updateAuditUser",
                 data:{"id":data.id,"auditUserId":value.name},
                 dataType:"json",
                 success:function(data){