sgj
8 天以前 1bec05ea1679112d4a722943d557f7f48d529d2e
智能抓拍页面修改
已删除2个文件
已修改1个文件
已添加5个文件
980 ■■■■ 文件已修改
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/SnapRecordService.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/SnapRecord.view.xml 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-view/src/main/java/com/fzzy/igds/SnapRecordPR.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/snapRecord/SnapRecordController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/snapRecord/SnapRecordManager.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/snapRecord/snapRecord-style.css 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/static/snapRecord/snapRecord.js 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-web/src/main/resources/templates/snapRecord/snapRecord.html 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
fzzy-igdss-core/src/main/java/com/fzzy/igds/service/SnapRecordService.java
@@ -1,6 +1,7 @@
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.SnapRecord;
@@ -21,6 +22,36 @@
    @Resource
    private SnapRecordMapper snapRecordMapper;
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•°æ®
     *
     * @param page
     * @param param
     */
    public void listPage(Page<SnapRecord> page, IgdsBaseParam param) {
        QueryWrapper<SnapRecord> queryWrapper = getQueryWrapper(param);
        snapRecordMapper.selectPage(page, queryWrapper);
    }
    /**
     * å°è£…查询条件
     *
     * @param param
     */
    public QueryWrapper<SnapRecord> getQueryWrapper(IgdsBaseParam param) {
        QueryWrapper<SnapRecord> queryWrapper = new QueryWrapper<>();
        param.setCompanyId(ContextUtil.getCompanyId());
        queryWrapper.eq("company_id", param.getCompanyId());
        if (StringUtils.isNotBlank(param.getDeptId())) {
            queryWrapper.eq("dept_id", param.getDeptId());
        }
        queryWrapper.orderByDesc("create_time");
        return queryWrapper;
    }
    public List<SnapRecord> listAll(IgdsBaseParam param) {
        if (null == param)
fzzy-igdss-view/src/main/java/com/fzzy/igds/SnapRecord.view.xml
ÎļþÒÑɾ³ý
fzzy-igdss-view/src/main/java/com/fzzy/igds/SnapRecordPR.java
ÎļþÒÑɾ³ý
fzzy-igdss-web/src/main/java/com/fzzy/sys/controller/snapRecord/SnapRecordController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,60 @@
package com.fzzy.sys.controller.snapRecord;
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.SnapRecord;
import com.fzzy.sys.manager.snapRecord.SnapRecordManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
@Slf4j
@Controller
@RequestMapping("/snapRecord")
public class SnapRecordController {
    private static final String prefix = "snapRecord";
    @Resource
    private SnapRecordManager snapRecordManager;
    @GetMapping
    public String getSnapRecord(
            Model model) {
        IgdsBaseParam param = new IgdsBaseParam();
        param.setPage(1);
        param.setLimit(6);
        Page<SnapRecord> images = snapRecordManager.pageData(param);
        model.addAttribute("snapRecordList", images.getRecords());
        model.addAttribute("currentPage", images.getCurrent());
        model.addAttribute("totalItems", images.getTotal());
        model.addAttribute("pageSize", images.getSize());
        return prefix + "/snapRecord";
    }
    /**
     * åˆ†é¡µèŽ·å–æ•°æ®
     *
     * @param param
     * @return
     */
    @RequestMapping("/pageData")
    @ResponseBody
    public PageResponse<Page<SnapRecord>> pageData(@RequestBody IgdsBaseParam param) {
        Page<SnapRecord> snapRecordPage = snapRecordManager.pageData(param);
        if (null == snapRecordPage.getRecords() || snapRecordPage.getRecords().isEmpty()) {
            return new PageResponse<>(RespCodeEnum.CODE_2000.getCode(), "获取到数据信息为空");
        }
        return new PageResponse<>(RespCodeEnum.CODE_0000, snapRecordPage);
    }
}
fzzy-igdss-web/src/main/java/com/fzzy/sys/manager/snapRecord/SnapRecordManager.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.fzzy.sys.manager.snapRecord;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fzzy.igds.data.IgdsBaseParam;
import com.fzzy.igds.domain.SnapRecord;
import com.fzzy.igds.service.SnapRecordService;
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;
@Slf4j
@Component
public class SnapRecordManager {
    @Resource
    private SnapRecordService snapRecordService;
    /**
     * åˆ†é¡µæŸ¥è¯¢æ•°æ®
     *
     * @param param
     * @return
     */
    public Page<SnapRecord> pageData(IgdsBaseParam param) {
        if (StringUtils.isEmpty(param.getCompanyId())) {
            param.setCompanyId(ContextUtil.getCompanyId());
        }
        Page<SnapRecord> corePage = new Page<>(param.getPage(), param.getLimit());
        snapRecordService.listPage(corePage, param);
        if (null == corePage.getRecords() || corePage.getRecords().isEmpty()) {
            return corePage.setRecords(new ArrayList<>());
        }
        return corePage;
    }
}
fzzy-igdss-web/src/main/resources/static/snapRecord/snapRecord-style.css
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
/* å›¾ç‰‡é¢„览层样式 */
.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: 15px;
}
.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: 195px;
    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;
    /*gap: 8px;*/
    /*margin: 12px 0;*/
}
/* åˆ†é¡µæ ·å¼ */
.pagination-container {
    display: flex;
    justify-content: center;
    /*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;
    }
}
fzzy-igdss-web/src/main/resources/static/snapRecord/snapRecord.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,278 @@
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: ['count', '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: ['count', 'prev', 'page', 'next', 'refresh', 'skip'],
        jump: function (obj, first) {
            if (!first) {
                searchRecord(obj.curr, obj.limit)
            }
        }
    });
}
/**
 * èŽ·å–æŠ“æ‹è®°å½•æ•°æ®
 * @param {Object} params - æŸ¥è¯¢å‚数对象
 * @param {Function} callback - å›žè°ƒå‡½æ•°
 */
function fetchSnapRecordData(params, callback) {
    $.ajax({
        url: '../../snapRecord/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
    };
    // æ·»åŠ è¡¨å•æŸ¥è¯¢æ¡ä»¶
    var form = document.getElementById('snapRecord-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-camera-slash"></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="/logo-sm.png" alt="${record.id}"
                     data-url="/logo-sm.png" data-id="${record.id}"
                     class="gallery-img" onclick="showSnapRecordPreview(this.getAttribute('data-url'))">
                <div class="gallery-info">
                    <div class="gallery-header">
                        <h3 class="gallery-title">${record.id}</h3>
                    </div>
                    <div class="gallery-meta">
                        <div class="meta-item">
                            <i class="layui-icon layui-icon-home"></i>
                            <span>${record.deptId || ''}</span>
                        </div>
                        <div class="meta-item">
                            <i class="layui-icon layui-icon-video"></i>
                            <span>${record.cameraId || ''}</span>
                        </div>
                        <div class="meta-item">
                            <i class="layui-icon layui-icon-date"></i>
                            <span>${formatDate(record.snapTime)}</span>
                        </div>
                    </div>
                    <div class="gallery-tags">
                        <span class="tag-person">
                            <i class="layui-icon layui-icon-face-smile"></i>
                            <span>测试标签</span>
                        </span>
                    </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') + ':' +
        String(d.getSeconds()).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 showSnapRecordPreview(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']});
    // è°ƒç”¨æ•°æ®è¯·æ±‚方法
    fetchSnapRecordData(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);
    });
}
fzzy-igdss-web/src/main/resources/templates/snapRecord/snapRecord.html
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,105 @@
<!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="@{/snapRecord/snapRecord-style.css}">
</head>
<body class="gray-bg">
<div class="container-div">
    <div class="row">
        <div class="col-sm-12 search-collapse">
            <form id="snapRecord-form">
                <div class="select-list">
                    <ul>
                        <li>
                            æ‰€å±žä»“库:<input type="text" name="deptId"/>
                        </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>
        <div class="col-sm-12 " style="padding-top: 10px;">
            <!-- å›¾ç‰‡ç½‘æ ¼ -->
            <div class="gallery-grid" id="gallery-container">
                <!-- å›¾ç‰‡ä¸ºç©ºæ—¶æ˜¾ç¤º -->
                <div th:if="${#lists.isEmpty(snapRecordList)}" class="empty-state">
                    <i class="fa-solid fa-camera-slash"></i>
                    <h3>暂无抓拍记录</h3>
                    <p>当前没有可展示的抓拍记录数据</p>
                </div>
                <!-- å›¾ç‰‡å¡ç‰‡ -->
                <div th:each="snapRecord : ${snapRecordList}" class="gallery-item">
<!--                    <img th:src="${snapRecord.imgPath}" th:alt="${snapRecord.id}"-->
<!--                         th:data-url="${snapRecord.imgPath}" th:data-id="${snapRecord.id}"-->
                    <img th:src="@{/logo-sm.png}" th:alt="${snapRecord.id}"
                         th:data-url="@{/logo-sm.png}" th:data-id="${snapRecord.id}"
                         class="gallery-img" onclick="showSnapRecordPreview(this.getAttribute('data-url'))">
                    <div class="gallery-info">
                        <div class="gallery-header">
                            <h3 class="gallery-title" th:text="${snapRecord.id}"></h3>
                        </div>
                        <div class="gallery-meta">
                            <div class="meta-item">
                                <i class="layui-icon layui-icon-home"></i>
                                <span th:text="${snapRecord.deptId}"></span>
                            </div>
                            <div class="meta-item">
                                <i class="layui-icon layui-icon-video"></i>
                                <span th:text="${snapRecord.cameraId}"></span>
                            </div>
                            <div class="meta-item">
                                <i class="layui-icon layui-icon-date"></i>
                                <span th:text="${#dates.format(snapRecord.snapTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
                            </div>
                        </div>
                        <!-- æ ‡ç­¾åˆ—表 -->
                        <div class="gallery-tags">
                            <span class="tag-person">
                                <i class="layui-icon layui-icon-face-smile"></i>
                                <span>测试标签</span>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
            <!-- åˆ†é¡µæŽ§ä»¶ -->
            <div class="pagination-container" th:if="${not #lists.isEmpty(snapRecordList)}">
                <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="@{/snapRecord/snapRecord.js}"></script>
<script th:inline="javascript">
    var currentPage = [[${currentPage}]];
    var totalItems = [[${totalItems}]];
    var pageSize = [[${pageSize}]];
</script>
</body>
</html>