From 1e0b151f8e1fab091fbc24051baefc33fa677052 Mon Sep 17 00:00:00 2001
From: sgj <1442489573@qq.com>
Date: 星期三, 10 十二月 2025 11:17:56 +0800
Subject: [PATCH] 电子巡更,巡更详情,巡更轨迹图添加

---
 fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/trajectoryMap.html |   72 ++++
 fzzy-igdss-web/src/main/resources/static/security/snap/snapRecord.js                        |    5 
 fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord-style.css             |  203 ++++++++++++
 fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html                     |    7 
 fzzy-igdss-web/src/main/resources/templates/security/snap/snapRecord/snapRecord.html        |    4 
 fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/security/PatrolRecordManager.java         |   50 +++
 fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolRecord.java                        |    6 
 fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord.js                    |  281 +++++++++++++++++
 fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/patrolRecord.html  |  132 ++++++++
 fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolRecordController.java   |   72 ++++
 fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolRecordService.java                |   84 +++++
 fzzy-igdss-web/src/main/resources/static/security/eventInfo/eventInfo.js                    |    3 
 fzzy-igdss-web/src/main/resources/templates/security/eventInfo/eventInfo.html               |    2 
 13 files changed, 909 insertions(+), 12 deletions(-)

diff --git a/fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolRecord.java b/fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolRecord.java
index d2a61c2..d5db741 100644
--- a/fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolRecord.java
+++ b/fzzy-igdss-core/src/main/java/com/fzzy/igds/domain/PatrolRecord.java
@@ -42,11 +42,6 @@
     @TableField("point_name")
     private String pointName;
 
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
-    @Column(name = "create_time", columnDefinition = "datetime COMMENT '宸¢�绘椂闂�'")
-    @TableField("create_time")
-    private Date createTime;
-
     @Column(name = "longitude", columnDefinition = "decimal(20,6) COMMENT '缁忓害'")
     @TableField("longitude")
     private String longitude;
@@ -68,6 +63,7 @@
 
     //宸℃洿鐓х墖鍏ㄨ矾寰�
     @Transient
+    @TableField(exist = false)
     private String imgPath;
 
 }
diff --git a/fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolRecordService.java b/fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolRecordService.java
new file mode 100644
index 0000000..c9c1e50
--- /dev/null
+++ b/fzzy-igdss-core/src/main/java/com/fzzy/igds/service/PatrolRecordService.java
@@ -0,0 +1,84 @@
+package com.fzzy.igds.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fzzy.igds.data.BaseResp;
+import com.fzzy.igds.data.IgdsBaseParam;
+import com.fzzy.igds.domain.PatrolRecord;
+import com.fzzy.igds.mapper.PatrolRecordMapper;
+import com.fzzy.igds.utils.ContextUtil;
+import com.ruoyi.common.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+@Service
+public class PatrolRecordService {
+
+    @Resource
+    private PatrolRecordMapper patrolRecordMapper;
+
+    /**
+     * 鍒嗛〉鏌ヨ鏁版嵁
+     *
+     * @param page
+     * @param param
+     */
+    public void listPage(Page<PatrolRecord> page, IgdsBaseParam param) {
+        QueryWrapper<PatrolRecord> queryWrapper = getQueryWrapper(param);
+        patrolRecordMapper.selectPage(page, queryWrapper);
+    }
+
+    public List<PatrolRecord> listAll(IgdsBaseParam param) {
+        QueryWrapper<PatrolRecord> queryWrapper = getQueryWrapper(param);
+        return patrolRecordMapper.selectList(queryWrapper);
+    }
+
+    /**
+     * 灏佽鏌ヨ鏉′欢
+     *
+     * @param param
+     */
+    public QueryWrapper<PatrolRecord> getQueryWrapper(IgdsBaseParam param) {
+        QueryWrapper<PatrolRecord> queryWrapper = new QueryWrapper<>();
+
+        param.setCompanyId(ContextUtil.getCompanyId());
+        queryWrapper.eq("company_id", param.getCompanyId());
+
+        if (StringUtils.isNotBlank(param.getName())) {
+            queryWrapper.eq("point_name", param.getName());
+        }
+        if (StringUtils.isNotBlank(param.getKey())) {
+            queryWrapper.eq("patrol_id", param.getKey());
+        }
+        queryWrapper.orderByDesc("id");
+
+        return queryWrapper;
+    }
+
+
+
+    public BaseResp addData(PatrolRecord patrolRecord) {
+        patrolRecord.setId(ContextUtil.generateId());
+        patrolRecord.setCompanyId(ContextUtil.getCompanyId());
+        patrolRecord.setUpdateBy(ContextUtil.getLoginUserName());
+        patrolRecord.setUpdateTime(new Date());
+        patrolRecord.setCreateBy(ContextUtil.getLoginUserName());
+        patrolRecord.setCreateTime(new Date());
+        return patrolRecordMapper.insert(patrolRecord) > 0 ? BaseResp.success() : BaseResp.error("娣诲姞澶辫触");
+    }
+
+    public BaseResp updateData(PatrolRecord patrolRecord) {
+        patrolRecord.setUpdateBy(ContextUtil.getLoginUserName());
+        patrolRecord.setUpdateTime(new Date());
+        return patrolRecordMapper.updateById(patrolRecord) > 0 ? BaseResp.success() : BaseResp.error("鏇存柊澶辫触");
+    }
+
+    public BaseResp deleteData(PatrolRecord patrolRecord) {
+        return patrolRecordMapper.deleteById(patrolRecord) > 0 ? BaseResp.success() : BaseResp.error("鍒犻櫎澶辫触");
+    }
+}
diff --git a/fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolRecordController.java b/fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolRecordController.java
new file mode 100644
index 0000000..bcf10d3
--- /dev/null
+++ b/fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/security/PatrolRecordController.java
@@ -0,0 +1,72 @@
+package com.fzzy.sys.controller.security;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fzzy.igds.constant.RespCodeEnum;
+import com.fzzy.igds.data.IgdsBaseParam;
+import com.fzzy.igds.data.PageResponse;
+import com.fzzy.igds.domain.PatrolRecord;
+import com.fzzy.sys.manager.security.PatrolRecordManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Slf4j
+@Controller
+@RequestMapping("/security/patrol/patrolRecord")
+public class PatrolRecordController {
+
+    private static final String prefix = "security/patrol/patrolRecord";
+
+    @Resource
+    private PatrolRecordManager patrolRecordManager;
+
+
+    @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";
+    }
+
+    /**
+     * 鍒嗛〉鑾峰彇鏁版嵁
+     *
+     * @param param
+     * @return
+     */
+    @RequestMapping("/pageData")
+    @ResponseBody
+    public PageResponse<Page<PatrolRecord>> pageData(@RequestBody IgdsBaseParam param) {
+        Page<PatrolRecord> patrolRecordPage = patrolRecordManager.pageData(param);
+        if (null == patrolRecordPage.getRecords() || patrolRecordPage.getRecords().isEmpty()) {
+            return new PageResponse<>(RespCodeEnum.CODE_2000.getCode(), "鑾峰彇鍒版暟鎹俊鎭负绌�");
+        }
+        return new PageResponse<>(RespCodeEnum.CODE_0000, patrolRecordPage);
+    }
+}
diff --git a/fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/security/PatrolRecordManager.java b/fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/security/PatrolRecordManager.java
new file mode 100644
index 0000000..a246799
--- /dev/null
+++ b/fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/security/PatrolRecordManager.java
@@ -0,0 +1,50 @@
+package com.fzzy.sys.manager.security;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fzzy.igds.data.IgdsBaseParam;
+import com.fzzy.igds.domain.PatrolRecord;
+import com.fzzy.igds.service.PatrolRecordService;
+import com.fzzy.igds.utils.ContextUtil;
+import com.ruoyi.common.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Component
+public class PatrolRecordManager {
+
+    @Resource
+    private PatrolRecordService patrolRecordService;
+
+    /**
+     * 鍒嗛〉鏌ヨ鏁版嵁
+     *
+     * @param param
+     * @return
+     */
+    public Page<PatrolRecord> pageData(IgdsBaseParam param) {
+        if (StringUtils.isEmpty(param.getCompanyId())) {
+            param.setCompanyId(ContextUtil.getCompanyId());
+        }
+
+        Page<PatrolRecord> corePage = new Page<>(param.getPage(), param.getLimit());
+        patrolRecordService.listPage(corePage, param);
+
+        if (null == corePage.getRecords() || corePage.getRecords().isEmpty()) {
+            return corePage.setRecords(new ArrayList<>());
+        }
+
+        return corePage;
+    }
+    public List<PatrolRecord> listAll(IgdsBaseParam param) {
+        if (StringUtils.isEmpty(param.getCompanyId())) {
+            param.setCompanyId(ContextUtil.getCompanyId());
+        }
+
+        return patrolRecordService.listAll(param);
+    }
+}
diff --git a/fzzy-igdss-web/src/main/resources/static/security/eventInfo/eventInfo.js b/fzzy-igdss-web/src/main/resources/static/security/eventInfo/eventInfo.js
index 6421a2c..24a1a58 100644
--- a/fzzy-igdss-web/src/main/resources/static/security/eventInfo/eventInfo.js
+++ b/fzzy-igdss-web/src/main/resources/static/security/eventInfo/eventInfo.js
@@ -195,8 +195,7 @@
         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') + ':' +
-        String(d.getSeconds()).padStart(2, '0');
+        String(d.getMinutes()).padStart(2, '0') ;
 }
 
 /**
diff --git a/fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord-style.css b/fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord-style.css
new file mode 100644
index 0000000..268a484
--- /dev/null
+++ b/fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord-style.css
@@ -0,0 +1,203 @@
+/* 鍥剧墖棰勮灞傛牱寮� */
+.img-preview {
+    display: none;
+    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;
+}
+
+.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;
+    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 {
+    padding: 15px;
+}
+
+.gallery-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 10px;
+}
+
+.gallery-title {
+    font-size: 1.5rem;
+    font-weight: 600;
+    color: #333;
+    margin: 0;
+    flex: 1;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.gallery-meta {
+    display: flex;
+    flex-direction: column;
+    gap: 2px;
+}
+
+.meta-item {
+    display: flex;
+    align-items: center;
+    font-size: 1.3rem;
+    color: #666;
+}
+
+.meta-item i {
+    width: 16px;
+    margin-right: 6px;
+    color: #999;
+    font-size: 1.25rem;
+}
+
+.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;
+    }
+
+}
\ No newline at end of file
diff --git a/fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord.js b/fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord.js
new file mode 100644
index 0000000..a5d57e7
--- /dev/null
+++ b/fzzy-igdss-web/src/main/resources/static/security/patrol/patrolRecord.js
@@ -0,0 +1,281 @@
+var layer;
+var laypage;
+
+$(function () {
+    // 鍒濆鍖栧垎椤�
+    layui.use(['laypage', '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();
+        return;
+    }
+
+    // 鏄剧ず鍒嗛〉
+    $('.pagination-container').show();
+
+    // 鐢熸垚宸℃璁板綍鍗$墖
+    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>        
+                </div>
+            </div>
+        `;
+    });
+
+    container.innerHTML = html;
+}
+
+/**
+ * 鏍煎紡鍖栨棩鏈�
+ * @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();
+        }
+    });
+
+    // 閿洏浜嬩欢鐩戝惉
+    document.addEventListener('keydown', function (e) {
+        if (e.key === 'Escape' && preview.style.display === 'flex') {
+            closePreview();
+        }
+    });
+
+    // 鍏抽棴棰勮鍑芥暟
+    function closePreview() {
+        preview.style.display = 'none';
+        previewImg.src = '';
+    }
+}
+
+/**
+ * 鏄剧ず鍥剧墖棰勮
+ * @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);
+    });
+}
diff --git a/fzzy-igdss-web/src/main/resources/static/security/snap/snapRecord.js b/fzzy-igdss-web/src/main/resources/static/security/snap/snapRecord.js
index 9d7f6b4..3152a96 100644
--- a/fzzy-igdss-web/src/main/resources/static/security/snap/snapRecord.js
+++ b/fzzy-igdss-web/src/main/resources/static/security/snap/snapRecord.js
@@ -194,8 +194,9 @@
         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') + ':' +
-        String(d.getSeconds()).padStart(2, '0');
+        String(d.getMinutes()).padStart(2, '0')
+        // + ':' +
+        // String(d.getSeconds()).padStart(2, '0');
 }
 
 /**
diff --git a/fzzy-igdss-web/src/main/resources/templates/security/eventInfo/eventInfo.html b/fzzy-igdss-web/src/main/resources/templates/security/eventInfo/eventInfo.html
index 6181a3f..a85257a 100644
--- a/fzzy-igdss-web/src/main/resources/templates/security/eventInfo/eventInfo.html
+++ b/fzzy-igdss-web/src/main/resources/templates/security/eventInfo/eventInfo.html
@@ -80,7 +80,7 @@
                                 </div>
                                 <div class="meta-item" style="width: 50%">
                                     <i class="layui-icon layui-icon-date"></i>
-                                    <span th:text="${#dates.format(eventInfo.time, 'yyyy-MM-dd HH:mm:ss')}"></span>
+                                    <span th:text="${#dates.format(eventInfo.time, 'yyyy-MM-dd HH:mm')}"></span>
                                 </div>
                             </div>
                             <div class="meta-item">
diff --git a/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html b/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html
index d95056b..99cf153 100644
--- a/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html
+++ b/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrol.html
@@ -99,6 +99,7 @@
                         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-info btn-xs '  + '" href="javascript:void(0)" onclick="patrolDetail(\'' + row.id + '\')"><i class="fa fa-list-ul"></i>璇︽儏</a> ');
                         return actions.join('');
                     }
                 }]
@@ -106,6 +107,12 @@
         $.table.init(options);
     });
 
+    /*璇︽儏*/
+    function patrolDetail(patrolId) {
+        var url = prefix + '/patrolRecord/' + patrolId;
+        $.modal.openTab("宸℃洿璇︽儏", url);
+    }
+
     function openPatrolConf() {
         var url = ctx + "security/patrol/patrolConf";
         $.modal.openTab("宸℃洿閰嶇疆", url);
diff --git a/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/patrolRecord.html b/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/patrolRecord.html
new file mode 100644
index 0000000..e178b82
--- /dev/null
+++ b/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/patrolRecord.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<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">
+    <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}">
+</head>
+<body class="gray-bg">
+<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>
+        </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>
+                </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>
+            </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>
+        </div>
+    </div>
+</div>
+<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>
+
+</body>
+</html>
diff --git a/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/trajectoryMap.html b/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/trajectoryMap.html
new file mode 100644
index 0000000..33effe3
--- /dev/null
+++ b/fzzy-igdss-web/src/main/resources/templates/security/patrol/patrolRecord/trajectoryMap.html
@@ -0,0 +1,72 @@
+<!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">
+    <th:block th:include="include :: header('杞ㄨ抗鍥惧睍绀�')"/>
+    <!-- 鐧惧害鍦板浘API -->
+    <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=R3FfyIEbBAWNckTqRSopHQktdkgp924F"></script>
+</head>
+<body>
+<!-- 鍦板浘瀹瑰櫒 -->
+<div class="container-div" id="map-container">
+</div>
+<th:block th:include="include :: footer"/>
+<script th:inline="javascript">
+    // 1. 鑾峰彇鍚庣浼犻�掔殑杞ㄨ抗鏁版嵁
+    const trackPoints = [[${trackPoints}]];
+    // 杞崲涓虹櫨搴﹀湴鍥惧潗鏍囨暟缁�
+    const path = trackPoints.map(point => new BMapGL.Point(point.longitude, point.latitude));
+
+    // 2. 鍒濆鍖栧湴鍥�
+    function initMap() {
+        // 鍒涘缓鍦板浘瀹炰緥锛屼腑蹇冪偣璁句负绗竴涓建杩圭偣
+        const map = new BMapGL.Map("map-container");
+        const centerPoint = path[0] || new BMapGL.Point(116.404, 39.915);
+        map.centerAndZoom(centerPoint, 14); // 14涓哄湴鍥剧缉鏀剧骇鍒�
+        map.enableScrollWheelZoom(true); // 寮�鍚紶鏍囨粴杞缉鏀�
+
+        // 3. 娣诲姞杞ㄨ抗绾�
+        const polyline = new BMapGL.Polyline(path, {
+            strokeColor: "#3388ff", // 绾块鑹�
+            strokeWeight: 5, // 绾垮搴�
+            strokeOpacity: 0.8 // 绾块�忔槑搴�
+        });
+        map.addOverlay(polyline);
+
+        // 4. 涓烘瘡涓建杩圭偣娣诲姞鏍囪鍜屼俊鎭獥鍙�
+        trackPoints.forEach((point, index) => {
+            const markerPoint = new BMapGL.Point(point.longitude, point.latitude);
+            // 鍒涘缓鏍囪
+            const marker = new BMapGL.Marker(markerPoint);
+            map.addOverlay(marker);
+
+            // 鍒涘缓淇℃伅绐楀彛鍐呭
+            const infoWindow = new BMapGL.InfoWindow(`
+                    <div style="font-size:14px;">
+                        <p>搴忓彿锛�${index + 1}</p>
+                        <p>缁忓害锛�${point.longitude}</p>
+                        <p>绾害锛�${point.latitude}</p>
+                        <p>鏃堕棿锛�${point.createTime}</p>
+                    </div>
+                `);
+
+            // 鐐瑰嚮鏍囪鏄剧ず淇℃伅绐楀彛
+            marker.addEventListener("click", () => {
+                map.openInfoWindow(infoWindow, markerPoint);
+            });
+        });
+
+        // 5. 璋冩暣鍦板浘瑙嗛噹浠ユ樉绀烘暣涓建杩�
+        if (path.length > 1) {
+            map.setViewport(path); // 鑷姩閫傞厤杞ㄨ抗鑼冨洿
+        }
+    }
+
+    // 椤甸潰鍔犺浇瀹屾垚鍚庡垵濮嬪寲鍦板浘
+    window.onload = initMap;
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/fzzy-igdss-web/src/main/resources/templates/security/snap/snapRecord/snapRecord.html b/fzzy-igdss-web/src/main/resources/templates/security/snap/snapRecord/snapRecord.html
index cc3d037..28689e1 100644
--- a/fzzy-igdss-web/src/main/resources/templates/security/snap/snapRecord/snapRecord.html
+++ b/fzzy-igdss-web/src/main/resources/templates/security/snap/snapRecord/snapRecord.html
@@ -30,7 +30,7 @@
                 </div>
             </form>
             <div class="btn-group-sm" role="group">
-                <a class="btn btn-success" onclick="openConf()" shiro:hasPermission="web:security:snap:snapRecord:view">
+                <a class="btn btn-success" onclick="openConf()">
                     <i class="fa fa-plus"></i> 鎶撴媿閰嶇疆
                 </a>
             </div>
@@ -79,7 +79,7 @@
                                 </div>
                                 <div class="meta-item" style="width: 50%">
                                     <i class="layui-icon layui-icon-date"></i>
-                                    <span th:text="${#dates.format(snapRecord.snapTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
+                                    <span th:text="${#dates.format(snapRecord.snapTime, 'yyyy-MM-dd HH:mm')}"></span>
                                 </div>
                             </div>
                             <div class="meta-item">

--
Gitblit v1.9.3