已重命名5个文件
已删除2个文件
已添加12个文件
已修改28个文件
50513 ■■■■ 文件已修改
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/AbstractApiCameraService.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/ApiCameraManager.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/ApiCameraService.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/data/ApiCameraData.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/data/ApiCameraResp.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/data/ApiSnapReq.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/impl/DefaultPlayServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/impl/DefaultPtzServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/impl/DefaultSnapServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/constant/CameraPtzType.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/constant/CameraSnapType.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/constant/SnapType.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/Camera.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/Patrol.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolConf.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolKey.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/DicService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolConfService.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/DicPR.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/SecCamera.view.xml 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/inout/InoutApiController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolConfController.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolRecordController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/SecurityController.java 75 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/common/CommonManager.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/group/GroupManager.java 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/group/chinaMapList.js 14081 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/group/gis.js 100 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/group/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/group/mapList.js 33650 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord-style.css 259 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord.js 412 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/security/video-aerial-dept.js 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/security/video-control.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/security/video-list-dept.js 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/security/video-list.css 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/patrol/add.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolConf/add.html 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolConf/edit.html 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolConf/patrolConf.html 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/patrolRecord.html 156 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/video-aerial-dept.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/video-list-dept.html 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/security/video-list.html 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/AbstractApiCameraService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.fzzy.igds.camera;
import com.fzzy.igds.camera.data.ApiCameraData;
import com.fzzy.igds.camera.data.ApiCameraResp;
import com.fzzy.igds.camera.data.ApiSnapReq;
import com.fzzy.igds.domain.Camera;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
 * @Description æŽ¥å£æŠ½è±¡å®žçŽ°ç±»ï¼ŒæŠ½è±¡å®žçŽ°ç±»ï¼Œæä¾›é»˜è®¤å®žçŽ°ï¼Œå…·ä½“ä¸šåŠ¡å®žçŽ°ç»§æ‰¿è¯¥æŠ½è±¡ç±»ï¼Œå¹¶å®žçŽ°æŠ½è±¡æ–¹æ³•
 * @Author CZT
 * @Date 2025/12/11 10:10
 */
@Slf4j
public abstract class AbstractApiCameraService implements ApiCameraService {
    @Override
    public ApiCameraResp getPlayAddr(ApiCameraData apiCameraDto) {
        return new ApiCameraResp(ApiCameraResp.CODE_SUCCESS, "当前协议无需执行当前协议");
    }
    @Override
    public ApiCameraResp ptzMedia(ApiCameraData apiCameraDto) {
        return new ApiCameraResp(ApiCameraResp.CODE_SUCCESS, "当前协议无需执行当前协议");
    }
    @Override
    public ApiCameraResp ptzPreset(ApiCameraData apiCameraDto) {
        return new ApiCameraResp(ApiCameraResp.CODE_SUCCESS, "当前协议无需执行当前协议");
    }
    @Override
    public ApiCameraResp keepAlive(ApiCameraData apiCameraDto) {
        return new ApiCameraResp(ApiCameraResp.CODE_SUCCESS, "当前协议无需执行当前协议");
    }
    @Override
    public List<Camera> searchCamera(ApiCameraData apiCameraDto) {
        return null;
    }
    @Override
    public ApiCameraResp snapImg(ApiSnapReq apiCameraDto) {
        return new ApiCameraResp(ApiCameraResp.CODE_SUCCESS, "当前协议无需执行当前协议");
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/ApiCameraManager.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.fzzy.igds.camera;
import com.fzzy.igds.constant.CameraPlayType;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * è§†é¢‘接口管理,用于管理不同播放方式的协议接口,业务通过当前管理调用不同的实现
 */
@Component(ApiCameraManager.BEAN_ID)
public class ApiCameraManager implements ApplicationContextAware {
    public static final String BEAN_ID = "core.apiCameraManager";
    public static Map<String, ApiCameraService> remoteMap = new HashMap<>();
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, ApiCameraService> grainMap = applicationContext.getBeansOfType(ApiCameraService.class);
        for (String key : grainMap.keySet()) {
            remoteMap.put(grainMap.get(key).getType(), grainMap.get(key));
        }
    }
    /**
     *  æ ¹æ®ç±»åž‹æ ‡ç­¾å°è£…不同的接口实现,
     *
     * @param type å¯ä»¥æ˜¯playType,可以是snapType,可以是ptzType
     * @return æŽ¥å£å®žçް
     */
    public ApiCameraService getApiCameraService(String type) {
        ApiCameraService apiCameraService = remoteMap.get(type);
        if (null == apiCameraService) {
            apiCameraService = remoteMap.get(CameraPlayType.PLAY_TYPE_DEFAULT.getCode());
        }
        return apiCameraService;
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/ApiCameraService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package com.fzzy.igds.camera;
import com.fzzy.igds.camera.data.ApiCameraData;
import com.fzzy.igds.camera.data.ApiCameraResp;
import com.fzzy.igds.camera.data.ApiSnapReq;
import com.fzzy.igds.domain.Camera;
import java.util.List;
/**
 * @Description è§†é¢‘流媒体调用接口,通过系统配置的播放方式调用不同的流媒体实现。
 * @Author CZT
 * @Date 2025/12/11 10:10
 */
public interface ApiCameraService {
    /**
     * @return é…ç½®çš„类型标签
     */
    String getType();
    /**
     * æ ¹æ®å‚数获取播放地址
     *
     * @param apiCameraDto
     * @return
     */
    ApiCameraResp getPlayAddr(ApiCameraData apiCameraDto);
    /**
     * è®¾å¤‡äº‘台操作
     *
     * @param apiCameraDto
     * @return
     */
    ApiCameraResp ptzMedia(ApiCameraData apiCameraDto);
    /**
     * é¢„置位设置
     *
     * @param apiCameraDto
     * @return
     */
    ApiCameraResp ptzPreset(ApiCameraData apiCameraDto);
    /**
     * æ’­æ”¾è¿žæŽ¥ä¿æŒåœ¨çº¿ï¼Œé’ˆå¯¹éœ€è¦å½“前接口的流媒体生效
     *
     * @param apiCameraDto
     * @return
     */
    ApiCameraResp keepAlive(ApiCameraData apiCameraDto);
    /**
     * é€šè¿‡æµåª’体接口调用流媒体配置的摄像头信息
     *
     * @param apiCameraDto
     * @return
     */
    List<Camera> searchCamera(ApiCameraData apiCameraDto);
    /**
     * æŠ“拍接口,需要根据抓拍方式调整
     *
     * @param apiCameraDto
     * @return
     */
    ApiCameraResp snapImg(ApiSnapReq apiCameraDto);
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/data/ApiCameraData.java
ÎļþÃû´Ó fzzy-igdss-core/src/main/java/com/fzzy/igds/data/ApiCameraData.java ÐÞ¸Ä
@@ -1,4 +1,4 @@
package com.fzzy.igds.data;
package com.fzzy.igds.camera.data;
import lombok.Data;
@@ -36,10 +36,15 @@
     * IP
     */
    private String ip;
    /**
     * WEB端口
     */
    private Integer webPort;
    /**
     * æŽ§åˆ¶ç«¯å£
     */
    private Integer controlPort;
    private Integer ctrlPort;
    /**
     * æ’­æ”¾æ–¹å¼
     */
@@ -48,6 +53,11 @@
     * æŠ“拍方式
     **/
    private String snapType;
    /**
     * äº‘台方式
     **/
    private String ptzType;
    /**
     * ç›‘控SN
     */
@@ -69,8 +79,8 @@
     */
    private int speed = 129;//速度(0-255 é»˜è®¤129)
    /**
     * äº‘台控制命令 1=上,2=下,3=左,4=右,5=左上,6=左下,7=右上,8=右下,0=停止,9=变倍小,10 = å˜å€åŠ 
     * é¢„置位命令 1=设置,2=执行,3=删除
     *云台控制命令 1=上,2=下,3=左,4=右,5=左上,6=左下,7=右上,8=右下,0=停止,9=变倍小,10 = å˜å€åŠ ï¼Œ11 = å˜ç„¦åœ
     *预置位命令 1=设置,2=执行,3=删除
     */
    private String command;
    /**
@@ -78,7 +88,7 @@
     */
    private String preset;
    /**
     * RTSP地址
     * åª’体地址
     */
    private String mediaAddr;
    /**
@@ -89,8 +99,9 @@
     * å¤–网播放地址
     */
    private String urlOut;
    /**
     * è¯·æ±‚æ–¹IP,用于判断是内网播放,还是外网播放
     * æ˜¯å¦ä½¿ç”¨å¤–网播放地址默认否
     */
    private String requireIp;
    private boolean extNetwork = false;
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/data/ApiCameraResp.java
ÎļþÃû´Ó fzzy-igdss-core/src/main/java/com/fzzy/igds/data/ApiCameraResp.java ÐÞ¸Ä
@@ -1,4 +1,4 @@
package com.fzzy.igds.data;
package com.fzzy.igds.camera.data;
import lombok.Data;
@@ -26,6 +26,7 @@
    private String playUrl;  //播放地址
    private String playType; //播放方式
    private String snapType; //播放方式
    private String ptzType; //云台方式
    private String appkey; //安防平台appKey
    private String secret; //安防平台秘钥
    private String ip;     //设备IP
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/data/ApiSnapReq.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
package com.fzzy.igds.camera.data;
import lombok.Data;
import java.io.Serializable;
/**
 * @Description æ‘„像头抓拍参数
 * @Author CZT
 * @Date 2024/12/11 10:10
 */
@Data
public class ApiSnapReq implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private String orderId;
    //系统内部摄像头主键或者配置ID
    private String bizId;
    private String companyId;//组织编码
    private String deptId;//分库编码
    /**
     * æ’­æ”¾æ–¹å¼
     */
    private String playType;
    /**
     * æŠ“拍方式
     **/
    private String snapType;
    private String ptzType;
    /**
     * é…å¥—序号
     **/
    private String sort;
    /**
     * è®¾å¤‡å”¯ä¸€ID,主要与流媒体匹配使用
     */
    private String sn;
    /**
     * ç›‘控账号
     */
    private String ip;
    /**
     * ç›‘控密码
     */
    private Integer port;
    /**
     * ç›‘控账号
     */
    private String loginId;
    /**
     * ç›‘控密码
     */
    private String password;
    /**
     * é€šé“号
     */
    private Integer chanNum;
    /**
     * RTSP地址
     */
    private String mediaAddr;
    /**
     * æŠ“拍终端序列号,非必填字段。
     */
    private String serSn;
    /**
     * å›¾ç‰‡ä¿å­˜åœ°å€
     */
    private String filePath;
    /**
     * å›¾ç‰‡åç§°
     */
    private String fileName;
    private String cameraName;
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/impl/DefaultPlayServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.fzzy.igds.camera.impl;
import com.fzzy.igds.camera.AbstractApiCameraService;
import com.fzzy.igds.constant.CameraPlayType;
import org.springframework.stereotype.Component;
/**
 * @Description ç³»ç»Ÿé»˜è®¤ä¸åšä»»ä½•接口实现和处理
 * @Author CZT
 * @Date 2025/12/11 10:10
 */
@Component
public class DefaultPlayServiceImpl extends AbstractApiCameraService {
    @Override
    public String getType() {
        return CameraPlayType.PLAY_TYPE_DEFAULT.getCode();
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/impl/DefaultPtzServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.fzzy.igds.camera.impl;
import com.fzzy.igds.camera.AbstractApiCameraService;
import com.fzzy.igds.constant.CameraPtzType;
import org.springframework.stereotype.Component;
/**
 * @Description ç³»ç»Ÿé»˜è®¤ä¸åšä»»ä½•接口实现和处理
 * @Author CZT
 * @Date 2025/12/11 10:10
 */
@Component
public class DefaultPtzServiceImpl extends AbstractApiCameraService {
    @Override
    public String getType() {
        return CameraPtzType.PTZ_TYPE_NONE.getCode();
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/camera/impl/DefaultSnapServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.fzzy.igds.camera.impl;
import com.fzzy.igds.camera.AbstractApiCameraService;
import com.fzzy.igds.constant.CameraSnapType;
import org.springframework.stereotype.Component;
/**
 * @Description ç³»ç»Ÿé»˜è®¤ä¸åšä»»ä½•接口实现和处理
 * @Author CZT
 * @Date 2025/12/11 10:10
 */
@Component
public class DefaultSnapServiceImpl extends AbstractApiCameraService {
    @Override
    public String getType() {
        return CameraSnapType.SNAP_TYPE_NONE.getCode();
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/constant/CameraPtzType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
package com.fzzy.igds.constant;
import lombok.Getter;
/**
 * @Description äº‘台控制方式
 * @Author CZT
 * @Date 2024/12/10 16:38
 */
@Getter
public enum CameraPtzType {
    PTZ_TYPE_NONE("NONE", "不控制"),
    PTZ_TYPE_HIK_ISAPI("HIK-ISAPI", "海康IS-API云台"),
    PTZ_TYPE_DAHUA_API("DAHUA-HTTP-API", "大华HTTP-API云台"),
    PTZ_TYPE_FZZY_ONVIF("FZZY-ONVIF", "风正致远Onvif内网云台");
    private String code;
    private String msg;
    private CameraPtzType(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public static String getMsg(String code) {
        if (null == code) return null;
        if (CameraPtzType.PTZ_TYPE_NONE.getCode().equals(code)) return CameraPtzType.PTZ_TYPE_NONE.getMsg();
        if (CameraPtzType.PTZ_TYPE_HIK_ISAPI.getCode().equals(code)) return CameraPtzType.PTZ_TYPE_HIK_ISAPI.getMsg();
        if (CameraPtzType.PTZ_TYPE_DAHUA_API.getCode().equals(code)) return CameraPtzType.PTZ_TYPE_DAHUA_API.getMsg();
        if (CameraPtzType.PTZ_TYPE_FZZY_ONVIF.getCode().equals(code)) return CameraPtzType.PTZ_TYPE_FZZY_ONVIF.getMsg();
        return code;
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/constant/CameraSnapType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.fzzy.igds.constant;
/**
 * @Description æŠ“拍方式
 * @Author CZT
 * @Date 2025/11/25 15:28
 */
public enum CameraSnapType {
    SNAP_TYPE_NONE("NONE", "不抓拍"),
    SNAP_TYPE_FZZY_PLUGIN("FZZY-PLUGIN", "FZZY_RSTP插件抓拍"),
    SNAP_TYPE_FZZY_PLUGIN_V2("FZZY-PLUGIN_V2", "FZZY_API插件抓拍"),
    SNAP_TYPE_HIK_ISAPI("HIK-ISAPI", "海康ISAPI抓拍"),
    SNAP_TYPE_DAHUA_HTTP_API("DAHUA-HTTP-API", "大华HTTP_API抓拍");
    private String code;
    private String msg;
    private CameraSnapType(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public String getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    public static String getMsg(String code) {
        if (null == code) return null;
        if (CameraSnapType.SNAP_TYPE_NONE.getCode().equals(code)) return CameraSnapType.SNAP_TYPE_NONE.getMsg();
        if (CameraSnapType.SNAP_TYPE_FZZY_PLUGIN.getCode().equals(code)) return CameraSnapType.SNAP_TYPE_FZZY_PLUGIN.getMsg();
        if (CameraSnapType.SNAP_TYPE_FZZY_PLUGIN_V2.getCode().equals(code)) return CameraSnapType.SNAP_TYPE_FZZY_PLUGIN_V2.getMsg();
        if (CameraSnapType.SNAP_TYPE_HIK_ISAPI.getCode().equals(code)) return CameraSnapType.SNAP_TYPE_HIK_ISAPI.getMsg();
        if (CameraSnapType.SNAP_TYPE_DAHUA_HTTP_API.getCode().equals(code)) return CameraSnapType.SNAP_TYPE_DAHUA_HTTP_API.getMsg();
        return code;
    }
}
fzzy-igdss-core/src/main/java/com/fzzy/igds/constant/SnapType.java
ÎļþÒÑɾ³ý
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/Camera.java
@@ -96,6 +96,10 @@
    @TableField("snap_type")
    private String snapType;
    @Column(name = "ptz_type", columnDefinition = "varchar(40) COMMENT '云台方式'")
    @TableField("ptz_type")
    private String ptzType;
    @Column(name = "sort", columnDefinition = "varchar(2) COMMENT '配套序号'")
    @TableField("sort")
    private String sort = "1";
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/Patrol.java
@@ -32,9 +32,13 @@
    private String userId;
    @Id
    @Column(name = "batch_id", columnDefinition = "varchar(40) COMMENT '班次编号'")
    @TableField("batch_id")
    private String batchId;
    @Column(name = "conf_id", columnDefinition = "varchar(40) COMMENT '班次编号'")
    @TableField("conf_id")
    private String confId;
    @Column(name = "conf_name", columnDefinition = "varchar(40) COMMENT '班次名称'")
    @TableField("conf_name")
    private String confName;
    @Column(name = "dept_id", columnDefinition = "varchar(40) COMMENT '所属库区'")
    @TableField("dept_id")
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolConf.java
@@ -27,20 +27,24 @@
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "batch_id", columnDefinition = "varchar(40) COMMENT '班次编号'")
    @TableId(value = "batch_id", type = IdType.NONE)
    @TableField("batch_id")
    private String batchId;
    @Column(name = "id", columnDefinition = "varchar(40) COMMENT '班次编号'")
    @TableId(value = "id", type = IdType.NONE)
    @TableField("id")
    private String id;
    @Column(name = "dept_id", columnDefinition = "varchar(40) COMMENT '所属库区'")
    @TableField("dept_id")
    private String deptId;
    @Column(name = "batch_name", columnDefinition = "varchar(40) COMMENT '班次名称'")
    @TableField("batch_name")
    private String batchName;
    @Column(name = "name", columnDefinition = "varchar(40) COMMENT '班次名称'")
    @TableField("name")
    private String name;
    @Column(name = "user_name", columnDefinition = "varchar(40) COMMENT '巡逻人'")
    @Column(name = "user_id", columnDefinition = "varchar(200) COMMENT '巡逻人账号'")
    @TableField("user_id")
    private String userId;
    @Column(name = "user_name", columnDefinition = "varchar(200) COMMENT '巡逻人'")
    @TableField("user_name")
    private String userName;
fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolKey.java
@@ -18,7 +18,7 @@
        private String userId;
        private String batchId;
        private String confId;
    public PatrolKey(){
            super();
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/DicService.java
@@ -189,7 +189,15 @@
     */
    public List<SysDictData> triggerSnapType() {
        List<SysDictData> list = new ArrayList<SysDictData>();
        for (SnapType w : SnapType.values()) {
        for (CameraSnapType w : CameraSnapType.values()) {
            list.add(new SysDictData(w.getMsg(), w.getCode()));
        }
        return list;
    }
    public List<SysDictData> triggerPtzType() {
        List<SysDictData> list = new ArrayList<SysDictData>();
        for (CameraPtzType w : CameraPtzType.values()) {
            list.add(new SysDictData(w.getMsg(), w.getCode()));
        }
        return list;
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolConfService.java
@@ -38,11 +38,17 @@
     */
    public QueryWrapper<PatrolConf> getQueryWrapper(PatrolConf param) {
        QueryWrapper<PatrolConf> queryWrapper = new QueryWrapper<>();
        if (param == null) {
            param = new PatrolConf();
        }
        // è®¾ç½®å…¬å¸ID并作为查询条件
        param.setCompanyId(ContextUtil.getCompanyId());
        queryWrapper.eq("company_id", param.getCompanyId());
        if (StringUtils.isNotEmpty(param.getDeptId())) {
            queryWrapper.eq("dept_id", param.getDeptId());
        }
        // æŒ‰åˆ›å»ºæ—¶é—´å€’序排序
@@ -68,8 +74,8 @@
     * @return å½±å“è¡Œæ•°
     */
    public int insertData(PatrolConf param) {
        if (StringUtils.isEmpty(param.getBatchId())) {
            param.setBatchId(ContextUtil.generateId());
        if (StringUtils.isEmpty(param.getId())) {
            param.setId(ContextUtil.generateId());
        }
        return patrolConfMapper.insert(param);
    }
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolService.java
@@ -38,6 +38,14 @@
        if (StringUtils.isNotBlank(param.getDeptId())) {
            queryWrapper.eq("dept_id", param.getDeptId());
        }
        if (StringUtils.isNotBlank(param.getUserName())) {
            queryWrapper.like("user_name", param.getUserName());
        }
        if (StringUtils.isNotBlank(param.getConfName())) {
            queryWrapper.like("conf_name", param.getConfName());
        }
        queryWrapper.orderByDesc("create_time");
        return queryWrapper;
fzzy-igdss-view/src/main/java/com/fzzy/igds/DicPR.java
@@ -132,6 +132,16 @@
    }
    /**
     * äº‘台方式
     * ${dorado.getDataProvider("dicPR#triggerPtzType").getResult()}
     *
     * @return
     */
    @DataProvider
    public List<SysDictData> triggerPtzType() {
        return dicService.triggerPtzType();
    }
    /**
     * æ£€éªŒç±»åˆ«
     * <p>
     * ${dorado.getDataProvider("dicPR#triggerCheckType").getResult()}
fzzy-igdss-view/src/main/java/com/fzzy/igds/SecCamera.view.xml
@@ -137,7 +137,6 @@
          <Property name="keyProperty">id</Property>
          <Property name="valueProperty">kqmc</Property>
        </Property>
        <Property name="readOnly">true</Property>
      </PropertyDef>
      <PropertyDef name="name">
        <Property></Property>
@@ -188,7 +187,6 @@
      </PropertyDef>
      <PropertyDef name="sort">
        <Property name="label">配套序号</Property>
        <Property name="required">true</Property>
        <Property name="mapping">
          <Property name="mapValues">
            <Collection>
@@ -260,6 +258,16 @@
        <Property name="label">抓拍方式</Property>
        <Property name="mapping">
          <Property name="mapValues">${dorado.getDataProvider(&quot;dicPR#triggerSnapType&quot;).getResult()}</Property>
          <Property name="keyProperty">dictValue</Property>
          <Property name="valueProperty">dictLabel</Property>
        </Property>
        <Property name="required">true</Property>
      </PropertyDef>
      <PropertyDef name="ptzType">
        <Property></Property>
        <Property name="label">云台方式</Property>
        <Property name="mapping">
          <Property name="mapValues">${dorado.getDataProvider(&quot;dicPR#triggerPtzType&quot;).getResult()}</Property>
          <Property name="keyProperty">dictValue</Property>
          <Property name="valueProperty">dictLabel</Property>
        </Property>
@@ -786,6 +794,21 @@
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">type</Property>
                <Property name="property">type</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">brand</Property>
                <Property name="property">brand</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">ip</Property>
                <Property name="property">ip</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">chanNum</Property>
                <Property name="property">chanNum</Property>
                <Editor/>
@@ -796,8 +819,8 @@
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">ip</Property>
                <Property name="property">ip</Property>
                <Property name="name">spdwlx</Property>
                <Property name="property">spdwlx</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
@@ -808,16 +831,6 @@
              <AutoFormElement>
                <Property name="name">webPort</Property>
                <Property name="property">webPort</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">spdwlx</Property>
                <Property name="property">spdwlx</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">sort</Property>
                <Property name="property">sort</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
@@ -886,13 +899,9 @@
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:2">
                <Property name="name">sn</Property>
                <Property name="property">sn</Property>
                <Editor>
                  <TextEditor id="sn">
                    <Property name="blankText"> -- æµåª’体平台中设备SN --</Property>
                  </TextEditor>
                </Editor>
                <Property name="name">ptzType</Property>
                <Property name="property">ptzType</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:3">
                <Property name="name">mediaAddr</Property>
@@ -901,6 +910,15 @@
                <Editor>
                  <TextEditor id="mediaAddr">
                    <Property name="blankText"> -- ç‚¹å‡»å³ä¾§é€‰æ‹©ï¼Œæˆ–者手动填写 --</Property>
                  </TextEditor>
                </Editor>
              </AutoFormElement>
              <AutoFormElement layoutConstraint="colSpan:5">
                <Property name="name">sn</Property>
                <Property name="property">sn</Property>
                <Editor>
                  <TextEditor id="sn">
                    <Property name="blankText"> -- æµåª’体平台中设备SN --</Property>
                  </TextEditor>
                </Editor>
              </AutoFormElement>
@@ -938,23 +956,8 @@
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">createBy</Property>
                <Property name="property">createBy</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">createTime</Property>
                <Property name="property">createTime</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">updateBy</Property>
                <Property name="property">updateBy</Property>
                <Editor/>
              </AutoFormElement>
              <AutoFormElement>
                <Property name="name">updateTime</Property>
                <Property name="property">updateTime</Property>
                <Editor/>
              </AutoFormElement>
            </AutoForm>
@@ -994,7 +997,8 @@
</ClientEvent>
    </Trigger>
    <Dialog id="dialogMeidaSelect" layout="vbox padding:10">
      <Property name="width">650</Property>
      <Property name="width">800</Property>
      <Property name="height">80%</Property>
      <Property name="caption">流媒体地址选择</Property>
      <Buttons/>
      <Children>
@@ -1010,10 +1014,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text1.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1028,10 +1033,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text2.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1046,10 +1052,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text3.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1064,10 +1071,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text4.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1082,10 +1090,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text5.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1100,10 +1109,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text6.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1118,10 +1128,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text7.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1136,10 +1147,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text8.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1154,10 +1166,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text9.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1172,10 +1185,11 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text10.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
@@ -1190,12 +1204,24 @@
          </Label>
          <Button layoutConstraint="right">
            <ClientEvent name="onClick">view.get(&quot;#mediaAddr&quot;).set(&quot;text&quot;,view.get(&quot;#text11.text&quot;));&#xD;
view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
</ClientEvent>
              view.get(&quot;#dialogMeidaSelect&quot;).hide();&#xD;
            </ClientEvent>
            <Property name="caption">选择</Property>
            <Property name="iconClass">fa fa-check</Property>
            <Property name="exClassName">btn1</Property>
          </Button>
        </Container>
        <Container>
          <Label>
            <Property name="text">信息说明</Property>
            <Property name="style">
              <Property name="font-weight">bold</Property>
            </Property>
          </Label>
          <Label>
            <Property name="text">{0}=用户名;{1}=密码;{2}=IP;{3}=端口;{4}=通道号;{5}=序列号;</Property>
          </Label>
        </Container>
      </Children>
      <Tools/>
    </Dialog>
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/inout/InoutApiController.java
@@ -1,5 +1,6 @@
package com.fzzy.sys.controller.inout;
import com.fzzy.igds.camera.data.ApiCameraResp;
import com.fzzy.igds.constant.RespCodeEnum;
import com.fzzy.igds.data.*;
import com.fzzy.igds.utils.SystemUtil;
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolConfController.java
@@ -2,10 +2,12 @@
import com.fzzy.igds.domain.PatrolConf;
import com.fzzy.igds.utils.ContextUtil;
import com.fzzy.sys.manager.common.CommonManager;
import com.fzzy.sys.manager.security.PatrolConfManager;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ShiroUtils;
@@ -29,11 +31,14 @@
    @Resource
    private PatrolConfManager patrolConfManager;
    @Resource
    private CommonManager commonManager;
    /**
     * å·¡æ›´é…ç½®é¡µé¢
     */
    @GetMapping()
    public String patrolConf() {
    public String patrolConf(ModelMap mmap) {
        return prefix + "/patrolConf";
    }
@@ -71,6 +76,8 @@
     */
    @GetMapping("/add")
    public String add(ModelMap mmap) {
        //巡逻人列表
        mmap.put("userList", commonManager.listUserData());
        return prefix + "/add";
    }
@@ -86,8 +93,8 @@
        }
        param.setCreateBy(getLoginName());
        param.setCreateTime(new Date());
        if (StringUtils.isEmpty(param.getBatchId())) {
            param.setBatchId(ContextUtil.generateId());
        if (StringUtils.isEmpty(param.getId())) {
            param.setId(ContextUtil.generateId());
        }
        return toAjax(patrolConfManager.insertData(param));
    }
@@ -99,6 +106,8 @@
    public String edit(@PathVariable("id") String id, ModelMap mmap) {
        PatrolConf record = patrolConfManager.selectById(id);
        mmap.put("patrolConf", record);
        //巡逻人列表
        mmap.put("userList", commonManager.listUserData());
        return prefix + "/edit";
    }
@@ -114,9 +123,9 @@
        }
        param.setUpdateBy(getLoginName());
        param.setUpdateTime(new Date());
        PatrolConf patrolConf = patrolConfManager.selectById(param.getBatchId());
        PatrolConf patrolConf = patrolConfManager.selectById(param.getId());
        if (patrolConf == null) {
            param.setBatchId(ContextUtil.generateId());
            param.setId(ContextUtil.generateId());
            return toAjax(patrolConfManager.insertData(param));
        }
@@ -130,7 +139,7 @@
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        patrolConfManager.deleteDataById( ids);
        patrolConfManager.deleteDataById(ids);
        return success();
    }
}
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolController.java
@@ -1,7 +1,10 @@
package com.fzzy.sys.controller.security;
import com.fzzy.igds.domain.Patrol;
import com.fzzy.igds.domain.PatrolConf;
import com.fzzy.igds.utils.ContextUtil;
import com.fzzy.sys.manager.common.CommonManager;
import com.fzzy.sys.manager.security.PatrolConfManager;
import com.fzzy.sys.manager.security.PatrolManager;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
@@ -29,6 +32,12 @@
    @Resource
    private PatrolManager patrolManager;
    @Resource
    private PatrolConfManager patrolConfManager;
    @Resource
    private CommonManager commonManager;
    /**
     * ç”µå­å·¡æ›´é¡µé¢
     *
@@ -36,7 +45,9 @@
     * @date 2025/12/06
     */
    @GetMapping()
    public String patrol() {
    public String patrol(ModelMap mmap) {
        //获取库区回显列表
        mmap.put("deptList", commonManager.listDeptData());
        return prefix + "/patrol";
    }
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolRecordController.java
@@ -35,31 +35,25 @@
    @GetMapping("/{patrolId}")
    public String getPatrolRecordById(@PathVariable("patrolId") String patrolId, Model model) {
        IgdsBaseParam param = new IgdsBaseParam();
        param.setPage(1);
        param.setLimit(6);
        param.setKey(patrolId);
        Page<PatrolRecord> records = patrolRecordManager.pageData(param);
        model.addAttribute("patrolRecordList", records.getRecords());
        model.addAttribute("currentPage", records.getCurrent());
        model.addAttribute("totalItems", records.getTotal());
        model.addAttribute("pageSize", records.getSize());
        model.addAttribute("patrolId", patrolId);
        return prefix + "/patrolRecord";
    }
    /**
     * èŽ·å–è½¨è¿¹å›¾é¡µé¢
     */
    @GetMapping("trajectoryMap/{patrolId}")
    public String showTrajectoryMap(@PathVariable("patrolId") String patrolId, Model model) {
        IgdsBaseParam param = new IgdsBaseParam();
        param.setKey(patrolId);
        List<PatrolRecord> trackPoints = patrolRecordManager.listAll(param);
        model.addAttribute("trackPoints", trackPoints);
        return prefix + "/trajectoryMap";
        model.addAttribute("patrolRecordList", trackPoints);
        return prefix + "/patrolRecord";
    }
//
//    /**
//     * èŽ·å–è½¨è¿¹å›¾é¡µé¢
//     */
//    @GetMapping("trajectoryMap/{patrolId}")
//    public String showTrajectoryMap(@PathVariable("patrolId") String patrolId, Model model) {
//
//        IgdsBaseParam param = new IgdsBaseParam();
//        param.setKey(patrolId);
//        List<PatrolRecord> trackPoints = patrolRecordManager.listAll(param);
//        model.addAttribute("trackPoints", trackPoints);
//
//        return prefix + "/trajectoryMap";
//    }
    /**
     * åˆ†é¡µèŽ·å–æ•°æ®
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/SecurityController.java
@@ -17,9 +17,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
@@ -40,39 +38,88 @@
    private CoreDeptService deptService;
    /**
     * ç›‘控概览
     *
     * åº“区安防页面
     * @param type 1.表示2.5D鸟瞰图页面预览;2.表示列表预览页面
     * @param view
     * @return
     */
    @RequestMapping("/aerial-video")
    public String aerialVideo(
            @RequestParam(value = "type", required = false) String type,
            ModelMap view) {
    @RequestMapping("/video-dept")
    public String videoDept(@RequestParam(value = "type", required = false) String type,
                              ModelMap view) {
        if (StringUtils.isBlank(type)) {
            type = "2";
        }
        SysUser user = ContextUtil.getLoginUser();
        view.put(Constant.MODEL_KEY_LOGIN_USER, user);
        String deptId = ContextUtil.subDeptId(user);
        List<Camera> listCamera = secManager.listCamera(deptId, user.getCompanyId());
        view.put("deptId", deptId);
        List<Camera> listCamera = secManager.listCamera(deptId, user.getCompanyId());
        view.put("listCamera", listCamera);
        //默认监控列表页面
        String viewUrl = prefix + "/video-list";
        String viewUrl = prefix + "/video-list-dept";
        if (StringUtils.isNotBlank( type) && "1".equals(type)) {
        if("1".equals(type)){
            viewUrl = prefix + "/video-aerial-dept";
            //鸟瞰图
            Dept dept = deptService.getDeptById(deptId);
            if (dept != null && StringUtils.isNotEmpty(dept.getImgPath())) {
                view.put("backgroundImg", dept.getImgPath());
                viewUrl = prefix + "/video-aerial";
            }
        }
        if("2".equals(type)){
            viewUrl = prefix + "/video-list-dept";
        }
        return viewUrl;
    }
    /**
     * ç›‘管安防页面
     * @param type 1.表示2.5D鸟瞰图页面预览;2.表示列表预览页面
     * @param view
     * @return
     */
    @RequestMapping("/video-super")
    public String videoSuper(@RequestParam(value = "type", required = false) String type,
                             ModelMap view) {
        if (StringUtils.isBlank(type)) {
            type = "2";
        }
        SysUser user = ContextUtil.getLoginUser();
        view.put(Constant.MODEL_KEY_LOGIN_USER, user);
        String deptId = ContextUtil.subDeptId(user);
        view.put("deptId", deptId);
        List<Camera> listCamera = secManager.listCamera(deptId, user.getCompanyId());
        view.put("listCamera", listCamera);
        //默认监控列表页面
        String viewUrl = prefix + "/video-list-dept";
        if("1".equals(type)){
            viewUrl = prefix + "/video-aerial-dept";
            //鸟瞰图
            Dept dept = deptService.getDeptById(deptId);
            if (dept != null && StringUtils.isNotEmpty(dept.getImgPath())) {
                view.put("backgroundImg", dept.getImgPath());
            }
        }
        if("2".equals(type)){
            viewUrl = prefix + "/video-list-dept";
        }
        return viewUrl;
    }
    /**
     * é¸Ÿçž°å›¾é¡µé¢ -- è§†é¢‘播放,通过播放参数不同跳转不同页面播放
fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/common/CommonManager.java
@@ -2,13 +2,19 @@
import com.fzzy.igds.constant.DepotType;
import com.fzzy.igds.domain.Depot;
import com.fzzy.igds.domain.Dept;
import com.fzzy.igds.service.CoreDeptService;
import com.fzzy.igds.service.DepotService;
import com.fzzy.igds.service.DicService;
import com.fzzy.igds.utils.ContextUtil;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@@ -20,13 +26,20 @@
@Slf4j
@Component
public class CommonManager {
    @Resource
    private DepotService depotService;
    @Resource
    private DicService dicService;
    @Resource
    private CoreDeptService coreDeptService;
    @Autowired
    private ISysUserService userService;
    /**
     * æ ¹æ®å­—典类型获取字典列表
     *
     * @param parentCode
     * @param companyId
     * @return
@@ -58,9 +71,19 @@
    }
    /**
     * èŽ·å–åˆ†åº“åˆ—è¡¨
     *
     * @author sgj
     * @date 2025/12/12
     */
    public List<Dept> listDeptData() {
        return coreDeptService.getDeptData();
    }
    /**
     * æ ¹æ®ä»“库编码获取仓库类型
     *
     * @param depotId
     * @return
     */
@@ -74,4 +97,17 @@
        return depotType;
    }
    /**
     * èŽ·å–ç”¨æˆ·åˆ—è¡¨
     *
     * @author sgj
     * @date 2025/12/12
     */
    public List<SysUser>  listUserData() {
        SysUser user = new SysUser() ;
        user.setCompanyId(ContextUtil.getCompanyId());
        user.setDeptId(Long.valueOf(ContextUtil.subDeptId(null)));
        return userService.selectUserList(user);
    }
}
fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/group/GroupManager.java
@@ -42,8 +42,18 @@
        List<DicArea> list = new ArrayList<>();
        list.add(area);
        if (Constant.AREA_TYPE_1.equals(area.getType())) {
            List<DicArea> children = dicAreaService.listData(area.getCode(), null, null);
            if (null != children && children.size() > 0) {
            //市州级别,只查询伊犁
            List<DicArea> children = dicAreaService.listData(null, null, "654000");
            if (null != children && !children.isEmpty()) {
                for (DicArea child : children) {
                    if (Constant.AREA_TYPE_2.equals(child.getType())) {
                        //区县
                        List<DicArea> childrenItem = dicAreaService.listData(child.getCode(), null, null);
                        if (null != childrenItem && !childrenItem.isEmpty()) {
                            list.addAll(childrenItem);
                        }
                    }
                }
                list.addAll(children);
            }
        }
@@ -59,22 +69,31 @@
     */
    public List<DicArea> getAreaAndChild(String areaCode) {
        List<DicArea> areaList = dicAreaService.listData(null, null, areaCode);
        if (null == areaList || areaList.isEmpty()) {
        DicArea area = dicAreaService.listDicAreaByCode(areaCode);
        if (null == area) {
            return null;
        }
        List<DicArea> children;
        for (DicArea dicArea : areaList) {
            if (Constant.AREA_TYPE_1.equals(dicArea.getType())) {
                children = dicAreaService.listData(dicArea.getCode(), null, null);
                if (null != children && children.size() > 0) {
                    dicArea.setChildren(children);
        List<DicArea> list = new ArrayList<>();
        if (Constant.AREA_TYPE_1.equals(area.getType())) {
            //市州级别,只查询伊犁
            List<DicArea> children = dicAreaService.listData(null, null, "654000");
            if (null != children && !children.isEmpty()) {
                for (DicArea child : children) {
                    if (Constant.AREA_TYPE_2.equals(child.getType())) {
                        //区县
                        List<DicArea> childrenItem = dicAreaService.listData(child.getCode(), null, null);
                        if (null != childrenItem && !childrenItem.isEmpty()) {
                            child.setChildren(childrenItem);
                        }
                    }
                }
                area.setChildren(children);
            }
        }
        return areaList;
        }
        list.add(area);
        return list;
    }
    /**
@@ -84,7 +103,6 @@
     * @return
     */
    public List<Dept> getAllDept(String companyId) {
        return deptService.listDept(null, companyId, null);
    }
}
fzzy-igdss-web/src/main/resources/static/group/chinaMapList.js
¶Ô±ÈÐÂÎļþ
ÎļþÌ«´ó
fzzy-igdss-web/src/main/resources/static/group/gis.js
@@ -127,9 +127,10 @@
/**
 * èŽ·å–å¸‚å·žä¸‹åº“åŒºä¿¡æ¯
 */
function getDeptArea(province, county) {
function getDeptArea(province, city, county) {
    var list = [];
    if (deptList) {
        //省
        if (province && province.length > 0) {
            var str1 = province.substring(0, 2);
            for (var i = 0; i < deptList.length; i++){
@@ -137,12 +138,20 @@
                    list.push(deptList[i]);
                }
            }
        }
        if (county && county.length > 0) {
            var str2 = county.substring(0, 4);
        //市州
        if (city && city.length > 0) {
            var str2 = city.substring(0, 4);
            for (var i = 0; i < deptList.length; i++) {
                if(deptList[i].xzqhdm.startsWith(str2)){
                    list.push(deptList[i]);
                }
            }
        }
        //区县
        if (county && county.length > 0) {
            for (var i = 0; i < deptList.length; i++) {
                if(deptList[i].xzqhdm === county){
                    list.push(deptList[i]);
                }
            }
@@ -155,20 +164,25 @@
/**
 * ç”¨æˆ·ç‚¹å‡»åŸŽå¸‚或者县级区级渲染库区点位
 */
function renderAreas(deptId) {
    var d = allAreaMap[deptId];
function renderAreas(code) {
    var d = allAreaMap[code];
    if (d) {
        closeInfoWindow();
        removeColor();
        delMarker();
        //map.setCity(deptId);
        renderColor(deptId);
        renderColor(code);
        var a = [];
        //省
        if ("1" == d.type) {
            a = getDeptArea(deptId, "")
            a = getDeptArea(code, "", "");
        }
        //市州
        if ("2" == d.type) {
            a = getDeptArea("", deptId)
            a = getDeptArea("", code, "")
        }
        //区县
        if ("3" == d.type) {
            a = getDeptArea("", "", code)
        }
        if (a && a.length > 0) {
            for (var i = 0; i < a.length; i++) {
@@ -176,10 +190,10 @@
            }
        }
        //刷新数据
        county = deptId;
        county = code;
        // ajaxFoodNum();
    } else {
        console.log("没有获取到该行政区划:" + deptId);
        console.log("没有获取到该行政区划:" + code);
    }
}
@@ -209,6 +223,7 @@
    if (areaList) {
        var html = "";
        var childs = [];
        var childsItem = [];
        var areas = [];
        for (var i = 0; i < areaList.length; i++) {
            html += "<div style=\"width: 305px; overflow: hidden\">" +
@@ -220,7 +235,7 @@
                (areaList[i].name ? areaList[i].name : "") +
                "</a>" +
                "</div>";
            if (areaList[i].children && areaList[i].children.length > 0) {
            if (areaList[i].children && areaList[i].children.length > 0) {   //市州
                childs = areaList[i].children;
                for (var j = 0; j < childs.length; j++) {
                    html += "<ul class=\"sup-menu-ul  menu-h\">" +
@@ -232,23 +247,58 @@
                        (childs[j].name ? childs[j].name : "") +
                        "</a>" +
                        "</div>";
                    areas = getDeptArea("", childs[j].code);
                    if (areas && areas.length > 0) {
                        for (var k = 0; k < areas.length; k++) {
                            html += "<div class=\"sup-menu-box\">" +
                                "<p>" +
                                "<span class=\"i-icon32 fl\"><img src=\"/img/web/group/icon-kuqu.png\"/></span>" +
                                "<a href=\"#\" onclick=\"showAreaInfo('" + areas[k].id + "')\">" + areas[k].kqmc + "</a>" +
                                "</p>" +
                    if (childs[j].children && childs[j].children.length > 0) {   //市州
                        childsItem = childs[j].children;
                        for (var j = 0; j < childsItem.length; j++) {
                            html += "<ul class=\"sup-menu-ul  menu-h\">" +
                                "<li>" +
                                "<div class=\"sup-menu-h\">" +
                                "<i class=\"i-icon fl\"><img src=\"/img/web/group/icon-sj.png\"/></i>" +
                                "<a href=\"###\" onclick=\"renderAreas('" + childsItem[j].code + "')\">" +
                                "<span class=\"i-icon32 fl\"><img src=\"/img/web/group/c-i2.png\"/></span>" +
                                (childsItem[j].name ? childsItem[j].name : "") +
                                "</a>" +
                                "</div>";
                            areas = getDeptArea("","", childsItem[j].code);
                            if (areas && areas.length > 0) {
                                for (var k = 0; k < areas.length; k++) {
                                    html += "<div class=\"sup-menu-box\">" +
                                        "<p>" +
                                        "<span class=\"i-icon32 fl\"><img src=\"/img/web/group/icon-kuqu.png\"/></span>" +
                                        "<a href=\"#\" onclick=\"showAreaInfo('" + areas[k].id + "')\">" + areas[k].kqmc + "</a>" +
                                        "</p>" +
                                        "</div>";
                                }
                            }
                            html += "</li>" +
                                "</ul>";
                        }
                    } else {
                        //没有子节点,直接就是库区
                        areas = getDeptArea("", "", areaList[i].code);
                        if (areas && areas.length > 0) {
                            for (var k = 0; k < areas.length; k++) {
                                html += "<ul class=\"sup-menu-ul\">" +
                                    "<li>" +
                                    "<div class=\"sup-menu-h\">" +
                                    "<i class=\"i-icon fl\"><img src=\"/img/web/group/icon-sj.png\"/></i>" +
                                    "<a href=\"###\" onclick=\"renderAreas('" + areas[k].code + "')\">" +
                                    "<span class=\"i-icon32 fl\"><img src=\"/img/web/group/icon-kuqu.png\"/></span>" +
                                    (areas[k].name ? areas[k].name : "") +
                                    "</a>" +
                                    "</div>";
                                html += "<div class=\"sup-menu-box\">" +
                                    "</div>";
                                html += "</li>" +
                                    "</ul>";
                            }
                        }
                    }
                    html += "</li>" +
                        "</ul>";
                }
            } else {
                //没有子节点,直接就是区级别
                areas = getDeptArea("", areaList[i].code);
                //没有子节点,直接就是库区
                areas = getDeptArea("", "",areaList[i].code);
                if (areas && areas.length > 0) {
                    for (var k = 0; k < areas.length; k++) {
                        html += "<ul class=\"sup-menu-ul\">" +
fzzy-igdss-web/src/main/resources/static/group/index.js
@@ -19,7 +19,7 @@
var number3 = 2;// å‚¨é‡é¥¼å›¾åˆ‡æ¢æ€»æ•°é‡
var mapChart = null;
var geoMap = [{name: '乌鲁木齐', value: [87.617733, 43.792818]}]; //默认点位
var geoMap = [{name: '伊犁哈萨克自治州', value: [81.317946, 43.92186]}]; //默认点位
var map = chinaMapOutline; //默认加载全国地图
$(function () {
    // åˆå§‹åŒ–页面
@@ -43,7 +43,7 @@
    initMap();
    //加载指定地区地图
    renderMapPoints("新疆维吾尔自治区");
    renderMapPoints("乌鲁木齐市,克拉玛依市,吐鲁番市,哈密市,昌吉回族自治州,博尔塔拉蒙古自治州,巴音郭楞蒙古自治州,阿克苏地区,克孜勒苏柯尔克孜自治州,喀什地区,和田地区,伊犁哈萨克自治州,塔城地区,阿勒泰地区");
    // è¯·æ±‚库区信息
    // ajaxDeptArea();
    // èŽ·å–å…¬å¸ä¿¡æ¯
@@ -87,10 +87,12 @@
        for (var i = 0; i < all.length; i++) {
            if(all[i].properties.name == names[j]){
                map.features.push(all[i]);
                geoMap.push({
                    name: all[i].properties.centerName,
                    value: [all[i].properties.center[0], all[i].properties.center[1], 12]
                });
                if(all[i].properties.name == "伊犁哈萨克自治州"){
                    geoMap.push({
                        name: all[i].properties.centerName,
                        value: [all[i].properties.center[0], all[i].properties.center[1], 12]
                    });
                }
                renderMap();
                break;
            }
fzzy-igdss-web/src/main/resources/static/group/mapList.js
ÎļþÌ«´ó
fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord-style.css
@@ -1,203 +1,96 @@
/* å›¾ç‰‡é¢„览层样式 */
.img-preview {
    display: none;
#map {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.9);
    z-index: 1000;
    justify-content: center;
    align-items: center;
    z-index: 1;
}
.preview-content {
    max-width: 90%;
    max-height: 90%;
    position: relative;
}
.preview-img {
    max-width: 100%;
    max-height: 90vh;
    border-radius: 4px;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.close-preview {
    position: absolute;
    top: -40px;
    right: -10px;
    color: white;
    font-size: 2rem;
    cursor: pointer;
    background: rgba(0, 0, 0, 0.5);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: all 0.3s ease;
}
.close-preview:hover {
    background: rgba(255, 255, 255, 0.2);
    transform: scale(1.1);
}
/* å›¾ç‰‡ç½‘格样式 */
.gallery-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
    gap: 20px;
    margin-bottom: 5px;
}
.gallery-item {
    background: white;
/* å³ä¾§è½¨è¿¹å¡ç‰‡æ‚¬æµ®å±‚ */
.track-card-panel {
    position: fixed;
    top: 20px;
    right: 20px;
    bottom: 20px;
    width: 380px;
    background: #fff;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    transition: all 0.3s ease;
}
.gallery-item:hover {
    transform: translateY(-5px);
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.12);
}
.gallery-img {
    width: 100%;
    height: 240px;
    object-fit: cover;
    cursor: pointer;
    transition: all 0.3s ease;
}
.gallery-img:hover {
    opacity: 0.95;
}
.gallery-info {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
    z-index: 10; /* å±‚级高于地图 */
    padding: 15px;
    overflow-y: auto; /* çºµå‘滚动 */
    overflow-x: hidden; /* éšè—æ¨ªå‘滚动 */
}
.gallery-header {
/* å¡ç‰‡é¢æ¿æ ‡é¢˜ */
.panel-title {
    font-size: 18px;
    font-weight: 600;
    color: #333;
    padding-bottom: 10px;
    border-bottom: 1px solid #e6e6e6;
    margin-bottom: 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
}
.gallery-title {
    font-size: 1.5rem;
    font-weight: 600;
.panel-title .count {
    font-size: 14px;
    color: #1890ff;
    font-weight: normal;
}
/* å•个轨迹卡片 */
.track-card {
    padding: 12px;
    border: 1px solid #f0f0f0;
    border-radius: 6px;
    margin-bottom: 10px;
    cursor: pointer;
    transition: all 0.2s ease;
}
.track-card:hover {
    border-color: #1890ff;
    background: #f5f8ff;
    transform: translateX(-2px);
}
.track-card.active {
    border-color: #1890ff;
    background: #e6f7ff;
}
/* å¡ç‰‡å†…信息行 */
.card-row {
    display: flex;
    margin-bottom: 6px;
    font-size: 14px;
    line-height: 1.5;
}
.card-row:last-child {
    margin-bottom: 0;
}
.card-row .label {
    width: 80px;
    color: #666;
    flex-shrink: 0;
}
.card-row .value {
    color: #333;
    margin: 0;
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gallery-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
/* æ»šåŠ¨æ¡ç¾ŽåŒ– */
.track-card-panel::-webkit-scrollbar {
    width: 6px;
}
.meta-item {
    display: flex;
    align-items: center;
    font-size: 1.3rem;
    color: #666;
.track-card-panel::-webkit-scrollbar-track {
    background: #f5f5f5;
    border-radius: 3px;
}
.meta-item i {
    width: 16px;
    margin-right: 6px;
    color: #999;
    font-size: 1.25rem;
.track-card-panel::-webkit-scrollbar-thumb {
    background: #d9d9d9;
    border-radius: 3px;
}
.gallery-filename i {
    margin-right: 5px;
    font-size: 0.7rem;
}
/* æ ‡ç­¾æ ·å¼ */
.gallery-tags {
    display: flex;
    flex-wrap: wrap;
    margin-left: auto;
    gap: 3px;
    /*margin: 12px 0;*/
}
/* åˆ†é¡µæ ·å¼ */
.pagination-container {
    display: flex;
    justify-content: flex-end;
    width: 100%;
    /*margin-top: 40px;*/
}
/* ç©ºçŠ¶æ€æ ·å¼ */
.empty-state {
    grid-column: 1 / -1;
    text-align: center;
    padding: 60px 20px;
    color: #999;
}
.empty-state i {
    font-size: 4rem;
    margin-bottom: 20px;
    color: #ddd;
}
.empty-state h3 {
    font-size: 1.5rem;
    margin-bottom: 10px;
    color: #666;
}
/* å“åº”式设计 */
@media (max-width: 992px) {
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
        gap: 25px;
    }
}
@media (max-width: 768px) {
    .main-nav li {
        margin: 0 10px;
    }
    .gallery-grid {
        grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
        gap: 20px;
    }
    .gallery-img {
        height: 180px;
    }
}
@media (max-width: 576px) {
    .gallery-grid {
        grid-template-columns: 1fr;
    }
    .gallery-img {
        height: 200px;
    }
.track-card-panel::-webkit-scrollbar-thumb:hover {
    background: #1890ff;
}
fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord.js
@@ -1,281 +1,169 @@
var layer;
var laypage;
$(function () {
    // åˆå§‹åŒ–分页
    layui.use(['laypage', 'layer'], function () {
$(document).ready(function () {
    layui.use(['layer'], function () {
        layer = layui.layer;
        laypage = layui.laypage;
        // åˆå§‹åŒ–分页组件
        initPagination();
    });
    // åˆå§‹åŒ–图片预览功能
    initImagePreview();
});
/**
 * åˆå§‹åŒ–分页组件
 */
function initPagination() {
    laypage.render({
        elem: 'pagination',
        count: typeof totalItems !== 'undefined' ? totalItems : 0,
        limit: typeof pageSize !== 'undefined' ? pageSize : 6,
        curr: typeof currentPage !== 'undefined' ? currentPage : 1,
        layout: ['prev', 'page', 'next', 'refresh', 'skip'],
        jump: function (obj, first) {
            if (!first) {
                searchRecord(obj.curr, obj.limit)
            }
        }
    });
}
/**
 * é‡æ–°åˆå§‹åŒ–分页组件
 * @param {number} totalCount - æ€»è®°å½•æ•°
 * @param {number} pageSize - æ¯é¡µå¤§å°
 * @param {number} currentPage - å½“前页码
 */
function reinitPagination(totalCount, pageSize, currentPage) {
    laypage.render({
        elem: 'pagination',
        count: totalCount,
        limit: pageSize,
        curr: currentPage,
        layout: ['prev', 'page', 'next', 'refresh', 'skip'],
        jump: function (obj, first) {
            if (!first) {
                searchRecord(obj.curr, obj.limit)
            }
        }
    });
}
/**
 * èŽ·å–å·¡æ£€è®°å½•æ•°æ®
 * @param {Object} params - æŸ¥è¯¢å‚数对象
 * @param {Function} callback - å›žè°ƒå‡½æ•°
 */
function fetchPatrolRecordData(params, callback) {
    $.ajax({
        url: '../../patrol/patrolRecord/pageData',
        type: 'POST',
        dataType: "json",
        contentType: "application/json;charset=UTF-8",
        data: JSON.stringify(params),
        success: function (response) {
            if (response.code === '0000') {
                callback(null, response.data);
            } else {
                callback(new Error(response.msg || '数据加载失败'), null);
            }
        },
        error: function (xhr, status, error) {
            callback(new Error('请求失败,请稍后重试'), null);
        }
    });
}
/**
 * æž„建查询参数
 * @param {number} page - é¡µç 
 * @param {number} size - æ¯é¡µå¤§å°
 * @returns {Object} æŸ¥è¯¢å‚数对象
 */
function buildQueryParams(page, size) {
    var params = {
        page: page,
        limit: size,
        key: patrolId  //主表id查询
    };
    // æ·»åŠ è¡¨å•æŸ¥è¯¢æ¡ä»¶
    var form = document.getElementById('patrolRecord-form');
    if (form) {
        var inputs = form.querySelectorAll('input[name], select[name]');
        inputs.forEach(function(input) {
            if (input.value) { // åªæ·»åŠ éžç©ºå€¼
                params[input.name] = input.value;
            }
        });
    }
    return params;
}
/**
 * æ›´æ–°å·¡æ£€è®°å½•画廊内容
 * @param {Array} records - å·¡æ£€è®°å½•数据
 */
function updateGallery(records) {
    var container = document.getElementById('gallery-container');
    if (!container) return;
    // æ¸…空现有内容
    container.innerHTML = '';
    if (!records || records.length === 0) {
        // æ˜¾ç¤ºç©ºçŠ¶æ€
        container.innerHTML = `
            <div class="empty-state">
                <i class="fa-solid fa-clipboard-list"></i>
                <h3>暂无巡检记录</h3>
                <p>当前没有可展示的巡检记录数据</p>
            </div>
        `;
        // éšè—åˆ†é¡µ
        $('.pagination-container').hide();
function initMap() {
    // å¯åˆ é™¤ä»£ç å¼€å§‹
    // æ£€æŸ¥ç™¾åº¦åœ°å›¾API是否加载成功
    if (typeof BMapGL === 'undefined') {
        layer.msg("地图加载失败,请检查网络连接!", {icon: 2});
        return;
    }
    // æ˜¾ç¤ºåˆ†é¡µ
    $('.pagination-container').show();
    // æ£€æŸ¥å®¹å™¨æ˜¯å¦å­˜åœ¨
    var mapContainer = document.getElementById("map");
    if (!mapContainer) {
        layer.msg("地图容器未找到!", {icon: 2});
        return;
    }
    // ç”Ÿæˆå·¡æ£€è®°å½•卡片
    var html = '';
    records.forEach(function(record) {
        html += `
            <div class="gallery-item">
                <img src="${record.imgName || '/logo-sm.png'}" alt="${record.id}"
                     data-url="${record.imgName || '/logo-sm.png'}" data-id="${record.id}"
                     class="gallery-img" onclick="showPatrolRecordPreview(this.getAttribute('data-url'))">
                <div class="gallery-info">
                    <div class="gallery-header">
                        <h3 class="gallery-title">${record.pointName || record.id}</h3>
                    <!--
                        <div class="gallery-tags">
                            <span class="tag-person">
                                <i class="layui-icon layui-icon-user"></i>
                                <span>'未知'</span>
                            </span>
                        </div>
                         -->
                    </div>
                    <div class="gallery-meta">
                         <div style="display: flex; align-items: center; gap: 15px;width: 100%">
                             <div class="meta-item" style="width: 50%">
                                <i class="layui-icon layui-icon-location"></i>
                                <span>${record.longitude || ''}</span>
                            </div>
                            <div class="meta-item">
                                <i class="layui-icon layui-icon-location"></i>
                                <span>${record.latitude || ''}</span>
                            </div>
                         </div>
                        <div class="meta-item" style="width: 50%">
                                <i class="layui-icon layui-icon-date"></i>
                                <span>${formatDate(record.createTime)}</span>
                            </div>
                    </div>
    // æ£€æŸ¥æ•°æ®
    if (!patrolRecordList || patrolRecordList.length === 0) {
        layer.msg("暂无轨迹数据!", {icon: 2});
        var defaultPoint = new BMapGL.Point(116.404, 39.915);
        map.centerAndZoom(defaultPoint, 12);
        map.enableScrollWheelZoom(true);
        return;
    }
    //可删除代码结束
    // ========== ç™¾åº¦åœ°å›¾åˆå§‹åŒ–与轨迹渲染 ==========
    // 1. åˆå§‹åŒ–地图
    var map = new BMapGL.Map("map");
    // 2. èŽ·å–è½¨è¿¹ç‚¹æ•°æ®
    if (patrolRecordList.length === 0) {
        layer.msg("暂无轨迹数据!", {icon: 2});
        var defaultPoint = new BMapGL.Point(116.404, 39.915);
        map.centerAndZoom(defaultPoint, 14);
        map.enableScrollWheelZoom(true);
        return;
    }
    // 3. æž„造轨迹点数组和标记点数组
    var points = [];       // è½¨è¿¹æŠ˜çº¿ç‚¹
    var markers = [];      // åœ°å›¾æ ‡è®°ç‚¹
    var cardElements = document.querySelectorAll('.track-card'); // æ‰€æœ‰å¡ç‰‡å…ƒç´ 
    patrolRecordList.forEach(function (record, index) {
        var lng = record.longitude;
        var lat = record.latitude;
        var point = new BMapGL.Point(lng, lat);
        points.push(point);
        // åˆ›å»ºåœ°å›¾æ ‡è®°ç‚¹
        var marker = new BMapGL.Marker(point);
        markers.push(marker);
        // æ ‡è®°ç‚¹å¼¹çª—信息
        var infoWindow = new BMapGL.InfoWindow(`
                <div style="font-size: 12px; line-height: 1.8;">
                    <p><strong>点位名称:</strong>${record.pointName}</p>
                    <p><strong>巡检人:</strong>${record.createBy}</p>
                    <p><strong>巡检时间:</strong>${new Date(record.createTime).toLocaleString()}</p>
                    <p><strong>经纬度:</strong>${lat}, ${lng}</p>
                    <p><strong>轨迹点ID:</strong>${record.id}</p>
                </div>
            </div>
        `;
            `);
        // æ ‡è®°ç‚¹ç‚¹å‡»äº‹ä»¶ï¼šé«˜äº®å¯¹åº”卡片 + æ˜¾ç¤ºå¼¹çª—
        marker.addEventListener("click", function () {
            // ç§»é™¤æ‰€æœ‰å¡ç‰‡çš„active样式
            cardElements.forEach(el => el.classList.remove('active'));
            // é«˜äº®å½“前卡片
            cardElements[index].classList.add('active');
            // æ»šåŠ¨åˆ°å½“å‰å¡ç‰‡
            cardElements[index].scrollIntoView({behavior: 'smooth', block: 'center'});
            // æ˜¾ç¤ºå¼¹çª—
            this.openInfoWindow(infoWindow);
        });
        // å¡ç‰‡ç‚¹å‡»äº‹ä»¶ï¼šå®šä½åˆ°å¯¹åº”标记点 + é«˜äº®å¡ç‰‡
        cardElements[index].addEventListener("click", function () {
            // ç§»é™¤æ‰€æœ‰å¡ç‰‡çš„active样式
            cardElements.forEach(el => el.classList.remove('active'));
            // é«˜äº®å½“前卡片
            this.classList.add('active');
            // åœ°å›¾ä¸­å¿ƒå®šä½åˆ°å½“前标记点
            map.centerAndZoom(point, 15);
            // æ˜¾ç¤ºæ ‡è®°ç‚¹å¼¹çª—
            marker.openInfoWindow(infoWindow);
            // è½»å¾®åŠ¨ç”»æ•ˆæžœ
            marker.setAnimation(BMAP_ANIMATION_BOUNCE);
            setTimeout(() => marker.setAnimation(null), 1500);
        });
        map.addOverlay(marker);
    });
    container.innerHTML = html;
}
    // å¯»æ‰¾points中间的点位
    var midIndex = Math.floor(points.length / 2);
    const centerPoint = points[midIndex] || new BMapGL.Point(116.404, 39.915);
    map.centerAndZoom(centerPoint, 13); // 14为地图缩放级别
/**
 * æ ¼å¼åŒ–日期
 * @param {string|number} date - æ—¥æœŸå­—符串或时间戳
 */
function formatDate(date) {
    if (!date) return '';
    var d = new Date(date);
    return d.getFullYear() + '-' +
        String(d.getMonth() + 1).padStart(2, '0') + '-' +
        String(d.getDate()).padStart(2, '0') + ' ' +
        String(d.getHours()).padStart(2, '0') + ':' +
        String(d.getMinutes()).padStart(2, '0') ;
}
/**
 * åˆå§‹åŒ–图片预览功能
 */
function initImagePreview() {
    var preview = document.getElementById('imgPreview');
    var previewImg = document.getElementById('previewImg');
    var closeBtn = document.getElementById('closePreview');
    // å¦‚果预览元素不存在,则不初始化
    if (!preview || !previewImg) {
        return;
    }
    // å…³é—­æŒ‰é’®ç‚¹å‡»äº‹ä»¶
    if (closeBtn) {
        closeBtn.addEventListener('click', closePreview);
    }
    // ç‚¹å‡»é¢„览区域外关闭
    preview.addEventListener('click', function (e) {
        if (e.target === preview) {
            closePreview();
        }
    // 4. ç»˜åˆ¶è½¨è¿¹æŠ˜çº¿
    var polyline = new BMapGL.Polyline(points, {
        strokeColor: "#1890ff", // ä¸»è‰²è°ƒï¼šè“è‰²
        strokeWeight: 6,        // æŠ˜çº¿å®½åº¦
        strokeOpacity: 0.8,     // é€æ˜Žåº¦
        strokeStyle: 'solid'    // å®žçº¿
    });
    map.addOverlay(polyline);
    // é”®ç›˜äº‹ä»¶ç›‘听
    document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape' && preview.style.display === 'flex') {
            closePreview();
        }
    });
    // // 5. èµ·ç‚¹/终点特殊标记
    // // èµ·ç‚¹æ ‡è®°
    // var startMarker = new BMapGL.Marker(points[0], {
    //     icon: new BMapGL.Icon("http://api.map.baidu.com/img/markers.png", new BMapGL.Size(25, 34), {
    //         offset: new BMapGL.Size(12, 34),
    //         imageOffset: new BMapGL.Size(0, 0) // èµ·ç‚¹å›¾æ ‡
    //     })
    // });
    // map.addOverlay(startMarker);
    // // startMarker.setLabel(new BMapGL.Label("起点:" + patrolRecordList[0].pointName, {
    // //     offset: new BMapGL.Size(30, -15),
    // //     styles: {fontSize: '12px', color: '#fff', background: '#52c41a', padding: '0px 14px', borderRadius: '3px'}
    // // }));
    // startMarker.setLabel(new BMapGL.Label("起点:" + patrolRecordList[0].pointName, {
    //     offset: new BMapGL.Size(30, -15),
    //     styles: {
    //         fontSize: '12px',
    //         color: '#fff',
    //         background: '#52c41a',
    //         padding: '8px 8px',  // å·¦å³padding保持一致(14px),保证背景两侧空间对称
    //         borderRadius: '3px',
    //         textAlign: 'center'  // æ–°å¢žï¼šå¼ºåˆ¶æ–‡å­—在背景内水平居中
    //     }
    // }));
    //
    // // ç»ˆç‚¹æ ‡è®°
    // var endMarker = new BMapGL.Marker(points[points.length - 1], {
    //     icon: new BMapGL.Icon("http://api.map.baidu.com/img/markers.png", new BMapGL.Size(25, 34), {
    //         offset: new BMapGL.Size(12, 34),
    //         imageOffset: new BMapGL.Size(-114, 0) // ç»ˆç‚¹å›¾æ ‡
    //     })
    // });
    // map.addOverlay(endMarker);
    // endMarker.setLabel(new BMapGL.Label("终点:" + patrolRecordList[patrolRecordList.length - 1].pointName, {
    //     offset: new BMapGL.Size(30, -15),
    //     styles: {fontSize: '12px', color: '#fff', background: '#ff4d4f', padding: '0px 14px', borderRadius: '3px'}
    // }));
    // å…³é—­é¢„览函数
    function closePreview() {
        preview.style.display = 'none';
        previewImg.src = '';
    }
}
    // 6. åœ°å›¾è‡ªé€‚应所有轨迹点
    map.enableScrollWheelZoom(true); // å¼€å¯æ»šè½®ç¼©æ”¾
    map.setViewport(points); // é€‚配所有轨迹点
/**
 * æ˜¾ç¤ºå›¾ç‰‡é¢„览
 * @param {string} imgUrl å›¾ç‰‡URL
 */
function showPatrolRecordPreview(imgUrl) {
    var preview = document.getElementById('imgPreview');
    var previewImg = document.getElementById('previewImg');
    if (preview && previewImg) {
        previewImg.src = imgUrl;
        preview.style.display = 'flex';
    }
}
/**
 * è¯»å–巡检记录
 */
function searchRecord(page , size) {
    var pageNumber = 1;
    var sizeNumber = 6;
    if (pageSize && pageSize > 0){
        size = pageSize;
    }
    if (size && size > 0){
        sizeNumber = size;
    }
    if (page && page > 0){
        pageNumber = page;
    }
    // æž„造查询参数,从第一页开始
    var queryParams = buildQueryParams(pageNumber, sizeNumber);
    // æ˜¾ç¤ºloading
    var loadingIndex = layer.load(1, {shade: [0.1, '#fff']});
    // è°ƒç”¨æ•°æ®è¯·æ±‚方法
    fetchPatrolRecordData(queryParams, function(error, data) {
        // å…³é—­loading
        layer.close(loadingIndex);
        if (error) {
            layer.msg(error.message);
            return;
        }
        // æ›´æ–°é¡µé¢æ•°æ®
        updateGallery(data.records);
        // é‡æ–°åˆå§‹åŒ–分页组件
        reinitPagination(data.total, data.size, data.current);
    // 7. åˆå§‹æç¤º
    layer.msg("轨迹加载完成!点击卡片可定位到对应点位", {
        icon: 1,
        time: 3000,
        offset: ['20px', '20px']
    });
}
// é¡µé¢åŠ è½½å®ŒæˆåŽåˆå§‹åŒ–åœ°å›¾
window.onload = initMap;
fzzy-igdss-web/src/main/resources/static/security/video-aerial-dept.js
fzzy-igdss-web/src/main/resources/static/security/video-control.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
/**
 * PTZ å…¬å…±æ–¹æ³•,引用之前需要先定义curCamera对象
 * æ‰§è¡Œå‘½ä»¤ç¼–码
 * äº‘台控制命令 1=上,2=下,3=左,4=右,5=左上,6=左下,7=右上,8=右下,0=停止,9=变倍小,10 = å˜å€åŠ ï¼Œ11 = å˜ç„¦åœ
 * é¢„置位命令 1=设置,2=执行,3=删除
 * æ•°æ®å°†curCamera对象封装为APi å¯¹è±¡å‘送给云平台
 */
function getParam(command, preset) {
    return {
        playType: curCamera.playType,
        ptzType: curCamera.ptzType,
        snapType: curCamera.snapType,
        cameraId: curCamera.id,
        cameraName: curCamera.name,
        ip: curCamera.ip,
        sn: curCamera.sn,
        webPort: curCamera.webPort,
        ctrlPort: curCamera.controlPort,
        channel: curCamera.chanNum,
        loginId: curCamera.loginId,
        pwd: curCamera.pwd,
        mediaAddr: curCamera.mediaAddr,
        urlIn: curCamera.urlIn,
        urlOut: curCamera.urlOut,
        command: command,
        preset: preset
    }
}
//云台控制
function ptzControl(command) {
   // layer.msg('开始调用云台……', {icon: 1, time: 1200,offset:'rb'});
    const param = getParam(command, null);
    const url = "../../basic/security/ptz-media";
    sendControlCommand(url, param);
}
//预置位控制
function presetControl(command) {
    //layer.msg('开始执行……', {icon: 1, time: 1200,offset:'rb'});
    const preset = $("#preset").val();
    const param = getParam(command, preset);
    const url = "../../basic/security/ptz-media";
    sendControlCommand(url, param);
}
//停止移动
function moveStop() {
    //layer.msg('开始调用云台……', {icon: 1, time: 1200,offset:'rb'});
    const param = getParam(0, null);
    const url = "../../basic/security/ptz-media";
    sendControlCommand(url, param);
}
//变焦停
function zoomStop() {
    //doNothing
}
//发送控制命令
function sendControlCommand(url, param) {
    $.ajax({
        type: "POST",
        url: url,
        dataType: 'JSON',
        contentType: "application/json;charset=UTF-8",
        data: JSON.stringify(param),
        success: function (data) {
            if (data.code === "ERROR") {
                layer.msg('执行失败', {icon: 2, time: 1500,offset:'rb'});
            } else {
                layer.msg('执行成功', {icon: 1, time: 1200,offset:'rb'});
            }
        }
    })
}
fzzy-igdss-web/src/main/resources/static/security/video-list-dept.js
ÎļþÃû´Ó fzzy-igdss-web/src/main/resources/static/security/video-list.js ÐÞ¸Ä
@@ -1,4 +1,6 @@
var layer;
var splitWin = 1;  //分屏数,默认1分屏
var windowsNum = 1; //播放窗口下标,手动选择模式下使用
var timer;
var table;
var cameraData;
@@ -23,6 +25,65 @@
});
/**
 * æ’­æ”¾çª—口选中
 * @param win1 åˆ†å±æ•°
 * @param win2 é€‰ä¸­çª—口数
 */
function selectWin(win1,win2) {
    removeSelectCss();
    splitWin = win1;
    windowsNum = win2;
    addSelectCss();
}
/**
 * å޻除选䏭CSS
 */
function removeSelectCss() {
    $("#f" + splitWin + "_d" + windowsNum).removeClass("selectWin");
}
/**
 * å¢žåР选䏭CSS
 */
function addSelectCss() {
    $("#f" + splitWin + "_d" + windowsNum).addClass("selectWin");
}
/**
 * åˆ†å±åˆ‡æ¢
 * @param tagNum  åˆ†å±æ•°
 */
function fenping(tagNum) {
    //切换分屏图标及页面
    if (tagNum == 1) {
        $("#f_1").attr("src", "/img/web/group/fp_1_active.png");
        $("#f_4").attr("src", "/img/web/group/fp_4.png");
        $("#f_9").attr("src", "/img/web/group/fp_9.png");
        $("#video_1").css('display', 'block');
        $("#video_4").css('display', 'none');
        $("#video_9").css('display', 'none');
    }
    if (tagNum == 4) {
        $("#f_1").attr("src", "/img/web/group/fp_1.png");
        $("#f_4").attr("src", "/img/web/group/fp_4_active.png");
        $("#f_9").attr("src", "/img/web/group/fp_9.png");
        $("#video_1").css('display', 'none');
        $("#video_4").css('display', 'block');
        $("#video_9").css('display', 'none');
    }
    if (tagNum == 9) {
        $("#f_1").attr("src", "/img/web/group/fp_1.png");
        $("#f_4").attr("src", "/img/web/group/fp_4.png");
        $("#f_9").attr("src", "/img/web/group/fp_9_active.png");
        $("#video_1").css('display', 'none');
        $("#video_4").css('display', 'none');
        $("#video_9").css('display', 'block');
    }
}
/**
 * ç‚¹å‡»æ’­æ”¾
 * @param cameraId
 */
fzzy-igdss-web/src/main/resources/static/security/video-list.css
@@ -43,7 +43,7 @@
.sp-boxWrap,
.sp-box {
    height: 550px;
    height: 830px;
}
.sp-box {
@@ -321,13 +321,13 @@
}
.sp-bianbei{
    width: 47%;
    width: 60%;
    height: 40px;
    background: #4c5863;
    -webkit-border-radius: 30px;
    border-radius: 30px;
    overflow: hidden;
    margin: 10px 0;
    margin: 10px 0 0 60px;
    text-align: center;
}
fzzy-igdss-web/src/main/resources/templates/security/patrol/add.html
@@ -23,7 +23,7 @@
                <div class="form-group">
                    <label class="col-sm-4 control-label">班次编号:</label>
                    <div class="col-sm-8">
                        <input name="batchId" id="batchId" placeholder="请输入" class="form-control " type="text"
                        <input name="confId" id="confId" placeholder="请输入" class="form-control " type="text"
                               maxlength="30">
                    </div>
                </div>
@@ -34,7 +34,7 @@
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">巡逻人:</label>
                    <div class="col-sm-8">
                        <input name="userName" id="userName" placeholder="请输入" class="form-control " type="text"
                        <input name="userId" id="userId" placeholder="请输入" class="form-control " type="text"
                               maxlength="30" required>
                    </div>
                </div>
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html
@@ -12,7 +12,10 @@
                <div class="select-list">
                    <ul>
                        <li>
                            åç§°ï¼š<input type="text" name="name"/>
                            å·¡é€»äººï¼š<input type="text" name="userName"/>
                        </li>
                        <li>
                            ç­æ¬¡åç§°ï¼š<input type="text" name="confName"/>
                        </li>
                        <li>
                            <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
@@ -24,18 +27,18 @@
        </div>
        <div class="btn-group-sm" id="toolbar" role="group">
            <a class="btn btn-success" onclick="$.operate.add()" >
                <i class="fa fa-plus"></i> æ–°å¢ž
            </a>
            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" >
                <i class="fa fa-edit"></i> ä¿®æ”¹
            </a>
            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" >
                <i class="fa fa-remove"></i> åˆ é™¤
            </a>
            <a class="btn btn-warning" onclick="$.table.exportExcel()" >
                <i class="fa fa-download"></i> å¯¼å‡º
            </a>
<!--            <a class="btn btn-success" onclick="$.operate.add()" >-->
<!--                <i class="fa fa-plus"></i> æ–°å¢ž-->
<!--            </a>-->
<!--            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" >-->
<!--                <i class="fa fa-edit"></i> ä¿®æ”¹-->
<!--            </a>-->
<!--            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" >-->
<!--                <i class="fa fa-remove"></i> åˆ é™¤-->
<!--            </a>-->
<!--            <a class="btn btn-warning" onclick="$.table.exportExcel()" >-->
<!--                <i class="fa fa-download"></i> å¯¼å‡º-->
<!--            </a>-->
            <a class="btn btn-success" onclick="openPatrolConf()" >
                <i class="fa fa-plus"></i> å·¡æ›´é…ç½®
            </a>
@@ -49,7 +52,7 @@
<th:block th:include="include :: select2-js" />
<script th:inline="javascript">
    var prefix = ctx + "security/patrol";
    var deptList = [[${deptList}]];
    $(function() {
        var options = {
@@ -61,6 +64,10 @@
            sortName: "id",
            sortOrder: "asc",
            modalName: "参数",
            showSearch:false,
            showRefresh:false,
            showColumns:false,
            showToggle:false,
            columns: [{
                checkbox: true
            },
@@ -73,13 +80,21 @@
                    field: 'deptId',
                    title: '所属库区',
                    align: 'left',
                    // formatter: function(value, row, index) {
                    //     return $.table.tooltip(value);
                    // }
                    //根据deptList回显诗句
                    formatter: function(value, row, index) {
                        var deptName = '';
                        deptList.forEach(function (item) {
                            if (item.id == value) {
                                deptName = item.kqmc;
                            }
                        })
                        return $.table.tooltip(deptName);
                    }
                },
                {
                    field: 'batchId',
                    title: '班次编号',
                    field: 'confName',
                    title: '班次名称',
                    align: 'left',
                    // formatter: function(value, row, index) {
                    //     return $.table.tooltip(value);
@@ -97,8 +112,8 @@
                    align: 'center',
                    formatter: function(value, row, index) {
                        var actions = [];
                        actions.push('<a class="btn btn-success btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        actions.push('<a class="btn btn-danger btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
                        // actions.push('<a class="btn btn-success btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        // actions.push('<a class="btn btn-danger btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
                        actions.push('<a class="btn btn-info btn-xs '  + '" href="javascript:void(0)" onclick="patrolDetail(\'' + row.id + '\')"><i class="fa fa-list-ul"></i>详情</a> ');
                        return actions.join('');
                    }
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolConf/add.html
@@ -7,14 +7,14 @@
<body>
<div class="main-content">
    <form id="form-patrol-add" class="form-horizontal">
        <input name="deptId" type="hidden" id="treeId"/>
        <input name="userId" type="hidden" id="userId"/>
        <div class="row">
            <div class="col-sm-6">
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">班次名称:</label>
                    <div class="col-sm-8">
                        <input name="batchName" id="batchName" placeholder="请输入" class="form-control " type="text"
                        <input name="name" id="name" placeholder="请输入" class="form-control " type="text"
                               maxlength="30" required>
                    </div>
                </div>
@@ -23,8 +23,30 @@
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">巡逻人:</label>
                    <div class="col-sm-8">
                        <input name="userName" id="userName" placeholder="请输入" class="form-control " type="text"
                               maxlength="30" required>
                        <select name="userName" id="userName" class="form-control select2" multiple required onchange="changeUser(this)">
                            <option value="">请选择巡逻人</option>
                            <option th:each="user : ${userList}" th:value="${user.userName}" th:data-userid="${user.userId}" th:text="${user.userName}"></option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-sm-6">
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">开始时间:</label>
                    <div class="col-sm-8">
                        <input name="start" placeholder="请选择开始时间" data-type="datetime" class="form-control time-input" type="text"
                               required>
                    </div>
                </div>
            </div>
            <div class="col-sm-6">
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">结束时间:</label>
                    <div class="col-sm-8">
                        <input name="end" placeholder="请选择结束时间" data-type="datetime" class="form-control time-input" type="text"
                               required>
                    </div>
                </div>
            </div>
@@ -33,7 +55,7 @@
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: select2-js"/>
<script>
<script type="text/javascript">
    var prefix = ctx + "security/patrol/patrolConf";
    $("#form-cabinet-add").validate({
@@ -50,6 +72,13 @@
        }
    }
    function changeUser(selectElement) {
        var selectedOptions = Array.from(selectElement.selectedOptions);
        var userIds = selectedOptions.map(option => option.getAttribute('data-userid')).filter(id => id);
        var userIdStr = userIds.join(',');
        $("#userId").val(userIdStr);
    }
</script>
</body>
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolConf/edit.html
@@ -7,13 +7,14 @@
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
    <form class="form-horizontal m" id="form-patrol-edit" th:object="${patrolConf}">
        <input id="id" name="id" th:field="*{batchId}" type="hidden">
        <input id="id" name="id" th:field="*{id}" type="hidden">
        <input name="userId" type="hidden"  th:field="*{userId}" id="userId"/>
        <div class="row">
            <div class="col-sm-6">
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">班次名称:</label>
                    <div class="col-sm-8">
                        <input name="batchName" id="batchName" th:field="*{batchName}" placeholder="请输入" class="form-control "
                        <input name="name" id="name" th:field="*{name}" placeholder="请输入" class="form-control "
                               type="text"
                               maxlength="30" required>
                    </div>
@@ -23,9 +24,34 @@
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">巡逻人:</label>
                    <div class="col-sm-8">
                        <input name="userName" id="userName" th:field="*{userName}" placeholder="请输入" class="form-control "
                               type="text"
                               maxlength="30" required>
                        <select name="userName" id="userName" class="form-control select2" multiple required onchange="changeUser(this)">
                            <option value="">请选择巡逻人</option>
                            <option th:each="user : ${userList}"
                                    th:value="${user.userName}"
                                    th:text="${user.userName}"
                                    th:data-userid="${user.userId}"
                                    th:selected="${#strings.contains(patrolConf.userId, user.userId)}"></option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-sm-6">
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">开始时间:</label>
                    <div class="col-sm-8">
                        <input id="start" name="startTime" th:value="*{#dates.format(start, 'yyyy-MM-dd HH:mm:ss')}"   data-type="datetime" placeholder="请选择开始时间" class="form-control time-input" type="text" required>
                    </div>
                </div>
            </div>
            <div class="col-sm-6">
                <div class="form-group">
                    <label class="col-sm-4 control-label is-required">结束时间:</label>
                    <div class="col-sm-8">
                        <input id="end"  name="endTime" th:value="*{#dates.format(end, 'yyyy-MM-dd HH:mm:ss')}" data-type="datetime" placeholder="请选择结束时间" class="form-control time-input" type="text" required>
                    </div>
                </div>
            </div>
@@ -36,7 +62,6 @@
<th:block th:include="include :: footer"/>
<th:block th:include="include :: select2-js"/>
<script type="text/javascript">
    var prefix = ctx + "security/patrol/patrolConf";
@@ -52,6 +77,14 @@
            $.operate.save(prefix + "/edit", $('#form-patrol-edit').serialize());
        }
    }
    function changeUser(selectElement) {
        var selectedOptions = Array.from(selectElement.selectedOptions);
        var userIds = selectedOptions.map(option => option.getAttribute('data-userid')).filter(id => id);
        var userIdStr = userIds.join(',');
        $("#userId").val(userIdStr);
    }
</script>
</body>
</html>
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolConf/patrolConf.html
@@ -7,21 +7,21 @@
<body class="gray-bg">
<div class="container-div">
    <div class="row">
        <div class="col-sm-12 search-collapse">
            <form id="property-form">
                <div class="select-list">
                    <ul>
                        <li>
                            åç§°ï¼š<input type="text" name="name"/>
                        </li>
                        <li>
                            <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
                            <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
                        </li>
                    </ul>
                </div>
            </form>
        </div>
<!--        <div class="col-sm-12 search-collapse">-->
<!--            <form id="property-form">-->
<!--                <div class="select-list">-->
<!--                    <ul>-->
<!--                        <li>-->
<!--                            åç§°ï¼š<input type="text" name="name"/>-->
<!--                        </li>-->
<!--                        <li>-->
<!--                            <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>-->
<!--                            <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>-->
<!--                        </li>-->
<!--                    </ul>-->
<!--                </div>-->
<!--            </form>-->
<!--        </div>-->
        <div class="btn-group-sm" id="toolbar" role="group">
            <a class="btn btn-success" onclick="$.operate.add()" >
@@ -33,9 +33,9 @@
            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" >
                <i class="fa fa-remove"></i> åˆ é™¤
            </a>
            <a class="btn btn-warning" onclick="$.table.exportExcel()" >
                <i class="fa fa-download"></i> å¯¼å‡º
            </a>
<!--            <a class="btn btn-warning" onclick="$.table.exportExcel()" >-->
<!--                <i class="fa fa-download"></i> å¯¼å‡º-->
<!--            </a>-->
        </div>
        <div class="col-sm-12 select-table table-striped">
            <table id="bootstrap-table"></table>
@@ -55,19 +55,23 @@
            updateUrl: prefix + "/edit/{id}",
            removeUrl: prefix + "/remove",
            exportUrl: prefix + "/export",
            sortName: "batchId",
            sortName: "id",
            sortOrder: "asc",
            modalName: "参数",
            showSearch:false,
            showRefresh:false,
            showColumns:false,
            showToggle:false,
            columns: [{
                checkbox: true
            },
                {
                    field: 'batchId',
                    field: 'id',
                    title: '主键',
                    visible: false,
                },
                {
                    field: 'batchName',
                    field: 'name',
                    title: '班次名称',
                    align: 'left',
                    // formatter: function(value, row, index) {
@@ -86,8 +90,8 @@
                    align: 'center',
                    formatter: function(value, row, index) {
                        var actions = [];
                        actions.push('<a class="btn btn-success btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.batchId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        actions.push('<a class="btn btn-danger btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.batchId + '\')"><i class="fa fa-remove"></i>删除</a>');
                        actions.push('<a class="btn btn-success btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        actions.push('<a class="btn btn-danger btn-xs '  + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
                        return actions.join('');
                    }
                }]
fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/patrolRecord.html
@@ -1,132 +1,64 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="renderer" content="webkit">
    <meta charset="UTF-8">
    <title>巡检轨迹展示</title>
    <!-- Layui CSS(用于基础样式) -->
    <th:block th:include="include :: header('巡更记录')"/>
    <link rel="stylesheet" type="text/css" th:href="@{/ajax/libs/layui-ruoyi/css/layui.css}"/>
    <link rel="stylesheet" th:href="@{/security/patrol/patrolRecord-style.css}">
    <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=R3FfyIEbBAWNckTqRSopHQktdkgp924F"></script>
</head>
<body class="gray-bg">
<body>
<div class="container-div">
    <div class="row">
        <div class="col-sm-12 search-collapse"
             style="display: flex; justify-content: space-between; align-items: center;">
            <form id="patrolRecord-form">
                <div class="select-list">
                    <ul>
                        <li>
                            å·¡æ›´ç‚¹ï¼š<input type="text" name="name"/>
                        </li>
                        <li>
                            <a class="btn btn-primary btn-rounded btn-sm" onclick="searchRecord()"><i
                                    class="fa fa-search"></i>&nbsp;搜索</a>
                            <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i
                                    class="fa fa-refresh"></i>&nbsp;重置</a>
                        </li>
                    </ul>
                </div>
            </form>
            <div class="btn-group-sm" role="group">
                <!-- å¦‚果需要添加按钮可以放在这里 -->
                <a class="btn btn-success" onclick="openTrajectoryMap()" >
                    <i class="fa fa-search"></i> è½¨è¿¹å›¾æŸ¥çœ‹
                </a>
        <!-- ç™¾åº¦åœ°å›¾å®¹å™¨ -->
        <div id="map"></div>
        <!-- å³ä¾§è½¨è¿¹å¡ç‰‡æ‚¬æµ®å±‚ -->
        <div class="track-card-panel">
            <div class="panel-title">
                å·¡æ£€è½¨è¿¹ç‚¹
                <span class="count" th:text="'共 ' + ${#lists.size(patrolRecordList)} + ' ä¸ªç‚¹ä½'"></span>
            </div>
        </div>
        <div class="col-sm-12 " style="padding-top: 10px;">
            <!-- å·¡æ£€è®°å½•网格 -->
            <div class="gallery-grid" id="gallery-container">
                <!-- è®°å½•为空时显示 -->
                <div th:if="${#lists.isEmpty(patrolRecordList)}" class="empty-state">
                    <i class="fa-solid fa-clipboard-list"></i>
                    <h3>暂无巡检记录</h3>
                    <p>当前没有可展示的巡检记录数据</p>
            <!-- è½¨è¿¹å¡ç‰‡åˆ—表(Thymeleaf循环渲染) -->
            <div th:each="record,stat : ${patrolRecordList}" class="track-card" data-index="${stat.index}">
                <div class="card-row">
                    <span class="label">序号:</span>
                    <span class="value" th:text="${stat.index + 1}"></span>
                </div>
                <!-- è®°å½•卡片 -->
                <div th:each="patrolRecord : ${patrolRecordList}" class="gallery-item">
                    <img th:src="${patrolRecord.imgName ?: '/logo-sm.png'}" th:alt="${patrolRecord.id}"
                         th:data-url="${patrolRecord.imgName ?: '/logo-sm.png'}" th:data-id="${patrolRecord.id}"
                         class="gallery-img" onclick="showPatrolRecordPreview(this.getAttribute('data-url'))">
                    <div class="gallery-info">
                        <div class="gallery-header">
                            <h3 class="gallery-title" th:text="${patrolRecord.pointName ?: patrolRecord.id}"></h3>
                            <!-- æ ‡ç­¾åˆ—表 -->
<!--                            <div class="gallery-tags">-->
<!--                                <span class="tag-person">-->
<!--                                    <i class="layui-icon layui-icon-user"></i>-->
<!--                                    <span th:text="'未知'"></span>-->
<!--                                </span>-->
<!--                            </div>-->
                        </div>
                        <div class="gallery-meta">
                            <div style="display: flex; align-items: center; gap: 15px;width: 100%">
                                <div class="meta-item" style="width: 50%">
                                    <i class="layui-icon layui-icon-location"></i>
                                    <span th:text="${patrolRecord.longitude ?: ''}"></span>
                                </div>
                                <div class="meta-item" style="width: 50%">
                                    <i class="layui-icon layui-icon-location"></i>
                                    <span th:text="${patrolRecord.latitude ?: ''}"></span>
                                </div>
                            </div>
                            <div class="meta-item" >
                                <i class="layui-icon layui-icon-date"></i>
                                <span th:text="${#dates.format(patrolRecord.createTime, 'yyyy-MM-dd HH:mm')}"></span>
                            </div>
                        </div>
                    </div>
                <div class="card-row">
                    <span class="label">点位名称:</span>
                    <span class="value" th:text="${record.pointName}"></span>
                </div>
            </div>
            <!-- åˆ†é¡µæŽ§ä»¶ -->
            <div class="pagination-container" th:if="${not #lists.isEmpty(patrolRecordList)}">
                <div id="pagination"></div>
            </div>
        </div>
    </div>
    <!-- å›¾ç‰‡é¢„览层 -->
    <div class="img-preview" id="imgPreview">
        <div class="preview-content">
            <img src="" alt="预览图片" class="preview-img" id="previewImg">
            <div class="close-preview" id="closePreview">
                <i class="layui-icon layui-icon-clear"></i>
                <div class="card-row">
                    <span class="label">巡检人:</span>
                    <span class="value" th:text="${record.createBy}"></span>
                </div>
                <div class="card-row">
                    <span class="label">巡检时间:</span>
                    <span class="value" th:text="${#dates.format(record.createTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
                </div>
                <div class="card-row">
                    <span class="label">经纬度:</span>
                    <span class="value" th:text="${record.latitude} + ', ' + ${record.longitude}"></span>
                </div>
                <div class="card-row">
                    <span class="label">轨迹点ID:</span>
                    <span class="value" th:text="${record.id}"></span>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- å¼•å…¥Layui JS -->
<th:block th:include="include :: footer"/>
<script th:src="@{/ajax/libs/layui-ruoyi/layui.js}"></script>
<script th:src="@{/security/patrol/patrolRecord.js}"></script>
<script th:inline="javascript">
    var prefix = ctx + "security/patrol/patrolRecord";
    var currentPage = [[${currentPage}]];
    var totalItems = [[${totalItems}]];
    var pageSize = [[${pageSize}]];
    var patrolId = [[${patrolId}]];
    function openTrajectoryMap() {
        var url = prefix + '/trajectoryMap/'+patrolId ;
        var options = {
            title: "轨迹图",
            width: 500,
            height: 500,
            url: url,
            btn: 0,
            yes: function (index, layero) {
                $.modal.close(index);
            }
        };
        $.modal.openOptions(options);
    }
<script  th:inline="javascript">
    var patrolRecordList = [[${patrolRecordList}]];
</script>
</body>
</html>
</html>
fzzy-igdss-web/src/main/resources/templates/security/video-aerial-dept.html
ÎļþÃû´Ó fzzy-igdss-web/src/main/resources/templates/security/video-aerial.html ÐÞ¸Ä
@@ -67,7 +67,7 @@
<script th:src="@{/common/constant.js}"></script>
<script th:src="@{/common/igds-common.js}"></script>
<script th:src="@{/js/plugins/drag/drag-drop.js}"></script>
<script th:src="@{/security/video-aerial.js}"></script>
<script th:src="@{/security/video-aerial-dept.js}"></script>
<!-- å¼¹å‡ºæ“ä½œæ¡† -->
<div class="layui-tab-content" id="aerialDialog" style="display: none;">
fzzy-igdss-web/src/main/resources/templates/security/video-list-dept.html
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,355 @@
<!DOCTYPE html>
<html lang="zh-cn" xmlns:th=http://www.thymeleaf.org>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="renderer" content="webkit">
    <title>智慧粮库管理平台-监控列表</title>
    <link rel="stylesheet" th:href="@{/ajax/libs/layui/css/layui.css}"/>
    <link rel="stylesheet" th:href="@{/security/video-list.css}">
    <style>
        html, body, .full {
            width: 100%;
            height: 100%;
            overflow-y: hidden;
        }
        .layui-fluid {
            position: relative;
            margin: 0 auto;
            padding: unset;
        }
        .layui-col-space20 {
            margin: unset;
        }
        .layui-col-space20 > * {
            padding: 10px 5px;
        }
        .sp-showItem2 {
            height: 690px;
        }
        .sp-box {
            height: 820px;
        }
        .sp-rl > span {
            line-height: 50px;
            color: #bbc3cd;
            font-size: 20px;
        }
        .sp-table {
            height: 355px;
        }
        .pdgxq-table1 {
            background-color: transparent;
            margin: 0;
        }
        .pdgxq-table1 thead tr th {
            color: #ef344a;
            font-size: 18px;
        }
        .pdgxq-table1 thead tr {
            background: #141C25 !important;
            border-bottom: 1px solid #ef344a;
        }
        .layui-table td, .layui-table th {
            padding: 9px 5px;
        }
        .pdgxq-table1 th, .pdgxq-table1 td {
            text-align: center;
            min-height: 32px;
            line-height: 32px;
            font-size: 14px;
        }
        .pdgxq-table1 tbody tr:nth-child(odd) {
            background-color: #262d33;
        }
        .pdgxq-table1 td em {
            color: #ef344a;
        }
        .layui-table td, .layui-table th {
            padding: 9px 5px;
        }
        .pdgxq-table1 td {
            color: #fff;
            cursor: pointer;
        }
        .fenping_icon {
            position: absolute;
            right: 30px;
            top: 16px;
        }
        .div_v1 {
            width: 99.8%;
            height: 760px;
            float: left;
            background-color: #333;
            text-align: center;
            color: #FFF;
            font-size: 20px;
        }
        .div_v4 {
            width: 49.88%;
            height: 379.5px;
            float: left;
            background-color: #333;
            text-align: center;
            color: #FFF;
            font-size: 20px;
        }
        .div_v9 {
            width: 33.22%;
            height: 252.6px;
            float: left;
            background-color: #333;
            text-align: center;
            color: #FFF;
            font-size: 20px;
        }
        .bor_t_l {
            border-top: 1px solid #777;
            border-left: 1px solid #777;
        }
        .bor_b {
            border-bottom: 1px solid #777;
        }
        .bor_r {
            border-right: 1px solid #777;
        }
        .selectWin {
            border: 1px solid #a52222;
        }
        .video {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body class="pdgxq-body">
<div class="i-container">
    <div class="jmkt-main">
        <div class="layui-fluid">
            <div class="sp-boxWrap layui-row layui-col-space20">
                <div class="layui-col-lg9 layui-col-md9">
                    <div class="pdgxq-m1-left sp-box">
                        <div class="pdgxq-H">
                            <h3>
                                <i></i>视频实时预览
                            </h3>
                            <div class="fenping_icon">
                                <img onclick="fenping(1)" id="f_1" style="width: 30px" th:src="@{/img/web/group/fp_1_active.png}"/>
                                <img onclick="fenping(4)" id="f_4" style="width: 30px" th:src="@{/img/web/group/fp_4.png}"/>
                                <img onclick="fenping(9)" id="f_9" style="width: 30px" th:src="@{/img/web/group/fp_9.png}"/>
                            </div>
                        </div>
                        <div class="sp-tab-db" style="padding: 5px 10px 15px 10px;">
                            <!--一分屏 é»˜è®¤æ˜¾ç¤º-->
                            <div id="video_1" class="right-videoWrap">
                                <div id="f1_d1" onclick="selectWin(1,1)" class="div_v1 bor_t_l bor_b bor_r">
                                    <video class="video" id="video1_1" autoplay="" muted="" playsinline=""></video>
                                </div>
                            </div>
                            <!--四分屏 é»˜è®¤æ˜¾ç¤º-->
                            <div id="video_4" class="right-videoWrap" style="display: none;">
                                <div id="f4_d1" onclick="selectWin(4,1)" class="div_v4 bor_t_l">
                                    <video class="video" id="video4_1" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f4_d2" onclick="selectWin(4,2)" class="div_v4 bor_t_l bor_r">
                                    <video class="video" id="video4_2" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f4_d3" onclick="selectWin(4,3)" class="div_v4 bor_t_l bor_b">
                                    <video class="video" id="video4_3" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f4_d4" onclick="selectWin(4,4)" class="div_v4 bor_t_l bor_b bor_r">
                                    <video class="video" id="video4_4" autoplay="" muted="" playsinline=""></video>
                                </div>
                            </div>
                            <!--九分屏 é»˜è®¤éšè—-->
                            <div id="video_9" class="right-videoWrap" style="display: none;">
                                <div id="f9_d1" onclick="selectWin(9,1)" class="div_v9 bor_t_l">
                                    <video class="video" id="video9_1" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d2" onclick="selectWin(9,2)" class="div_v9 bor_t_l">
                                    <video class="video" id="video9_2" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d3" onclick="selectWin(9,3)" class="div_v9 bor_t_l bor_r">
                                    <video class="video" id="video9_3" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d4" onclick="selectWin(9,4)" class="div_v9 bor_t_l">
                                    <video class="video" id="video9_4" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d5" onclick="selectWin(9,5)" class="div_v9 bor_t_l">
                                    <video class="video" id="video9_5" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d6" onclick="selectWin(9,6)" class="div_v9 bor_t_l bor_r">
                                    <video class="video" id="video9_6" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d7" onclick="selectWin(9,7)" class="div_v9 bor_t_l bor_b">
                                    <video class="video" id="video9_7" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d8" onclick="selectWin(9,8)" class="div_v9 bor_t_l bor_b">
                                    <video class="video" id="video9_8" autoplay="" muted="" playsinline=""></video>
                                </div>
                                <div id="f9_d9" onclick="selectWin(9,9)" class="div_v9 bor_t_l bor_b bor_r">
                                    <video class="video" id="video9_9" autoplay="" muted="" playsinline=""></video>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!--pdgxq-m1-left end-->
                <div class="layui-col-lg3 layui-col-md3">
                    <div class="pdgxq-m1-right sp-box" style="height: 400px">
                        <div class="pdgxq-H">
                            <h3>
                                <i></i>云台控制
                            </h3>
                        </div>
                        <div class="sp-cz-wrap">
                            <div class="sp-cz-box">
                                <ul>
                                    <li class="sp-cz-l1">
                                        <a href="javascript:;" onmousedown="ptzControl(5)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a>
                                    </li>
                                    <li class="sp-cz-l2">
                                        <a href="javascript:;" onmousedown="ptzControl(1)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a>
                                    </li>
                                    <li class="sp-cz-l3">
                                        <a href="javascript:;" onmousedown="ptzControl(7)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a>
                                    </li>
                                    <li class="sp-cz-l4">
                                        <a href="javascript:;" onmousedown="ptzControl(3)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a>
                                    </li>
                                    <li class="sp-cz-l5">
                                        <a href="javascript:;">
                                        </a>
                                    </li>
                                    <li class="sp-cz-l6">
                                        <a href="javascript:;" onmousedown="ptzControl(4)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a>
                                    </li>
                                    <li class="sp-cz-l7">
                                        <a href="javascript:;" onmousedown="ptzControl(6)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a>
                                    </li>
                                    <li class="sp-cz-l8">
                                        <a href="javascript:;" onmousedown="ptzControl(2)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a></li>
                                    <li class="sp-cz-l9">
                                        <a href="javascript:;" onmousedown="ptzControl(8)"
                                           onmouseup="moveStop()">
                                            <img th:src="@{/img/web/security/sp-arrow.png}"/>
                                        </a></li>
                                </ul>
                            </div>
                            <div class="sp-bianbei fl">
                                <button type="button" class="sp-sxBtn sp-czBtn" onmousedown="ptzControl(9)" onmouseup="zoomStop()">
                                    <i>-</i>
                                </button>
                                <span>变焦</span>
                                <button type="button" class="sp-fdBtn sp-czBtn" onmousedown="ptzControl(10)" onmouseup="zoomStop()">
                                    <i>+</i>
                                </button>
                            </div>
                        </div>
                    </div>
                    <div class="pdgxq-m1-right sp-box" style="height: 410px;margin-top: 10px">
                        <div class="pdgxq-H">
                            <h3>
                                <i></i>设备列表
                            </h3>
                        </div>
                        <div class="sp-table-box">
                            <div class="sp-table">
                                <table class="layui-table pdgxq-table1" lay-skin="nob">
                                    <colgroup>
                                        <col width="70%">
                                        <col width="15%">
                                        <col width="15%">
                                    </colgroup>
                                    <thead>
                                    <tr>
                                        <th>名称</th>
                                        <th>类型</th>
                                        <th>状态</th>
                                    </tr>
                                    </thead>
                                    <tbody id="cameraList">
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
                <!--pdgxq-m1-left end-->
            </div>
            <!--sp-boxWrap end-->
        </div>
    </div>
    <!--jmkt-main end-->
</div>
<!--i-container end-->
<script th:inline="javascript">
    var listCamera = [[${listCamera}]];
</script>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/ajax/libs/layui/layui.js}"></script>
<script th:src="@{/common/constant.js}"></script>
<script th:src="@{/security/video-list-dept.js}"></script>
<script th:src="@{/security/video-control.js}"></script>
</body>
</html>
fzzy-igdss-web/src/main/resources/templates/security/video-list.html
ÎļþÒÑɾ³ý