日常开发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>

问题总结

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

相关推荐
陶甜也5 小时前
ThreeJS曲线动画:打造炫酷3D路径运动
前端·vue·threejs
楊无好5 小时前
react中的受控组件与非受控组件
前端·react.js
菠萝+冰5 小时前
react虚拟滚动
前端·javascript·react.js
落一落,掉一掉5 小时前
第十三周前端加密绕过
前端
前端初见6 小时前
快速上手TypeScript,TS速通
javascript·ubuntu·typescript
Onlyᝰ6 小时前
前端tree树
javascript·vue.js·elementui
高德开放平台7 小时前
实战案例|借助高德开放平台实现智慧位置服务:路线导航的开发与实践
前端·后端
hemoo7 小时前
如何让echart的lengend在指定位置换行
javascript·echarts
老前端的功夫7 小时前
# HTTP缓存:从懵懵懂懂到了如指掌
前端