本文将分为以下几个部分,你可以根据自己的需求选择性地进行改造:

- 改造前的准备与规划
- 基础改造:优化默认图集列表
- 进阶改造:实现现代化的图片展示效果
- 高级改造:增加交互功能(如灯箱、缩放)
- 模板代码示例与详解
改造前的准备与规划
在动手修改代码之前,做好准备工作可以事半功倍。
备份!备份!备份!
任何模板修改都有风险,请务必备份你的原始模板文件(通常是 /templets/default/article_image.htm)和相关CSS、JS文件。
明确改造目标 你希望图集达到什么样的效果?
- 更美观? (更换CSS样式)
- 加载更快? (优化图片、懒加载)
- 交互更强? (增加灯箱、缩放、滑动效果)
- 排版更灵活? (支持多列、瀑布流)
了解织梦图集的数据结构 织梦图集的核心数据存储在两个地方:

- 主表 (
#@__archives): 存储图集的基本信息,如标题、简介等。 - 附加表 (
#@__addonimages): 存储图集中的所有图片信息,包括imgurl(图片地址)、alt(图片说明)、ismain(是否为封面图) 等。
理解这个结构有助于你后续调用和修改数据。
准备工具
- 代码编辑器: 如 VS Code、Sublime Text、Notepad++ 等。
- 浏览器开发者工具: 用于调试CSS和JS,实时预览效果。
- 前端库: 如 Bootstrap、Swiper、PhotoSwipe 等,可以帮你快速实现专业效果。
基础改造:优化默认图集列表
这是最简单的改造,主要针对织梦默认的 {dede:field.body/} 标签生成的HTML结构进行优化。
默认结构问题: 默认生成的HTML通常是这样的:

<div class="picFocus">
<ul>
<li><img src="..." alt="..."></li>
<li><img src="..." alt="..."></li>
</ul>
</div>
结构简单,样式单一。
改造方法:
增加图片说明 (alt
确保每张图片都有有意义的 alt 属性,这有利于SEO和用户体验,织梦默认调用时,alt 可能是空的,你需要手动在后台为每张图片填写说明,或者在模板中做一些处理。
优化HTML结构
为了让样式更容易控制,我们可以给图片列表添加一个更规范的容器和类名。
找到模板文件中的 {dede:field.body/},通常它被一个 <div> 包裹,我们可以修改这个 <div> 的类名。
将:
<div class="pics">
{dede:field.body/}
</div>
修改为:
<div class="my-gallery" itemscope itemtype="http://schema.org/ImageGallery">
{dede:field.body/}
</div>
my-gallery: 自定义的类名,方便我们用CSS或JS进行样式控制。itemscope itemtype="...": 添加了Schema.org标记,有助于搜索引擎理解这是一个图集,对SEO有好处。
使用CSS进行基础美化
在模板的 <head> 部分或外部的CSS文件中,添加以下样式:
/* 清除默认样式和间距 */
.my-gallery, .my-gallery * {
box-sizing: border-box;
}
.my-gallery ul {
list-style: none;
padding: 0;
margin: 0;
display: flex; /* 使用Flexbox实现横向排列或换行 */
flex-wrap: wrap; /* 允许换行 */
gap: 10px; /* 图片之间的间距 */
}
.my-gallery ul li {
margin: 0;
padding: 0;
}
.my-gallery ul li img {
width: 100%; /* 让图片宽度自适应容器 */
height: auto; /* 保持图片比例 */
display: block; /* 去除图片下方的空隙 */
border-radius: 8px; /* 圆角 */
box-shadow: 0 2px 8px rgba(0,0,0,0.1); /* 阴影效果 */
transition: transform 0.3s ease, box-shadow 0.3s ease; /* 添加过渡动画 */
}
.my-gallery ul li img:hover {
transform: scale(1.05); /* 鼠标悬停时轻微放大 */
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
通过以上基础改造,你的图集列表就会变得整齐、美观,并且有简单的悬停效果。
进阶改造:实现现代化的图片展示效果
如果默认的 {dede:field.body/} 无法满足你的布局需求(如瀑布流、多列等),你可以选择不使用它,而是通过自定义调用图集数据的方式来实现。
改造思路:
- 在模板中,我们不使用
{dede:field.body/}。 - 使用
{dede:imagelist}标签直接从附加表中获取所有图片数据。 - 在
{dede:imagelist}循环中,用你自定义的HTML结构来展示每一张图片。
模板代码示例:
<!-- 在 article_image.htm 中,替换掉 {dede:field.body/} 这一行 -->
<div class="advanced-gallery">
<div class="container">
<div class="row">
<!-- 使用 dede:imagelist 自定义调用 -->
{dede:imagelist}
<div class="col-md-4 col-sm-6 mb-4">
<!-- 这里是你自定义的每张图片的HTML结构 -->
<div class="img-card">
<a href="[field:imgurl/]" class="img-link" title="[field:text/]">
<img src="[field:imgurl/]" alt="[field:text/]" class="img-fluid">
</a>
<div class="img-caption text-center mt-2">
<p>[field:text/]</p>
</div>
</div>
</div>
{/dede:imagelist}
</div>
</div>
</div>
代码解释:
{dede:imagelist}: 循环调用当前图集的所有图片。[field:imgurl/]: 图片地址。[field:text/]: 图片说明。col-md-4 col-sm-6: 这类类名通常配合Bootstrap等CSS框架使用,可以实现响应式的多列布局(大屏幕3列,中等屏幕2列)。img-fluid: Bootstrap类名,使图片响应式。
配合CSS框架: 如果你使用了Bootstrap,上面的代码可以直接工作,如果你不使用,可以用纯CSS实现类似效果:
.advanced-gallery .row {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding: 0;
}
.advanced-gallery .col-md-4 {
flex: 0 0 calc(33.333333% - 20px); /* 大屏幕3列,减去间距 */
max-width: calc(33.333333% - 20px);
}
.advanced-gallery .col-sm-6 {
flex: 0 0 calc(50% - 20px); /* 中等屏幕2列 */
max-width: calc(50% - 20px);
}
@media (max-width: 768px) {
.advanced-gallery .col-md-4,
.advanced-gallery .col-sm-6 {
flex: 0 0 100%;
max-width: 100%;
}
}
.img-card {
border-radius: 8px;
overflow: hidden; /* 让图片圆角生效 */
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.img-link {
display: block;
}
.img-link img {
width: 100%;
height: 250px; /* 固定高度,或者使用 object-fit: cover; */
object-fit: cover; /* 保持比例,填充区域 */
transition: transform 0.3s ease;
}
.img-link:hover img {
transform: scale(1.1);
}
.img-caption {
background: #fff;
padding: 10px;
}
高级改造:增加交互功能(如灯箱、缩放)
这是提升用户体验最关键的一步,我们以集成 PhotoSwipe 这个强大的开源图片灯箱库为例。
PhotoSwipe 优点:
- 轻量、快速、免费。
- 支持触摸滑动。
- 支持键盘导航。
- 对移动端友好。
集成步骤:
第1步:引入PhotoSwipe文件
在图集模板文件的 <head> 标签内引入PhotoSwipe的CSS和JS文件,你可以从其官网下载,或使用CDN。
<head> <!-- ... 其他 head 内容 ... --> <!-- PhotoSwipe CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css"> <!-- 你的自定义CSS --> <link rel="stylesheet" href="/css/your-styles.css"> </head> <body> <!-- ... 页面内容 ... --> <!-- PhotoSwipe JS 最好放在 body 结尾处 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"></script> <!-- 你的自定义JS --> <script src="/js/your-scripts.js"></script> </body>
第2步:修改HTML结构,添加PhotoSwipe所需属性
我们需要修改图集的HTML,让它符合PhotoSwipe的要求,这需要用到 data-size (图片尺寸) 和 data-pswp-width/height。
由于织梦默认不提供图片尺寸,我们需要在后台上传图片时记录,或者通过JS获取,这里我们采用一个变通方法:在 {dede:imagelist} 中假设一个固定尺寸,或者通过JS动态计算。
修改后的模板HTML:
<!-- 1. 添加一个用于初始化的根元素 -->
<div class="my-gallery" data-pswp-uid="1">
<!-- 2. 使用 dede:imagelist -->
{dede:imagelist}
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="[field:imgurl/]"
itemprop="contentUrl"
data-size="800x600" <!-- 这里需要填写图片的实际尺寸,是关键! -->
data-med="[field:imgurl/]"
data-med-size="1024x768">
<img src="[field:imgurl/]"
alt="[field:text/]"
itemprop="thumbnail"
style="width:100%; height:auto;">
</a>
<figcaption itemprop="caption description">[field:text/]</figcaption>
</figure>
{/dede:imagelist}
</div>
<!-- 3. PhotoSwipe的根元素(通常放在body末尾) -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<div class="pswp__bg"></div>
<div class="pswp__scroll-wrap">
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
第3步:编写初始化JS
创建一个新的JS文件(如 /js/init-gallery.js),并在页面底部引入它。
// /js/init-gallery.js
var initPhotoSwipeFromDOM = function(gallerySelector) {
var parseThumbnailElements = function(el) {
var thumbElements = el.childNodes,
numNodes = thumbElements.length,
items = [],
figureEl,
linkEl,
size,
item;
for(var i = 0; i < numNodes; i++) {
figureEl = thumbElements[i]; // <figure> element
// include only element nodes
if(figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0]; // <a> element
size = linkEl.getAttribute('data-size').split('x');
// create slide object
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10),
author: linkEl.getAttribute('data-author')
};
if(figureEl.children.length > 1) {
// <figcaption> content
item.title = figureEl.children[1].innerHTML;
}
if(linkEl.children.length > 0) {
// <img> thumbnail element, retrieving thumbnail url
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl; // save link to element for getThumbBoundsFn
items.push(item);
}
return items;
};
// find nearest parent element
var closest = function closest(el, fn) {
return el && ( fn(el) ? el : closest(el.parentNode, fn) );
};
// triggers when user clicks on thumbnail
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
// find root element of slide
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
});
if(!clickedListItem) {
return;
}
// find index of clicked item by looping through all child nodes
// alternatively, you may define data-index attributes on all figure elements
var clickedGallery = clickedListItem.parentNode,
childNodes = clickedListItem.parentNode.childNodes,
numChildNodes = childNodes.length,
nodeIndex = 0,
index;
for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1) {
continue;
}
if(childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};
// parse picture index and gallery ID from URL (#&pid=1&gid=2)
var photoswipeParseHash = function() {
var hash = window.location.hash.substring(1),
params = {};
if(hash.length < 5) {
return params;
}
var vars = hash.split('&');
for (var i = 0; i < vars.length; i++) {
if(!vars[i]) {
continue;
}
var pair = vars[i].split('=');
if(pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
if(params.gid) {
params.gid = parseInt(params.gid, 10);
}
return params;
};
var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) {
var pswpElement = document.querySelectorAll('.pswp')[0],
gallery,
options,
items;
items = parseThumbnailElements(galleryElement);
// define options (if needed)
options = {
// define gallery index (for URL)
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function(index) {
// See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
}
};
// PhotoSwipe initialization
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
// loop through all gallery elements and bind events
var galleryElements = document.querySelectorAll( gallerySelector );
for(var i = 0, l = galleryElements.length; i < l; i++) {
galleryElements[i].setAttribute('data-pswp-uid', i+1);
galleryElements[i].onclick = onThumbnailsClick;
}
// Parse URL and open gallery if it contains #&pid=3&gid=1
var hashData = photoswipeParseHash();
if(hashData.pid && hashData.gid) {
openPhotoSwipe( hashData.pid , galleryElements[ hashData.gid - 1 ], true, true );
}
};
// execute above function
initPhotoSwipeFromDOM('.my-gallery');
最后一步:处理图片尺寸
data-size="800x600" 是个大问题,织梦不提供这个信息。
- 方法A(推荐):后台手动填写,修改织梦源码,在图集上传时增加一个“尺寸”输入框,但这比较复杂。
- 方法B(折中):使用JS获取,在上传图片时,用工具记录下每张图的尺寸,然后手动填写到模板里,对于少量图集可行。
- 方法C(不完美):使用原图尺寸,在
{dede:imagelist}中调用原图[field:imgurl/],然后用JS获取其自然宽高,这会增加页面加载时的计算量,且可能因为图片跨域而失败。
模板代码示例与详解(综合版)
这里提供一个综合了基础美化和PhotoSwipe集成的完整 article_image.htm 模板示例。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">{dede:field.title/}_织梦图集</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- PhotoSwipe CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css">
<!-- 自定义CSS -->
<style>
/* 基础布局和样式 */
body { font-family: 'Helvetica Neue', Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 1200px; margin: 20px auto; padding: 0 15px; }
/* 图集样式 */
.my-gallery {
background: #f9f9f9;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.my-gallery figure {
margin: 0;
padding: 0;
display: inline-block;
width: calc(25% - 20px); /* 默认4列,减去间距 */
margin-right: 20px;
vertical-align: top;
text-align: center;
}
.my-gallery figure a {
display: block;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
}
.my-gallery figure a:hover {
transform: translateY(-5px);
}
.my-gallery figure img {
width: 100%;
height: 200px;
object-fit: cover;
display: block;
}
.my-gallery figcaption {
margin-top: 10px;
font-size: 0.9em;
color: #666;
}
/* 响应式调整 */
@media (max-width: 992px) {
.my-gallery figure { width: calc(33.333% - 20px); }
}
@media (max-width: 768px) {
.my-gallery figure { width: calc(50% - 20px); }
}
@media (max-width: 576px) {
.my-gallery figure { width: 100%; margin-right: 0; }
}
</style>
</head>
<body>
<div class="container">
<h1>{dede:field.title/}</h1>
<p class="info">作者:{dede:field.writer/} 时间:{dede:field.pubdate function="MyDate('Y-m-d H:i',@me)"/}</p>
<div class="my-gallery" data-pswp-uid="1">
{dede:imagelist}
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<!--
注意:这里的 data-size 需要你手动填写每张图片的原始尺寸(宽x高)
data-size="1920x1080"
-->
<a href="[field:imgurl/]"
itemprop="contentUrl"
data-size="1200x800" <!-- 【请务必修改这里!】 -->
data-med="[field:imgurl/]"
data-med-size="1200x800">
<img src="[field:imgurl/]"
alt="[field:text/]"
itemprop="thumbnail"
style="width:100%; height:auto;">
</a>
<figcaption itemprop="caption description">[field:text/]</figcaption>
</figure>
{/dede:imagelist}
</div>
</div>
<!-- PhotoSwipe 核心文件 -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<div class="pswp__bg"></div>
<div class="pswp__scroll-wrap">
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
<!-- PhotoSwipe JS 和初始化脚本 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"></script>
<script src="/js/init-gallery.js"></script> <!-- 引入我们上面创建的初始化脚本 -->
</body>
</html>
通过以上步骤,你就成功地将一个基础的织梦图集模板改造成为一个具有现代化外观和专业交互功能的图集展示页面,核心在于 规划 -> 备份 -> 修改结构 -> 添加样式/脚本 -> 调试。
