jiangping
2023-12-05 4aba5c05fd1c525f2daaa004fbfec45d997b2e29
海康接口对接开发
已添加9个文件
已修改12个文件
1060 ■■■■■ 文件已修改
.idea/compiler.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/libraries/Maven__commons_net_commons_net_3_8_0.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_admin/src/main/java/com/doumee/api/business/HkSyncController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/config/mybatis/EasySqlInjector.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/config/mybatis/MyBatisPlusConfig.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/BaseResponse.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/request/AcsDeviceListRequest.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/respose/AcsDeviceInfoResponse.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/respose/AcsDeviceListResponse.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/core/utils/FtpUtil.java 652 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/business/DeviceMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/CarEventService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/HkSyncService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/HkSyncServiceImpl.java 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/openapi/src/main/java/com/doumee/model/response/erp/UserListRespone.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/compiler.xml
@@ -2,6 +2,7 @@
<project version="4">
  <component name="CompilerConfiguration">
    <annotationProcessing>
      <profile default="true" name="Default" enabled="true" />
      <profile name="Maven default annotation processors profile" enabled="true">
        <sourceOutputDir name="target/generated-sources/annotations" />
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
.idea/libraries/Maven__commons_net_commons_net_3_8_0.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
<component name="libraryTable">
  <library name="Maven: commons-net:commons-net:3.8.0">
    <CLASSES>
      <root url="jar://$MAVEN_REPOSITORY$/commons-net/commons-net/3.8.0/commons-net-3.8.0.jar!/" />
    </CLASSES>
    <JAVADOC>
      <root url="jar://$MAVEN_REPOSITORY$/commons-net/commons-net/3.8.0/commons-net-3.8.0-javadoc.jar!/" />
    </JAVADOC>
    <SOURCES>
      <root url="jar://$MAVEN_REPOSITORY$/commons-net/commons-net/3.8.0/commons-net-3.8.0-sources.jar!/" />
    </SOURCES>
  </library>
</component>
server/dmvisit_admin/src/main/java/com/doumee/api/business/HkSyncController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
package com.doumee.api.business;
import com.doumee.api.BaseController;
import com.doumee.core.annotation.excel.ExcelExporter;
import com.doumee.core.annotation.pr.PreventRepeat;
import com.doumee.core.haikang.model.param.request.AcsDeviceListRequest;
import com.doumee.core.haikang.service.HKService;
import com.doumee.core.model.ApiResponse;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.Device;
import com.doumee.service.business.DeviceService;
import com.doumee.service.business.HkSyncService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
@Api(tags = "海康数据同步接口")
@RestController
@RequestMapping("/business/hksync")
public class HkSyncController extends BaseController {
    @Autowired
    private HkSyncService hkSyncService;
    @PreventRepeat
    @ApiOperation("全量同步门禁设备接口")
    @PostMapping("/getDevices")
    @RequiresPermissions("business:hksync:device")
    public ApiResponse getDevices(@RequestBody AcsDeviceListRequest param) {
        hkSyncService.syncHkDevices(param);
        return ApiResponse.success(null);
    }
}
server/dmvisit_service/src/main/java/com/doumee/config/mybatis/EasySqlInjector.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
package com.doumee.config.mybatis;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import java.util.List;
public class EasySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass ) {
        // æ³¨æ„ï¼šæ­¤SQL注入器继承了DefaultSqlInjector(默认注入器),调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }
}
server/dmvisit_service/src/main/java/com/doumee/config/mybatis/MyBatisPlusConfig.java
@@ -20,4 +20,9 @@
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    @Bean
    public EasySqlInjector sqlInjector() {
        return new EasySqlInjector();
    }
}
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKConstants.java
@@ -9,6 +9,7 @@
public class HKConstants {
    private Logger logger = LoggerFactory.getLogger(HKConstants.class);
    //海康平台根据现场环境配置http还是https
    public static final String RESPONSE_SUCCEE = "0";
    public static String https ;
    /**
     * èƒ½åŠ›å¼€æ”¾å¹³å°çš„ç½‘ç«™è·¯å¾„   è·¯å¾„不用修改,就是/artemis
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/BaseResponse.java
@@ -4,6 +4,7 @@
@Data
public class BaseResponse<T> {
    /**
     * è¿”回码
     * 0:成功
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/request/AcsDeviceListRequest.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.doumee.core.haikang.model.param.request;
import lombok.Data;
@Data
public class AcsDeviceListRequest {
 private String   name    ;//string    False    åç§°ï¼Œæ¨¡ç³Šæœç´¢ï¼Œæœ€å¤§é•¿åº¦32,若包含中文,最大长度指不超过按照指定编码的字节长度,即getBytes(“utf-8”).length
    private String[]        regionIndexCodes    ;//string[]    False    åŒºåŸŸç¼–号,可以为空; String[],支持根据区域批量查询;区域编号个数<=1000个;单个长度<=64Byte;,可从查询区域列表v2接口获取返回参数indexCode
    private Boolean      isSubRegion;//    boolean    False    true时,搜索regionIndexCodes及其子孙区域的资源;  false时,只搜索 regionIndexCodes的资源
    private Integer      pageNo    ;//integer    True    å½“前页码
    private Integer      pageSize;//    integer    True    åˆ†é¡µå¤§å°
    private String[]     authCodes    ;//string[]    False    æƒé™ç é›†åˆï¼Œè¯¦è§é™„录A.3 èµ„源权限码中门禁设备对应的资源权限码
}
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/respose/AcsDeviceInfoResponse.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.doumee.core.haikang.model.param.respose;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
public class AcsDeviceInfoResponse {
 private String   indexCode    ;//string    False    èµ„源唯一编码
private String   resourceType;//    string    False    èµ„源类型,详见附录A.2 èµ„源类型
private String   name;//    string    False    èµ„源名称
private String   parentIndexCode;//    string    False    çˆ¶çº§èµ„源编号
private String   devTypeCode;//    string    False    é—¨ç¦è®¾å¤‡ç±»åž‹ç¼–码,详见附录A.7 é—¨ç¦è®¾å¤‡ç±»åž‹ä¸­é—¨ç¦è®¾å¤‡ç±»åž‹ç¼–号
private String   devTypeDesc;//    string    False    é—¨ç¦è®¾å¤‡ç±»åž‹åž‹å·ï¼Œè¯¦è§é™„录A.7 é—¨ç¦è®¾å¤‡ç±»åž‹ä¸­é—¨ç¦è®¾å¤‡ç±»åž‹
private String   deviceCode    ;//string    False    ä¸»åŠ¨è®¾å¤‡ç¼–å·
private String   manufacturer;//    string    False    åނ商
private String   regionIndexCode;//    string    False    æ‰€å±žåŒºåŸŸ
private String   regionPath    ;//string    False    æ‰€å±žåŒºåŸŸè·¯å¾„,以@符号分割,包含本节点
private String   treatyType;//    string    False    æŽ¥å…¥åè®®ï¼Œè¯¦è§é™„录A.6 ç¼–码设备接入协议
private Integer   cardCapacity;//    number    False    è®¾å¤‡å¡å®¹é‡
private Integer   fingerCapacity;//    number    False    æŒ‡çº¹å®¹é‡
private Integer   veinCapacity;//    number    False    æŒ‡é™è„‰å®¹é‡
private Integer faceCapacity    ;//number    False    äººè„¸å®¹é‡
private Integer   doorCapacity;//    number    False    é—¨å®¹é‡
private String   deployId    ;//string    False    æ‹¨ç 
private String   createTime    ;//string    False    åˆ›å»ºæ—¶é—´
private String   updateTime    ;//string    False    æ›´æ–°æ—¶é—´
private String   description;//    string    False    æè¿°
private String   netZoneId    ;//string    False    æ‰€å±žç½‘域
private String   acsReaderVerifyModeAbility    ;//string    False    æ”¯æŒè®¤è¯æ–¹å¼ï¼Œæ•°æ®ä¸ºåè¿›åˆ¶
private String   regionName    ;//string    False    åŒºåŸŸåç§°
private String   regionPathName;//    string    False    æ‰€å±žåŒºåŸŸè·¯å¾„名,以"/"分隔
private String   ip    ;//string    False    é—¨ç¦è®¾å¤‡IP
private String   port;//    string    False    é—¨ç¦è®¾å¤‡ç«¯å£
private String   capability;//    string    False    è®¾å¤‡èƒ½åЛ集(含设备上的智能能力),详见附录A.44 è®¾å¤‡èƒ½åЛ集
private String   devSerialNum;//    string    False    è®¾å¤‡åºåˆ—号
private String   dataVersion;//    string    False    ç‰ˆæœ¬å·
}
server/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/respose/AcsDeviceListResponse.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.doumee.core.haikang.model.param.respose;
import lombok.Data;
import java.util.List;
@Data
public class AcsDeviceListResponse {
   private int total;//    number    False    æŸ¥è¯¢æ•°æ®è®°å½•总数
   private int pageSize;//    number    False    æ¯é¡µè®°å½•总数
   private int pageNo    ;// number    False    å½“前页码
   private List<AcsDeviceInfoResponse> list    ;// object[]    False    æƒé™ç»„对象列表
}
server/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java
@@ -417,6 +417,24 @@
        }
        return  null;
    }
    /**
     *门禁设备查询(分页)
     * @return
     */
    public  BaseResponse<AcsDeviceListResponse>   acsDeviceList(AcsDeviceListRequest param){
        log.error("【海康门禁设备查询】================开始===="+JSONObject.toJSONString(param));
        try {
            String res = HKTools.acsDeviceList(JSONObject.toJSONString(param));
            TypeReference typeReference =
                    new TypeReference< BaseResponse<AcsDeviceListResponse> >(){};
            BaseResponse<AcsDeviceListResponse>   result = JSONObject.parseObject(res, typeReference.getType());
            log.error("【海康门禁设备查询】================成功====\n"+res);
            return  result;
        }catch (Exception e){
            log.error("【海康门禁设备查询】================失败====:\n"+ e.getMessage());
        }
        return  null;
    }
}
server/dmvisit_service/src/main/java/com/doumee/core/utils/FtpUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,652 @@
package com.doumee.core.utils;
import java.io.*;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import sun.misc.BASE64Encoder;
/** */
/**
 * æ”¯æŒæ–­ç‚¹ç»­ä¼ çš„FTP实用类
 *
 * @author BenZhou http://www.bt285.cn
 * @version 0.1 å®žçŽ°åŸºæœ¬æ–­ç‚¹ä¸Šä¼ ä¸‹è½½
 * @version 0.2 å®žçŽ°ä¸Šä¼ ä¸‹è½½è¿›åº¦æ±‡æŠ¥
 * @version 0.3 å®žçŽ°ä¸­æ–‡ç›®å½•åˆ›å»ºåŠä¸­æ–‡æ–‡ä»¶åˆ›å»ºï¼Œæ·»åŠ å¯¹äºŽä¸­æ–‡çš„æ”¯æŒ
 */
@Slf4j
public class FtpUtil {
    public FTPClient ftpClient = new FTPClient();
    public FtpUtil() {
        // è®¾ç½®å°†è¿‡ç¨‹ä¸­ä½¿ç”¨åˆ°çš„命令输出到控制台
        this.ftpClient.addProtocolCommandListener(new PrintCommandListener(
                new PrintWriter(System.out)));
    }
    public FtpUtil(String hostname, int port, String username, String password)
            throws IOException {
        // è®¾ç½®å°†è¿‡ç¨‹ä¸­ä½¿ç”¨åˆ°çš„命令输出到控制台
        connect(hostname, port, username, password);
    }
    /** */
    /**
     * è¿žæŽ¥åˆ°FTP服务器
     *
     * @param hostname
     *            ä¸»æœºå
     * @param port
     *            ç«¯å£
     * @param username
     *            ç”¨æˆ·å
     * @param password
     *            å¯†ç 
     * @return æ˜¯å¦è¿žæŽ¥æˆåŠŸ
     * @throws IOException
     */
    public boolean connect(String hostname, int port, String username,
            String password) throws IOException {
        ftpClient.connect(hostname, port);
        ftpClient.setControlEncoding("GBK");
        if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            if (ftpClient.login(username, password)) {
                return true;
            }
        }
        disconnect();
        return false;
    }
    /** */
    /**
     * ä»ŽFTP服务器上下载文件,支持断点续传,上传百分比汇报
     *
     * @param remote
     *            è¿œç¨‹æ–‡ä»¶è·¯å¾„
     * @param local
     *            æœ¬åœ°æ–‡ä»¶è·¯å¾„
     * @return ä¸Šä¼ çš„状态
     * @throws IOException
     */
    public String download(String remote, String local) throws IOException {
        // è®¾ç½®è¢«åŠ¨æ¨¡å¼
        ftpClient.enterLocalPassiveMode();
        // è®¾ç½®ä»¥äºŒè¿›åˆ¶æ–¹å¼ä¼ è¾“
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        String result;
        // æ£€æŸ¥è¿œç¨‹æ–‡ä»¶æ˜¯å¦å­˜åœ¨
        FTPFile[] files = ftpClient.listFiles(new String(
                remote.getBytes("GBK"), "iso-8859-1"));
        if (files.length != 1) {
            // System.out.println("远程文件不存在");
            return "远程文件不存在";
        }
        long lRemoteSize = files[0].getSize();
        File f = new File(local);
        // æœ¬åœ°å­˜åœ¨æ–‡ä»¶ï¼Œè¿›è¡Œæ–­ç‚¹ä¸‹è½½
        if (f.exists()) {
            long localSize = f.length();
            // åˆ¤æ–­æœ¬åœ°æ–‡ä»¶å¤§å°æ˜¯å¦å¤§äºŽè¿œç¨‹æ–‡ä»¶å¤§å°
            if (localSize >= lRemoteSize) {
                // System.out.println("本地文件大于远程文件,下载中止");
                // return "本地文件大于远程文件,下载中止";
            }
            // è¿›è¡Œæ–­ç‚¹ç»­ä¼ ï¼Œå¹¶è®°å½•状态
            FileOutputStream out = new FileOutputStream(f, true);
            ftpClient.setRestartOffset(localSize);
            InputStream in = ftpClient.retrieveFileStream(new String(remote
                    .getBytes("GBK"), "iso-8859-1"));
            byte[] bytes = new byte[1024];
            long step = lRemoteSize / 100;
            long process = localSize / step;
            int c;
            while ((c = in.read(bytes)) != -1) {
                out.write(bytes, 0, c);
                localSize += c;
                long nowProcess = localSize / step;
                if (nowProcess > process) {
                    process = nowProcess;
                    if (process % 10 == 0)
                        System.out.println("下载进度:" + process);
                    // TODO æ›´æ–°æ–‡ä»¶ä¸‹è½½è¿›åº¦,值存放在process变量中
                }
            }
            in.close();
            out.close();
            boolean isDo = ftpClient.completePendingCommand();
            if (isDo) {
                result = "300";
                // result = DownloadStatus.Download_From_Break_Success;
            } else {
                result = "400";
                // result = DownloadStatus.Download_From_Break_Failed;
            }
        } else {
            OutputStream out = new FileOutputStream(f);
            InputStream in = ftpClient.retrieveFileStream(new String(remote
                    .getBytes("GBK"), "iso-8859-1"));
            byte[] bytes = new byte[1024];
            long step = lRemoteSize / 100;
            long process = 0;
            long localSize = 0L;
            int c;
            while ((c = in.read(bytes)) != -1) {
                out.write(bytes, 0, c);
                localSize += c;
                long nowProcess = localSize / step;
                if (nowProcess > process) {
                    process = nowProcess;
                    if (process % 10 == 0)
                        System.out.println("下载进度:" + process);
                    // TODO æ›´æ–°æ–‡ä»¶ä¸‹è½½è¿›åº¦,值存放在process变量中
                }
            }
            in.close();
            out.close();
            boolean upNewStatus = ftpClient.completePendingCommand();
            if (upNewStatus) {
                result = "500";
                // result = DownloadStatus.Download_New_Success;
            } else {
                // result = DownloadStatus.Download_New_Failed;
                result = "600";
            }
        }
        return result;
    }
    /** */
    /**
     * ä¸Šä¼ æ–‡ä»¶åˆ°FTP服务器,支持断点续传
     *
     * @param local
     *            æœ¬åœ°æ–‡ä»¶åç§°ï¼Œç»å¯¹è·¯å¾„
     * @param remote
     *            è¿œç¨‹æ–‡ä»¶è·¯å¾„,使用/home/directory1/subdirectory/file.ext或是
     *            http://www.guihua.org /subdirectory/file.ext
     *            æŒ‰ç…§Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
     * @return ä¸Šä¼ ç»“æžœ
     * @throws IOException
     */
    public String upload(String local, String remote) throws IOException {
        // è®¾ç½®PassiveMode传输
        ftpClient.enterLocalPassiveMode();
        // è®¾ç½®ä»¥äºŒè¿›åˆ¶æµçš„æ–¹å¼ä¼ è¾“
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setControlEncoding("GBK");
        String result;
        // å¯¹è¿œç¨‹ç›®å½•的处理
        String remoteFileName = remote;
        if (remote.contains(File.separator)) {
            remoteFileName = remote.substring(remote.lastIndexOf(File.separator) + 1);
            // åˆ›å»ºæœåŠ¡å™¨è¿œç¨‹ç›®å½•ç»“æž„ï¼Œåˆ›å»ºå¤±è´¥ç›´æŽ¥è¿”å›ž
            if (StringUtils.equals(CreateDirecroty(remote, ftpClient), "2")) {
                return "2";
            }
        }
     // æ£€æŸ¥è¿œç¨‹æ˜¯å¦å­˜åœ¨æ–‡ä»¶
        FTPFile[] files = ftpClient.listFiles(new String(remoteFileName
                .getBytes("GBK"), "iso-8859-1"));
        if (files.length == 1) {
            long remoteSize = files[0].getSize();
            File f = new File(local);
            long localSize = f.length();
            if (remoteSize == localSize) {
                return "700";
                // return UploadStatus.File_Exits;
            } else if (remoteSize > localSize) {
                return "800";
                // return UploadStatus.Remote_Bigger_Local;
            }
            // å°è¯•移动文件内读取指针,实现断点续传
            result = uploadFile(remoteFileName, f, ftpClient, remoteSize);
            // å¦‚果断点续传没有成功,则删除服务器上文件,重新上传
            if (StringUtils.equals(result, "1")) {
                if (!ftpClient.deleteFile(remoteFileName)) {
                    return "1";
                }
                result = uploadFile(remoteFileName, f, ftpClient, 0);
            }
        } else {
            result = uploadFile(remoteFileName, new File(local), ftpClient, 0);
        }
        return result;
    }
    public int getNumFromStr(String str,char searchstr) {
        int count = 0;
        char[] charArray = str.toCharArray();
        for (char param : charArray) {
            if (param == searchstr) {
                count++;
            }
        }
        return count;
    }
    /** */
    /**
     * ä¸Šä¼ æ–‡ä»¶åˆ°FTP服务器,支持断点续传
     *
     * @param localFile
     *            æœ¬åœ°æ–‡ä»¶æµ
     * @param remote
     *            è¿œç¨‹æ–‡ä»¶è·¯å¾„,使用/home/directory1/subdirectory/file.ext或是
     *            http://www.guihua.org /subdirectory/file.ext
     *            æŒ‰ç…§Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
     * @return ä¸Šä¼ ç»“æžœ
     * @throws IOException
     */
    public String uploadFile(File localFile, String remote) throws IOException {
        // è®¾ç½®PassiveMode传输
        ftpClient.enterLocalPassiveMode();
        // è®¾ç½®ä»¥äºŒè¿›åˆ¶æµçš„æ–¹å¼ä¼ è¾“
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setControlEncoding("GBK");
        String result;
        // å¯¹è¿œç¨‹ç›®å½•的处理
        String remoteFileName = remote ;
         if (remote.contains(File.separator)) {
            remoteFileName = remote.substring(remote.lastIndexOf(File.separator) + 1);
            // åˆ›å»ºæœåŠ¡å™¨è¿œç¨‹ç›®å½•ç»“æž„ï¼Œåˆ›å»ºå¤±è´¥ç›´æŽ¥è¿”å›ž
            if (StringUtils.equals(CreateDirecroty(remote, ftpClient), "2")) {
                return "2";
            }
        }
        // æ£€æŸ¥è¿œç¨‹æ˜¯å¦å­˜åœ¨æ–‡ä»¶
        FTPFile[] files = ftpClient.listFiles(new String(remoteFileName
                .getBytes("GBK"), "iso-8859-1"));
        if (files.length == 1) {
            long remoteSize = files[0].getSize();
            long localSize = localFile.length();
            if (remoteSize == localSize) {
                return "700";
                // return UploadStatus.File_Exits;
            } else if (remoteSize > localSize) {
                return "800";
                // return UploadStatus.Remote_Bigger_Local;
            }
            // å°è¯•移动文件内读取指针,实现断点续传
            result = uploadFile(remoteFileName, localFile, ftpClient,
                    remoteSize);
            // å¦‚果断点续传没有成功,则删除服务器上文件,重新上传
            if (StringUtils.equals(result, "1")) {
                if (!ftpClient.deleteFile(remoteFileName)) {
                    return "1";
                }
                result = uploadFile(remoteFileName, localFile, ftpClient, 0);
            }
            // if (result == UploadStatus.Upload_From_Break_Failed) {
            // if (!ftpClient.deleteFile(remoteFileName)) {
            // return UploadStatus.Delete_Remote_Faild;
            // }
            // result = uploadFile(remoteFileName, f, ftpClient, 0);
            // }
        } else {
            result = uploadFile(remoteFileName, localFile, ftpClient, 0);
        }
        return result;
    }
    /** */
    /**
     * æ–­å¼€ä¸Žè¿œç¨‹æœåŠ¡å™¨çš„è¿žæŽ¥
     *
     * @throws IOException
     */
    public void disconnect() throws IOException {
        if (ftpClient.isConnected()) {
            ftpClient.disconnect();
        }
    }
    /** */
    /**
     * é€’归创建远程服务器目录
     *
     * @param remote
     *            è¿œç¨‹æœåŠ¡å™¨æ–‡ä»¶ç»å¯¹è·¯å¾„
     * @param ftpClient
     *            FTPClient对象
     * @return ç›®å½•创建是否成功
     * @throws IOException
     */
    public String CreateDirecroty(String remote, FTPClient ftpClient)
            throws IOException {
        String status = "1";
        // UploadStatus status = UploadStatus.Create_Directory_Success;
        String directory = remote.substring(0, remote.lastIndexOf(File.separator) + 1);
        if (!directory.equalsIgnoreCase(File.separator)
                && !ftpClient.changeWorkingDirectory(new String(directory
                .getBytes("GBK"), "iso-8859-1"))) {
            // å¦‚果远程目录不存在,则递归创建远程服务器目录
            int start = 0;
            int end = 0;
            if (directory.startsWith(File.separator)) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory
                    .indexOf(File.separator, start);
            while (true) {
                String subDirectory = new String(remote.substring(start, end)
                        .getBytes("GBK"), "iso-8859-1");
                if (!ftpClient.changeWorkingDirectory(subDirectory)) {
                    if (ftpClient.makeDirectory(subDirectory)) {
                        ftpClient.changeWorkingDirectory(subDirectory);
                    } else {
                        System.out.println("创建目录失败");
                        return "2";
                        // return UploadStatus.Create_Directory_Fail;
                    }
                }
                start = end + 1;
                end = directory.indexOf(File.separator,
                        start);
                // æ£€æŸ¥æ‰€æœ‰ç›®å½•是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return status;
    }
    /**
     * ä¸Šä¼ æ–‡ä»¶åˆ°æœåС噍,新上传和断点续传
     *
     * @param remoteFile
     *            è¿œç¨‹æ–‡ä»¶åï¼Œåœ¨ä¸Šä¼ ä¹‹å‰å·²ç»å°†æœåŠ¡å™¨å·¥ä½œç›®å½•åšäº†æ”¹å˜
     * @param localFile
     *            æœ¬åœ°æ–‡ä»¶File句柄,绝对路径
     *            éœ€è¦æ˜¾ç¤ºçš„处理进度步进值
     * @param ftpClient
     *            FTPClient引用
     * @return
     * @throws IOException
     */
    public String uploadFile(String remoteFile, File localFile,
            FTPClient ftpClient, long remoteSize) throws IOException {
        String status;
        // æ˜¾ç¤ºè¿›åº¦çš„上传
        long step = localFile.length() / 100;
        step=step ==0?1:step;
        long process = 0;
        long localreadbytes = 0L;
//        System.out.println(remoteFile +"-------------------------"+localFile.getPath().toString());
        RandomAccessFile raf = new RandomAccessFile(localFile, "r");
        OutputStream out = ftpClient.appendFileStream(new String(remoteFile
                .getBytes("GBK"), "iso-8859-1"));
        // æ–­ç‚¹ç»­ä¼ 
        if (remoteSize > 0) {
            ftpClient.setRestartOffset(remoteSize);
            process = remoteSize / step;
            raf.seek(remoteSize);
            localreadbytes = remoteSize;
        }
        byte[] bytes = new byte[1024];
        int c;
        while ((c = raf.read(bytes)) != -1) {
            out.write(bytes, 0, c);
            localreadbytes += c;
            if (localreadbytes / step != process) {
                process = localreadbytes / step;
                System.out.println("上传进度:" + process);
                // TODO æ±‡æŠ¥ä¸Šä¼ çŠ¶æ€
            }
        }
        out.flush();
        raf.close();
        out.close();
        boolean result = ftpClient.completePendingCommand();
        if (remoteSize > 0) {
            status = result ? "0" : "1";
            // status = result ? UploadStatus.Upload_From_Break_Success
            // : UploadStatus.Upload_From_Break_Failed;
        } else {
            status = result ? "0" : "1";
            // status = result ? UploadStatus.Upload_New_File_Success
            // : UploadStatus.Upload_New_File_Failed;
        }
        return status;
    }
    public byte[] getOnlineInputsteam(String url){
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse resp = httpClient.execute(httpGet);// è°ƒç”¨æœåŠ¡å™¨æŽ¥å£
//            return  resp.getEntity().getContent();
            byte[] data = EntityUtils.toByteArray(resp.getEntity());// å°†è¿”回的图片或者文件转化成字节数组的形式
    //        BASE64Encoder encoder = new BASE64Encoder();
    //        String imageBase64 = encoder.encode(data);
    //            String imageBase64 = "data:image/jpg;base64," + encoder.encodeBuffer(data).trim();
    //            imageBase64 = imageBase64.replaceAll("\n", "").replaceAll("\r", "").replaceAll(" ", "");//删除 \r\n
            return data;
        } catch (Exception e) {
            log.error("获取图片异常:{}",e.getMessage());
        }
        return  null;
    }
    public boolean uploadOnlineFile(String url,String ftpPath, String fileName) throws Exception
    {
        byte[] buf = getOnlineInputsteam(url);
        if(buf == null){
            return  false;
        }
        try
        {
            ftpClient.enterLocalPassiveMode();// å¼€å¯è¢«åŠ¨æ¨¡å¼
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            CreateDirecroty( ftpPath,ftpClient);
            String printWorkingDirectory = ftpClient.printWorkingDirectory();
            System.out.println("获取当前目录:" + printWorkingDirectory);
            boolean flag = ftpClient.storeFile(new String(fileName.getBytes("GBK"), "iso-8859-1"), new ByteArrayInputStream(buf));
            // é€šè¿‡å‘送 QUIT å‘½ä»¤æ³¨é”€ FTP æœåС噍
            ftpClient.logout();
            return  flag;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (ftpClient.isConnected()){
                    ftpClient.disconnect();
            }
        }
        return false;
    }
    /**
     * åˆ é™¤ä¸€ä¸ªæ–‡ä»¶
     */
    public boolean deleteFile(String filename) {
        boolean flag = true;
        try {
            flag = ftpClient.deleteFile(filename);
            if (flag) {
                System.out.println("删除文件成功!");
            } else {
                System.out.println("删除文件失败!");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return flag;
    }
    public static void main(String[] args) throws Exception {
        try {
            FtpUtil ftpUtil = new FtpUtil("175.27.187.84", 21, "ftpuser","doumee168" );
            ftpUtil.uploadOnlineFile("https://profile-avatar.csdnimg.cn/default.jpg!1", "test"+File.separator, UUID.randomUUID().toString()+"test.jpg");
            /*FtpUtil myFtp = new FtpUtil("106.15.54.228", 21, "ftptlg",
                    "tlg168.com");
            System.out.println(myFtp.upload("D:\\devices.sql", "/1111/devices.sql"));
            // myFtp.ftpClient.makeDirectory(new String("电视剧".getBytes("GBK"),
            // "iso-8859-1"));
            // myFtp.ftpClient.changeWorkingDirectory(new String("电视剧"
            // .getBytes("GBK"), "iso-8859-1"));
            // myFtp.ftpClient.makeDirectory(new String("走西口".getBytes("GBK"),
            // "iso-8859-1"));
            // System.out.println(myFtp.upload("http://www.5a520.cn /yw.flv",
            // "/yw.flv", 5));
            // System.out.println(myFtp.upload("http://www.5a520.cn /走西口24.mp4",
            // "/央视走西口/新浪网/走西口24.mp4"));
            *//**
             * t.connect("pengtu", "61.191.61.226", 2122, "yangnet",
             * "yanglong@doumee.com"); File file = new File(
             * "D:\\lib/commons-net-3.3-bin/commons-net-3.3/NOTICE.txt");
             *
             *
             *//*
            System.out.println(myFtp.download("/1/2/NOTICE.txt", "D:\\哈.txt"));
            myFtp.deleteFile("/1/2/NOTICE.txt");
            myFtp.disconnect();
            System.out.println("java版本号:" + System.getProperty("java.version")); // java版本号
            System.out
                    .println("Java提供商名称:" + System.getProperty("java.vendor")); // Java提供商名称
            System.out.println("Java提供商网站:"
                    + System.getProperty("java.vendor.url")); // Java提供商网站
            System.out.println("jre目录:" + System.getProperty("java.home")); // Java,哦,应该是jre目录
            System.out.println("Java虚拟机规范版本号:"
                    + System.getProperty("java.vm.specification.version")); // Java虚拟机规范版本号
            System.out.println("Java虚拟机规范提供商:"
                    + System.getProperty("java.vm.specification.vendor")); // Java虚拟机规范提供商
            System.out.println("Java虚拟机规范名称:"
                    + System.getProperty("java.vm.specification.name")); // Java虚拟机规范名称
            System.out.println("Java虚拟机版本号:"
                    + System.getProperty("java.vm.version")); // Java虚拟机版本号
            System.out.println("Java虚拟机提供商:"
                    + System.getProperty("java.vm.vendor")); // Java虚拟机提供商
            System.out.println("Java虚拟机名称:"
                    + System.getProperty("java.vm.name")); // Java虚拟机名称
            System.out.println("Java规范版本号:"
                    + System.getProperty("java.specification.version")); // Java规范版本号
            System.out.println("Java规范提供商:"
                    + System.getProperty("java.specification.vendor")); // Java规范提供商
            System.out.println("Java规范名称:"
                    + System.getProperty("java.specification.name")); // Java规范名称
            System.out.println("Java类版本号:"
                    + System.getProperty("java.class.version")); // Java类版本号
            System.out.println("Java类路径:"
                    + System.getProperty("java.class.path")); // Java类路径
            System.out.println("Java lib路径:"
                    + System.getProperty("java.library.path")); // Java lib路径
            System.out.println("Java输入输出临时路径:"
                    + System.getProperty("java.io.tmpdir")); // Java输入输出临时路径
            System.out
                    .println("Java编译器:" + System.getProperty("java.compiler")); // Java编译器
            System.out.println("Java执行路径:"
                    + System.getProperty("java.ext.dirs")); // Java执行路径
            System.out.println("操作系统名称:" + System.getProperty("os.name")); // æ“ä½œç³»ç»Ÿåç§°
            System.out.println("操作系统的架构:" + System.getProperty("os.arch")); // æ“ä½œç³»ç»Ÿçš„æž¶æž„
            System.out.println("操作系统版本号:" + System.getProperty("os.version")); // æ“ä½œç³»ç»Ÿç‰ˆæœ¬å·
            System.out.println("文件分隔符:" + System.getProperty("file.separator")); // æ–‡ä»¶åˆ†éš”符
            System.out.println("路径分隔符:" + System.getProperty("path.separator")); // è·¯å¾„分隔符
            System.out.println("直线分隔符:" + System.getProperty("line.separator")); // ç›´çº¿åˆ†éš”符
            System.out.println("操作系统用户名:" + System.getProperty("user.name")); // ç”¨æˆ·å
            System.out.println("操作系统用户的主目录:" + System.getProperty("user.home")); // ç”¨æˆ·çš„主目录
            System.out.println("当前程序所在目录:" + System.getProperty("user.dir")); // å½“前程序所在目录*/
        } catch (IOException e) {
            System.out.println("连接FTP出错:" + e.getMessage());
        }
    }
    /***
     * @上传文件夹
     * @param localDirectory
     *            å½“地文件夹
     * @param remoteDirectoryPath
     *            Ftp æœåŠ¡å™¨è·¯å¾„ ä»¥ç›®å½•File.separator结束
     * */
    public boolean uploadDirectory(String localDirectory,
            String remoteDirectoryPath) throws Exception {
        File src = new File(localDirectory);
        try {
            remoteDirectoryPath =  remoteDirectoryPath  + File.separator;
//            System.out.println(remoteDirectoryPath+":===============创建目录=================");
            boolean makeDirFlag = this.ftpClient.makeDirectory(remoteDirectoryPath);
        }catch (IOException e) {
            e.printStackTrace();
            log.info(remoteDirectoryPath + "目录创建失败");
            return false;
        }
        File[] allFile = src.listFiles();
        for (int currentFile = 0;currentFile < allFile.length;currentFile++) {
            File f =allFile[currentFile];
            String srcName=    f.getPath().toString();
//            System.out.println(srcName+":====================读取文件======================");
            String tPath = remoteDirectoryPath+f.getName();
            if (!f.isDirectory()) {
//                System.out.println(srcName+":====================开始传输文件======================");
                int dNum = getNumFromStr(tPath,File.separator.toCharArray()[0]);
                uploadFile(f, tPath);
                if(dNum -2>=0){
                    for (int i = 0; i < dNum-1; i++) {
                        this.ftpClient.changeToParentDirectory();
                    }
                }
            }else{
//                System.out.println(srcName+":====================创建子目录======================");
                uploadDirectory(srcName,
                        tPath+File.separator);
            }
//            System.out.println(srcName+":====================上传完毕======================");
        }
        return true;
    }
    /***
     * @上传文件夹
     * @param pathName
     *             æ–‡ä»¶å¤¹
     * */
    public boolean delDirectory(String pathName ) throws Exception {
        try {
            this.ftpClient.changeWorkingDirectory( pathName.substring(0, pathName.lastIndexOf(File.separator)) );
            ftpClient.removeDirectory(pathName);
        }catch (IOException e) {
            e.printStackTrace();
            log.info(pathName + "目录删除失败");
            return  false;
        }
        return true;
    }
}
server/dmvisit_service/src/main/java/com/doumee/dao/business/DeviceMapper.java
@@ -3,10 +3,14 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.doumee.dao.business.model.Device;
import java.util.Collection;
/**
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
public interface DeviceMapper extends BaseMapper<Device> {
    Integer insertBatchSomeColumn(Collection<Device> entityList);
}
server/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java
@@ -52,13 +52,13 @@
    @ExcelColumn(name="备注")
    private String remark;
    @ApiModelProperty(value = "题目")
    @ExcelColumn(name="题目")
    private String title;
    @ApiModelProperty(value = "设别名")
    @ExcelColumn(name="设别名")
    private String name;
    @ApiModelProperty(value = "海康标识", example = "1")
    @ExcelColumn(name="海康标识")
    private Integer hkId;
    private String hkId;
    @ApiModelProperty(value = "海康同步状态 0未同步 1已同步", example = "1")
    @ExcelColumn(name="海康同步状态 0未同步 1已同步")
@@ -79,7 +79,7 @@
    @ApiModelProperty(value = "资源类型", example = "1")
    @ExcelColumn(name="资源类型")
    private BigDecimal resourceType;
    private String resourceType;
    @ApiModelProperty(value = "编号")
    @ExcelColumn(name="编号")
server/dmvisit_service/src/main/java/com/doumee/service/business/CarEventService.java
@@ -26,7 +26,6 @@
     * @param id ä¸»é”®
     */
    void deleteById(Integer id);
    /**
     * åˆ é™¤
     *
server/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java
@@ -1,5 +1,6 @@
package com.doumee.service.business;
import com.doumee.core.haikang.model.param.request.AcsDeviceListRequest;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.dao.business.model.Device;
@@ -94,4 +95,5 @@
     * @return long
     */
    long count(Device device);
}
server/dmvisit_service/src/main/java/com/doumee/service/business/HkSyncService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.doumee.service.business;
import com.doumee.core.haikang.model.param.request.AcsDeviceListRequest;
/**
 * åœè½¦åœºäº‹ä»¶æŽ¨é€è®°å½•表Service定义
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
public interface HkSyncService {
    String syncHkDevices(AcsDeviceListRequest param);
}
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java
@@ -1,7 +1,16 @@
package com.doumee.service.business.impl;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.core.haikang.model.HKConstants;
import com.doumee.core.haikang.model.param.BaseResponse;
import com.doumee.core.haikang.model.param.request.AcsDeviceListRequest;
import com.doumee.core.haikang.model.param.respose.AcsDeviceInfoResponse;
import com.doumee.core.haikang.model.param.respose.AcsDeviceListResponse;
import com.doumee.core.haikang.service.HKService;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.Utils;
import com.doumee.dao.business.DeviceMapper;
import com.doumee.dao.business.model.Device;
@@ -10,10 +19,14 @@
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@@ -26,6 +39,9 @@
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private HKService hkService;
    @Override
    public Integer create(Device device) {
@@ -112,8 +128,8 @@
        if (pageWrap.getModel().getRemark() != null) {
            queryWrapper.lambda().eq(Device::getRemark, pageWrap.getModel().getRemark());
        }
        if (pageWrap.getModel().getTitle() != null) {
            queryWrapper.lambda().eq(Device::getTitle, pageWrap.getModel().getTitle());
        if (pageWrap.getModel().getName() != null) {
            queryWrapper.lambda().eq(Device::getName, pageWrap.getModel().getName());
        }
        if (pageWrap.getModel().getHkId() != null) {
            queryWrapper.lambda().eq(Device::getHkId, pageWrap.getModel().getHkId());
@@ -185,4 +201,5 @@
        QueryWrapper<Device> wrapper = new QueryWrapper<>(device);
        return deviceMapper.selectCount(wrapper);
    }
}
server/dmvisit_service/src/main/java/com/doumee/service/business/impl/HkSyncServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,175 @@
package com.doumee.service.business.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.core.haikang.model.HKConstants;
import com.doumee.core.haikang.model.param.BaseResponse;
import com.doumee.core.haikang.model.param.request.AcsDeviceListRequest;
import com.doumee.core.haikang.model.param.respose.AcsDeviceInfoResponse;
import com.doumee.core.haikang.model.param.respose.AcsDeviceListResponse;
import com.doumee.core.haikang.service.HKService;
import com.doumee.core.model.PageData;
import com.doumee.core.model.PageWrap;
import com.doumee.core.utils.Constants;
import com.doumee.core.utils.DateUtil;
import com.doumee.core.utils.Utils;
import com.doumee.dao.business.DeviceMapper;
import com.doumee.dao.business.model.Device;
import com.doumee.service.business.DeviceService;
import com.doumee.service.business.HkSyncService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * è®¾å¤‡ä¿¡æ¯è¡¨Service实现
 * @author æ±Ÿè¹„蹄
 * @date 2023/11/30 15:33
 */
@Service
public class HkSyncServiceImpl implements HkSyncService {
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private HKService hkService;
    @Override
//    @Async
    public String syncHkDevices(AcsDeviceListRequest param){
        List<Device> deleteList = new ArrayList<>();
        List<Device> addList = new ArrayList<>();
        List<Device> editList = new ArrayList<>();
        List<AcsDeviceInfoResponse> allHkList = new ArrayList<>();
        Date date = new Date();
        //查询全部门禁设备数据
        List<Device> allList = deviceMapper.selectList(null);
        boolean hasNext = true;
        int curTotal = 0;
        while (hasNext){
            //分页遍历循环查询所有门禁设备数据
            param = new AcsDeviceListRequest();
            param.setPageNo(1);
            param.setPageSize(10000);
            BaseResponse<AcsDeviceListResponse> response = hkService.acsDeviceList(param);
            if(response == null || !StringUtils.equals(response.getCode(), HKConstants.RESPONSE_SUCCEE)){
                throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(), "对不起,海康同步数据失败~");
            }
            AcsDeviceListResponse r = response.getData();
            curTotal += 10000;
            if(curTotal >= r.getTotal()){
                hasNext = false;
            }
            List<AcsDeviceInfoResponse> tlist = r.getList();
        }
        //判断获取删除的门禁设备,逻辑删除
        getAddAndEditList(allList,allHkList,addList,editList,date);
        getDeleteList(allList,allHkList,deleteList,date);
        if(deleteList.size()>0){
            //逻辑删除
            for(Device d : deleteList){
                deviceMapper.updateById(d);
            }
        }
        if(addList.size()>0){
            deviceMapper.insertBatchSomeColumn(addList);
        }
        if(editList.size()>0){
            for(Device d : editList){
                deviceMapper.updateById(d);
            }
        }
        return "同步门禁数据:新增【"+addList.size()+"】条,更新【"+editList.size()+"】条,删除【"+deleteList.size()+"】条";
    }
    private void getAddAndEditList(List<Device> allList, List<AcsDeviceInfoResponse> allHkList, List<Device> addList, List<Device> editList, Date date) {
        if(allHkList!=null && allHkList.size()>0){
            for(AcsDeviceInfoResponse device : allHkList){
                Device model = getExistedDevice(device,allList);
                if(model !=null){
                    //如果已存在,则更新数据
                    model =  initDeviceByHkData(model,device,date);
                    editList.add(model);
                }else{
                    //如果不存在,则新增数据
                    model = new Device();
                    model =  initDeviceByHkData(model,device,date);
                    addList.add(model);
                }
            }
        }
    }
    /**
     * åˆå§‹åŒ–海康入库数据
     * @param model
     * @param device
     * @param date
     * @return
     */
    private Device initDeviceByHkData(Device model, AcsDeviceInfoResponse device,Date date) {
        model.setIsdeleted(Constants.ZERO);
        model.setIp(device.getIp());
        model.setHkDate(date);
        model.setCreateDate(DateUtil.StringToDate2(device.getCreateTime()));
        model.setEditDate(DateUtil.StringToDate2(device.getUpdateTime()));
        model.setNo(device.getDeviceCode());
        model.setHkId(device.getIndexCode());
        model.setName(device.getName());
        model.setHkStatus(Constants.ONE);
        model.setType(Constants.ZERO);
        model.setResourceType(device.getResourceType());
        model.setDevTypeCode(device.getDevTypeCode());
        model.setManufature(device.getManufacturer());
        model.setPort(device.getPort());
        return  model;
    }
    private Device getExistedDevice(AcsDeviceInfoResponse device, List<Device> allList) {
        if(allList.size()>0){
            for(Device r : allList){
                if(StringUtils.equals(r.getHkId(), device.getIndexCode())){
                    //表示未删除
                    return  r;
                }
            }
        }
        return  null;
    }
    private void getDeleteList(List<Device> allList, List<AcsDeviceInfoResponse> allHkList,List<Device> deleteList ,Date date) {
        if(allList!=null && allList.size()>0){
            for(Device device : allList){
                if(isDeletedDevice(device,allHkList)){
                    device.setIsdeleted(Constants.ONE);
                    device.setEditDate(date);
                    deleteList.add(device);
                }
            }
        }
    }
    private boolean isDeletedDevice(Device device, List<AcsDeviceInfoResponse> allHkList) {
        if(allHkList.size()>0){
            for(AcsDeviceInfoResponse r : allHkList){
                if(StringUtils.equals(device.getHkId(), r.getIndexCode())){
                    //表示未删除
                    return  false;
                }
            }
        }
        return  true;
    }
}
server/openapi/src/main/java/com/doumee/model/response/erp/UserListRespone.java
@@ -34,7 +34,7 @@
    private Date editDate;
    @ApiModelProperty(value = "所属组织编码")
    private String orgId;
    @ApiModelProperty(value = "人脸照片地址")
    @ApiModelProperty(value = "人脸照片地址,图片公网访问地址")
    private String faceImg;
    @ApiModelProperty(value = "工号")
    private String code;
server/pom.xml
@@ -271,6 +271,11 @@
      <artifactId>artemis-http-client</artifactId>
      <version>1.1.3</version>
    </dependency>
    <dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>3.8.0</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>