From 214cda58c3786972c958da5c6d54a135490a3c11 Mon Sep 17 00:00:00 2001
From: rk <94314517@qq.com>
Date: 星期四, 05 二月 2026 09:13:16 +0800
Subject: [PATCH] 功能开发

---
 server/admin/src/main/java/com/doumee/api/business/CategoryController.java                  |   11 
 server/admin/src/main/java/com/doumee/job/CommonTestJob.java                                |    2 
 server/admin/src/main/java/com/doumee/job/DistributableTestJob.java                         |    2 
 server/services/src/main/java/com/doumee/service/business/CategoryService.java              |   10 
 server/services/src/main/java/com/doumee/core/iPass/IPass.java                              |   96 ++
 server/services/src/main/java/com/doumee/service/system/impl/SystemLoginServiceImpl.java    |  101 ++
 server/services/src/main/java/com/doumee/dao/system/model/SystemUser.java                   |    3 
 server/admin/src/main/java/com/doumee/job/DistributableTestJobDistributer.java              |    2 
 server/services/src/main/java/com/doumee/core/utils/Base64Util.java                         | 1184 ++++++++++++++++++++++++++++++++++
 server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java                        |   36 
 server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java                       |    1 
 server/services/src/main/java/com/doumee/biz/system/SystemUserBiz.java                      |    2 
 server/services/src/main/java/com/doumee/service/system/impl/SystemUserServiceImpl.java     |    8 
 server/services/src/main/java/com/doumee/config/shiro/ShiroToken.java                       |   43 +
 server/services/src/main/java/com/doumee/biz/system/impl/SystemUserBizImpl.java             |   11 
 server/services/src/main/java/com/doumee/config/shiro/ShiroConfig.java                      |    1 
 server/services/src/main/java/com/doumee/service/system/SystemUserService.java              |    4 
 server/services/src/main/java/com/doumee/service/business/MemberService.java                |    2 
 server/services/src/main/java/com/doumee/dao/business/model/Category.java                   |    4 
 server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java |   13 
 server/services/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java          |   27 
 server/services/src/main/java/com/doumee/core/utils/ZbomAESUtils.java                       |   89 ++
 server/services/src/main/java/com/doumee/dao/system/dto/DingTalkLoginDTO.java               |   21 
 server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java                   |    2 
 server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java     |  107 ++
 /dev/null                                                                                   |   33 
 server/services/src/main/java/com/doumee/dao/system/dto/LoginDTO.java                       |    6 
 server/web/src/main/java/com/doumee/api/web/LoginController.java                            |   94 ++
 server/admin/src/main/java/com/doumee/config/quartz/SnippetScannerConfig.java               |   18 
 server/services/src/main/java/com/doumee/api/system/SystemController.java                   |   17 
 server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java                         |    4 
 server/services/src/main/java/com/doumee/dao/vo/ZhanQuVO.java                               |   29 
 server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java       |   45 
 server/services/src/main/java/com/doumee/service/system/SystemLoginService.java             |    5 
 34 files changed, 1,891 insertions(+), 142 deletions(-)

diff --git a/server/admin/src/main/java/com/doumee/api/business/CategoryController.java b/server/admin/src/main/java/com/doumee/api/business/CategoryController.java
index 6bec36e..badf273 100644
--- a/server/admin/src/main/java/com/doumee/api/business/CategoryController.java
+++ b/server/admin/src/main/java/com/doumee/api/business/CategoryController.java
@@ -20,6 +20,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -105,4 +106,14 @@
     public ApiResponse findById(@PathVariable Integer id) {
         return ApiResponse.success(categoryService.findById(id));
     }
+
+
+    @ApiOperation("鎴樺尯淇℃伅鍚屾")
+    @GetMapping("/syncZhanQu")
+    public ApiResponse syncZhanQu() throws IOException {
+        categoryService.syncZhanQu();
+        return ApiResponse.success("鍚屾鎴愬姛");
+    }
+
+
 }
diff --git a/server/admin/src/main/java/com/doumee/config/quartz/SnippetScannerConfig.java b/server/admin/src/main/java/com/doumee/config/quartz/SnippetScannerConfig.java
index 27fd766..31c163d 100644
--- a/server/admin/src/main/java/com/doumee/config/quartz/SnippetScannerConfig.java
+++ b/server/admin/src/main/java/com/doumee/config/quartz/SnippetScannerConfig.java
@@ -20,13 +20,13 @@
                 .build();
     }
 
-    @Bean
-    public Trigger getSnippetScannerTrigger() {
-        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
-        return TriggerBuilder.newTrigger()
-                .forJob(getSnippetScanner())
-                .withIdentity("snippetScannerTrigger")
-                .withSchedule(scheduleBuilder)
-                .build();
-    }
+//    @Bean
+//    public Trigger getSnippetScannerTrigger() {
+//        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
+//        return TriggerBuilder.newTrigger()
+//                .forJob(getSnippetScanner())
+//                .withIdentity("snippetScannerTrigger")
+//                .withSchedule(scheduleBuilder)
+//                .build();
+//    }
 }
diff --git a/server/admin/src/main/java/com/doumee/job/CommonTestJob.java b/server/admin/src/main/java/com/doumee/job/CommonTestJob.java
index 859efef..2c1ca71 100644
--- a/server/admin/src/main/java/com/doumee/job/CommonTestJob.java
+++ b/server/admin/src/main/java/com/doumee/job/CommonTestJob.java
@@ -12,7 +12,7 @@
  * @since 2025/03/31 16:44
  */
 @Slf4j
-@Component("commonTestJob")
+//@Component("commonTestJob")
 public class CommonTestJob extends BaseJob {
 
     @Override
diff --git a/server/admin/src/main/java/com/doumee/job/DistributableTestJob.java b/server/admin/src/main/java/com/doumee/job/DistributableTestJob.java
index 3414b64..7225d37 100644
--- a/server/admin/src/main/java/com/doumee/job/DistributableTestJob.java
+++ b/server/admin/src/main/java/com/doumee/job/DistributableTestJob.java
@@ -16,7 +16,7 @@
  * @since 2025/03/31 16:44
  */
 @Slf4j
-@Component("distributableTestJob")
+//@Component("distributableTestJob")
 public class DistributableTestJob extends BaseJob {
 
     @Override
diff --git a/server/admin/src/main/java/com/doumee/job/DistributableTestJobDistributer.java b/server/admin/src/main/java/com/doumee/job/DistributableTestJobDistributer.java
index 03f5a23..e0a88d8 100644
--- a/server/admin/src/main/java/com/doumee/job/DistributableTestJobDistributer.java
+++ b/server/admin/src/main/java/com/doumee/job/DistributableTestJobDistributer.java
@@ -14,7 +14,7 @@
  * @author  dm
  * @since 2025/03/31 16:44
  */
-@Component("distributableTestJobDistributer")
+//@Component("distributableTestJobDistributer")
 public class DistributableTestJobDistributer extends BaseDistributer<SystemPermission> {
 
     @Autowired
diff --git a/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java b/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java
deleted file mode 100644
index fe20237..0000000
--- a/server/admin/src/main/java/com/doumee/job/InitializeCodeJob.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.doumee.job;
-
-import com.doumee.core.job.BaseJob;
-import com.doumee.core.job.JobContext;
-import com.doumee.core.job.JobParam;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-/**
- * 鍒濆鍖栬鍗曠紪鍙�
- * @author  dm
- * @since 2025/03/31 16:44
- */
-@Slf4j
-@Component("InitializeCodeJob")
-public class InitializeCodeJob extends BaseJob {
-
-//    @Autowired
-//    private OrdersService ordersService;
-
-    @Override
-    public JobContext execute(JobParam param) {
-        JobContext jobContext = new JobContext();
-        try {
-//            ordersService.initializeCode();
-            jobContext.setContext("鍒濆鍖栬鍗曠紪鍙�");
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return jobContext;
-    }
-}
diff --git a/server/services/src/main/java/com/doumee/api/system/SystemController.java b/server/services/src/main/java/com/doumee/api/system/SystemController.java
index 366e4bf..f0a489b 100644
--- a/server/services/src/main/java/com/doumee/api/system/SystemController.java
+++ b/server/services/src/main/java/com/doumee/api/system/SystemController.java
@@ -8,9 +8,11 @@
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.model.ApiResponse;
 import com.doumee.core.model.LoginUserInfo;
+import com.doumee.dao.system.dto.DingLoginDTO;
 import com.doumee.dao.system.dto.LoginDTO;
 import com.doumee.dao.system.dto.UpdatePwdDto;
 import com.doumee.service.system.SystemLoginService;
+import com.taobao.api.ApiException;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -21,6 +23,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
 
 /**
  * @author  dm
@@ -48,9 +51,23 @@
         return ApiResponse.success(systemLoginService.loginByPassword(dto, request));
     }
 
+
+
+    @PreventRepeat(limit = 10, lockTime = 10000)
+    @ApiOperation("閽夐拤鎺堟潈鐧诲綍")
+//    @EncryptionReq
+//    @EncryptionResp
+    @PostMapping("/loginByDingTalk")
+    public ApiResponse<Map<String,Object>> loginByDingTalk (@Validated @RequestBody DingLoginDTO dto, HttpServletRequest request) throws ApiException {
+        return ApiResponse.success(systemLoginService.loginByDingTalk(dto, request));
+    }
+
+
+
     @ApiOperation("閫�鍑虹櫥褰�")
     @PostMapping("/logout")
     public ApiResponse logout () {
+        systemUserBiz.cleanUnionId(this.getLoginUser().getId());
         Subject subject = SecurityUtils.getSubject();
         subject.logout();
         return ApiResponse.success(null);
diff --git a/server/services/src/main/java/com/doumee/biz/system/SystemUserBiz.java b/server/services/src/main/java/com/doumee/biz/system/SystemUserBiz.java
index 10c44ac..dad35ea 100644
--- a/server/services/src/main/java/com/doumee/biz/system/SystemUserBiz.java
+++ b/server/services/src/main/java/com/doumee/biz/system/SystemUserBiz.java
@@ -48,7 +48,7 @@
      * @param systemUser 璇﹁CreateSystemUserDTO
      */
     void create(CreateSystemUserDTO systemUser);
-
+    void cleanUnionId(Integer userId);
     /**
      * 淇敼鐢ㄦ埛淇℃伅
      *
diff --git a/server/services/src/main/java/com/doumee/biz/system/impl/SystemUserBizImpl.java b/server/services/src/main/java/com/doumee/biz/system/impl/SystemUserBizImpl.java
index 5a9c7a0..5c9a9b9 100644
--- a/server/services/src/main/java/com/doumee/biz/system/impl/SystemUserBizImpl.java
+++ b/server/services/src/main/java/com/doumee/biz/system/impl/SystemUserBizImpl.java
@@ -1,5 +1,7 @@
 package com.doumee.biz.system.impl;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.doumee.biz.system.SystemUserBiz;
 import com.doumee.core.exception.BusinessException;
 import com.doumee.core.constants.ResponseStatus;
@@ -159,6 +161,15 @@
         systemUserService.updateById(systemUser);
     }
 
+
+    @Override
+    public void cleanUnionId(Integer userId){
+        LambdaUpdateWrapper<SystemUser> w = new UpdateWrapper<SystemUser>().lambda().set(SystemUser::getUnionId,null)
+                .eq(SystemUser::getId,userId);
+        systemUserService.updateByWrapper(w);
+
+    }
+
     @Override
     @Transactional
     public void createUserRole(CreateUserRoleDTO dto) {
diff --git a/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java b/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
index 9c0b262..a2b868c 100644
--- a/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
+++ b/server/services/src/main/java/com/doumee/config/jwt/JwtTokenUtil.java
@@ -7,6 +7,7 @@
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
 import lombok.extern.slf4j.Slf4j;
+import org.checkerframework.checker.units.qual.C;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
diff --git a/server/services/src/main/java/com/doumee/config/shiro/ShiroConfig.java b/server/services/src/main/java/com/doumee/config/shiro/ShiroConfig.java
index 2c82de1..d77057a 100644
--- a/server/services/src/main/java/com/doumee/config/shiro/ShiroConfig.java
+++ b/server/services/src/main/java/com/doumee/config/shiro/ShiroConfig.java
@@ -87,6 +87,7 @@
         Map<String, String> map = new LinkedHashMap<>();
         // 璺緞鎷︽埅閰嶇疆
         map.put("/system/login", "anon");
+        map.put("/system/loginByDingTalk", "anon");
         map.put("/system/logout", "anon");
         map.put("/common/captcha", "anon");
         // - 鏀捐swagger
diff --git a/server/services/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java b/server/services/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java
index 9f66e68..62b7599 100644
--- a/server/services/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java
+++ b/server/services/src/main/java/com/doumee/config/shiro/ShiroCredentialsMatcher.java
@@ -25,17 +25,22 @@
 
     @Override
     public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
-        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
-        SystemUser queryUserDto = new SystemUser();
-        queryUserDto.setUsername(usernamePasswordToken.getUsername());
-        queryUserDto.setDeleted(Boolean.FALSE);
-        SystemUser systemUser = systemUserService.findOne(queryUserDto);
-        if (systemUser == null) {
-            return Boolean.FALSE;
+        ShiroToken shiroToken = (ShiroToken) token;
+        if(!shiroToken.getDdLogin()){
+            SystemUser queryUserDto = new SystemUser();
+            queryUserDto.setUsername(shiroToken.getUsername());
+            queryUserDto.setDeleted(Boolean.FALSE);
+            SystemUser systemUser = systemUserService.findOne(queryUserDto);
+            if (systemUser == null) {
+                return Boolean.FALSE;
+            }
+            // 鍔犲瘑瀵嗙爜
+            String pwd = Utils.Secure.encryptPassword(new String(shiroToken.getPassword()), systemUser.getSalt());
+            // 姣旇緝瀵嗙爜
+            return this.equals(pwd, systemUser.getPassword());
+        }else{
+            return true;
         }
-        // 鍔犲瘑瀵嗙爜
-        String pwd = Utils.Secure.encryptPassword(new String(usernamePasswordToken.getPassword()), systemUser.getSalt());
-        // 姣旇緝瀵嗙爜
-        return this.equals(pwd, systemUser.getPassword());
+
     }
 }
diff --git a/server/services/src/main/java/com/doumee/config/shiro/ShiroToken.java b/server/services/src/main/java/com/doumee/config/shiro/ShiroToken.java
new file mode 100644
index 0000000..b4fb5f5
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/config/shiro/ShiroToken.java
@@ -0,0 +1,43 @@
+package com.doumee.config.shiro;
+
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.springframework.stereotype.Component;
+
+/**
+ * 鑷畾涔塗oken 锛屽鐞嗚璇佸拰鏉冮檺
+ * @author Eva.Caesar Liu
+ * @date 2022/04/18 18:12
+ */
+@Component
+public class ShiroToken extends UsernamePasswordToken {
+
+    /**
+     * 鍏徃ID
+     */
+    String unionId;
+    Boolean isDdLogin;
+
+    public ShiroToken() {
+    }
+    public ShiroToken(String unionId, String username, String password, boolean isDdLogin) {
+        super(username,  password, false, (String)null);
+        this.unionId = unionId;
+        this.isDdLogin = isDdLogin;
+    }
+
+    public Boolean getDdLogin() {
+        return isDdLogin;
+    }
+
+    public void setDdLogin(Boolean ddLogin) {
+        isDdLogin = ddLogin;
+    }
+
+    public String getUnionId() {
+        return unionId;
+    }
+
+    public void setUnionId(String unionId) {
+        this.unionId = unionId;
+    }
+}
diff --git a/server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java b/server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java
index 4942d4f..5a460f2 100644
--- a/server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java
+++ b/server/services/src/main/java/com/doumee/core/dingTalk/DingTalk.java
@@ -82,32 +82,14 @@
         return accessToken;
     }
 
-    private String getAccessToken(String corpId) {
-        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
-        config.protocol = "https";
-        config.regionId = "central";
-        try {
-            com.aliyun.dingtalkoauth2_1_0.Client client = new com.aliyun.dingtalkoauth2_1_0.Client(config);
-            com.aliyun.dingtalkoauth2_1_0.models.GetTokenRequest getTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetTokenRequest()
-                    .setClientId(clientId)
-                    .setClientSecret(clientSecret)
-                    .setGrantType("client_credentials");
-            GetTokenResponse response = client.getToken(corpId, getTokenRequest);
-            return response.getBody().accessToken;
-        } catch (TeaException err) {
-            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
-                // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰�
-                log.error("Error getting access token: {}", err.getMessage());
-            }
-
-        } catch (Exception _err) {
-            TeaException err = new TeaException(_err.getMessage(), _err);
-            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
-                // err 涓惈鏈� code 鍜� message 灞炴�э紝鍙府鍔╁紑鍙戝畾浣嶉棶棰�
-                log.error("Error getting access token: {}", err.getMessage());
-            }
-        }
-        return null;
+    private String getAccessToken() throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+        OapiGettokenRequest req = new OapiGettokenRequest();
+        req.setAppkey(clientId);
+        req.setAppsecret(clientSecret);
+        req.setHttpMethod("GET");
+        OapiGettokenResponse rsp = client.execute(req);
+        return rsp.getAccessToken();
     }
 
 
@@ -115,7 +97,7 @@
         DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
         OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
         req.setCode(dto.getCode());
-        OapiV2UserGetuserinfoResponse rsp = client.execute(req, getAccessToken(dto.getCorpId()));
+        OapiV2UserGetuserinfoResponse rsp = client.execute(req, getAccessToken());
         if(rsp.getErrcode().equals(Constants.DD_ERR_CODE)){
            return  rsp.getResult();
         }else{
diff --git a/server/services/src/main/java/com/doumee/core/iPass/IPass.java b/server/services/src/main/java/com/doumee/core/iPass/IPass.java
new file mode 100644
index 0000000..c971735
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/core/iPass/IPass.java
@@ -0,0 +1,96 @@
+package com.doumee.core.iPass;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.doumee.core.constants.Constants;
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.doumee.dao.vo.ZhanQuVO;
+import okhttp3.*;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @Author : Rk
+ * @create 2026/2/3 15:15
+ */
+public class IPass {
+
+    private static  String userName = "djpt";
+    private static  String password = "CwzOdj3G8Y05NRu9pWjcmmODj56/6iZjSD33couFE3XNrkNjEQUZwnkLEGN6ot1O7b9q/K+PsRNh7iRquL4ZYQdajIM3P+qxn8Q1eW2eICmwMY0L+vWpBK30xU+DX6yzkt5/meitCa5rZERUWUGAfAfimdvhfCazLseXdB3x/ieJ+/C+22LH0gIZoqiC0xqh+xR5NENu0lcC7PLJoCE0rzq+LLY7TNwmv6Ghxjbq5cCuxMd0H6uD3nKM/13+TNLuod5/9RzGBo966CUqLqS2L6XTqZkGCRwJL7pvD0+ZAnM36gXC1aTXT4Z6bYnwsGfpu7MjHODGSrzhrQEXS2Gbfg==";
+    private static String tokenUrl = "https://ipaasuat.zhibang.com:4430/open-api/rest/core/auth/login";
+    private static String zhanquUrl = "https://ipaasuat.zhibang.com:4430/open-api/mdm/cust-territories-trees/query";
+
+    public String getIPassToken() throws IOException {
+        OkHttpClient client = new OkHttpClient().newBuilder()
+                .build();
+        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
+        Map<String,String> requestBody = new HashMap<>();
+        requestBody.put("userName",userName);
+        requestBody.put("password",password);
+        RequestBody body = RequestBody.create(mediaType, JSONObject.toJSON(requestBody).toString());
+        Request request = new Request.Builder()
+                .url(tokenUrl)
+                .method("POST", body)
+                .addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
+                .addHeader("Content-Type", "application/json; charset=utf-8")
+                .build();
+        Response response = client.newCall(request).execute();
+        if(Objects.isNull(response)){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"鑾峰彇IPASS鎺堟潈鏉冮檺澶辫触,璇疯仈绯荤鐞嗗憳");
+        }
+        if(!Constants.equalsInteger(200,response.code())){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"鑾峰彇IPASS鎺堟潈鏉冮檺澶辫触:"+response.message());
+        }
+        JSONObject jsonObject = JSONObject.parseObject(response.body().string());
+        String token = jsonObject.getString("identitytoken");
+        return  token;
+    }
+
+
+
+    public List<ZhanQuVO> getIPassZhanquList() throws IOException {
+        OkHttpClient client = new OkHttpClient().newBuilder()
+                .build();
+        MediaType mediaType = MediaType.parse("application/json");
+        Map<String,Object> requestBody = new HashMap<>();
+        requestBody.put("nodeLevel","1");
+        requestBody.put("pageNo","1");
+        requestBody.put("pageSize","1000");
+
+        RequestBody body = RequestBody.create(mediaType, JSONObject.toJSON(requestBody).toString());
+        Request request = new Request.Builder()
+                .url(zhanquUrl)
+                .method("POST", body)
+                .addHeader("identitytoken", getIPassToken())
+                .addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
+                .addHeader("Content-Type", "application/json")
+                .build();
+        Response response = client.newCall(request).execute();
+        if(Objects.isNull(response)){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"鑾峰彇IPASS鎴樺尯淇℃伅澶辫触,璇疯仈绯荤鐞嗗憳");
+        }
+        if(!Constants.equalsInteger(200,response.code())){
+            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"鑾峰彇IPASS鎴樺尯淇℃伅澶辫触:"+response.message());
+        }
+        JSONObject json = JSONObject.parseObject(response.body().string());
+        JSONArray jsonArray = json.getJSONArray("rows");
+        List<ZhanQuVO> zhanQuVOS = jsonArray.toJavaList(ZhanQuVO.class);
+        return zhanQuVOS;
+    }
+
+
+
+    public static void main(String[] args) throws IOException {
+        IPass iPass = new IPass();
+        iPass.getIPassZhanquList();
+    }
+
+
+}
diff --git a/server/services/src/main/java/com/doumee/core/utils/Base64Util.java b/server/services/src/main/java/com/doumee/core/utils/Base64Util.java
new file mode 100644
index 0000000..df63b3d
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/core/utils/Base64Util.java
@@ -0,0 +1,1184 @@
+package com.doumee.core.utils;
+
+/**
+ * Base64鏂囦欢瀛楃涓插鐞嗗伐鍏风被
+ * 
+ * @ClassName Base64Util
+ * @Description TODO
+ * @author jfli@woyitech.com
+ * @date 2016骞�5鏈�27鏃� 涓婂崍11:46:34
+ */
+public final class Base64Util {
+
+	/**
+	 * NO_OPTIONS=0
+	 */
+	public static final int NO_OPTIONS = 0;
+	/**
+	 * ENCODE = 1
+	 */
+	public static final int ENCODE = 1;
+
+	/**
+	 * DECODE = 0
+	 */
+	public static final int DECODE = 0;
+
+	/**
+	 * GZIP = 2
+	 */
+	public static final int GZIP = 2;
+	/**
+	 * DONT_BREAK_LINES = 8
+	 */
+	public static final int DONT_BREAK_LINES = 8;
+	/**
+	 * MAX_LINE_LENGTH = 76
+	 */
+	private static final int MAX_LINE_LENGTH = 76;
+
+	/**
+	 * EQUALS_SIGN(=)
+	 */
+	private static final byte EQUALS_SIGN = (byte) '=';
+
+	/**
+	 * NEW_LINE(enter)
+	 */
+	private static final byte NEW_LINE = (byte) '\n';
+
+	/**
+	 * PREFERRED_ENCODING(UTF-8)
+	 */
+	private static final String PREFERRED_ENCODING = "UTF-8";
+
+	/**
+	 * ALPHABET
+	 */
+	private static final byte[] ALPHABET;
+
+	/**
+	 * _NATIVE_ALPHABET
+	 */
+	private static final byte[] PRI_NATIVE_ALPHABET = new byte[] { 
+			(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D',
+			(byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I',
+			(byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M',
+			(byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R',
+			(byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
+			(byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
+			(byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
+			(byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
+			(byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n',
+			(byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's',
+			(byte) 't', (byte) 'u', (byte) 'v', (byte) 'w',
+			(byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1',
+			(byte) '2', (byte) '3', (byte) '4', (byte) '5',
+			(byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/' };
+
+	static {
+		byte[] priBytes = null;
+		try {
+			priBytes = 
+					"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+					.getBytes(PREFERRED_ENCODING);
+		} catch (java.io.UnsupportedEncodingException use) {
+			priBytes = PRI_NATIVE_ALPHABET; // Fall back to native encoding
+		} // end catch
+		ALPHABET = priBytes;
+	} // end static
+	
+	/**
+	 * DECODABET
+	 */
+	private static final byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal// 0// -// 8
+			-5, -5, // Whitespace: Tab and Linefeed
+			-9, -9, // Decimal 11 - 12
+			-5, // Whitespace: Carriage Return
+			-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - // 26
+			-9, -9, -9, -9, -9, // Decimal 27 - 31
+			-5, // Whitespace: Space
+			-9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
+			62, // Plus sign at decimal 43
+			-9, -9, -9, // Decimal 44 - 46
+			63, // Slash at decimal 47
+			52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
+			-9, -9, -9, // Decimal 58 - 60
+			-1, // Equals sign at decimal 61
+			-9, -9, -9, // Decimal 62 - 64
+			0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through // 'N'
+			14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O'// through 'Z'
+			-9, -9, -9, -9, -9, -9, // Decimal 91 - 96
+			26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a'// through 'm'
+			39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n'// through 'z'
+			-9, -9, -9, -9 // Decimal 123 - 126
+
+	};
+
+	// I think I end up not using the BAD_ENCODING indicator.
+	// private final static byte BAD_ENCODING = -9; // Indicates error in
+	// encoding
+	/**
+	 * WHITE_SPACE_ENC = -5
+	 */
+	private static final byte WHITE_SPACE_ENC = -5; // Indicates white space in
+	// encoding
+	/**
+	 * 	EQUALS_SIGN_ENC = -1							
+	 */
+	private static final byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in // encoding
+	
+	/**
+	 * 榛樿鏋勯�犲櫒
+	 * @Title Base64Util
+	 * @Description TODO
+	 */
+	private Base64Util() {
+	}
+
+	/**
+	 * 鍔犲瘑byte鏁扮粍
+	 * 
+	 * @param b4
+	 * @param threeBytes
+	 * @param numSigBytes
+	 * @return byte鏁扮粍
+	 */
+	private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes) {
+		encode3to4(threeBytes, 0, numSigBytes, b4, 0);
+		return b4;
+	} // end encode3to4
+
+	/**
+	 * 鍔犲瘑byte鏁扮粍
+	 * 
+	 * @param source
+	 * @param srcOffset
+	 * @param numSigBytes
+	 * @param destination
+	 * @param destOffset
+	 * @return byte鏁扮粍
+	 */
+	private static byte[] encode3to4(byte[] source, int srcOffset, 
+			int numSigBytes, byte[] destination,
+			int destOffset) {
+		// 1 2 3
+		// 01234567890123456789012345678901 Bit position
+		// --------000000001111111122222222 Array position from threeBytes
+		// --------| || || || | Six bit groups to index ALPHABET
+		// >>18 >>12 >> 6 >> 0 Right shift necessary
+		// 0x3f 0x3f 0x3f Additional AND
+
+		// Create buffer with zero-padding if there are only one or two
+		// significant bytes passed in the array.
+		// We have to shift left 24 in order to flush out the 1's that appear
+		// when Java treats a value as negative that is cast from a byte to an
+		// int.
+		int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
+				| (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
+				| (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
+
+		switch (numSigBytes) {
+		case 3:
+			destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+			destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+			destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
+			destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
+			return destination;
+
+		case 2:
+			destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+			destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+			destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
+			destination[destOffset + 3] = EQUALS_SIGN;
+			return destination;
+
+		case 1:
+			destination[destOffset] = ALPHABET[(inBuff >>> 18)];
+			destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
+			destination[destOffset + 2] = EQUALS_SIGN;
+			destination[destOffset + 3] = EQUALS_SIGN;
+			return destination;
+
+		default:
+			return destination;
+		} // end switch
+	} // end encode3to4
+
+	/**
+	 * 搴忓垪鍖栧璞¤浆鍖栧瓧绗︿覆
+	 * 
+	 * @param serializableObject
+	 * @return 瀛楃涓�
+	 */
+	public static String encodeObject(java.io.Serializable serializableObject) {
+		return encodeObject(serializableObject, NO_OPTIONS);
+	} // end encodeObject
+
+	/**
+	 * 搴忓垪鍖栧璞¤浆鍖栧瓧绗︿覆
+	 * 
+	 * @param serializableObject
+	 * @param options
+	 * @return 瀛楃涓�
+	 */
+	public static String encodeObject(java.io.Serializable serializableObject, int options) {
+		// Streams
+		java.io.ByteArrayOutputStream baos = null;
+		java.io.OutputStream b64os = null;
+		java.io.ObjectOutputStream oos = null;
+		java.util.zip.GZIPOutputStream gzos = null;
+
+		// Isolate options
+		int gzip = (options & GZIP);
+		int dontBreakLines = (options & DONT_BREAK_LINES);
+
+		try {
+			// ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
+			baos = new java.io.ByteArrayOutputStream();
+			b64os = new OutputStream(baos, ENCODE | dontBreakLines);
+
+			// GZip?
+			if (gzip == GZIP) {
+				gzos = new java.util.zip.GZIPOutputStream(b64os);
+				oos = new java.io.ObjectOutputStream(gzos);
+				// end if: gzip
+			} else {
+				oos = new java.io.ObjectOutputStream(b64os);
+			}
+			oos.writeObject(serializableObject);
+			// end try
+		} catch (java.io.IOException e) {
+			e.printStackTrace();
+			return null;
+			// end catch
+		} finally {
+			try {
+				oos.close();
+			} catch (Exception e) {
+			}
+			try {
+				gzos.close();
+			} catch (Exception e) {
+			}
+			try {
+				b64os.close();
+			} catch (Exception e) {
+			}
+			try {
+				baos.close();
+			} catch (Exception e) {
+			}
+		} // end finally
+
+		// Return value according to relevant encoding.
+		try {
+			return new String(baos.toByteArray(), PREFERRED_ENCODING);
+			// end try
+		} catch (java.io.UnsupportedEncodingException uue) {
+			return new String(baos.toByteArray());
+		} // end catch
+
+	} // end encode
+
+	/**
+	 * byte鏁扮粍杞寲瀛楃涓�
+	 * 
+	 * @param source
+	 * @return 瀛楃涓�
+	 */
+	public static String encodeBytes(byte[] source) {
+		return encodeBytes(source, 0, source.length, NO_OPTIONS);
+	} // end encodeBytes
+
+	/**
+	 * byte鏁扮粍杞寲瀛楃涓�
+	 * 
+	 * @param source
+	 * @param options
+	 * @return 瀛楃涓�
+	 */
+	public static String encodeBytes(byte[] source, int options) {
+		return encodeBytes(source, 0, source.length, options);
+	} // end encodeBytes
+
+	/**
+	 * byte鏁扮粍杞寲瀛楃涓�
+	 * 
+	 * @param source
+	 * @param off
+	 * @param len
+	 * @return 瀛楃涓�
+	 */
+	public static String encodeBytes(byte[] source, int off, int len) {
+		return encodeBytes(source, off, len, NO_OPTIONS);
+	} // end encodeBytes
+
+	/**
+	 * byte鏁扮粍杞寲瀛楃涓�
+	 * 
+	 * @param source
+	 * @param off
+	 * @param len
+	 * @param options
+	 * @return 瀛楃涓�
+	 */
+	public static String encodeBytes(byte[] source, int off, int len, int options) {
+		// Isolate options
+		int dontBreakLines = (options & DONT_BREAK_LINES);
+		int gzip = (options & GZIP);
+
+		// Compress?
+		if (gzip == GZIP) {
+			java.io.ByteArrayOutputStream baos = null;
+			java.util.zip.GZIPOutputStream gzos = null;
+			OutputStream b64os = null;
+
+			try {
+				// GZip -> Base64 -> ByteArray
+				baos = new java.io.ByteArrayOutputStream();
+				b64os = new OutputStream(baos, ENCODE | dontBreakLines);
+				gzos = new java.util.zip.GZIPOutputStream(b64os);
+
+				gzos.write(source, off, len);
+				gzos.close();
+				// end try
+			} catch (java.io.IOException e) {
+				e.printStackTrace();
+				return null;
+				// end catch
+			} finally {
+				try {
+					gzos.close();
+				} catch (Exception e) {
+				}
+				try {
+					b64os.close();
+				} catch (Exception e) {
+				}
+				try {
+					baos.close();
+				} catch (Exception e) {
+				}
+			} // end finally
+
+			// Return value according to relevant encoding.
+			try {
+				return new String(baos.toByteArray(), PREFERRED_ENCODING);
+				// end try
+			} catch (java.io.UnsupportedEncodingException uue) {
+				return new String(baos.toByteArray());
+			} // end catch
+			// end if: compress
+		} else {
+		// Else, don't compress. Better not to use streams at all then.
+			// Convert option to boolean in way that code likes it.
+			boolean breakLines = dontBreakLines == 0;
+
+			int len43 = len * 4 / 3;
+			byte[] outBuff = new byte[(len43) // Main 4:3
+					+ ((len % 3) > 0 ? 4 : 0) // Account for padding
+					+ (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New // lines
+			int d = 0;
+			int e = 0;
+			int len2 = len - 2;
+			int lineLength = 0;
+			for (; d < len2; d += 3, e += 4) {
+				encode3to4(source, d + off, 3, outBuff, e);
+
+				lineLength += 4;
+				if (breakLines && lineLength == MAX_LINE_LENGTH) {
+					outBuff[e + 4] = NEW_LINE;
+					e++;
+					lineLength = 0;
+				} // end if: end of line
+			} // en dfor: each piece of array
+
+			if (d < len) {
+				encode3to4(source, d + off, len - d, outBuff, e);
+				e += 4;
+			} // end if: some padding needed
+
+			// Return value according to relevant encoding.
+			try {
+				return new String(outBuff, 0, e, PREFERRED_ENCODING);
+				// end try
+			} catch (java.io.UnsupportedEncodingException uue) {
+				return new String(outBuff, 0, e);
+			} // end catch
+
+		} // end else: don't compress
+
+	} // end encodeBytes
+
+	/**
+	 * 琛ㄧず鐪嬩笉鎳傦紝姹傝ˉ鍏�
+	 * 
+	 * @param source
+	 * @param srcOffset
+	 * @param destination
+	 * @param destOffset
+	 * @return int
+	 */
+	private static int decode4to3(byte[] source, int srcOffset,
+			byte[] destination, int destOffset) {
+		// Example: Dk==
+		if (source[srcOffset + 2] == EQUALS_SIGN) {
+			// Two ways to do the same thing. Don't know which way I like best.
+			// int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6
+			// )
+			// | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 );
+			int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
+					| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);
+
+			destination[destOffset] = (byte) (outBuff >>> 16);
+			return 1;
+		} else if (source[srcOffset + 3] == EQUALS_SIGN) {// Example: DkL=
+			// Two ways to do the same thing. Don't know which way I like best.
+			// int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6
+			// )
+			// | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+			// | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 );
+			int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
+					| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
+					| ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);
+
+			destination[destOffset] = (byte) (outBuff >>> 16);
+			destination[destOffset + 1] = (byte) (outBuff >>> 8);
+			return 2;
+		} else {// Example: DkLE
+			try {
+				// Two ways to do the same thing. Don't know which way I like
+				// best.
+				// int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 )
+				// >>> 6 )
+				// | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 )
+				// | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 )
+				// | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 );
+				int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
+						| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
+						| ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6)
+						| ((DECODABET[source[srcOffset + 3]] & 0xFF));
+
+				destination[destOffset] = (byte) (outBuff >> 16);
+				destination[destOffset + 1] = (byte) (outBuff >> 8);
+				destination[destOffset + 2] = (byte) (outBuff);
+
+				return 3;
+			} catch (Exception e) {
+				// System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[
+				// source[ srcOffset ] ] ) );
+				// System.out.println(""+source[srcOffset+1]+ ": " + (
+				// DECODABET[ source[ srcOffset + 1 ] ] ) );
+				// System.out.println(""+source[srcOffset+2]+ ": " + (
+				// DECODABET[ source[ srcOffset + 2 ] ] ) );
+				// System.out.println(""+source[srcOffset+3]+ ": " + (
+				// DECODABET[ source[ srcOffset + 3 ] ] ) );
+				return -1;
+			} // e nd catch
+		}
+	} // end decodeToBytes
+
+	/**
+	 * 鍔犲瘑byte鏁版嵁
+	 * 
+	 * @param source
+	 *            鍘焍yte鏁扮粍
+	 * @param off
+	 *            寮�濮嬩綅缃�
+	 * @param len
+	 *            闀垮害
+	 * @return byte鏁扮粍
+	 */
+	public static byte[] decode(byte[] source, int off, int len) {
+		int len34 = len * 3 / 4;
+		byte[] outBuff = new byte[len34]; // Upper limit on size of output
+		int outBuffPosn = 0;
+
+		byte[] b4 = new byte[4];
+		int b4Posn = 0;
+		int i = 0;
+		byte sbiCrop = 0;
+		byte sbiDecode = 0;
+		for (i = off; i < off + len; i++) {
+			sbiCrop = (byte) (source[i] & 0x7f); // Only the low seven bits
+			sbiDecode = DECODABET[sbiCrop];
+
+			if (sbiDecode >= WHITE_SPACE_ENC){ // White space, Equals sign or
+												// better
+			
+				if (sbiDecode >= EQUALS_SIGN_ENC) {
+					b4[b4Posn++] = sbiCrop;
+					if (b4Posn > 3) {
+						outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
+						b4Posn = 0;
+
+						// If that was the equals sign, break out of 'for' loop
+						if (sbiCrop == EQUALS_SIGN){
+							break;
+						}
+					} // end if: quartet built
+
+				} // end if: equals sign or better
+				// end if: white space, equals sign or better
+			} else {
+				System.err.println("Bad Base64 input character at "
+						+ i + ": " + source[i] + "(decimal)");
+				return null;
+			} // end else:
+		} // each input character
+
+		byte[] out = new byte[outBuffPosn];
+		System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
+		return out;
+	} // end decode
+
+	/**
+	 * 灏嗗瓧绗︿覆杞寲涓篵yte鏁扮粍
+	 * 
+	 * @param s
+	 * @return byte鏁扮粍
+	 */
+	public static byte[] decode(String s) {
+		byte[] bytes;
+		try {
+			bytes = s.getBytes(PREFERRED_ENCODING);
+			// end try
+		} catch (java.io.UnsupportedEncodingException uee) {
+			bytes = s.getBytes();
+		} // end catch
+			// </change>
+
+		// Decode
+		bytes = decode(bytes, 0, bytes.length);
+
+		// Check to see if it's gzip-compressed
+		// GZIP Magic Two-Byte Number: 0x8b1f (35615)
+		if (bytes != null && bytes.length >= 4) {
+
+			int head = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
+			if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {
+				java.io.ByteArrayInputStream bais = null;
+				java.util.zip.GZIPInputStream gzis = null;
+				java.io.ByteArrayOutputStream baos = null;
+				byte[] buffer = new byte[2048];
+				int length = 0;
+
+				try {
+					baos = new java.io.ByteArrayOutputStream();
+					bais = new java.io.ByteArrayInputStream(bytes);
+					gzis = new java.util.zip.GZIPInputStream(bais);
+
+					while ((length = gzis.read(buffer)) >= 0) {
+						baos.write(buffer, 0, length);
+					} // end while: reading input
+
+					// No error? Get new bytes.
+					bytes = baos.toByteArray();
+					// end try
+				} catch (java.io.IOException e) {
+					// Just return originally-decoded bytes
+					// end catch
+				} finally {
+					try {
+						baos.close();
+					} catch (Exception e) {
+					}
+					try {
+						gzis.close();
+					} catch (Exception e) {
+					}
+					try {
+						bais.close();
+					} catch (Exception e) {
+					}
+				} // end finally
+
+			} // end if: gzipped
+		} // end if: bytes.length >= 2
+
+		return bytes;
+	} // end decode
+
+	/**
+	 * 灏嗗瓧绗︿覆杞寲涓篛bject瀵硅薄
+	 * 
+	 * @param encodedObject
+	 * @return Object
+	 */
+	public static Object decodeToObject(String encodedObject) {
+		// Decode and gunzip if necessary
+		byte[] objBytes = decode(encodedObject);
+
+		java.io.ByteArrayInputStream bais = null;
+		java.io.ObjectInputStream ois = null;
+		Object obj = null;
+
+		try {
+			bais = new java.io.ByteArrayInputStream(objBytes);
+			ois = new java.io.ObjectInputStream(bais);
+
+			obj = ois.readObject();
+			 // end try
+		} catch (java.io.IOException e) {
+			e.printStackTrace();
+			obj = null;
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+			obj = null;
+		} finally {
+			try {
+				bais.close();
+			} catch (Exception e) {
+			}
+			try {
+				ois.close();
+			} catch (Exception e) {
+			}
+		} // end finally
+
+		return obj;
+	} // end decodeObject
+
+	/**
+	 * 灏哹yte鏁扮粍杞崲鎴愭枃浠�
+	 * 
+	 * @param dataToEncode
+	 *            闇�瑕佽浆鎹㈢殑byte鏁扮粍
+	 * @param filename
+	 *            鏂囦欢鍚�,甯﹀悗缂�
+	 * @return 鏄惁杞崲鎴愬姛
+	 */
+	public static boolean encodeToFile(byte[] dataToEncode, String filename) {
+		boolean success = false;
+		OutputStream bos = null;
+		try {
+			bos = new OutputStream(new java.io.FileOutputStream(filename),
+					Base64Util.ENCODE);
+			bos.write(dataToEncode);
+			success = true;
+			// end try
+		} catch (java.io.IOException e) {
+
+			success = false;
+			// end catch: IOException
+		} finally {
+			try {
+				bos.close();
+			} catch (Exception e) {
+			}
+		} // end finally
+
+		return success;
+	} // end encodeToFile
+
+	/**
+	 * 灏嗗姞瀵嗗瓧绗︿覆杞崲鎴愭枃浠�
+	 * 
+	 * @param dataToDecode
+	 *            鍔犲瘑瀛楃涓�
+	 * @param filename
+	 *            鏂囦欢鍚嶏紝甯﹀悗缂�
+	 * @return 鏄惁杞崲鎴愬姛
+	 */
+	public static boolean decodeToFile(String dataToDecode, String filename) {
+		boolean success = false;
+		OutputStream bos = null;
+		try {
+			bos = new OutputStream(new java.io.FileOutputStream(filename),
+					Base64Util.DECODE);
+			bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));
+			success = true;
+			// end try
+		} catch (java.io.IOException e) {
+			success = false;
+			// end catch: IOException
+		} finally {
+			try {
+				bos.close();
+			} catch (Exception e) {
+			}
+		} // end finally
+
+		return success;
+	} // end decodeToFile
+
+	/**
+	 * 灏嗘枃浠跺姞瀵嗘垚byte鏁扮粍
+	 * 
+	 * @param filename
+	 *            鏂囦欢鍚嶏紝甯﹀悗缂�
+	 * @return byte鏁扮粍
+	 */
+	public static byte[] decodeFromFile(String filename) {
+		byte[] decodedData = null;
+		InputStream bis = null;
+		try {
+			// Set up some useful variables
+			java.io.File file = new java.io.File(filename);
+			byte[] buffer = null;
+			int length = 0;
+			int numBytes = 0;
+
+			// Check for size of file
+			if (file.length() > Integer.MAX_VALUE) {
+				System.err.println("File is too big for this convenience method ("
+						+ file.length() + " bytes).");
+				return null;
+			} // end if: file too big for int index
+			buffer = new byte[(int) file.length()];
+
+			// Open a stream
+			bis = new InputStream(
+					new java.io.BufferedInputStream(new java.io.FileInputStream(file)),
+					Base64Util.DECODE);
+
+			// Read until done
+			while ((numBytes = bis.read(buffer, length, 4096)) >= 0){
+				length += numBytes;
+			}
+			// Save in a variable to return
+			decodedData = new byte[length];
+			System.arraycopy(buffer, 0, decodedData, 0, length);
+			// end try
+		} catch (java.io.IOException e) {
+			System.err.println("Error decoding from file " + filename);
+			// end catch: IOException
+		} finally {
+			try {
+				bis.close();
+			} catch (Exception e) {
+			}
+		} // end finally
+
+		return decodedData;
+	} // end decodeFromFile
+
+	/**
+	 * 灏嗘枃浠惰浆鎹㈡垚瀛楃涓�
+	 * 
+	 * @param filename
+	 * @return 鏂囦欢杞崲鍚庣殑瀛楃涓�
+	 */
+	public static String encodeFromFile(String filename) {
+		String encodedData = null;
+		InputStream bis = null;
+		try {
+			// Set up some useful variables
+			java.io.File file = new java.io.File(filename);
+			byte[] buffer = new byte[(int) (file.length() * 1.4)];
+			int length = 0;
+			int numBytes = 0;
+
+			// Open a stream
+			bis = new InputStream(new java.io.BufferedInputStream(
+					new java.io.FileInputStream(file)),
+					Base64Util.ENCODE);
+
+			// Read until done
+			while ((numBytes = bis.read(buffer, length, 4096)) >= 0){
+				length += numBytes;
+			}
+
+			// Save in a variable to return
+			encodedData = new String(buffer, 0, length, Base64Util.PREFERRED_ENCODING);
+			 // end try
+		} catch (java.io.IOException e) {
+			System.err.println("Error encoding from file " + filename);
+			// end catch: IOException
+		} finally {
+			try {
+				bis.close();
+			} catch (Exception e) {
+			}
+		} // end finally
+
+		return encodedData;
+	} // end encodeFromFile
+
+	/**
+	 * 鍐呴儴绫籌nputStream
+	 * @ClassName  InputStream 
+	 * @Description  TODO
+	 * @author  jfli@woyitech.com
+	 * @date  2016骞�5鏈�27鏃� 涓嬪崍12:27:42
+	 */
+	public static class InputStream extends java.io.FilterInputStream {
+		/**
+		 * Encoding or decoding
+		 */
+		private boolean encode; // Encoding or decoding
+		/**
+		 * Current position in the buffer
+		 */
+		private int position; // 
+		/**
+		 * Small buffer holding converted data
+		 */
+		private byte[] buffer; // 
+		/**
+		 * Length of buffer (3 or 4)
+		 */
+		private int bufferLength; // 
+		/**
+		 *  Number of meaningful bytes in the buffer
+		 */
+		private int numSigBytes; //
+		/**
+		 * lineLength
+		 */
+		private int lineLength;
+		/**
+		 * Break lines at less than 80 characters
+		 */
+		private boolean breakLines; // 
+		
+		/**
+		 * 鏋勯�犲嚱鏁�
+		 * @Title InputStream
+		 * @Description TODO 
+		 * @param in
+		 */
+		public InputStream(java.io.InputStream in) {
+			this(in, DECODE);
+		} // end constructor
+		
+		/**
+		 * 鏋勯�犲嚱鏁�
+		 * @Title InputStream
+		 * @Description TODO 
+		 * @param in
+		 * @param options
+		 */
+		public InputStream(java.io.InputStream in, int options) {
+			super(in);
+			this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+			this.encode = (options & ENCODE) == ENCODE;
+			this.bufferLength = encode ? 4 : 3;
+			this.buffer = new byte[bufferLength];
+			this.position = -1;
+			this.lineLength = 0;
+		} // end constructor
+		
+		/**
+		 * read
+		 * @return int
+		 */
+		public int read() throws java.io.IOException {
+			// Do we need to get data?
+			if (position < 0) {
+				if (encode) {
+					byte[] b3 = new byte[3];
+					int numBinaryBytes = 0;
+					for (int i = 0; i < 3; i++) {
+						try {
+							int b = in.read();
+
+							// If end of stream, b is -1.
+							if (b >= 0) {
+								b3[i] = (byte) b;
+								numBinaryBytes++;
+							} // end if: not end of stream
+							// end try: read
+						} catch (java.io.IOException e) {
+							// Only a problem if we got no data at all.
+							if (i == 0){
+								throw e;
+								}
+
+						} // end catch
+					} // end for: each needed input byte
+
+					if (numBinaryBytes > 0) {
+						encode3to4(b3, 0, numBinaryBytes, buffer, 0);
+						position = 0;
+						numSigBytes = 4;
+						// end if: got data
+					} else {
+						return -1;
+					} // end else
+					 // end if: encoding
+				}else {// Else decoding
+					byte[] b4 = new byte[4];
+					int i = 0;
+					for (i = 0; i < 4; i++) {
+						// Read four "meaningful" bytes:
+						int b = 0;
+						do {
+							b = in.read();
+						} while (b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);
+
+						if (b < 0){
+							break; // Reads a -1 if end of stream
+						}
+
+						b4[i] = (byte) b;
+					} // end for: each needed input byte
+
+					if (i == 4) {
+						numSigBytes = decode4to3(b4, 0, buffer, 0);
+						position = 0;
+						// end if: got four characters
+					} else if (i == 0) {
+						return -1;
+						// end else if: also padded correctly
+					} else {
+						// Must have broken out from above.
+						throw new java.io.IOException("Improperly padded Base64 input.");
+					} // end
+
+				} // end else: decode
+			} // end else: get data
+
+			// Got data?
+			if (position >= 0) {
+				// End of relevant data?
+				if (position >= numSigBytes){
+					return -1;
+				}
+
+				if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) {
+					lineLength = 0;
+					return '\n';
+					// end if
+				} else {
+					lineLength++; // This isn't important when decoding
+									// but throwing an extra "if" seems
+									// just as wasteful.
+
+					int b = buffer[position++];
+
+					if (position >= bufferLength){
+						position = -1;
+					}
+					return b & 0xFF; // This is how you "cast" a byte that's
+										// intended to be unsigned.
+				} // end else
+				// end if: position >= 0
+			} else {// Else error
+				// When JDK1.4 is more accepted, use an assertion here.
+				throw new java.io.IOException("Error in Base64 code reading stream.");
+			} // end else
+		} // end read
+		
+		/**
+		 * read
+		 * @return int
+		 */
+		public int read(byte[] dest, int off, int len) throws java.io.IOException {
+			int i;
+			int b;
+			for (i = 0; i < len; i++) {
+				b = read();
+
+				// if( b < 0 && i == 0 )
+				// return -1;
+
+				if (b >= 0){
+					dest[off + i] = (byte) b;
+				}else if (i == 0){
+					return -1;
+				}else{
+					break; // Out of 'for' loop
+				}
+			} // end for: each byte read
+			return i;
+		} // end read
+
+	} // end inner class InputStream
+	/**
+	 * 鍐呴儴绫籓utputStream
+	 * @ClassName  OutputStream 
+	 * @Description  TODO
+	 * @author  jfli@woyitech.com
+	 * @date  2016骞�5鏈�27鏃� 涓嬪崍12:32:55
+	 */
+	public static class OutputStream extends java.io.FilterOutputStream {
+		/**
+		 * Encoding or decoding
+		 */
+		private boolean encode;
+		/**
+		 * Current position in the buffer
+		 */
+		private int position;
+		/**
+		 * Small buffer holding converted data
+		 */
+		private byte[] buffer;
+		/**
+		 * Length of buffer (3 or 4)
+		 */
+		private int bufferLength;
+		/**
+		 * lineLength
+		 */
+		private int lineLength;
+		/**
+		 *  Number of meaningful bytes in the buffer
+		 */
+		private boolean breakLines;
+		/**
+		 * Scratch used in a few places
+		 */
+		private byte[] b4; // 
+		/**
+		 * suspendEncoding
+		 */
+		private boolean suspendEncoding;
+		/**
+		 * 鏋勯�犲嚱鏁�
+		 * @Title OutputStream
+		 * @Description TODO 
+		 * @param out
+		 */
+		public OutputStream(java.io.OutputStream out) {
+			this(out, ENCODE);
+		} // end constructor
+		/**
+		 * 鏋勯�犲嚱鏁�
+		 * @Title OutputStream
+		 * @Description TODO 
+		 * @param out
+		 */
+		public OutputStream(java.io.OutputStream out, int options) {
+			super(out);
+			this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
+			this.encode = (options & ENCODE) == ENCODE;
+			this.bufferLength = encode ? 3 : 4;
+			this.buffer = new byte[bufferLength];
+			this.position = 0;
+			this.lineLength = 0;
+			this.suspendEncoding = false;
+			this.b4 = new byte[4];
+		} // end constructor
+		
+		/**
+		 * write
+		 */
+		public void write(int theByte) throws java.io.IOException {
+			// Encoding suspended?
+			if (suspendEncoding) {
+				super.out.write(theByte);
+				return;
+			} // end if: supsended
+
+			// Encode?
+			if (encode) {
+				buffer[position++] = (byte) theByte;
+				if (position >= bufferLength) {// Enough to encode.
+				
+					out.write(encode3to4(b4, buffer, bufferLength));
+
+					lineLength += 4;
+					if (breakLines && lineLength >= MAX_LINE_LENGTH) {
+						out.write(NEW_LINE);
+						lineLength = 0;
+					} // end if: end of line
+
+					position = 0;
+				} // end if: enough to output
+				// end if: encoding
+			} else {// Else, Decoding
+				// Meaningful Base64 character?
+				if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) {
+					buffer[position++] = (byte) theByte;
+					if (position >= bufferLength) {// Enough to output.
+					
+						int len = Base64Util.decode4to3(buffer, 0, b4, 0);
+						out.write(b4, 0, len);
+						// out.write( Base64.decode4to3( buffer ) );
+						position = 0;
+					} // end if: enough to output
+					 // end if: meaningful base64 character
+				} else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) {
+					throw new java.io.IOException("Invalid character in Base64 data.");
+				} // end else: not white space either
+			} // end else: decoding
+		} // end write
+		
+		/**
+		 * write
+		 */
+		public void write(byte[] theBytes, int off, int len) throws java.io.IOException {
+			// Encoding suspended?
+			if (suspendEncoding) {
+				super.out.write(theBytes, off, len);
+				return;
+			} // end if: supsended
+
+			for (int i = 0; i < len; i++) {
+				write(theBytes[off + i]);
+			} // end for: each byte written
+
+		} // end write
+		
+		/**
+		 * flushBase64 
+		 * @Title  flushBase64 
+		 * @Description  TODO
+		 * @author  jfli@woyitech.com
+		 * @throws java.io.IOException
+		 * @return 
+		 */
+		public void flushBase64() throws java.io.IOException {
+			if (position > 0) {
+				if (encode) {
+					out.write(encode3to4(b4, buffer, position));
+					position = 0;
+				} else {// end if: encoding
+					throw new java.io.IOException("Base64 input not properly padded.");
+				} // end else: decoding
+			} // end if: buffer partially full
+
+		} // end flush
+		/**
+		 * close
+		 */
+		public void close() throws java.io.IOException {
+			// 1. Ensure that pending characters are written
+			flushBase64();
+
+			// 2. Actually close the stream
+			// Base class both flushes and closes.
+			super.close();
+
+			buffer = null;
+			out = null;
+		} // end close
+		
+		/**
+		 * suspendEncoding = true
+		 * @Title  suspendEncoding 
+		 * @Description  TODO
+		 * @author  jfli@woyitech.com
+		 * @throws java.io.IOException
+		 * @return 
+		 */
+		public void suspendEncoding() throws java.io.IOException {
+			flushBase64();
+			this.suspendEncoding = true;
+		} // end suspendEncoding
+		
+		/**
+		 * suspendEncoding = false
+		 * @Title  resumeEncoding 
+		 * @Description  TODO
+		 * @author  jfli@woyitech.com
+		 * @return
+		 */
+		public void resumeEncoding() {
+			this.suspendEncoding = false;
+		} // end resumeEncoding
+
+	} // end inner class OutputStream
+
+	// public static void main(String[] args) {
+	//
+	// String filePath = "F:\\test\\璺ㄥ鐢靛晢浜嬩笟閮ㄩ�氳褰曪紙鍚堣偉鐮斿彂涓績锛�-20140722.doc";
+	//
+	// String str = Base64Util.encodeFromFile(filePath);
+	//
+	// Base64Util.decodeToFile(str, "F:\\123.doc");
+	// }
+}
diff --git a/server/services/src/main/java/com/doumee/core/utils/ZbomAESUtils.java b/server/services/src/main/java/com/doumee/core/utils/ZbomAESUtils.java
new file mode 100644
index 0000000..3c84c14
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/core/utils/ZbomAESUtils.java
@@ -0,0 +1,89 @@
+package com.doumee.core.utils;
+
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 瀵圭О鍔犲瘑(AES)
+ * 
+ * @author Joe
+ */
+public class ZbomAESUtils {
+	
+	public static final String INIT_VECTOR = "RandomInitVector";
+	public static final String PRIVATE_KEY = "zbom20180922!@#$";
+
+	/**
+	 * 鍔犲瘑
+	 * @param key 瀵嗛挜
+	 * @param value 鍔犲瘑鏁版嵁
+	 * @return
+	 */
+	public static String encrypt(String key, String value) {
+		try {
+			IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
+			SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
+
+			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
+			cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
+
+			byte[] encrypted = cipher.doFinal(value.getBytes());
+			return Base64Util.encodeBytes(encrypted);
+		}
+		catch (Exception ex) {
+			ex.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * 瑙e瘑
+	 * @param key 瀵嗛挜
+	 * @param encrypted 瑙e瘑鏁版嵁
+	 * @return
+	 */
+	public static String decrypt(String key, String encrypted) {
+		try {
+			IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
+			SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
+
+			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
+			cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+			byte[] original = cipher.doFinal(Base64Util.decode(encrypted));
+
+			return new String(original);
+		}
+		catch (Exception ex) {
+			ex.printStackTrace();
+		}
+		return null;
+	}
+
+	public static void main(String[] args) {
+
+		String str = "2[{\"broleName\":\"浠撶鍛榎",\"broleStatus\":\"Y\",\"operType\":\"0\",\"bonlyId\":842},{\"broleName\":\"缃戦�熸祴璇昞",\"broleStatus\":\"Y\",\"operType\":\"0\",\"bonlyId\":1282}]2019-01-11 11:59:07crmzbom20180922!@#$";
+//		System.out.println(str);
+//		System.out.println(MD5.string2MD5(str).toUpperCase());
+
+
+		String var = "Xrz4%2Fe1h3pbiLGfVlWYIM3VOMLDjJHkQSLSSErQRiS5vWgG%2B0sGXCQLaIW4Uod1izlp6RKC0K74P%0A1%2BzmgNK7ow%3D%3D";
+
+		//System.out.println(URLEncoder.encode("Xrz4%2Fe1h3pbiLGfVlWYIM12Vj0GtMaZ79IujEd4WNgM4d9QZcv%2BaqOzl%2FR2K%2Fs%2FVaAWS2OleN2uV%0A3lzglMli5g%3D%3D"));
+		String key = "zbom20180922!@#$"; // 128 bit key
+		Map resultMap = new HashMap();
+		resultMap.put("ssouserid", 499);
+		resultMap.put("appid", 2);
+		resultMap.put("entranceid", 4);
+//		System.out.println((URLDecoder.decode("PLFONVn89T%2FbNZKGRbMQaB9wYdaUNh1Wp88cfDBKykVXjdNH4CmfReijn6tl2i98CgyspshTTvg%2F%0AenRyPuIS4g%3D%3D")));
+
+//		System.out.println(URLDecoder.decode("Yu9FRXlPGZ6m4HXRhOsAOrfjRM384t%2FcEwtCtKhoyH3ETT83r3g4CWOc38PdcYRig2xXZNHHhLWu%0At7FNn%2FRjKQ%3D%3D"));
+		System.out.println(ZbomAESUtils.decrypt(ZbomAESUtils.PRIVATE_KEY, URLDecoder.decode(var)));
+
+		//System.out.println("------------>"+AESUtils.decrypt(AESUtils.PRIVATE_KEY, URLDecoder.decode("Yu9FRXlPGZ6m4HXRhOsAOuaM5QFPc0%2BV7yrYkGE2GgAZOfxMV2hdIgjKFy%2Bg%2BO816e6d4oOI6Zeh%0AJxt4tJZswhoSTG%2FW7uUU4AEKoJhoRMU%3D")));
+	}
+}
diff --git a/server/services/src/main/java/com/doumee/dao/business/model/Category.java b/server/services/src/main/java/com/doumee/dao/business/model/Category.java
index 9868a8d..05c988e 100644
--- a/server/services/src/main/java/com/doumee/dao/business/model/Category.java
+++ b/server/services/src/main/java/com/doumee/dao/business/model/Category.java
@@ -42,7 +42,7 @@
 
     @ApiModelProperty(value = "鍒涘缓鏃堕棿")
     @ExcelColumn(name="鍒涘缓鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
 
     @ApiModelProperty(value = "鏇存柊浜虹紪鐮�", example = "1")
@@ -51,7 +51,7 @@
 
     @ApiModelProperty(value = "鏇存柊鏃堕棿")
     @ExcelColumn(name="鏇存柊鏃堕棿")
-    @JsonFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date updateTime;
 
     @ApiModelProperty(value = "澶囨敞")
diff --git a/server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java b/server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java
index 32e9dd2..6a3fb05 100644
--- a/server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java
+++ b/server/services/src/main/java/com/doumee/dao/system/dto/DingLoginDTO.java
@@ -12,7 +12,7 @@
  * @since 2025/03/31 16:44
  */
 @Data
-@ApiModel("鐧诲綍鍙傛暟")
+@ApiModel("閽夐拤鎺堟潈鐧诲綍鍏ュ弬")
 public class DingLoginDTO implements Serializable {
 
     @NotBlank(message = "code涓嶈兘涓虹┖")
diff --git a/server/services/src/main/java/com/doumee/dao/system/dto/DingTalkLoginDTO.java b/server/services/src/main/java/com/doumee/dao/system/dto/DingTalkLoginDTO.java
new file mode 100644
index 0000000..7d94500
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/system/dto/DingTalkLoginDTO.java
@@ -0,0 +1,21 @@
+package com.doumee.dao.system.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * @author  dm
+ * @since 2025/03/31 16:44
+ */
+@Data
+@ApiModel("閽夐拤鎺堟潈鎸夌櫥褰曞弬鏁�")
+public class DingTalkLoginDTO implements Serializable {
+
+    @NotBlank(message = "code涓嶈兘涓虹┖")
+    @ApiModelProperty(value = "code")
+    private String code;
+}
diff --git a/server/services/src/main/java/com/doumee/dao/system/dto/LoginDTO.java b/server/services/src/main/java/com/doumee/dao/system/dto/LoginDTO.java
index 79c341e..dd5aa78 100644
--- a/server/services/src/main/java/com/doumee/dao/system/dto/LoginDTO.java
+++ b/server/services/src/main/java/com/doumee/dao/system/dto/LoginDTO.java
@@ -30,4 +30,10 @@
     @NotBlank(message = "楠岃瘉鐮乁UID涓嶈兘涓虹┖")
     @ApiModelProperty(value = "楠岃瘉鐮乁UID")
     private String uuid;
+
+    @ApiModelProperty(value = "unionId")
+    private String unionId;
+
+
+
 }
diff --git a/server/services/src/main/java/com/doumee/dao/system/model/SystemUser.java b/server/services/src/main/java/com/doumee/dao/system/model/SystemUser.java
index 3157800..1b687aa 100644
--- a/server/services/src/main/java/com/doumee/dao/system/model/SystemUser.java
+++ b/server/services/src/main/java/com/doumee/dao/system/model/SystemUser.java
@@ -85,4 +85,7 @@
     @ApiModelProperty(value = "鏄惁宸插垹闄�", hidden = true)
     private Boolean deleted;
 
+    @ApiModelProperty(value = "閽夐拤 unionId", hidden = true)
+    private String unionId;
+
 }
diff --git a/server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java b/server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java
index b7d2620..7d491ad 100644
--- a/server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java
+++ b/server/services/src/main/java/com/doumee/dao/vo/WebLoginUserVO.java
@@ -19,8 +19,8 @@
     @ApiModelProperty(value = "鐢ㄦ埛涓婚敭")
     private String id;
 
-    @ApiModelProperty(value = "鐢ㄦ埛瑙掕壊锛�   (dUser:鏍囪涓洪拤閽夌敤鎴�)")
-    private String roleType;
+    @ApiModelProperty(value = "鏄惁鏄剧ず璐圭敤淇℃伅:0=涓嶆樉绀猴紱1=鏄剧ず")
+    private Integer showFee;
 
     @ApiModelProperty(value = "鎴樺尯缂栫爜")
     private String zhanqu;
diff --git a/server/services/src/main/java/com/doumee/dao/vo/ZhanQuVO.java b/server/services/src/main/java/com/doumee/dao/vo/ZhanQuVO.java
new file mode 100644
index 0000000..9ed4b32
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/dao/vo/ZhanQuVO.java
@@ -0,0 +1,29 @@
+package com.doumee.dao.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Created by IntelliJ IDEA.
+ *
+ * @Author : Rk
+ * @create 2026/2/3 15:42
+ */
+@Data
+public class ZhanQuVO {
+
+    @ApiModelProperty(value = "鎴樺尯缂栫爜")
+    private String nodeCode;
+
+    @ApiModelProperty(value = "鎴樺尯鍚嶇О")
+    private String nodeName;
+
+    @ApiModelProperty(value = "鎴樺尯鐘舵�侊細")
+    private String nodeStatus;
+
+
+
+
+
+
+}
diff --git a/server/services/src/main/java/com/doumee/service/business/CategoryService.java b/server/services/src/main/java/com/doumee/service/business/CategoryService.java
index a48a0d1..81a4929 100644
--- a/server/services/src/main/java/com/doumee/service/business/CategoryService.java
+++ b/server/services/src/main/java/com/doumee/service/business/CategoryService.java
@@ -3,6 +3,8 @@
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
 import com.doumee.dao.business.model.Category;
+
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -96,5 +98,11 @@
     long count(Category category);
 
 
-    List<Category> getCategoryList(Integer type);
+    List<Category> getCategoryList(Integer type,Integer rank);
+
+    /**
+     * 鎴樺尯淇℃伅鍚屾
+     * @throws IOException
+     */
+    void syncZhanQu() throws IOException;
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/MemberService.java b/server/services/src/main/java/com/doumee/service/business/MemberService.java
index 28270d4..f8b6870 100644
--- a/server/services/src/main/java/com/doumee/service/business/MemberService.java
+++ b/server/services/src/main/java/com/doumee/service/business/MemberService.java
@@ -97,6 +97,6 @@
      */
     long count(Member model);
 
-    Member findDetailById(Integer id,String queryUserRole);
+    Member findDetailById(Integer id);
 
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
index c3a3117..6f231e7 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/CategoryServiceImpl.java
@@ -6,6 +6,7 @@
 import com.doumee.core.constants.Constants;
 import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.exception.BusinessException;
+import com.doumee.core.iPass.IPass;
 import com.doumee.core.model.LoginUserInfo;
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
@@ -15,6 +16,7 @@
 import com.doumee.dao.business.model.Category;
 import com.doumee.dao.business.model.Multifile;
 import com.doumee.dao.system.model.SystemUser;
+import com.doumee.dao.vo.ZhanQuVO;
 import com.doumee.service.business.CategoryService;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -23,6 +25,7 @@
 import com.github.yulichang.base.MPJBaseMapper;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.math3.analysis.function.Log;
 import org.apache.shiro.SecurityUtils;
 import org.checkerframework.checker.units.qual.C;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,10 +33,12 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * 鍒嗙被淇℃伅琛⊿ervice瀹炵幇
@@ -62,6 +67,17 @@
             throw new BusinessException(ResponseStatus.BAD_REQUEST);
         }
         LoginUserInfo loginUserInfo = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal();
+        if(Constants.equalsInteger(category.getType(),Constants.ZERO)){
+            if(categoryMapper.selectCount(new QueryWrapper<Category>().lambda()
+                    .eq(Category::getType,Constants.ZERO)
+                    .eq(Category::getDetail,category.getDetail())
+                    .eq(Category::getDeleted,Constants.ZERO)
+            )>Constants.ZERO){
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"璇ユ垬鍖虹紪鐮佸凡瀛樺湪");
+            }
+        }
+
+
         category.setDeleted(Constants.ZERO);
         category.setCreateTime(new Date());
         category.setCreateUser(loginUserInfo.getId());
@@ -127,12 +143,31 @@
         ){
             throw new BusinessException(ResponseStatus.BAD_REQUEST);
         }
+        if(Constants.equalsInteger(category.getType(),Constants.ZERO)){
+            if(categoryMapper.selectCount(new QueryWrapper<Category>().lambda()
+                    .eq(Category::getType,Constants.ZERO)
+                    .eq(Category::getDetail,category.getDetail())
+                    .eq(Category::getDeleted,Constants.ZERO)
+                    .ne(Category::getId,category.getId())
+            )>Constants.ZERO){
+                throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"璇ユ垬鍖虹紪鐮佸凡瀛樺湪");
+            }
+        }
         LoginUserInfo loginUserInfo = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal();
         category.setUpdateTime(new Date());
         category.setIsFixed(null);
         category.setUpdateUser(loginUserInfo.getId());
         categoryMapper.updateById(category);
+
+        if(Objects.isNull(category.getSortnum())){
+            categoryMapper.update(null,new UpdateWrapper<Category>().lambda()
+                    .set(Category::getSortnum,null)
+                    .eq(Category::getId,category.getId())
+            );
+        }
         dealBatchMultiFiles(category, category.getFileList(), loginUserInfo,true);
+
+
     }
     @Override
     public void updateStatus(Category category) {
@@ -234,6 +269,7 @@
             queryWrapper.eq(Category::getIsFixed, pageWrap.getModel().getIsFixed());
         }
         queryWrapper.orderByAsc(Category::getSortnum);
+        queryWrapper.orderByAsc(Category::getId);
         PageData<Category> result =PageData.from(categoryMapper.selectJoinPage(page, Category.class,queryWrapper));
         if(result!=null && result.getRecords()!=null){
             String path  = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.RESOURCE_PATH).getCode()
@@ -277,20 +313,19 @@
     }
 
     @Override
-    public List<Category> getCategoryList(Integer type){
+    public List<Category> getCategoryList(Integer type,Integer rank){
         List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda().eq(Category::getDeleted,Constants.ZERO).eq(Category::getStatus,Constants.ZERO)
                 .eq(Objects.nonNull(type),Category::getType,type)
+                .apply(Objects.nonNull(rank)&&Constants.equalsInteger(rank,Constants.ONE)," id in ( " +
+                        " select m.obj_id from multifile m where m.ISDELETED = 0 and m.OBJ_TYPE = 0  " +
+                        " ) ")
                 .orderByAsc(Category::getSortnum)
+                .orderByAsc(Category::getId)
         );
         if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(categoryList)){
-            String path  = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.RESOURCE_PATH).getCode()
-                    +systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE,Constants.CATEGORY_FILES).getCode();
-            for (Category category:categoryList) {
-                if(StringUtils.isNotBlank(category.getIcon())){
-                    category.setIconFull(path + category.getIcon());
-                }
-                if(Constants.equalsInteger(category.getType(),Constants.ONE) ){
-                    initMultifileList(category);
+            for(Category cate : categoryList){
+                if(Constants.equalsInteger(cate.getType(),Constants.ONE) ){
+                    initMultifileList(cate);
                 }
             }
         }
@@ -298,4 +333,58 @@
     }
 
 
+    @Override
+    @Transactional(rollbackFor = {Exception.class,BusinessException.class})
+    public void syncZhanQu() throws IOException {
+        LoginUserInfo loginUserInfo = (LoginUserInfo) SecurityUtils.getSubject().getPrincipal();
+        IPass iPass = new IPass();
+        List<ZhanQuVO> l =  iPass.getIPassZhanquList();
+        List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda()
+                .eq(Category::getType,Constants.ZERO)
+                .eq(Category::getDeleted,Constants.ZERO)
+        );
+        List<Category> updList = new ArrayList<>();
+        List<Category> addList = new ArrayList<>();
+        if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(l)){
+            for (ZhanQuVO zhanQuVO:l) {
+                Category category = this.vaildData(zhanQuVO,categoryList,loginUserInfo);
+                if(Objects.isNull(category.getId())){
+                    addList.add(category);
+                }else{
+                    updList.add(category);
+                }
+            }
+        }
+        if (com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(addList)) {
+            categoryMapper.insertOrUpdate(addList);
+        }
+        if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(updList)){
+            categoryMapper.insertOrUpdate(updList);
+        }
+    }
+
+
+    public Category vaildData(ZhanQuVO zhanQuVO , List<Category> categoryList, LoginUserInfo userInfo) {
+        Category returnData = new Category();
+        for (Category category:categoryList) {
+            if(category.getDetail().equals(zhanQuVO.getNodeCode())){
+                returnData = category   ;
+                returnData.setName(zhanQuVO.getNodeName());
+                returnData.setUpdateUser(userInfo.getId());
+                returnData.setUpdateTime(new Date());
+                return returnData;
+            }
+        }
+        returnData.setDetail(zhanQuVO.getNodeCode());
+        returnData.setCreateTime(new Date());
+        returnData.setDeleted(Constants.ZERO);
+        returnData.setStatus(zhanQuVO.getNodeStatus().equals("Y")?Constants.ZERO:Constants.ONE);
+        returnData.setName(zhanQuVO.getNodeName());
+        returnData.setCreateUser(userInfo.getId());
+        returnData.setType(Constants.ZERO);
+        returnData.setIsFixed(Constants.ZERO);
+        return returnData;
+    }
+
+
 }
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java
index 887bc64..8a5874f 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/ImportRecordServiceImpl.java
@@ -159,8 +159,8 @@
        queryWrapper.eq(pageWrap.getModel().getDoneNum() != null,ImportRecord::getDoneNum, pageWrap.getModel().getDoneNum());
        queryWrapper.eq(pageWrap.getModel().getErrorNum() != null,ImportRecord::getErrorNum, pageWrap.getModel().getErrorNum());
        queryWrapper.like(StringUtils.isNotBlank(pageWrap.getModel().getUpdateUserName()),SystemUser::getRealname, pageWrap.getModel().getUpdateUserName());
-       queryWrapper.ge(pageWrap.getModel().getEndtime() != null,ImportRecord::getCreateTime, pageWrap.getModel().getEndtime());
-       queryWrapper.ne(pageWrap.getModel().getStarttime() != null,ImportRecord::getCreateTime, pageWrap.getModel().getStarttime());
+       queryWrapper.ge(pageWrap.getModel().getStarttime() != null,ImportRecord::getCreateTime, pageWrap.getModel().getStarttime());
+       queryWrapper.le(pageWrap.getModel().getEndtime() != null,ImportRecord::getCreateTime, pageWrap.getModel().getEndtime());
        queryWrapper.orderByDesc(ImportRecord::getId);
         return PageData.from(importRecordMapper.selectPage(page, queryWrapper));
     }
@@ -180,7 +180,7 @@
         try {
             List<Category> categoryList = null;
             if(type == 0){
-              categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda().eq(Category::getDeleted,Constants.ZERO));
+              categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda().eq(Category::getDeleted,Constants.ZERO).eq(Category::getStatus,Constants.ZERO));
                 if(categoryList == null || categoryList.size()==0){
                     throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"瀵逛笉璧凤紝 璇诲彇鑰佸笀鍩烘暟鏁版嵁閰嶇疆鍑洪敊锛岃鍏堥厤缃熀纭�鏁版嵁淇℃伅锛�");
                 }
@@ -289,9 +289,13 @@
              if(StringUtils.isBlank(param.getTypeNames())){
                  throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"瀵逛笉璧凤紝绗�"+index+"琛屾暟鎹紝 鍟嗕笟鍖栫被鍨嬩俊鎭笉鑳戒负绌�");
              }
+             if(StringUtils.isBlank(param.getFieldNames())){
+                 throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"瀵逛笉璧凤紝绗�"+index+"琛屾暟鎹紝 鎿呴暱棰嗗煙淇℃伅涓嶈兘涓虹┖");
+             }
              if(StringUtils.isBlank(param.getFee())){
                  throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"瀵逛笉璧凤紝绗�"+index+"琛屾暟鎹紝 璐圭敤鏍囧噯淇℃伅涓嶈兘涓虹┖");
              }
+
           /*   if(pics!=null && StringUtils.isNotBlank(param.getImgurl())){
                 log.info("===================="+param.getImgurl());
                 int start = param.getImgurl().indexOf("(\"")+2;
@@ -340,7 +344,8 @@
                  member.setFee(new BigDecimal(param.getFee()));
              }catch (Exception e){
              }
-             member.setSex(StringUtils.equals(param.getSex(),"鐢�")?Constants.ZERO:(StringUtils.equals(param.getSex(),"濂�")?Constants.ZERO:null));
+             member.setSex(StringUtils.equals(param.getSex(),"鐢�")?Constants.ZERO:
+                     (StringUtils.equals(param.getSex(),"濂�")?Constants.ONE:null));
              member.setZhanquIds(getIdStrListByList(list0));
              member.setBustypeIds(getIdStrListByList(list1));
              member.setFieldIds(getIdStrListByList(list2));
diff --git a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
index 4c30251..f74f6c1 100644
--- a/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/business/impl/MemberServiceImpl.java
@@ -214,22 +214,23 @@
         Utils.MP.blankToNull(pageWrap.getModel());
         Member model = pageWrap.getModel();
         queryWrapper.selectAll(Member.class)
-                .selectAs(Category::getName, Member::getLevelName)
+                .select("t2.`NAME`", Member::getLevelName)
                 .selectAs(SystemUser::getRealname, Member::getUpdateUserName)
                 .leftJoin(SystemUser.class,SystemUser::getId,Member::getUpdateUser)
-                .leftJoin(Category.class,Category::getId,Member::getLevelId)
-                .apply(Objects.nonNull(model.getBustypeIds())," find_in_set( '["+model.getBustypeIds()+"]', t.BUSTYPE_IDS ) ")
+//                .leftJoin(Category.class,Category::getId,Member::getLevelId)
+                .leftJoin(" ( select c.* from category c  where c.deleted = 0 and c.status = 0 and c.type = 3  )   t2  on t.level_id = t2.id   ")
+//                .apply(Objects.nonNull(model.getBustypeIds())," find_in_set( '["+model.getBustypeIds()+"]', t.BUSTYPE_IDS ) ")
                 .apply(Objects.nonNull(model.getZhanquIds())," find_in_set( '["+model.getZhanquIds()+"]', t.ZHANQU_IDS ) ")
                 .like(StringUtils.isNotBlank(model.getName()),Member::getName, model.getName())
                 .eq(Objects.nonNull(model.getImportId()),Member::getImportId, model.getImportId())
                 .eq(Objects.nonNull(model.getStatus()),Member::getStatus, model.getStatus())
                 .eq(model.getContainDeleted()!=1,Member::getDeleted, Constants.ZERO)
-                .in(Objects.nonNull(model.getLevelId()),Category::getId, model.getLevelId())
+                .in(Objects.nonNull(model.getLevelId()),"t1.id", model.getLevelId())
                 .eq(Objects.nonNull(model.getCode()),Member::getCode, model.getCode())
                 .orderByDesc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.ZERO),Member::getFee)
                 .orderByAsc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.ONE),Member::getFee)
-                .orderByDesc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.TWO),Category::getDetail)
-                .orderByAsc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.THREE),Category::getDetail)
+                .orderByDesc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.TWO),"t2.SORTNUM")
+                .orderByAsc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.THREE),"t2.SORTNUM")
                 .orderByDesc(Objects.nonNull(model.getOrderByType())&&Constants.equalsInteger(model.getOrderByType(), Constants.FOUR),Member::getServeNum)
                 .orderByDesc(Member::getId)
         ;
@@ -244,6 +245,17 @@
             }
             queryWrapper.apply(sql);
         }
+
+
+        if(CollectionUtils.isNotEmpty(model.getBustypeIdList())){
+            String sql = "";
+            for (Integer s:model.getBustypeIdList()
+            ) {
+                sql = sql + (StringUtils.isNotBlank(sql)?" or ":"") + " find_in_set( '["+s+"]' , t.BUSTYPE_IDS ) ";
+            }
+            queryWrapper.apply(sql);
+        }
+
         if (StringUtils.isNotBlank(model.getQueryZQCode())) {
             Category zhanqu = categoryMapper.selectOne(new QueryWrapper<Category>().lambda()
                     .eq(Category::getDeleted,Constants.ZERO)
@@ -310,7 +322,7 @@
 
 
     @Override
-    public Member findDetailById(Integer id,String userRole) {
+    public Member findDetailById(Integer id) {
         Member member = memberMapper.selectJoinOne(Member.class, new MPJLambdaWrapper<Member>()
                 .selectAll(Member.class)
                 .select(" c1.NAME ", Member::getPromotionName)
@@ -334,17 +346,28 @@
            );
        }
 
+        List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().lambda()
+                        .eq(Category::getDeleted, Constants.ZERO)
+//                    .eq(Category::getType,Constants.TWO)
+                        .orderByAsc(Category::getSortnum)
+        );
+        if(CollectionUtils.isNotEmpty(categoryList)){
+            dealMemberField(member,categoryList);
+            dealMemberCategoryList(member, categoryList,Constants.ONE);
+        }
+
         String resourcePath = systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.RESOURCE_PATH).getCode();
         String path =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.MEMBER_FILES).getCode();
-        String roleConfig = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ROLE_CONFIG).getCode();
         member.setFullImgurl(StringUtils.isNotBlank(member.getImgurl())?(resourcePath  + path + member.getImgurl()):"");
         List<Cases> casesList = casesMapper.selectList(new QueryWrapper<Cases>().lambda()
                 .eq(Cases::getMemberId,member.getId())
                 .eq(Cases::getDeleted,Constants.ZERO)
+                .eq(Cases::getStatus,Constants.ZERO)
+                .orderByDesc(Cases::getStartDate)
                 .orderByDesc(Cases::getId)
         );
         if(CollectionUtils.isNotEmpty(casesList)){
-            String casePath =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CATEGORY_FILES).getCode();
+            String casePath =  systemDictDataBiz.queryByCode(Constants.OBJCET_STORAGE, Constants.CASES_FILES).getCode();
             for (Cases cases:casesList) {
                 List<Multifile> multifileList = multifileMapper.selectList(new QueryWrapper<Multifile>().lambda()
                         .eq(Multifile::getObjId,cases.getId())
@@ -358,10 +381,6 @@
                 cases.setFileList(multifileList);
             }
             member.setCasesList(casesList);
-        }
-        if(StringUtils.isBlank(roleConfig)||StringUtils.isBlank(userRole)
-                || !(roleConfig.contains(userRole)||userRole.equals(Constants.DD_USER_TYPE) )){
-            member.setFee(null);
         }
         return member;
     }
diff --git a/server/services/src/main/java/com/doumee/service/system/SystemLoginService.java b/server/services/src/main/java/com/doumee/service/system/SystemLoginService.java
index 57572c6..5250286 100644
--- a/server/services/src/main/java/com/doumee/service/system/SystemLoginService.java
+++ b/server/services/src/main/java/com/doumee/service/system/SystemLoginService.java
@@ -1,8 +1,11 @@
 package com.doumee.service.system;
 
+import com.doumee.dao.system.dto.DingLoginDTO;
 import com.doumee.dao.system.dto.LoginDTO;
+import com.taobao.api.ApiException;
 
 import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
 
 /**
  * 绯荤粺鐧诲綍
@@ -19,4 +22,6 @@
      * @return String
      */
     String loginByPassword (LoginDTO dto, HttpServletRequest request);
+
+    Map<String,Object> loginByDingTalk(DingLoginDTO dingLoginDTO, HttpServletRequest request) throws ApiException;
 }
diff --git a/server/services/src/main/java/com/doumee/service/system/SystemUserService.java b/server/services/src/main/java/com/doumee/service/system/SystemUserService.java
index a8a6043..05a20c8 100644
--- a/server/services/src/main/java/com/doumee/service/system/SystemUserService.java
+++ b/server/services/src/main/java/com/doumee/service/system/SystemUserService.java
@@ -1,10 +1,12 @@
 package com.doumee.service.system;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
 import com.doumee.dao.system.dto.QuerySystemUserDTO;
 import com.doumee.dao.system.model.SystemUser;
 import com.doumee.dao.system.vo.SystemUserListVO;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 
 import java.util.List;
 
@@ -44,6 +46,8 @@
      */
     void updateById(SystemUser systemUser);
 
+
+    void updateByWrapper(LambdaUpdateWrapper wrapper);
     /**
      * 鎵归噺涓婚敭鏇存柊
      *
diff --git a/server/services/src/main/java/com/doumee/service/system/impl/SystemLoginServiceImpl.java b/server/services/src/main/java/com/doumee/service/system/impl/SystemLoginServiceImpl.java
index 8f1b81f..cc7a8af 100644
--- a/server/services/src/main/java/com/doumee/service/system/impl/SystemLoginServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/system/impl/SystemLoginServiceImpl.java
@@ -1,14 +1,26 @@
 package com.doumee.service.system.impl;
 
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
+import com.doumee.config.shiro.ShiroToken;
+import com.doumee.core.constants.Constants;
+import com.doumee.core.dingTalk.DingTalk;
 import com.doumee.core.exception.BusinessException;
 import com.doumee.core.model.LoginUserInfo;
 import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.utils.Utils;
+import com.doumee.dao.system.SystemUserMapper;
+import com.doumee.dao.system.dto.DingLoginDTO;
+import com.doumee.dao.system.dto.DingTalkLoginDTO;
 import com.doumee.dao.system.dto.LoginDTO;
 import com.doumee.dao.system.model.SystemLoginLog;
+import com.doumee.dao.system.model.SystemUser;
 import com.doumee.service.common.CaptchaService;
 import com.doumee.service.system.SystemLoginLogService;
 import com.doumee.service.system.SystemLoginService;
+import com.taobao.api.ApiException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.SecurityUtils;
@@ -21,6 +33,9 @@
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
 
 @Slf4j
 @Service
@@ -40,8 +55,16 @@
     @Autowired
     private SystemLoginLogService systemLoginLogService;
 
+    @Autowired
+    private DingTalk dingTalk ;
+
+    @Autowired
+    private SystemUserMapper systemUserMapper;
+
+
     @Override
     public String loginByPassword(LoginDTO dto, HttpServletRequest request) {
+        log.error("鐧诲綍鍏ュ弬锛�"+ JSONObject.toJSONString(dto));
         SystemLoginLog loginLog = new SystemLoginLog();
         loginLog.setLoginUsername(dto.getUsername());
         loginLog.setLoginTime(new Date());
@@ -66,7 +89,81 @@
         }
         // 鏍¢獙鐢ㄦ埛鍚嶅拰瀵嗙爜
         Subject subject = SecurityUtils.getSubject();
-        UsernamePasswordToken token = new UsernamePasswordToken(dto.getUsername(), dto.getPassword());
+        ShiroToken token = new ShiroToken(null,dto.getUsername(), dto.getPassword(),false);
+        try {
+            subject.login(token);
+            loginLog.setUserId(((LoginUserInfo)subject.getPrincipal()).getId());
+            loginLog.setSuccess(Boolean.TRUE);
+            systemLoginLogService.create(loginLog);
+            if(StringUtils.isNotBlank(dto.getUnionId())){
+                //鏇存柊鐢ㄦ埛鐨剈nionID
+                this.dealDDUnionIdBiz(loginLog.getUserId(), dto.getUnionId());
+            }
+            return (String)subject.getSession().getId();
+        } catch (AuthenticationException e) {
+            log.error(ResponseStatus.ACCOUNT_INCORRECT.getMessage(), e);
+            loginLog.setReason(e.getMessage().length() > 200 ? (e.getMessage().substring(0, 190) + "...") : e.getMessage());
+            loginLog.setSuccess(Boolean.FALSE);
+            systemLoginLogService.create(loginLog);
+            throw new BusinessException(ResponseStatus.ACCOUNT_INCORRECT);
+        }
+    }
+
+
+    private void dealDDUnionIdBiz(Integer userId, String ddUnionId) {
+        if(StringUtils.isNotBlank(ddUnionId)){
+            //濡傛灉openId涓嶄负绌�,缁戝畾璇ョ敤鎴穙penid
+            systemUserMapper.update(null,new UpdateWrapper<SystemUser>().lambda()
+                    .set(SystemUser::getUnionId,null)
+                    .eq(SystemUser::getUnionId,ddUnionId)
+            );
+            systemUserMapper.update(null,new UpdateWrapper<SystemUser>().lambda()
+                    .set(SystemUser::getUnionId,ddUnionId)
+                    .eq(SystemUser::getId,userId));
+        }
+    }
+
+
+    @Override
+    public Map<String,Object> loginByDingTalk(DingLoginDTO dingLoginDTO, HttpServletRequest request) throws ApiException {
+        log.error("鎺堟潈閽夐拤鐧诲綍鍏ュ弬锛�"+ JSONObject.toJSONString(dingLoginDTO));
+        Map<String,Object> map = new HashMap<>();
+        OapiV2UserGetuserinfoResponse.UserGetByCodeResponse response = dingTalk.getDDUserByCode(dingLoginDTO);
+        if(Objects.nonNull(response)){
+            String unionId = response.getUnionid();
+            map.put("unionId",unionId);
+            map.put("loginStatus",false);
+            SystemUser systemUser = systemUserMapper.selectOne(new QueryWrapper<SystemUser>().lambda().eq(SystemUser::getUnionId,unionId)
+                    .last("limit 1")
+            );
+            if(Objects.nonNull(systemUser)&&!systemUser.getDeleted()){
+                loginByDingTalkCode(systemUser,unionId,request);
+                map.put("loginStatus",true);
+            }
+        }
+        log.error("鎺堟潈閽夐拤鐧诲綍鍑哄弬锛�"+ JSONObject.toJSONString(map));
+        return map;
+    }
+
+
+
+
+
+    public String loginByDingTalkCode(SystemUser systemUser,String unionId, HttpServletRequest request) {
+        SystemLoginLog loginLog = new SystemLoginLog();
+        loginLog.setLoginUsername(systemUser.getUsername());
+        loginLog.setLoginTime(new Date());
+        loginLog.setSystemVersion(systemVersion);
+        loginLog.setIp(Utils.User_Client.getIP(request));
+//        loginLog.setLocation(Utils.Location.getLocationString(loginLog.getIp()));
+        loginLog.setPlatform(Utils.User_Client.getPlatform(request));
+        loginLog.setClientInfo(Utils.User_Client.getBrowser(request));
+        loginLog.setOsInfo(Utils.User_Client.getOS(request));
+        loginLog.setServerIp(Utils.Server.getIP());
+
+        // 鏍¢獙鐢ㄦ埛鍚嶅拰瀵嗙爜
+        Subject subject = SecurityUtils.getSubject();
+        ShiroToken token = new ShiroToken(unionId,systemUser.getUsername(), null,true);
         try {
             subject.login(token);
             loginLog.setUserId(((LoginUserInfo)subject.getPrincipal()).getId());
@@ -81,4 +178,6 @@
             throw new BusinessException(ResponseStatus.ACCOUNT_INCORRECT);
         }
     }
+
+
 }
diff --git a/server/services/src/main/java/com/doumee/service/system/impl/SystemUserServiceImpl.java b/server/services/src/main/java/com/doumee/service/system/impl/SystemUserServiceImpl.java
index a341b0a..5cf3719 100644
--- a/server/services/src/main/java/com/doumee/service/system/impl/SystemUserServiceImpl.java
+++ b/server/services/src/main/java/com/doumee/service/system/impl/SystemUserServiceImpl.java
@@ -1,5 +1,7 @@
 package com.doumee.service.system.impl;
 
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.doumee.core.model.PageData;
@@ -62,6 +64,12 @@
     }
 
     @Override
+    public void updateByWrapper(LambdaUpdateWrapper wrapper) {
+        systemUserMapper.update(null,wrapper);
+    }
+
+
+    @Override
     @Transactional
     public void updateByIdInBatch(List<SystemUser> systemUsers) {
         if (CollectionUtils.isEmpty(systemUsers)) return;
diff --git a/server/web/src/main/java/com/doumee/api/web/LoginController.java b/server/web/src/main/java/com/doumee/api/web/LoginController.java
index 33cc68b..0c0d402 100644
--- a/server/web/src/main/java/com/doumee/api/web/LoginController.java
+++ b/server/web/src/main/java/com/doumee/api/web/LoginController.java
@@ -1,6 +1,8 @@
 package com.doumee.api.web;
 
+import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
 import com.doumee.api.BaseController;
@@ -11,13 +13,18 @@
 import com.doumee.core.annotation.pr.PreventRepeat;
 import com.doumee.core.annotation.trace.Trace;
 import com.doumee.core.constants.Constants;
+import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.dingTalk.DingTalk;
+import com.doumee.core.exception.BusinessException;
 import com.doumee.core.model.ApiResponse;
 import com.doumee.core.model.LoginUserInfo;
 import com.doumee.core.model.PageData;
 import com.doumee.core.model.PageWrap;
+import com.doumee.core.utils.AESUtils;
 import com.doumee.core.utils.HttpsUtil;
+import com.doumee.core.utils.ZbomAESUtils;
 import com.doumee.dao.business.dto.LoginRequestNewParam;
+import com.doumee.dao.business.dto.RoleRequestParam;
 import com.doumee.dao.business.model.Category;
 import com.doumee.dao.business.model.Member;
 import com.doumee.dao.system.dto.DingLoginDTO;
@@ -82,19 +89,31 @@
         LoginRequestNewParam requestParam = new LoginRequestNewParam();
         // UK_ERROR_URL = "http://u.zhibang.com/sso/web/token/error";
         String errorUrl =systemDictDataBiz.queryByCode(Constants.ZBOM_PARAM,Constants.ZBOM_UK_ERROR_URL).getCode();
-       /* try {
+        String token = "";
+        try {
             log.error("璇锋眰鍙傛暟TICK鏈�鍘熷===========锛�" + tick);
             JSONObject urlParams = new JSONObject();
             log.info("璇锋眰鍙傛暟锛�" + JSON.toJSONString(urlParams));
-            //TICKET_LOGIN_TEST = "http://testsso.zhibang.com:8080/esc-idm/api/v1/getUserInfo";
-            //TICKET_LOGIN = "https://sso.zbom.com/esc-idm/api/v1/getUserInfo";
             String url  = systemDictDataBiz.queryByCode(Constants.ZBOM_PARAM,Constants.ZBOM_TICKET_LOGIN_URL).getCode() + "?tick=" +  URLEncoder.encode(tick,Constants.UTF);
-            String post =  HttpsUtil.get(url,true);
+            String post =  HttpUtil.get(url);
             log.info("杩斿洖鍙傛暟锛�" + post);
             JSONObject json = JSONObject.parseObject(post);
-            if (StringUtils.equals(json.getString("code"), "0")) {
-                JSONObject userInfo = json.getJSONObject("data");
-                requestParam = JSONObject.toJavaObject(userInfo, LoginRequestNewParam.class);
+            if (StringUtils.equals(json.getString("code"), "1")) {
+                String dataE = json.getString("data");
+                //鍙嶈В鏋恡oken
+                String data =  ZbomAESUtils.decrypt( "zbom20180922!@#$",dataE);
+                JSONObject userInfo = JSONObject.parseObject(data);
+                log.error("U瀹㈢櫥褰曡繑鍥炲弬鏁帮細" + userInfo.toString());
+                WebLoginUserVO loginUserVO = new WebLoginUserVO();
+                loginUserVO.setId(userInfo.getString("buserPhone"));
+                if(userInfo.getString("distrcode").isEmpty()){
+                    loginUserVO.setShowFee(Constants.ONE);
+                }else{
+                    JSONArray jsonArray = userInfo.getJSONArray("ukRoles");
+                    this.setLoginShowFee(loginUserVO,jsonArray);
+                }
+                log.error("web鐢ㄦ埛淇℃伅"+JSONObject.toJSONString(loginUserVO));
+                token = jwtTokenUtil.generateToken(loginUserVO);
             } else {
                 log.error("妗堜緥搴撶郴缁熷崟鐐圭櫥褰曞け璐� 閿欒鍘熷洜鑾峰彇tick澶辫触" + json.getString("message"));
                 response.sendRedirect(errorUrl + "?title=" + enCode("鐧婚檰閿欒") + "&msg="+ enCode(json.getString("message")));
@@ -104,24 +123,46 @@
             log.error("ticket鎺ュ彛璇锋眰閿欒锛�" + e.getMessage());
             response.sendRedirect(errorUrl + "?title=" + enCode("鐧婚檰閿欒") + "&msg=" + enCode("绯荤粺绻佸繖锛岃绋嶅悗閲嶈瘯~"));
             return;
-        }*/
-        requestParam.setRediUrl("http://localhost:10087/#/login");
-        WebLoginUserVO loginUserVO = new WebLoginUserVO();
-        loginUserVO.setId("123");
-        loginUserVO.setRoleType("admin");
-        loginUserVO.setZhanqu("1");
-        String token = jwtTokenUtil.generateToken(loginUserVO);
+        }
+        requestParam.setRediUrl("https://test.doumee.cn/h5/");
+        log.error("璺宠浆鍦板潃璺宠浆淇℃伅锛�" + requestParam.getRediUrl()+"?token="+token);
         response.sendRedirect(requestParam.getRediUrl()+"?token="+token);
+    }
+
+
+    public void setLoginShowFee(WebLoginUserVO loginUserVO,JSONArray jsonArray){
+        String roleConfig = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ROLE_CONFIG).getCode();
+        loginUserVO.setShowFee(Constants.ZERO);
+        if(StringUtils.isBlank(roleConfig)){
+            return;
+        }
+        if(jsonArray.isEmpty()){
+            return;
+        }
+        String [] configRole = roleConfig.split(",");
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject  j = jsonArray.getJSONObject(i);
+            for (String s:configRole) {
+                if(s.equals(j.getString("frontroleid"))){
+                    loginUserVO.setShowFee(Constants.ONE);
+                    return;
+                }
+            }
+        }
     }
 
     @ApiOperation("閽夐拤鐧诲綍")
     @PostMapping("/ddLogin")
-    public ApiResponse<WebLoginUserVO> ddLogin(@Validated @RequestBody DingLoginDTO dingLoginDTO)  throws ApiException {
+    public ApiResponse<WebLoginUserVO> ddLogin(@RequestBody DingLoginDTO dingLoginDTO)  throws ApiException {
         WebLoginUserVO loginUserVO = new WebLoginUserVO();
+        log.error("閽夐拤鎺堟潈鐧诲綍鍏ュ弬锛�"+JSONObject.toJSONString(dingLoginDTO));
+        System.out.println("閽夐拤鎺堟潈鐧诲綍鍏ュ弬锛�"+JSONObject.toJSONString(dingLoginDTO));
         OapiV2UserGetuserinfoResponse.UserGetByCodeResponse response = dingTalk.getDDUserByCode(dingLoginDTO);
+        log.error("閽夐拤鎺堟潈鐧诲綍杩斿弬锛�"+JSONObject.toJSONString(response));
+        System.out.println("閽夐拤鎺堟潈鐧诲綍杩斿弬锛�"+JSONObject.toJSONString(response));
         if(Objects.nonNull(response)){
             loginUserVO.setId(response.getUserid());
-            loginUserVO.setRoleType(Constants.DD_USER_TYPE);
+            loginUserVO.setShowFee(Constants.ONE);
         }
         loginUserVO.setToken(jwtTokenUtil.generateToken(loginUserVO));
         return ApiResponse.success(loginUserVO);
@@ -148,21 +189,22 @@
     })
     public ApiResponse<PageData<Member>> memberPage(@RequestBody PageWrap<Member> pageWrap) {
         WebLoginUserVO loginUserVO = this.getMemberResponse();
-        pageWrap.getModel().setQueryUserRole(loginUserVO.getRoleType());
+        log.error("鍒嗛〉鏌ヨ鐢ㄦ埛淇℃伅"+JSONObject.toJSONString(loginUserVO));
         pageWrap.getModel().setQueryZQCode(loginUserVO.getZhanqu());
         PageData<Member> pageData = memberService.findPage(pageWrap);
+
         if(CollectionUtils.isNotEmpty(pageData.getRecords())){
-            String roleConfig = systemDictDataBiz.queryByCode(Constants.SYSTEM, Constants.ROLE_CONFIG).getCode();
-            if(StringUtils.isBlank(roleConfig)||StringUtils.isBlank(pageWrap.getModel().getQueryUserRole())
-                    || ! (roleConfig.contains(pageWrap.getModel().getQueryUserRole()) || pageWrap.getModel().getQueryUserRole().equals(Constants.DD_USER_TYPE) )){
+            log.error("鍒嗛〉鏁版嵁淇℃伅"+JSONObject.toJSONString(pageData.getRecords()));
+            if(Constants.equalsInteger(Constants.ZERO,loginUserVO.getShowFee())){
+                log.error("鍒嗛〉鏁版嵁淇℃伅娓呯┖閲戦");
                 pageData.getRecords().forEach(i->{
                     i.setFee(null);
                 });
             }
+            log.error("鍒嗛〉鏁版嵁淇℃伅娓呯┖鍚庢暟鎹�"+JSONObject.toJSONString(pageData.getRecords()));
         }
         return ApiResponse.success(pageData);
     }
-
 
 
     @LoginRequired
@@ -173,7 +215,11 @@
     })
     public ApiResponse<Member> memberPage(@RequestParam Integer id) {
         WebLoginUserVO loginUserVO = this.getMemberResponse();
-        return ApiResponse.success(memberService.findDetailById(id,loginUserVO.getRoleType()));
+        Member member = memberService.findDetailById(id);
+        if(Objects.nonNull(member)&&Constants.equalsInteger(Constants.ZERO,loginUserVO.getShowFee())){
+            member.setFee(null);
+        }
+        return ApiResponse.success(member);
     }
 
 
@@ -183,8 +229,8 @@
     @ApiImplicitParams({
             @ApiImplicitParam(paramType = "header", dataType = "String", name = "token", value = "鐢ㄦ埛token鍊�", required = true),
     })
-    public ApiResponse<List<Category>> categoryList(@RequestParam Integer type) {
-        return ApiResponse.success(categoryService.getCategoryList(type));
+    public ApiResponse<List<Category>> categoryList(@RequestParam Integer type,Integer rank) {
+        return ApiResponse.success(categoryService.getCategoryList(type,rank));
     }
 
 

--
Gitblit v1.9.3