日常开发20251022,传统HTML表格实现图片+视频+预览

问题描述

来了一个需求,参考一个页面,想实现如下效果。这效果,一般来说,没法搞。因为参考系统其他页面,也就应了下来。

问题分析

首先。是一个列表,有筛选,有分页;

其此。每条数据,结构比较复杂,有题干、有答案,有视频,有图片。

最后。当然,图片和视频都要去预览。

问题学习

万变不离其宗,还是一个table实现。

表单html部分:

复制代码
<div style="margin-left: 10%;margin-right:20%;border-radius:5px;">
<table id="dataTable"  class="table table-bordered table-striped"></table>&emsp;
</table>
</div>

js部分:

复制代码
<script>

    let url = "/detectionTestLog/showTopicDetailList";
    let paperId = '$paper.id' ;
    let typeArr = velocityMapToJson("$topicTypeMap");


    $(function () {
        searchList();
    });


    /**
     * 点击查询,加载列表数据
     */
    function searchList(){
        let params = {};
        params.paperId = paperId;
        params.topicId =  $("input[name='topicId']").val();
        load("dataTable", columns, url, params);
    }


    const columns = [
        {
            data: "classify", title: "", render: function (data, type, row, meta) {
                let html = "";
                html += "<div class='carImgDiv'>&emsp;";
                html += "<label>";
                html += (meta.row + 1) + "、" + row.content + " <span style='color: #aa7700'>(" + typeArr[row.type] + ")</span></label>&emsp;";
                html += "题目编号:" + row.topicId + "&emsp;" ;

                if (row.pics) {
                    let picsArr = row.pics.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>题干图片</label><br>'
                    for (let j = 0; j < picsArr.length; j++) {
                        html += '<img loading="lazy" data-src="https://static.chaboshi.cn/' + picsArr[j] + '" width="100px" style="margin: 10px">'
                    }
                    html += '</div>&emsp;'
                }
                if (row.videos) {
                    let videosArr = row.videos.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>题干视频</label><br>'
                    for (let j = 0; j < videosArr.length; j++) {
                        html += '<video width="320" height="240" controls><source src="https://static.chaboshi.cn/' + videosArr[j] + '" type="video/mp4"></video>'
                    }
                    html += '</div>&emsp;'
                }
                html += '<div class="input-group">&emsp;&emsp;'

                if (row.answerDetail) {
                    html += '<label>答案详情';
                    html += '<pre>' + row.answerDetail + '</pre>'
                }
                html += '</label></div>'
                if (row.answerPics) {
                    let picsArr = row.answerPics.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>答案详情图片</label><br>'
                    for (let j = 0; j < picsArr.length; j++) {
                        html += '<img loading="lazy" data-src="https://static.chaboshi.cn/' + picsArr[j] + '" width="100px" style="margin: 10px">'
                    }
                    html += '</div>'
                }
                if (row.answerVideos) {
                    let videosArr = row.answerVideos.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>答案详情视频</label><br>'
                    for (let j = 0; j < videosArr.length; j++) {
                        html += '<video width="320" height="240" controls><source src="https://static.chaboshi.cn/' + videosArr[j] + '" type="video/mp4"></video>'
                    }
                    html += '</div>&emsp;'
                }
                html += '</div>'

                html += '<div class="input-group">&emsp;&emsp;'
                html += '<label>正确答案(<span style="color: #19a05e;font-size: 22px;">✓</span>) </label>';
                html += '</div>'

                let answerIdHtml = '';
                if(row.topicAnswers){
                    for (let j = 0; j < row.topicAnswers.length; j++) {
                        let htmlContent = notNull(row.topicAnswers[j].content)?row.topicAnswers[j].content:'-';
                        if (row.topicAnswers[j].rightAnswers == true) {
                            htmlContent = '<span style="color: #19a05e;font-size: 22px;">✓</span>' + htmlContent
                        } else {
                            htmlContent = '&emsp;' + htmlContent
                        }
                        answerIdHtml += "<div class=\"input-group\"> &emsp;&emsp;" + htmlContent + "</div>"
                    }
                }
                html += '<div class="input-group"style="margin-left:28px">&emsp;&emsp;'
                html += '<pre>' + answerIdHtml + '</pre>'
                html += '</div>'

                html += '<div class="input-group">&emsp;&emsp;'
                html += '<label>选择情况</label>'
                html += '<strong style="margin-left: 15px;">答题次数:</strong><span>'+row.topicSum+'</span>';
                html += '<strong style="margin-left: 15px;">正确次数:</strong><span>'+row.rightCount+'</span><span>('+row.rightDesc+')</span>';
                html += '<strong style="margin-left: 15px;">错误次数:</strong><span>'+row.errorCount+'</span><span>('+row.errorDesc+')</span>';
                html += '<strong style="margin-left: 15px;">正确率:</strong><span>'+row.rightRate+'%</span>';

                html += '</div>'

                setTimeout(function () {
                    $("img[data-src]").each(function () {
                        $(this).attr("src", $(this).attr("data-src"));
                        $(this).removeAttr("data-src");
                    });
                    $('.carImgDiv').viewer()
                }, 1000)
                return html;
            }
        }
    ]


</script>

看到了吗,利用load("dataTable", columns, url, params);,实现分页的效果。但仅仅定义了一列,里边自定义了一段html片段,实现了这样一个效果,还是让人心里一惊。

这里也可以写setTimeout
复制代码
html += '</div>'

setTimeout(function () {
    $("img[data-src]").each(function () {
        $(this).attr("src", $(this).attr("data-src"));
        $(this).removeAttr("data-src");
    });
    $('.carImgDiv').viewer()
}, 1000)

这个方法的主要作用是实现图片的延迟加载(懒加载)并初始化图片查看器,具体功能如下: 1. **延迟执行逻辑**:通过 `setTimeout` 设置了1秒(1000毫秒)的延迟,等待1秒后再执行内部代码。 2. **图片加载处理**: - 选择所有带有 `data-src` 属性的 `img` 元素(`("img\[data-src\]")\`)。 - 遍历这些图片,将 \`data-src\` 属性的值赋值给 \`src\` 属性(\`(this).attr("src", (this).attr("data-src"))\`),此时图片才会真正开始加载。 - 移除 \`data-src\` 属性(\`(this).removeAttr("data-src")`),避免重复处理。 3. **初始化图片查看器**:调用 `$('.carImgDiv').viewer()` 方法,为类名为 `carImgDiv` 的元素初始化图片查看器插件(通常用于实现图片放大、预览等功能)。 简单来说,这段代码的目的是:等待1秒后,加载页面中标记为延迟加载的图片(通过 `data-src` 存储真实地址),并初始化对应的图片查看器功能。延迟1秒可能是为了等待页面其他资源加载完成,或配合某些交互场景。

渲染每一行结束,替换变量,实现图片预览的效果。那能不能渲染后,只执行一次呢?理论上当然可以,但是分散到每一行去执行,也不失为一个好办法。体验好、风险低。

完整源代码

复制代码
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>考卷题目详情</title>
    #parse("/views/inc/head.vm")
    <link rel="stylesheet" href="/kindeditor/default.css"/>
    <link rel="stylesheet" href="/kindeditor/prettify.css"/>
    <link rel="stylesheet" href="$!{cdn_domain}/css/viewer.css">

    <style>
        .center {
            text-align: center;
            border: #8c8c8c;
            outline: none;
            background-color: #eee;
            width: 80px;
            margin-top: 5px;
        }
    </style>
</head>
<body class="$!{skin}">
#parse("/views/inc/nav_top.vm")
<!-- Left side column. contains the logo and sidebar -->
<!-- UEditor -->
<script charset="utf-8" src="/kindeditor/kindeditor-all-min.js"></script>
<script charset="utf-8" src="/kindeditor/zh_CN.js"></script>
<script charset="utf-8" src="/kindeditor/prettify.js"></script>

</head>
#parse("/views/inc/nav_left.vm")

<!-- Main content -->
<section class="content">
    <div class="row">
        <div class="col-md-12">
            <!-- Advanced Tables -->
            <div class="panel panel-default">
                <div class="panel-body">
                    <form action="/detectionTestPaper/save" name="paperForm" method="post"
                          id="topicForm"
                          class="form-horizontal">
                        <input type="hidden" id="id" name="id" value="${paper.id}"/>
                        <input type="hidden" id="topicArr" name="topicArr"/>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">题目标题:</label>
                            <div class="col-sm-4">
                                <input class="input-css" style="border: #8c8c8c;" value="$!{paper.title}">
                            </div>
                        </div>&emsp;
                        <div class="form-group">
                            <label class="col-sm-2 control-label">考试次数:</label>
                            <div class="col-sm-8">
                                <div><label>
                                    <input class="input-css center" readonly value="$!{logCount}"/>&emsp;&emsp;
                                    考试人数:<input class="input-css center" readonly value="$!{testCount}"/>&emsp;
                                </label>
                                <label>
                                    题目编号: <input class="input-css center" name="topicId" type="number"/>&emsp;
                                </label>
                                    <button class="btn btn-info btn-xs" onclick="searchList(); return false;">查询</button>
                                </div>&emsp;
                            </div>
                        </div>&emsp;
                    </form>

                    <div style="margin-left: 10%;margin-right:20%;border-radius:5px;">
                        <table id="dataTable"  class="table table-bordered table-striped"></table>&emsp;
<!--                            <thead>-->
<!--                            <tr>-->
<!--                                <td>序号</td>-->
<!--                                <td>题目</td>-->
<!--                                <td>题型</td>-->
<!--                                <td>答题次数</td>-->
<!--                                <td>正确次数</td>-->
<!--                                <td>错误次数</td>-->
<!--                                <td>正确率</td>-->
<!--                            </tr>-->
<!--                            </thead>-->
<!--                            <tbody>-->
<!--                            #if($!topicList.size()>0)-->
<!--                            #foreach($e in $!topicList)-->
<!--                            <tr>-->
<!--                                <td>$foreach.count</td>-->
<!--                                <td>$e.content</td>-->
<!--                                <td>$!topicTypeMap[$e.type]</td>-->
<!--                                <td>$e.topicSum</td>-->
<!--                                <td>$e.rightAnswer</td>-->
<!--                                <td>$e.errorAnswer</td>-->
<!--                                #set($Double = 0.00)-->
<!--                                #set($fund= ($Double.parseDouble($e.rightAnswer) / $Double.parseDouble($e.topicSum)) * 100)-->
<!--                                <td>$number.format("#0.00", $fund)   %</td>-->
<!--                            </tr>-->
<!--                            #end-->
<!--                            #else-->
<!--                            <tr><td colspan='7' style="text-align: center;">暂无数据</td></tr>-->
<!--                            #end-->
<!--                            </tbody>-->
<!--                        </table>&emsp;-->
                    </div>
                </div>
            </div>
            <!--End Advanced Tables -->
        </div>
    </div>
</section>
#parse("/views/inc/nav_bottom.vm")

<script src="$!{cdn_domain}/js/viewer.js" type="text/javascript"></script>
<script>

    let url = "/detectionTestLog/showTopicDetailList";
    let paperId = '$paper.id' ;
    let typeArr = velocityMapToJson("$topicTypeMap");


    $(function () {
        searchList();
    });


    /**
     * 点击查询,加载列表数据
     */
    function searchList(){
        let params = {};
        params.paperId = paperId;
        params.topicId =  $("input[name='topicId']").val();
        load("dataTable", columns, url, params);
    }


    const columns = [
        {
            data: "classify", title: "", render: function (data, type, row, meta) {
                let html = "";
                html += "<div class='carImgDiv'>&emsp;";
                html += "<label>";
                html += (meta.row + 1) + "、" + row.content + " <span style='color: #aa7700'>(" + typeArr[row.type] + ")</span></label>&emsp;";
                html += "题目编号:" + row.topicId + "&emsp;" ;

                if (row.pics) {
                    let picsArr = row.pics.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>题干图片</label><br>'
                    for (let j = 0; j < picsArr.length; j++) {
                        html += '<img loading="lazy" data-src="https://static.chaboshi.cn/' + picsArr[j] + '" width="100px" style="margin: 10px">'
                    }
                    html += '</div>&emsp;'
                }
                if (row.videos) {
                    let videosArr = row.videos.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>题干视频</label><br>'
                    for (let j = 0; j < videosArr.length; j++) {
                        html += '<video width="320" height="240" controls><source src="https://static.chaboshi.cn/' + videosArr[j] + '" type="video/mp4"></video>'
                    }
                    html += '</div>&emsp;'
                }
                html += '<div class="input-group">&emsp;&emsp;'

                if (row.answerDetail) {
                    html += '<label>答案详情';
                    html += '<pre>' + row.answerDetail + '</pre>'
                }
                html += '</label></div>'
                if (row.answerPics) {
                    let picsArr = row.answerPics.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>答案详情图片</label><br>'
                    for (let j = 0; j < picsArr.length; j++) {
                        html += '<img loading="lazy" data-src="https://static.chaboshi.cn/' + picsArr[j] + '" width="100px" style="margin: 10px">'
                    }
                    html += '</div>'
                }
                if (row.answerVideos) {
                    let videosArr = row.answerVideos.split(",")
                    html += '<div class="input-group"style="margin-left:28px"><label>答案详情视频</label><br>'
                    for (let j = 0; j < videosArr.length; j++) {
                        html += '<video width="320" height="240" controls><source src="https://static.chaboshi.cn/' + videosArr[j] + '" type="video/mp4"></video>'
                    }
                    html += '</div>&emsp;'
                }
                html += '</div>'

                html += '<div class="input-group">&emsp;&emsp;'
                html += '<label>正确答案(<span style="color: #19a05e;font-size: 22px;">✓</span>) </label>';
                html += '</div>'

                let answerIdHtml = '';
                if(row.topicAnswers){
                    for (let j = 0; j < row.topicAnswers.length; j++) {
                        let htmlContent = notNull(row.topicAnswers[j].content)?row.topicAnswers[j].content:'-';
                        if (row.topicAnswers[j].rightAnswers == true) {
                            htmlContent = '<span style="color: #19a05e;font-size: 22px;">✓</span>' + htmlContent
                        } else {
                            htmlContent = '&emsp;' + htmlContent
                        }
                        answerIdHtml += "<div class=\"input-group\"> &emsp;&emsp;" + htmlContent + "</div>"
                    }
                }
                html += '<div class="input-group"style="margin-left:28px">&emsp;&emsp;'
                html += '<pre>' + answerIdHtml + '</pre>'
                html += '</div>'

                html += '<div class="input-group">&emsp;&emsp;'
                html += '<label>选择情况</label>'
                html += '<strong style="margin-left: 15px;">答题次数:</strong><span>'+row.topicSum+'</span>';
                html += '<strong style="margin-left: 15px;">正确次数:</strong><span>'+row.rightCount+'</span><span>('+row.rightDesc+')</span>';
                html += '<strong style="margin-left: 15px;">错误次数:</strong><span>'+row.errorCount+'</span><span>('+row.errorDesc+')</span>';
                html += '<strong style="margin-left: 15px;">正确率:</strong><span>'+row.rightRate+'%</span>';

                html += '</div>'

                setTimeout(function () {
                    $("img[data-src]").each(function () {
                        $(this).attr("src", $(this).attr("data-src"));
                        $(this).removeAttr("data-src");
                    });
                    $('.carImgDiv').viewer()
                }, 1000)
                return html;
            }
        }
    ]


</script>

</body>
</html>

问题总结

天地之大,无所不能,万变不离其宗。没什么不可以;老技术,也可以焕发新魅力。当然,也要非常积极的拥抱新技术。

相关推荐
weixin_382395237 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__7 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.8 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~9 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华10 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子12 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅12 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni12 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学14 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端