织梦DedeCMS修改文章保留原发布时间4步实操

织梦DedeCMS默认编辑文章会把pubdate刷新成当前时间,干扰首页排序、SEO时序信号和sitemap。本文给出archives_edit.htm一行代码改法、article_edit.php后端兜底、新增lastedit双时间字段方案、6步回归验证流程和DedeBIZ版本兼容说明,全程5分钟搞定。

张文保 更新 21 分钟阅读 2,272 阅读
本文目录
  1. 问题背景:为什么默认行为是这样
  2. 定位关键文件 archives_edit.htm
  3. 核心修改:一行代码搞定
  4. 配合后端逻辑确保万无一失
  5. 扩展玩法:分离"发布时间"和"最近编辑时间"
  6. 新增字段
  7. 在 article_edit.php 的保存逻辑里写入
  8. 在前台模板里调用
  9. 让 sitemap 改用 lastedit
  10. 加上 schema.org 结构化数据
  11. 修改后的全流程验证
  12. 版本兼容性与升级注意
  13. 保哥的踩坑案例
  14. 应急回滚方案
  15. 保哥的部署 SOP
  16. 常见问题解答
  17. 改完之后所有老文章的时间会怎么样?
  18. 升级DedeCMS时这个修改会被覆盖吗?
  19. 会不会影响DedeCMS的伪静态或者静态生成?
  20. 如果只想偶尔保留首发时间,平时还是按当前时间,怎么做?
  21. 修改之后织梦的文章管理列表页排序还正常吗?
  22. 批量发布的文章如何保证pubdate正确?
  23. 这套修改对其他CMS有参考意义吗?
  24. 有没有现成的DedeCMS插件可以一键搞定?

做织梦DedeCMS站点的朋友应该都遇到过一个让人抓狂的问题:明明只是改了一下错别字,文章的发布时间却被自动刷新成了当前时间,整篇文章在前台插队到了首页最上面,一下子打乱了整站的内容节奏。保哥这些年帮客户处理过几十次类似需求,今天把这个问题彻底讲清楚,从原理到改法到风险点一次写完,附带完整的回归验证步骤、扩展双时间字段方案和常见踩坑案例。

问题背景:为什么默认行为是这样

织梦DedeCMS默认在修改文章时会把 pubdate 字段重新写一次,写入的是当前服务器时间。这个设计在最初的版本里其实是有道理的——早期博客系统普遍把修改时间等同于发布时间,更新即意味着重新发布。

但放到今天的SEO和内容运营场景里,这个默认行为非常不友好:

  • 影响SEO时序信号:搜索引擎对文章首次发布时间是有记忆的,频繁刷新pubdate会让爬虫误以为你在做老文翻新,反而可能稀释权重;Google的Freshness算法会对短期内多次"重新发布"的内容降权处理。
  • 影响首页排序:织梦默认按pubdate倒序排列,改一篇老文等于把它推到首页第一条,干扰整站编排;
  • 影响sitemap:自动生成的sitemap.xml里 <lastmod> 也跟着变,提交给搜索引擎后看起来像全站大幅更新,触发不必要的重新抓取,浪费爬虫预算(Crawl Budget);
  • 影响RSS订阅:所有订阅器会把这篇文章当作新发布重新推送给读者,造成"已读再次推送"的体验问题。

所以保哥的做法是:分两个字段管理,pubdate 锁死为首发时间,senddate 或者新增一个 lastedit 字段记录最近编辑时间,前后台展示按需取用。本文先讲怎么把默认行为关掉,下一节再讲扩展玩法。

定位关键文件 archives_edit.htm

要修改的文件路径是:

/dede/templets/archives_edit.htm

注意这里的 /dede/ 是后台管理目录,很多站长会改名(建议改名,能挡掉90%的扫描器),如果你的后台目录是 /admin123/,那路径就变成 /admin123/templets/archives_edit.htm

这个文件本质上是文章编辑页的模板,DedeCMS的后台模板和前台模板是两套不同的引擎,后台模板里夹杂了大量原生PHP代码——PHP标签直接嵌在HTML里。我们要修改的就是其中一行PHP代码。

用SSH或FTP把文件下载下来,搜索关键字 nowtime

grep -n "nowtime" /www/wwwroot/example.com/dede/templets/archives_edit.htm

应该能看到类似这样的输出:

42:<?php $nowtime = GetDateTimeMk(time()); ?>

行号会因子版本不同略有差异,但格式是固定的。如果你用的是DedeBIZ或者其他二开版本,搜索关键字保持不变也能定位到。

核心修改:一行代码搞定

原代码:

<?php $nowtime = GetDateTimeMk(time()); ?>

这句的意思是:调用 GetDateTimeMk() 把当前时间戳格式化成织梦能识别的日期字符串,赋值给 $nowtime,然后在表单里作为发布时间字段的默认值显示出来。

保哥的修改方案是:

<?php $nowtime = GetDateTimeMk($arcRow["pubdate"]); ?>

关键变化是 time() 换成了 $arcRow["pubdate"]。这里的 $arcRow 是织梦在加载编辑页前从 dede_archives 表里读出来的当前文章原始数据,pubdate 字段就是这篇文章首次发布时的Unix时间戳。把它直接传给格式化函数,就能让编辑页表单里显示的发布时间和数据库里存的首发时间一致。

保存后保哥编辑任何一篇老文章,进入编辑页 → 直接点最下方的确定按钮 → 不修改时间字段 → 提交,pubdate字段在数据库里就纹丝不动了。

整个修改只动了一个函数参数,对其他逻辑零侵入,是最干净的修法。如果你的版本里没有 $arcRow(少数极老版本),可以替换成 $row$data 等同等含义的变量名,原理一样。

配合后端逻辑确保万无一失

第三节的修改只是改了编辑页表单的默认显示,理论上只要管理员不去主动改时间字段,提交回去也就是同一个时间。但保哥实测过一种边缘情况:如果你的浏览器开了某些表单自动填充插件,或者你的同事手抖点了设为当前时间的小按钮,pubdate还是会被覆盖。

所以保哥的做法是再加一道后端保险——直接修改 /dede/article_edit.php,把保存时的pubdate写入逻辑也锁死。找到这一段:

$pubdate = GetMkTime($pubdate);

在它前面或后面加一行:

// 强制保留首发时间,注释掉本行可恢复默认行为
$pubdate = $arcRow["pubdate"];

这样无论前端表单提交了什么时间值,最终落库的还是原始pubdate。如果你希望某些文章可以手动改时间,可以加一个判断条件,比如只有当用户勾选了强制更新发布时间复选框时才执行覆盖。完整带开关的逻辑:

if (!isset($_POST['keep_pubdate']) || $_POST['keep_pubdate'] != '1') {
    // 用户没勾"强制更新",保留首发时间
    $pubdate = $arcRow["pubdate"];
} else {
    // 用户主动勾选了,按表单提交的时间走
    $pubdate = GetMkTime($pubdate);
}

这种带开关的写法是保哥给客户做生产部署时的标准方案——既保证了默认安全(不会误改),又给运营留了灵活操作的口子。

扩展玩法:分离"发布时间"和"最近编辑时间"

保哥经手的稍微大一点的内容站,都会做一个改进:在文章表里新增 lastedit 字段,专门记录最近一次编辑时间,前台模板里同时展示两个时间。

新增字段

ALTER TABLE dede_archives ADD COLUMN lastedit INT(10) NOT NULL DEFAULT 0 COMMENT '最近编辑时间戳';

-- 把现有数据初始化为pubdate的值,避免显示1970-01-01
UPDATE dede_archives SET lastedit = pubdate WHERE lastedit = 0;

在 article_edit.php 的保存逻辑里写入

找到执行UPDATE的位置,把 lastedit 加进去:

$query = "UPDATE `dede_archives` SET
    title = '$title',
    pubdate = '$pubdate',
    lastedit = " . time() . ",
    sortrank = '$sortrank'
    WHERE id = '$id'";

在前台模板里调用

用织梦的自定义字段标签:

<p>首发:{dede:field name='pubdate' function='strftime("%Y-%m-%d",@me)'/}</p>
<p>最近更新:{dede:field name='lastedit' function='strftime("%Y-%m-%d",@me)'/}</p>

这样首页和列表页继续按pubdate排,但文章详情页能展示最近更新,对用户和搜索引擎都更友好。

让 sitemap 改用 lastedit

找到sitemap生成脚本(一般是 /plus/sitemap.php/data/sitemaps/ 下的生成器),把 <lastmod> 改成读 lastedit

<lastmod><?php echo date("Y-m-d", $row['lastedit']); ?></lastmod>

这样sitemap反映的是真实的内容更新时间,搜索引擎拿到这个信号能更精准地决定是否重新抓取。

加上 schema.org 结构化数据

现代SEO还要求在页面里输出 datePublished 和 dateModified 两个 JSON-LD 字段:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "{dede:field.title/}",
  "datePublished": "{dede:field name='pubdate' function='strftime("%Y-%m-%dT%H:%M:%S+08:00",@me)'/}",
  "dateModified": "{dede:field name='lastedit' function='strftime("%Y-%m-%dT%H:%M:%S+08:00",@me)'/}"
}
</script>

Google会基于这两个字段在搜索结果里展示"更新于X月X日"的提示,对点击率有正向影响。保哥的客户站接入这套结构化数据后,平均点击率提升了12%到18%。

修改后的全流程验证

保哥的习惯是改完任何一个底层逻辑都要跑一遍完整验证,避免线上翻车。

第一步:在测试环境复制一篇文章,记录原pubdate。

SELECT id, title, pubdate, FROM_UNIXTIME(pubdate) FROM dede_archives WHERE id = 1234;

第二步:进入后台编辑该文章,只改一下正文内容,不动时间字段,保存。

第三步:再次执行上面的SQL,确认pubdate字段没变,只有正文变了。

第四步:到前台首页和分类页看一眼,确认这篇文章没有冒泡到顶部。

第五步:触发sitemap重新生成,检查 <lastmod> 是否仍然是原值(如果你按第五节加了lastedit字段,可以让sitemap改用lastedit)。

第六步:用Google Search Console的URL检查工具实际抓一次这个URL,看渲染后页面里的JSON-LD时间字段是否符合预期。

六步全过,才算这次修改稳了。如果有任何一步异常,逐个回退到上一步定位问题。

版本兼容性与升级注意

这套修改在DedeCMS 5.7、5.8、DedeBIZ各版本下都验证过,行号略有差异但函数名和字段名都一致。一些特殊情况:

  • DedeCMS V5.7 SP2archives_edit.htm 里的nowtime定义在第38到45行之间,找到后按本文方案修改即可。
  • DedeBIZ 6.0+:DedeBIZ对编辑页做了Vue化重构,前端表单从API取数据,需要同时修改后端 /admin/api/archives_edit.php
  • UTF8与GBK版本:核心逻辑完全一致,只是文件编码不同,修改时注意保存时不要改变原编码(用Sublime或VSCode打开时确认右下角编码标识)。
  • GBK版本:保存为GBK需要确保编辑器没有BOM,否则会引发"Headers already sent"错误。

升级DedeCMS时这个修改会被覆盖。保哥的标准做法是把所有自定义修改记录在一个 patch.md 文档里,每次升级后照着清单重新打一遍。如果你用git管理代码,更优雅的做法是把每个补丁做成独立commit,升级后cherry-pick即可。

保哥的踩坑案例

2019年帮一个汽车配件B2B站做SEO诊断,客户反馈"我家文章发布的时候排名挺好,过几天就掉下去了"。保哥拿Google Search Console一看,每篇文章的Last Crawled时间和pubdate都对得上——说明每次客户编辑文章(修改产品参数、补充图片),pubdate都被刷新了,Google把它当作"新发布的内容"重新评估,但这些"新发布"的内容其实没有真正的内容增量,于是被Freshness算法降权。给客户上了本文的方案后,三个月内整站平均排名提升了 17 个位置,这个项目让保哥彻底意识到 pubdate 锁定对老站SEO的重要性。

另一个案例是2021年某个本地生活资讯站,编辑团队习惯每篇文章发布后多次微调,结果首页永远是"今天编辑的几篇"占据,真正的新闻爆款被压在第二屏。保哥引入双时间字段后,首页严格按pubdate排,编辑动作不影响排序,编辑团队反馈"现在终于能放心改文章了"。

应急回滚方案

万一改完上线之后发现有问题(极少见,但保哥的工程习惯是任何变更都要有回滚预案),按以下顺序回滚:

  1. 恢复 archives_edit.htm:从备份目录或者DedeCMS官方包里复制一份原始文件覆盖回去;
  2. 恢复 article_edit.php:把第四节加的"强制保留首发时间"那行注释掉或删除,恢复到执行 GetMkTime 的默认逻辑;
  3. 清后台缓存:DedeCMS后台 → 系统 → 系统设置 → 更新缓存,避免旧编译模板继续生效;
  4. 验证:编辑任意一篇测试文章,确认编辑页发布时间字段又恢复成了"当前时间"默认填充。

如果你按第五节加了 lastedit 字段,要回滚整个双时间字段方案,按反向顺序:先把模板里的 lastedit 调用去掉,再删除数据库字段(或保留字段但不再使用)。删字段的SQL是 ALTER TABLE dede_archives DROP COLUMN lastedit;,注意先备份。

保哥的实战经验:从来没有真正用过这套回滚预案,但每次部署生产前都会把回滚步骤写在工单里、贴到团队飞书群。有备无患是工程的基本素养,特别是在动后台核心文件的时候。

保哥的部署 SOP

给客户做这套修改时,保哥的标准 SOP 是:

  1. 测试环境先复制一份生产数据库和文件;
  2. 测试环境按本文方案修改并跑完六步验证;
  3. 把修改前后的文件 diff 输出保存到工单;
  4. 选业务低峰期(凌晨2点到4点)部署到生产;
  5. 部署前打 mysqldump 全量备份,文件备份打 tar.gz;
  6. 部署后立刻在生产环境复测六步验证;
  7. 持续监控 7 天,看是否有用户反馈或后台报错;
  8. 7天没问题后归档工单,关闭变更窗口。

这套 SOP 看起来繁琐,但对于运营了多年、流量上万的内容站来说,每一步都是在防止"小改动引爆大事故"。

常见问题解答

改完之后所有老文章的时间会怎么样?

不会动。这个修改只影响未来再次编辑文章时的行为,已经存在于数据库里的pubdate维持原样。如果你想批量把已经被刷掉的pubdate修回去,需要从备份里找数据,或者从senddate字段(部分版本里这个字段保留了首发时间)里恢复。具体SQL:UPDATE dede_archives SET pubdate = senddate WHERE pubdate > senddate; 注意先备份再执行。

升级DedeCMS时这个修改会被覆盖吗?

会。织梦的版本更新本质上是覆盖文件,所有手动改过的核心文件都会被覆盖回原版。保哥的建议是把所有自定义修改记录在一个patch笔记里,每次升级后照着清单重新打一遍。或者使用git管理整个站点目录,升级前先git stash,升级后git stash pop解决冲突。如果是大型团队,建议把所有patch做成shell脚本一键应用,避免人工漏打。

会不会影响DedeCMS的伪静态或者静态生成?

不会。pubdate影响的是文章URL中的日期段(如果你的伪静态规则用了Y/m/d这种),但只要pubdate不变,URL就不会变,已生成的静态文件也不需要重新生成。如果你的修改是让pubdate始终保留首发时间,反而能避免URL漂移这种糟糕的SEO事故。如果你担心,可以在改之前先备份一遍 /a/ 目录(生成的静态HTML),改完后对比文件modified时间是否有异常变化。

如果只想偶尔保留首发时间,平时还是按当前时间,怎么做?

做一个开关。在archives_edit.htm里加一个checkbox:<label><input type="checkbox" name="keep_pubdate" value="1"> 保留首发时间</label>,然后在article_edit.php里判断 if (!empty($_POST['keep_pubdate'])) { $pubdate = $arcRow["pubdate"]; }。这样默认行为不变,只有在编辑时主动勾选才锁定时间,灵活度更高,也更适合编辑团队协作。

修改之后织梦的文章管理列表页排序还正常吗?

正常。后台文章管理列表默认按发布时间倒序,pubdate锁定后这个排序也会保持稳定,不会因为你改了文章就跑到列表第一页。如果你想让后台列表按"最近编辑时间"排序,可以改 /dede/content_list.php 里的ORDER BY子句,把 ORDER BY arc.pubdate DESC 改成 ORDER BY arc.lastedit DESC(前提是你按第五节加了lastedit字段)。这样运营人员能优先看到最近改过的文章,方便复核。

批量发布的文章如何保证pubdate正确?

织梦的批量发布工具(比如采集插件、API发布)默认走 article_add.php 而不是 article_edit.php,所以本文的修改不会影响批量发布的初始时间。如果你的批量发布工具想自定义pubdate(比如把采集源的原始发布时间作为pubdate),需要在调用API时显式传入pubdate参数,并确保 article_add.php 里没有强制覆盖逻辑。具体实现因插件而异,参考所用插件的API文档。

这套修改对其他CMS有参考意义吗?

有。本质问题在所有CMS都存在:WordPress的 post_modified vs post_date、Typecho的 modified vs created、PHPCMS的 updatetime vs inputtime、帝国CMS的 newstime。WordPress和Typecho默认就分开管理,不需要改。PHPCMS和帝国CMS的默认行为和DedeCMS类似,需要类似的修改。保哥给客户做SEO优化时,第一件事就是确认CMS的发布时间和编辑时间是否分离,没分离的全部加上。

有没有现成的DedeCMS插件可以一键搞定?

保哥找过,市面上有几个号称能锁定pubdate的插件,但都是十年前的老插件,对DedeCMS V5.7 SP2及以后版本兼容性都不好,安装后经常报错。最稳妥的还是按本文手动改两行代码,全程5分钟搞定,且改动可见可控。如果你的团队有多个DedeCMS站点要批量处理,保哥建议把改法封装成一个 fix_pubdate.sh 脚本,sed替换+grep验证,几十秒处理一个站。

FAQPage + Article AI 引用友好版

TL;DR · 60–80 字摘要 · 适用 ChatGPT / Perplexity / Gemini / 文心 引用

织梦DedeCMS默认编辑文章会把pubdate刷新成当前时间,干扰首页排序、SEO时序信号和sitemap。本文给出archives_edit.htm一行代码改法、article_edit.php后端兜底、新增lastedit双时间字段方案、6步回归验证流程和DedeBIZ版本兼容说明,全程5分钟搞定。

关键实体 · Key Entities

  • 织梦发布时间
  • DedeCMS修改
  • pubdate保留
  • 织梦SEO
  • 织梦后台
  • 织梦CMS教程

引用元数据 · Citation Metadata

title:       织梦DedeCMS修改文章保留原发布时间4步实操
author:      张文保 (Paul Zhang) — PatPat SEO 经理
url:         https://zhangwenbao.com/dedecms-changes-the-time-of-release-after-updating-the-article.html
published:   2018-05-07
modified:    2026-05-16
source-type: First-hand expert commentary
language:    zh-CN
license:     CC BY-NC-SA 4.0 (要求保留原文链接与作者归属)
分享到
标签
版权声明

本文标题:《织梦DedeCMS修改文章保留原发布时间4步实操》

本文链接:https://zhangwenbao.com/dedecms-changes-the-time-of-release-after-updating-the-article.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交